Make the Brain the Chat's living background; float components on legibility-floored Glass - #64

Closed
kateebonner wants to merge 34 commits into
local/amicodefrom
amico/issue-56-living-chat
Closed

Make the Brain the Chat's living background; float components on legibility-floored Glass#64
kateebonner wants to merge 34 commits into
local/amicodefrom
amico/issue-56-living-chat

Conversation

@kateebonner

@kateebonnerkateebonner commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Closes#56

Integration branch for the Living Chat redesign, built slice-by-slice from the sub-issue DAG (#59#60#61#62#63; design-of-record: ADR 0002, merged via #58).

Landed:

Final gate on this branch: ui 402 pass / 0 fail · app 464 pass / 0 fail · typecheck 23/23 · lint 0 errors.

Honest pre-gate evidence (headless, dev build — NOT the gate): forced full tempo + 11s continuous scroll of a 144-message thread → dark p95 25.4ms / light 25.2ms, mean ≈16.3ms, 11–15 frames >33ms. The tail misses the 16.7ms budget in that proxy environment (dev-mode Solid, headless vsync, sampler riding the measured loop) — which is exactly what the pre-agreed governor valve is for. The real call happens on the reference laptop (checklist below).

Known follow-up candidates (from #61's browser pass, non-blocking): composer placeholder hint and reasoning-part still composite on standard/bare over the Brain.

🤖 Generated with Claude Code

kateebonnerand others added 19 commits July 25, 2026 02:26
The full-bleed Brain background component, ported from the old
kate/chat-brain-atmosphere branch and retargeted to the native engine on
this branch: suspend()->pause(), refreshTokens()->setTheme(scheme) read
from data-color-scheme, the requestRender font-ready hook degraded to a
resize() repaint, and the old-engine-only setActive/setReducedMotion
dropped (tempo work is slice #62). Environment plumbing carried over
verbatim: ResizeObserver->resize, theme MutationObserver, document
visibility + IntersectionObserver hard-pause, amicode:brain-hover
glances, and the diff-by-id event flush with a silent first restore.
The live feed is the inline strip's event derivation extracted to a
pure, session-scoped deriveBrainEvents(messages, getParts) so it is
unit-testable headless and shared by the mount: touches in message
order via the tool->brain-ref map, a chart after each completed
assistant turn with >=2 commits, replay=true for completed turns,
ids never repeated.
Tests: new brain-events derivation suite (9 cases) pinning the AC-4
contract; brain-engine suite extended with the background-mount driving
case (derived-stream growth, quiet replay-only first flush with nothing
queued, lossless theme swap over a restored atlas).
Part of #56 (ADR 0002 - the Brain becomes the Chat's background).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
One full-bleed BrainAtmosphere per Chat window, mounted as the first
child of the session pane card (now relative isolate) at -z-10: above
the pane's surface fill, below the conversation timeline, landing, and
composer, pointer-events none. Keyed on the active session id so a
titlebar tab swap remounts to that session's atlas with exactly one
engine/render loop alive; empty on the landing. The standalone
new-session draft page gets the same layer (no events - sparse seed).
The inline brain-strip timeline row is deleted: the Brain member is
dropped from the TimelineRow union, forcing out its key branch, the
timelineRows append, the keepMounted special-case, the render case, and
the framed-row exclusion. The working-indicator shimmer (Thinking row)
is untouched, guarded by a new row-model suite; the strip's
click-to-expand is obviated (the engine has no node hit-testing).
Part of #56 (ADR 0002 - the Brain becomes the Chat's background).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Two-tier Glass token system over the Brain background (ADR 0002):
standard (prose/bubbles/composer) and dense (code/diffs/run-plots),
one shared 18px blur, tint carries all contrast. Each tier's alpha is
DERIVED per theme+mode — the least alpha clearing WCAG-AA with a +0.3
safety margin (target 4.8) over that mode's reference frame, read from
the brain engine's own PALETTES (dark: peak-bloom #fff676; light:
#8f8000 — the light brain never paints #fff676). Dense additionally
converges every graphical mark (syntax tokens, diff fills, run-plot
strokes) to within 0.2 of native and holds WCAG 1.4.11's 3:1.
- glass-tokens.ts: WCAG math (ported from the old branch), pure
deriveGlassTiers(tokens, frame) — no blur argument by design —
collectMarks, and the generateGlassCss emitter for every bundled
theme, scoped html[data-theme][data-color-scheme] with a
@supports-not near-opaque fallback (alpha >= 0.95)
- glass.css: committed generated output, registered in styles index;
exposes only [data-glass="standard"|"dense"] surfaces — no component
opts in within this slice, rendered output unchanged
- generate:glass script mirrors generate:tailwind wiring
- brain-engine.ts: export PALETTES (data seam only, no behavior change)
- glass-tokens.test.ts: headless contrast certification for oc-2
light+dark — body/code text floors + margin, mark rule, strict tier
ordering, blur-never-a-term guard, keying purity, fallback floor,
byte-for-byte drift guard, and the muted-grey-rides-dense invariant
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…st cadence) (#62)
One draw-gate honored by both the rAF loop and the manual tick(): full
musical tempo while active / in-flight / unfurling, ~8fps breathing at
rest (REST_FRAME_MS ported from the atmosphere branch engine). touch/
chart/highlight/resize/resume/setTheme beat the throttle via
requestRender so feedback stays immediate. BrainEngineStats gains
active + scale.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Boot is the amico core alone — the vault-skeleton preload, its
force-settle layout, and the demo-trace thought-edges are gone (ADR
0002 rejects the breathing skeleton atlas). The graph grows only from
real touches; two engines share no state (all state closure-local).
The camera is a constant core-centered zoom: no per-frame
fit-to-farthest, no close-up follow, no glance steering — growth
densifies in place. stats().scale exposes the fixed zoom; ambient
ghost picks tolerate an empty edge set.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The cap is the whole graph (core + GRAFT_CAP), not just live-* grafts:
eviction picks the least-recently-touched node — recency stamped by a
monotonic touch counter, not the beat clock (which stalls at rest).
Only the current live node and in-flight pulse endpoints are exempt;
atlas keep / charting / replay grant no immunity, so marathon sessions
can never grow the node set or per-frame draw cost without limit.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…rest (#62)
With prefers-reduced-motion set the engine never breathes at idle: once
the post-event nudge window (NUDGE_MS, rebased onto the frame timebase,
never performance.now()) elapses with nothing in flight, ticks draw
nothing and the rAF chain ends — a touch/chart/highlight/resume re-arms
one bounded burst. This is the accessibility terminal (ADR 0002),
independent of slice #63's frame-time ease. pause() clears any
scheduled frame; the lifecycle suite now pins zero-draws-while-hidden.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…#62)
Re-add the `active` output that #59's createBrainEvents dropped:
deriveBrainActive (pure, headless-tested — non-idle means busy or
retrying) feeds a memo that session.tsx passes to <BrainAtmosphere
active>, which plumbs it to engine.setActive. The draft page keeps the
default at-rest Brain (no session, no busy signal). Test helpers
(drive/clears) consolidated at file scope.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Everything floats over the mounted Brain (ADR 0002): the seven content
archetypes opt into slice #60's tier tokens — STANDARD on the user
bubble, assistant prose (which gains its first card), and the composer;
DENSE on code blocks, diffs, run-plots/run-windows, and tool cards (the
tool-collapsible root, so trigger + expanded output float as one unit
across single tools and context/shell groups). The tier token owns
fill/edge/radius/shadow everywhere — the opaque --surface-base bubble
fill, the composer's layer-01 fill + raised shadow, and the dock band's
background-stronger tiling are gone, so the Brain stays live in the
gaps (session-turn row frames and column wrappers stay transparent).
Muted/secondary ink never composites against the ultra-transparent
standard tint (certified to fail AA by #60): the prose meta, user-
message meta, composer footer controls, prose blockquotes, the child-
session stub, and the bubble's file/agent highlights all ride dense-
backed inline zones styled with --glass-dense-bg — the #60 token, no
new tint/blur literal anywhere. Shiki's inlined theme surface defers
to the dense card; the diff card's sticky header occludes with the
dense token instead of opaque chrome. The ghost-collapsible reset is
scoped :not([data-glass]) so the tier fill survives specificity.
Tests extend #60's certified surface onto the components:
- glass-float.test.ts (ui): the 7-archetype tier map as a table test —
body→standard ≥4.8 (AA + margin), code/diff→dense ≥4.5, marks→dense
≥3:1 (1.4.11) without native drift, muted-role never on standard —
measured with #60's exported validator math over the running-brain
reference frame in both oc-2 modes; plus source contracts (tier
attributes on the real markup, no ad-hoc literals in the restyled
card rules, repo-wide data-glass allowlist: two tier values only,
never on Rail/titlebar/Panels chrome).
- glass-float.test.ts (app): composer/diff/child-stub tier contracts,
gaps-stay-live (no glass, no fill on session-turn + containers), and
the sticky session-title header's pre-existing chrome blur untouched.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The sparse-seed boot (#62) removed the last importer; the latent skeleton
atlas was the superseded design's raw material (flagged by the #62 engineer,
removed at integration).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ver blur (#63)
A frame-time state machine observing the ONE Brain render loop: rolling-p95
over the 16.7ms budget for a sustained ~2s window steps motion down the
tempo ladder (allegro -> andante -> largo) with eased paint-cadence caps,
then to a motion full-stop, then terminally hard-pauses the canvas to a
static blurred field. Dual-guard hysteresis (13ms restore threshold + a ~2x
clear window, one level per window) prevents oscillation; the sample window
resets on every step so a stale regime never cascades an unearned step.
Measurement pauses with the engine (hidden / off-screen / reduced-motion):
stalled gaps are discarded, never fed as phantom over-budget frames. The
governor is independent of the reduced-motion accessibility terminal (#62)
and is bypassed entirely under it. Its only levers are tempo and the
terminal pause — no path writes a glass token, a style, or any CSS; stats()
now emits the discrete motion level. governed:false (the dev
force-full-tempo hook's engine seam) disables it for un-eased worst-case
perf capture.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…isables the governor (#63)
Ported from the old branch's perf-capture hook and extended per the issue:
the param now ALSO disables the perf governor (governed:false), so a gated
run — headless proxy or the reference laptop — measures the un-eased worst
case. DEV-gated, inert in prod. Also DEV-only window.__amicoBrainStats for
the trace harness and the manual gate checklist to read engine stats live.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…h themes (#63)
Playwright spec over the real app on the e2e mock-server harness: boots the
144-message fixture thread with the dev force-full-tempo hook (Brain pinned
busy, governor disabled — the un-eased worst case), scrolls continuously
for >=11s per theme inside the SAME rAF loop that samples frame intervals,
and emits a p95 / max / frames>33ms report per theme.
Labeled and asserted as the PRE-GATE PROXY only: the spec pins that the
harness runs and reports (shape, duration, theme coverage, forced state) —
it asserts NO numeric frame-time outcome. The release gate stays the manual
sign-off on the pinned reference laptop (issue #63, HITL).
Run: cd packages/app && bunx playwright test e2e/perf/brain-governor-trace.spec.ts
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…re-emptively eases (#63)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@kateebonner

Copy link
Copy Markdown
ContributorAuthor

HITL sign-off checklist — reference-laptop 60fps gate (#63)

The one open acceptance criterion on this PR. Run on the reference laptop, battery-powered:

  • Pin the machine: model, OS, battery %, VS Code + webview (Chromium) version — write them here.
  • Launch the dev lane: opencode serve --port 4099 + bun --cwd packages/app dev --port 5990 with VITE_OPENCODE_SERVER_PORT=4099 (the force hook is DEV-gated by design).
  • Open the Chat in the VS Code webview on a real thread of ≥40 cards with ?brainForceActive appended; verify in devtools: window.__amicoBrainStats()active: true, motion: "full".
  • Record a ≥10s continuous scroll (devtools Performance panel, or the rAF sampler in Add the perf governor (ease motion, never blur) and gate 60fps on the reference laptop #63's notes ~600 frames).
  • Pass = p95 ≤ 16.7ms AND zero frames > 33ms. Repeat in both themes (flip the chat scheme mid-session — Brain/Glass re-key losslessly).
  • Write the numbers here and sign off.

If the gate fails: remove ?brainForceActive and confirm the governor engages under load — watch __amicoBrainStats().motion step eased-1 → eased-2 → full-stop → hard-paused with the frosted look intact — then decide accept-with-valve vs iterate. (Headless dev-proxy already suggests the tail will need the valve; see PR body.)

🤖 Generated with Claude Code

@kateebonner
kateebonner marked this pull request as ready for review July 25, 2026 16:28
kateebonnerand others added 8 commits July 25, 2026 16:30
…sed question dock
Live design-review iteration with Kate (2026-07-25) on the Living Chat:
- Glass is ONE recipe everywhere: blur 8px + per-mode tint (dark: 4% white
frost + backdrop brightness(0.4); light: 5% near-white). The dark tint's
direction flips to a frost veil (lighter than ground, classic glass) with
the brightness term modeled honestly in the contrast derivation.
- The marks law (WCAG 1.4.11 dense certification) is WAIVED by design
decision; dense==standard. Muted ink is recorded as not-certified.
Tests rewritten to record the waiver rather than certify the old law.
- Cards no longer span the thread: prose fit-content ≤ min(88%,72ch),
user bubbles ≤ min(82%,64ch), tool cards ≤ 92%.
- The question dock floats on glass (8th archetype); its muted hint and
answers summary ride dense-backed zones; opaque fill scoped to
:not([data-glass]).
Part of #56 (PR #64); supersedes the #60/#61 tier law per Kate's call.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…cipe
Receipt chip, ask card (+options), run window (hover regression fixed),
inline entity card, entity rail chips, widget-preview shell, entity-view
inner atoms (tier/skeleton/formula/badge/seq/status pills), and the classic
in-chat landing (one standard card; starter buttons on dense-zone fills,
accent-edge instead of a yellow border on light). Semantic error state is a
danger tint over the glass, never an opaque surface. No !important fills.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Permission dock joins the question dock on the unified glass card (dock-prompt
generalized across kinds, permission footer flattened the same way); todo /
followup / revert trays carry the standard hook (opaque tray fill loses to
glass.css by import order); todo scroll-fade rides the glass tint; question
option tiles become dense-zone fills with the accent-soft hover, never an
opaque layer.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Opaque bands inside glassed cards defer to the dense-zone token (edit/write/
apply-patch sticky triggers, accordion header+expanded body inside any glassed
card, StickyAccordionHeader, timeline diff expanded view); the task/subagent
card is a dense zone with the accent-soft hover; diagnostics become a critical
tint over the frost; error/retry/assistant-error cards ride glass with a danger
tint; bare-muted-ink rows get their #60 backing (thinking indicator, reasoning
part, tool-loaded-file rows, turn divider label, comment-strip chips); user
attachment chips carry the dense hook; jump-to-bottom converts its hand-rolled
near-glass to the single recipe; the sticky session-title band converts its
chrome gradient/blur literals to the glass vars; inline-code chips ride the
dense token.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…cipe
Dialogs (one dialog.css edit covers delete-session/entity/fork/MCP/file/model/
unpaid/usage-exceeded launch sites), ImagePreview lightbox, popovers, dropdown
menus, shared Select menus, slash/@ autocomplete, project picker, model
selector, toast v2 — all ride the glass vars (tint + shared blur/brightness +
edge) with the legacy token as no-theme fallback; item highlights move to the
accent-soft state fill. Tooltips, the markdown code-fence copy tooltip and the
legacy toast keep their deliberate INVERSE ink on a HEAVIER glass (denser
float-token tint + shared blur/edge, never a raw opaque token); the copy
button itself rides the dense token. Drag overlay and the legacy composer
clip-mask stay heavier by function (masking), now token-mix + blur; composer
attachment tiles/pills and the theme-blind bg-black/50 name bar move to token
tints; legacy composer path gets the standard hook; composer loading stub and
review-tab header/diff surfaces convert to the glass tokens; classic landing
metadata gets a dense-zone chip.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ll audit
ui: allowlist covers every swept file (+ pre-allowed entries for the parallel
draft-landing rebuild: pages/new-session.tsx, session-new-design-view, and the
work-order's pages/session/new-session.tsx alias); new assertions pin the
AMICO family hooks + no-opaque-layer fills, dock unification across kinds,
question-option dense tiles, no-opaque-band-inside-glass (sticky triggers,
accordion, task card, diagnostics tint, diff view, inline code), muted-ink
backings, floating-chrome recipes (dialog/popover/menu/select/toast-v2/
ImagePreview), heavier inverse glass for tooltip/toast/copy-tooltip, review
surfaces, and error-tint-over-glass replacing the old no-glass error ruling.
app: sticky title band asserted on the glass vars (chrome literals banned),
timeline data-glass census, dock/composer chrome coverage, drag-overlay and
legacy clip-mask pinned as heavier-by-function token mixes.
These fail if any fix is reverted.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…st Brain
The empty landing shows the full latent network ("everything amico could
think") as a clustered ellipsoid cloud rotating in 3D, projected inside the
existing canvas engine (new constellation mode; reuses the rAF loop, governor,
pause/resume, theme re-key, reduced-motion). Curated core + seeded procedural
densification → identical constellation every launch. Dim monochrome + whisper
cluster tints, ZERO #fff676 (yellow stays exclusive to live thought). Twinkle +
breath micro-motion; static ¾ tableau under reduced-motion. First prompt →
ignition dissolve → live session graph. Removes the opaque new-session hero
wrapper that was occluding the Brain entirely, and glasses the draft-landing
chips + metadata. DEV knobs: ?constellationSpeed/Density/Tint/Fog.
Design of record: grilled with Kate 2026-07-25 (landing-only; clustered cloud;
canvas projection; mono+cluster-tint; ignition dissolve; twinkle+breath; static
tableau; uniform full-bleed). Part of #56 (PR #64).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
kateebonnerand others added 2 commits July 25, 2026 17:16
# Conflicts:
#	packages/app/src/components/session/session-new-view.tsx
#	packages/ui/src/amicode/getting-started.tsx
…k composer, typewriter placeholder, 3D constellation in-session
Live design-review iteration with Kate (2026-07-25) on the Living Chat:
Glass
- Max transparency: dark tint derives to fully transparent (backdrop
brightness 0.4 -> 0.8; less darkening lets the constellation read through).
AA retained for LIGHT, waived-and-recorded for DARK standard (the landing
constellation is yellow-free, so it reads there). Tests record the trade.
- The glass tier is now JUST blur + tint + radius — no border outline, no top
sheen/inset line, no box-shadow (Kate: "no border, no top line, no shadow").
Composer
- One background: dock-surface shell/tray opaque fills scoped to :not([data-glass])
so the glass wins as one uniform surface; footer inset fill removed (was a
visible second background).
- Full-bleed bottom dock: full width, stuck to the bottom, ~35% viewport height
(ui-ux-pro-max: primary CTA without eclipsing the hero), edge-to-edge (radius/
border/shadow zeroed). Fixed the flex height-chain so it fills to the bottom.
- Removed the model-provider H-mark/AMICODE wordmark and the project/folder
picker from the landing.
Landing
- Starter chip wall removed (competed with the constellation + composer).
Discovery now lives in the composer as a rotating TYPEWRITER placeholder that
types out the real starter prompts letter-by-letter with a blinking caret;
freezes on focus (Tab accepts the shown one), static under reduced motion.
- Constellation contrast bumped (edge alpha 0.10 -> 0.17, nodes x1.4).
Session parity
- The 3D constellation is now the background EVERYWHERE (session too), not the
sparse 2D live graph — the launch and session are one surface. (Live-thought
node pulsing is the next layer.)
Gates: ui 438 / app 473 / typecheck 23/23 / lint 0 errors. Part of #56 (PR #64).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@kateebonner

Copy link
Copy Markdown
ContributorAuthor

Live design-tuning batch (Kate, 2026-07-25) — commit 69ebf7e

The design evolved significantly beyond the original slices through a live review session. Landed:

  • Glass — now purely blur + tint + radius: dark derives to fully transparent (brightness 0.8), no border, no top sheen, no box-shadow. AA kept for light, waived+recorded for dark standard (the landing constellation is yellow-free).
  • Composer — one uniform glass surface (two-tone fixed); full-bleed bottom dock, ~35% viewport height, edge-to-edge; wordmark + project/folder picker removed.
  • Landing — starter-chip wall removed; discovery moved into the composer as a rotating typewriter placeholder (types the real starters letter-by-letter, blinking caret, Tab-to-accept, reduced-motion static). Constellation contrast bumped.
  • Session parity — the 3D constellation is now the background in-session too (not the sparse 2D graph); launch + session are one surface.

Queued (next): live-thought node pulsing over the constellation (data-true layer), card width containment, and folding the effort/variant selector into the model dropdown.

Gates: ui 438 / app 473 / typecheck 23/23 / lint 0 errors.

🤖 Generated with Claude Code

…lass sweep
Overnight batch 2 (Kate 2026-07-25), three asks:
1. Live thought over the constellation — the '+ live thought' half of
'constellation + live thought': real session touches flare their node
in css.thought (#fff676 dark / #8f8000 light) over the latent web —
rise 150ms, ease-out decay ~1.6s, expanding ring, incident-edge
glints, touched label beside the flare (fg ink + halo). Labels hash
deterministically into their category lobe with a visible-node walk
(a flare the user can't see isn't thought). Replays restore silently;
re-touches refresh instead of stacking; capped at 24; reduced motion
holds ONE statically lit node. Dev hook window.__amicoBrainTouch
(mirrors __amicoBrainStats) previews flares without a real turn.
+7 tests incl. byte-determinism under touches and the color-law
boundary (latent web ink stays yellow-free with zero touches).
2. Thinking effort folded INTO the model surface — the standalone
Default/None/High footer Select is gone (both composer paths). New
ModelVariantRow renders in the paid ModelSelectorPopover AND the
unpaid dialog (Kate's dev path): chips on --accent-fill-soft /
--accent-edge, keeps the menu open on pick; the collapsed trigger
reads 'Model · High' so effort stays visible at rest.
3. Session glass sweep to the launch-composer feel — glass is
blur+tint+radius ONLY, now enforced in-session: dock-prompt ring +
permission/question footer border-top scoped off-glass; composer
focus ring removed; comment chips borderless; dock radius 10px →
var(--radius-lg). Width containment: tool collapsibles, diffs group,
reasoning-part, error-card all share the prose measure
(min(88%, 72ch)) — floating cards on the Brain, never full-width
bands.
Gate: ui 445 / app 473 / typecheck 23 projects / lint 0 errors.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@kateebonner

Copy link
Copy Markdown
ContributorAuthor

Overnight batch 2 — 05fa001d0

All three queued items from the live-tuning session, plus the new ask (session components on the launch-composer feel):

1. Live thought over the constellation ✨

The "+ live thought" half of constellation + live thought is in. As amico works, each real touch flares its constellation node in the thought color (#fff676 dark / #8f8000 light — the brand law holds per scheme): fast rise, ~1.6s ease-out decay, an expanding ring, glints down the node's incident edges, and the touched label ("session.tsx", "amico-vault") named beside the flare.

  • Labels hash deterministically into their category lobe (file work lights the code lobe, skills the skills lobe…), then walk to a visible node — a flare you can't see isn't thought.
  • History replays silently on mount; re-touches refresh their flare instead of stacking; capped at 24 so a torrent stays a shimmer.
  • Reduced motion: the tableau holds one statically lit node — where amico is now.
  • Dev preview without a real turn: window.__amicoBrainTouch({label:"x.ts", type:"resource"}) in the console (the ?-param pattern doesn't survive the router redirect, so this rides the __amicoBrainStats hook pattern instead).
  • +7 tests: flare paint, light-scheme ink, silent replay, refresh-not-stack, decay-to-rest, reduced-motion tableau, and byte-determinism under touches. The latent-web color law tests still pin zero yellow with zero touches.

2. Thinking effort lives in the model menu

The standalone Default/None/High Select is gone (both composer paths). A ModelVariantRow renders inside the paid popover and the unpaid dialog (the dev/free path — it would otherwise have lost the control entirely): chips on --accent-fill-soft/--accent-edge, picking one keeps the menu open. The collapsed trigger now reads "DeepSeek V4 Fl… · High" so effort stays visible at rest.

3. Session glass sweep — the launch-composer feel everywhere

Glass = blur + tint + radius, nothing else, now enforced in-session too:

  • dock-prompt (permission/question card): 1px ring removed, footer border-top removed (one surface, same law as the composer footer), radius 10px → --radius-lg.
  • In-session composer: focus-within ring removed (the caret carries focus; drag keeps its dashed dropzone).
  • Comment chips: borderless dense tint.
  • Width containment: tool collapsibles ("Explored · 2 searches"), the diffs group, reasoning, and error cards all share the prose measure — min(88%, 72ch) — so the thread reads as floating cards over the Brain, never full-width bands.

Verified live in both themes on real sessions (silent replay ✓, live flare mid-session ✓, permission card ✓).

Gate: ui 445 / app 473 / typecheck / lint 0 errors.

kateebonnerand others added 4 commits July 26, 2026 12:38
… session composer = launch dock
Live review with Kate (2026-07-26), three asks:
1. 'I don't see the flares' — thought was landing behind the message
column's glass. The engine now takes an occlusion set (occlude());
session.tsx measures the real layout (timeline column band + composer
dock) and BrainAtmosphere feeds it fresh before every event flush, so
flares land in the GUTTERS where the Brain is actually visible
(fallback: merely-visible beats nothing). While the session works,
the NEWEST flare holds lit as a sustained 'amico is HERE' cursor and
decays out when the turn ends. +3 tests (gutter avoidance, hold/decay,
fully-occluded fallback).
2. Cards hug their contents — tool collapsibles and the diffs group are
width: fit-content up to the prose measure, never a padded-out band.
3. The session composer IS the launch composer — same full-bleed bottom
dock (~35% of the pane, edge-to-edge one-surface glass) via
placement='inline'; starter/typewriter suggestions stay gated to the
EMPTY LANDING (params.id gates on rotation, typing, Tab-accept,
placeholder). Legacy layout keeps the floating column card.
Gate: ui 448 / app 473 / typecheck / lint 0 errors.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ttom-stacked flow + full-width header
Live review with Kate (2026-07-26), second batch:
- Thought-tracking camera v2: rotation eases to a stop while flares are
alive and the view zooms (1.6x) + glides the newest thought to the
CENTER of the frame (Kate's call — replaces the gutter stage). All 6
confirmed findings from the adversarial review workflow fixed:
(1) conPulses is RECENCY-ordered — a re-touch splices to the end, so
the camera + busy-hold follow the re-fired concept, never a stale
array-last pulse; (2) ignite() no longer spins the stopped web back up
mid-dissolve (conRotK frozen during ignite) and the camera fast-eases
home (tau 200ms) before the live layer co-paints; (3) an OS
reduced-motion flip mid-track snaps the camera home instantly;
(4) edges/glints/ring/bloom scale with the zoom — a camera dolly, not
dots inflating over a hairline web; (5) flare seating is computed in
AMBIENT space so the zoomed viewport never funnels subsequent flares
into one slice; (6) the busy-hold is budgeted (~30s) so a wedged
active signal or ?brainForceActive cannot freeze the camera forever.
+2 tests (hold budget, seat-vs-camera split); 452 ui tests green.
- Session header: full-width band, bottom padding tight unless the
entity-chips rail rendered (CSS :has), and the band now lives OUTSIDE
the scroller, pinned at the pane top.
- Messages: rows span the pane — user messages justify RIGHT, amico's
justify LEFT (each card keeps its reading measure); the Brain owns the
middle where the camera stages thought.
- Bottom-stacked flow (messenger law): the SCROLLER's height is
content-driven up to the space the header leaves and anchors to the
bottom, so a short thread sits just above the composer; inside it
scrolling stays classic top-anchored — virtua's geometry is untouched
(an mt-auto-in-viewport variant starved virtua's visible range and
was abandoned). startMargin 0, sticky-accordion offsets updated.
Gate: ui 452 / app 473 / typecheck / lint 0 errors.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Kate 2026-07-26 (component audit): the collapsed 'edit · Failed' chip was
banding across the pane — width: fit-content capped at the prose measure,
matching the width law every timeline card now follows.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…erity
Kate 2026-07-26: glass is blur+tint+radius; the 2px Card accent rail read
as a border on the failed/error cards. content:none on the ::before for
tool-error-card and .error-card — the danger tint, icon, and ink alone
mark severity.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@kateebonner
kateebonner marked this pull request as draft July 26, 2026 23:19
@kateebonner

Copy link
Copy Markdown
ContributorAuthor

Parked 2026-07-26 — converting to draft. Aaron's call: not pursuing this UI direction right now. Everything through 83d070ae4 is on the branch (living-chat glass redesign, thought-tracking camera, bottom-stacked edge-justified flow, effort-in-model-menu, component audit + width law). The branch is the complete archive of the direction if we return to it; the component library artifact documents every surface.

@kateebonner
kateebonner marked this pull request as ready for review July 29, 2026 00:21
@kateebonner
kateebonner marked this pull request as draft July 29, 2026 00:23
@jack-champagne

Copy link
Copy Markdown
Member

@kateebonner — question before this ages further: is anything here still worth keeping?

Asking because ADR 0002, which this implements, is marked superseded on mainline:

Status: Superseded by ADR 0003 (direction parked 2026-07-26; the Brain moved to the context-tree top panel instead of becoming the chat background)

and ADR 0003 (Accepted, 2026-07-27, on Aaron's 2026-07-26 feedback) is explicit:

Supersedes: ADR 0002 (Brain as chat background — direction parked)
… Aaron's feedback reframed what the graph is for: not ambience, but orientationThe graph moves out of the timeline into a pinned top panel … the ambient background direction is parked.

The ADR-0003 replacement has fully landed

All of this is on local/amicode and shipped in v1.17.3-amicode.11:

So the top-panel + first-class vault surface direction is done and released.

What's still unique to this branch

brain-engine.ts and context-tree-engine.ts are already on main — the graph engine itself made it across. What has no counterpart is the presentation layer for the parked direction:

only in #64
glass.css (778 lines), glass-tokens.ts, script/generate-glass.ts
brain-atmosphere.tsx / .css
brain-constellation.ts
brain-perf-governor.test.ts, brain-events.ts, e2e/perf/brain-governor-trace.spec.ts

16 added files, 54 modified, 1 deleted.

Why I'm asking rather than just closing

Two things in there look potentially valuable independent of the parked background direction:

  1. The legibility machineryglass-tokens.ts plus the WCAG-AA-floored tint derivation. ADR 0002 records that the earlier attempt failed exactly one AA check (muted grey on the most translucent tier), so this encodes a real lesson. Worth salvaging if any surface still layers text on translucency — the session header's backdrop-blur comes to mind, given fix(session): header backdrop-blur off while the context-tree band is open #97 just had to switch it off over the context-tree band.
  2. brain-perf-governor + the e2e perf trace — frame-budget governance for the graph. The organic context tree that did land has the same cost profile, so a perf governor may be wanted regardless of where the graph renders.

If neither is worth extracting, this is a clean close — the direction is parked and the replacement is released. If either is, they'd be small standalone PRs rather than resurrecting 71 files.

For context on the state: it is still a draft, CONFLICTING/DIRTY, 72 commits behind mainline, and its checks are all CANCELLED from before #2 fixed the runner labels — so CI has never actually evaluated this branch.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Make the Brain the Chat's living background; float components on legibility-floored Glass

2 participants

@kateebonner@jack-champagne
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Make the Brain the Chat's living background; float components on legibility-floored Glass - #64

Closed
kateebonner wants to merge 34 commits into
local/amicodefrom
amico/issue-56-living-chat
Closed

Make the Brain the Chat's living background; float components on legibility-floored Glass#64
kateebonner wants to merge 34 commits into
local/amicodefrom
amico/issue-56-living-chat

Conversation

@kateebonner

@kateebonnerkateebonner commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Closes#56

Integration branch for the Living Chat redesign, built slice-by-slice from the sub-issue DAG (#59#60#61#62#63; design-of-record: ADR 0002, merged via #58).

Landed:

Final gate on this branch: ui 402 pass / 0 fail · app 464 pass / 0 fail · typecheck 23/23 · lint 0 errors.

Honest pre-gate evidence (headless, dev build — NOT the gate): forced full tempo + 11s continuous scroll of a 144-message thread → dark p95 25.4ms / light 25.2ms, mean ≈16.3ms, 11–15 frames >33ms. The tail misses the 16.7ms budget in that proxy environment (dev-mode Solid, headless vsync, sampler riding the measured loop) — which is exactly what the pre-agreed governor valve is for. The real call happens on the reference laptop (checklist below).

Known follow-up candidates (from #61's browser pass, non-blocking): composer placeholder hint and reasoning-part still composite on standard/bare over the Brain.

🤖 Generated with Claude Code

kateebonnerand others added 19 commits July 25, 2026 02:26
The full-bleed Brain background component, ported from the old
kate/chat-brain-atmosphere branch and retargeted to the native engine on
this branch: suspend()->pause(), refreshTokens()->setTheme(scheme) read
from data-color-scheme, the requestRender font-ready hook degraded to a
resize() repaint, and the old-engine-only setActive/setReducedMotion
dropped (tempo work is slice #62). Environment plumbing carried over
verbatim: ResizeObserver->resize, theme MutationObserver, document
visibility + IntersectionObserver hard-pause, amicode:brain-hover
glances, and the diff-by-id event flush with a silent first restore.
The live feed is the inline strip's event derivation extracted to a
pure, session-scoped deriveBrainEvents(messages, getParts) so it is
unit-testable headless and shared by the mount: touches in message
order via the tool->brain-ref map, a chart after each completed
assistant turn with >=2 commits, replay=true for completed turns,
ids never repeated.
Tests: new brain-events derivation suite (9 cases) pinning the AC-4
contract; brain-engine suite extended with the background-mount driving
case (derived-stream growth, quiet replay-only first flush with nothing
queued, lossless theme swap over a restored atlas).
Part of #56 (ADR 0002 - the Brain becomes the Chat's background).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
One full-bleed BrainAtmosphere per Chat window, mounted as the first
child of the session pane card (now relative isolate) at -z-10: above
the pane's surface fill, below the conversation timeline, landing, and
composer, pointer-events none. Keyed on the active session id so a
titlebar tab swap remounts to that session's atlas with exactly one
engine/render loop alive; empty on the landing. The standalone
new-session draft page gets the same layer (no events - sparse seed).
The inline brain-strip timeline row is deleted: the Brain member is
dropped from the TimelineRow union, forcing out its key branch, the
timelineRows append, the keepMounted special-case, the render case, and
the framed-row exclusion. The working-indicator shimmer (Thinking row)
is untouched, guarded by a new row-model suite; the strip's
click-to-expand is obviated (the engine has no node hit-testing).
Part of #56 (ADR 0002 - the Brain becomes the Chat's background).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Two-tier Glass token system over the Brain background (ADR 0002):
standard (prose/bubbles/composer) and dense (code/diffs/run-plots),
one shared 18px blur, tint carries all contrast. Each tier's alpha is
DERIVED per theme+mode — the least alpha clearing WCAG-AA with a +0.3
safety margin (target 4.8) over that mode's reference frame, read from
the brain engine's own PALETTES (dark: peak-bloom #fff676; light:
#8f8000 — the light brain never paints #fff676). Dense additionally
converges every graphical mark (syntax tokens, diff fills, run-plot
strokes) to within 0.2 of native and holds WCAG 1.4.11's 3:1.
- glass-tokens.ts: WCAG math (ported from the old branch), pure
deriveGlassTiers(tokens, frame) — no blur argument by design —
collectMarks, and the generateGlassCss emitter for every bundled
theme, scoped html[data-theme][data-color-scheme] with a
@supports-not near-opaque fallback (alpha >= 0.95)
- glass.css: committed generated output, registered in styles index;
exposes only [data-glass="standard"|"dense"] surfaces — no component
opts in within this slice, rendered output unchanged
- generate:glass script mirrors generate:tailwind wiring
- brain-engine.ts: export PALETTES (data seam only, no behavior change)
- glass-tokens.test.ts: headless contrast certification for oc-2
light+dark — body/code text floors + margin, mark rule, strict tier
ordering, blur-never-a-term guard, keying purity, fallback floor,
byte-for-byte drift guard, and the muted-grey-rides-dense invariant
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…st cadence) (#62)
One draw-gate honored by both the rAF loop and the manual tick(): full
musical tempo while active / in-flight / unfurling, ~8fps breathing at
rest (REST_FRAME_MS ported from the atmosphere branch engine). touch/
chart/highlight/resize/resume/setTheme beat the throttle via
requestRender so feedback stays immediate. BrainEngineStats gains
active + scale.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Boot is the amico core alone — the vault-skeleton preload, its
force-settle layout, and the demo-trace thought-edges are gone (ADR
0002 rejects the breathing skeleton atlas). The graph grows only from
real touches; two engines share no state (all state closure-local).
The camera is a constant core-centered zoom: no per-frame
fit-to-farthest, no close-up follow, no glance steering — growth
densifies in place. stats().scale exposes the fixed zoom; ambient
ghost picks tolerate an empty edge set.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The cap is the whole graph (core + GRAFT_CAP), not just live-* grafts:
eviction picks the least-recently-touched node — recency stamped by a
monotonic touch counter, not the beat clock (which stalls at rest).
Only the current live node and in-flight pulse endpoints are exempt;
atlas keep / charting / replay grant no immunity, so marathon sessions
can never grow the node set or per-frame draw cost without limit.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…rest (#62)
With prefers-reduced-motion set the engine never breathes at idle: once
the post-event nudge window (NUDGE_MS, rebased onto the frame timebase,
never performance.now()) elapses with nothing in flight, ticks draw
nothing and the rAF chain ends — a touch/chart/highlight/resume re-arms
one bounded burst. This is the accessibility terminal (ADR 0002),
independent of slice #63's frame-time ease. pause() clears any
scheduled frame; the lifecycle suite now pins zero-draws-while-hidden.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…#62)
Re-add the `active` output that #59's createBrainEvents dropped:
deriveBrainActive (pure, headless-tested — non-idle means busy or
retrying) feeds a memo that session.tsx passes to <BrainAtmosphere
active>, which plumbs it to engine.setActive. The draft page keeps the
default at-rest Brain (no session, no busy signal). Test helpers
(drive/clears) consolidated at file scope.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Everything floats over the mounted Brain (ADR 0002): the seven content
archetypes opt into slice #60's tier tokens — STANDARD on the user
bubble, assistant prose (which gains its first card), and the composer;
DENSE on code blocks, diffs, run-plots/run-windows, and tool cards (the
tool-collapsible root, so trigger + expanded output float as one unit
across single tools and context/shell groups). The tier token owns
fill/edge/radius/shadow everywhere — the opaque --surface-base bubble
fill, the composer's layer-01 fill + raised shadow, and the dock band's
background-stronger tiling are gone, so the Brain stays live in the
gaps (session-turn row frames and column wrappers stay transparent).
Muted/secondary ink never composites against the ultra-transparent
standard tint (certified to fail AA by #60): the prose meta, user-
message meta, composer footer controls, prose blockquotes, the child-
session stub, and the bubble's file/agent highlights all ride dense-
backed inline zones styled with --glass-dense-bg — the #60 token, no
new tint/blur literal anywhere. Shiki's inlined theme surface defers
to the dense card; the diff card's sticky header occludes with the
dense token instead of opaque chrome. The ghost-collapsible reset is
scoped :not([data-glass]) so the tier fill survives specificity.
Tests extend #60's certified surface onto the components:
- glass-float.test.ts (ui): the 7-archetype tier map as a table test —
body→standard ≥4.8 (AA + margin), code/diff→dense ≥4.5, marks→dense
≥3:1 (1.4.11) without native drift, muted-role never on standard —
measured with #60's exported validator math over the running-brain
reference frame in both oc-2 modes; plus source contracts (tier
attributes on the real markup, no ad-hoc literals in the restyled
card rules, repo-wide data-glass allowlist: two tier values only,
never on Rail/titlebar/Panels chrome).
- glass-float.test.ts (app): composer/diff/child-stub tier contracts,
gaps-stay-live (no glass, no fill on session-turn + containers), and
the sticky session-title header's pre-existing chrome blur untouched.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The sparse-seed boot (#62) removed the last importer; the latent skeleton
atlas was the superseded design's raw material (flagged by the #62 engineer,
removed at integration).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ver blur (#63)
A frame-time state machine observing the ONE Brain render loop: rolling-p95
over the 16.7ms budget for a sustained ~2s window steps motion down the
tempo ladder (allegro -> andante -> largo) with eased paint-cadence caps,
then to a motion full-stop, then terminally hard-pauses the canvas to a
static blurred field. Dual-guard hysteresis (13ms restore threshold + a ~2x
clear window, one level per window) prevents oscillation; the sample window
resets on every step so a stale regime never cascades an unearned step.
Measurement pauses with the engine (hidden / off-screen / reduced-motion):
stalled gaps are discarded, never fed as phantom over-budget frames. The
governor is independent of the reduced-motion accessibility terminal (#62)
and is bypassed entirely under it. Its only levers are tempo and the
terminal pause — no path writes a glass token, a style, or any CSS; stats()
now emits the discrete motion level. governed:false (the dev
force-full-tempo hook's engine seam) disables it for un-eased worst-case
perf capture.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…isables the governor (#63)
Ported from the old branch's perf-capture hook and extended per the issue:
the param now ALSO disables the perf governor (governed:false), so a gated
run — headless proxy or the reference laptop — measures the un-eased worst
case. DEV-gated, inert in prod. Also DEV-only window.__amicoBrainStats for
the trace harness and the manual gate checklist to read engine stats live.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…h themes (#63)
Playwright spec over the real app on the e2e mock-server harness: boots the
144-message fixture thread with the dev force-full-tempo hook (Brain pinned
busy, governor disabled — the un-eased worst case), scrolls continuously
for >=11s per theme inside the SAME rAF loop that samples frame intervals,
and emits a p95 / max / frames>33ms report per theme.
Labeled and asserted as the PRE-GATE PROXY only: the spec pins that the
harness runs and reports (shape, duration, theme coverage, forced state) —
it asserts NO numeric frame-time outcome. The release gate stays the manual
sign-off on the pinned reference laptop (issue #63, HITL).
Run: cd packages/app && bunx playwright test e2e/perf/brain-governor-trace.spec.ts
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…re-emptively eases (#63)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@kateebonner

Copy link
Copy Markdown
ContributorAuthor

HITL sign-off checklist — reference-laptop 60fps gate (#63)

The one open acceptance criterion on this PR. Run on the reference laptop, battery-powered:

  • Pin the machine: model, OS, battery %, VS Code + webview (Chromium) version — write them here.
  • Launch the dev lane: opencode serve --port 4099 + bun --cwd packages/app dev --port 5990 with VITE_OPENCODE_SERVER_PORT=4099 (the force hook is DEV-gated by design).
  • Open the Chat in the VS Code webview on a real thread of ≥40 cards with ?brainForceActive appended; verify in devtools: window.__amicoBrainStats()active: true, motion: "full".
  • Record a ≥10s continuous scroll (devtools Performance panel, or the rAF sampler in Add the perf governor (ease motion, never blur) and gate 60fps on the reference laptop #63's notes ~600 frames).
  • Pass = p95 ≤ 16.7ms AND zero frames > 33ms. Repeat in both themes (flip the chat scheme mid-session — Brain/Glass re-key losslessly).
  • Write the numbers here and sign off.

If the gate fails: remove ?brainForceActive and confirm the governor engages under load — watch __amicoBrainStats().motion step eased-1 → eased-2 → full-stop → hard-paused with the frosted look intact — then decide accept-with-valve vs iterate. (Headless dev-proxy already suggests the tail will need the valve; see PR body.)

🤖 Generated with Claude Code

@kateebonner
kateebonner marked this pull request as ready for review July 25, 2026 16:28
kateebonnerand others added 8 commits July 25, 2026 16:30
…sed question dock
Live design-review iteration with Kate (2026-07-25) on the Living Chat:
- Glass is ONE recipe everywhere: blur 8px + per-mode tint (dark: 4% white
frost + backdrop brightness(0.4); light: 5% near-white). The dark tint's
direction flips to a frost veil (lighter than ground, classic glass) with
the brightness term modeled honestly in the contrast derivation.
- The marks law (WCAG 1.4.11 dense certification) is WAIVED by design
decision; dense==standard. Muted ink is recorded as not-certified.
Tests rewritten to record the waiver rather than certify the old law.
- Cards no longer span the thread: prose fit-content ≤ min(88%,72ch),
user bubbles ≤ min(82%,64ch), tool cards ≤ 92%.
- The question dock floats on glass (8th archetype); its muted hint and
answers summary ride dense-backed zones; opaque fill scoped to
:not([data-glass]).
Part of #56 (PR #64); supersedes the #60/#61 tier law per Kate's call.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…cipe
Receipt chip, ask card (+options), run window (hover regression fixed),
inline entity card, entity rail chips, widget-preview shell, entity-view
inner atoms (tier/skeleton/formula/badge/seq/status pills), and the classic
in-chat landing (one standard card; starter buttons on dense-zone fills,
accent-edge instead of a yellow border on light). Semantic error state is a
danger tint over the glass, never an opaque surface. No !important fills.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Permission dock joins the question dock on the unified glass card (dock-prompt
generalized across kinds, permission footer flattened the same way); todo /
followup / revert trays carry the standard hook (opaque tray fill loses to
glass.css by import order); todo scroll-fade rides the glass tint; question
option tiles become dense-zone fills with the accent-soft hover, never an
opaque layer.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Opaque bands inside glassed cards defer to the dense-zone token (edit/write/
apply-patch sticky triggers, accordion header+expanded body inside any glassed
card, StickyAccordionHeader, timeline diff expanded view); the task/subagent
card is a dense zone with the accent-soft hover; diagnostics become a critical
tint over the frost; error/retry/assistant-error cards ride glass with a danger
tint; bare-muted-ink rows get their #60 backing (thinking indicator, reasoning
part, tool-loaded-file rows, turn divider label, comment-strip chips); user
attachment chips carry the dense hook; jump-to-bottom converts its hand-rolled
near-glass to the single recipe; the sticky session-title band converts its
chrome gradient/blur literals to the glass vars; inline-code chips ride the
dense token.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…cipe
Dialogs (one dialog.css edit covers delete-session/entity/fork/MCP/file/model/
unpaid/usage-exceeded launch sites), ImagePreview lightbox, popovers, dropdown
menus, shared Select menus, slash/@ autocomplete, project picker, model
selector, toast v2 — all ride the glass vars (tint + shared blur/brightness +
edge) with the legacy token as no-theme fallback; item highlights move to the
accent-soft state fill. Tooltips, the markdown code-fence copy tooltip and the
legacy toast keep their deliberate INVERSE ink on a HEAVIER glass (denser
float-token tint + shared blur/edge, never a raw opaque token); the copy
button itself rides the dense token. Drag overlay and the legacy composer
clip-mask stay heavier by function (masking), now token-mix + blur; composer
attachment tiles/pills and the theme-blind bg-black/50 name bar move to token
tints; legacy composer path gets the standard hook; composer loading stub and
review-tab header/diff surfaces convert to the glass tokens; classic landing
metadata gets a dense-zone chip.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ll audit
ui: allowlist covers every swept file (+ pre-allowed entries for the parallel
draft-landing rebuild: pages/new-session.tsx, session-new-design-view, and the
work-order's pages/session/new-session.tsx alias); new assertions pin the
AMICO family hooks + no-opaque-layer fills, dock unification across kinds,
question-option dense tiles, no-opaque-band-inside-glass (sticky triggers,
accordion, task card, diagnostics tint, diff view, inline code), muted-ink
backings, floating-chrome recipes (dialog/popover/menu/select/toast-v2/
ImagePreview), heavier inverse glass for tooltip/toast/copy-tooltip, review
surfaces, and error-tint-over-glass replacing the old no-glass error ruling.
app: sticky title band asserted on the glass vars (chrome literals banned),
timeline data-glass census, dock/composer chrome coverage, drag-overlay and
legacy clip-mask pinned as heavier-by-function token mixes.
These fail if any fix is reverted.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…st Brain
The empty landing shows the full latent network ("everything amico could
think") as a clustered ellipsoid cloud rotating in 3D, projected inside the
existing canvas engine (new constellation mode; reuses the rAF loop, governor,
pause/resume, theme re-key, reduced-motion). Curated core + seeded procedural
densification → identical constellation every launch. Dim monochrome + whisper
cluster tints, ZERO #fff676 (yellow stays exclusive to live thought). Twinkle +
breath micro-motion; static ¾ tableau under reduced-motion. First prompt →
ignition dissolve → live session graph. Removes the opaque new-session hero
wrapper that was occluding the Brain entirely, and glasses the draft-landing
chips + metadata. DEV knobs: ?constellationSpeed/Density/Tint/Fog.
Design of record: grilled with Kate 2026-07-25 (landing-only; clustered cloud;
canvas projection; mono+cluster-tint; ignition dissolve; twinkle+breath; static
tableau; uniform full-bleed). Part of #56 (PR #64).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
kateebonnerand others added 2 commits July 25, 2026 17:16
# Conflicts:
#	packages/app/src/components/session/session-new-view.tsx
#	packages/ui/src/amicode/getting-started.tsx
…k composer, typewriter placeholder, 3D constellation in-session
Live design-review iteration with Kate (2026-07-25) on the Living Chat:
Glass
- Max transparency: dark tint derives to fully transparent (backdrop
brightness 0.4 -> 0.8; less darkening lets the constellation read through).
AA retained for LIGHT, waived-and-recorded for DARK standard (the landing
constellation is yellow-free, so it reads there). Tests record the trade.
- The glass tier is now JUST blur + tint + radius — no border outline, no top
sheen/inset line, no box-shadow (Kate: "no border, no top line, no shadow").
Composer
- One background: dock-surface shell/tray opaque fills scoped to :not([data-glass])
so the glass wins as one uniform surface; footer inset fill removed (was a
visible second background).
- Full-bleed bottom dock: full width, stuck to the bottom, ~35% viewport height
(ui-ux-pro-max: primary CTA without eclipsing the hero), edge-to-edge (radius/
border/shadow zeroed). Fixed the flex height-chain so it fills to the bottom.
- Removed the model-provider H-mark/AMICODE wordmark and the project/folder
picker from the landing.
Landing
- Starter chip wall removed (competed with the constellation + composer).
Discovery now lives in the composer as a rotating TYPEWRITER placeholder that
types out the real starter prompts letter-by-letter with a blinking caret;
freezes on focus (Tab accepts the shown one), static under reduced motion.
- Constellation contrast bumped (edge alpha 0.10 -> 0.17, nodes x1.4).
Session parity
- The 3D constellation is now the background EVERYWHERE (session too), not the
sparse 2D live graph — the launch and session are one surface. (Live-thought
node pulsing is the next layer.)
Gates: ui 438 / app 473 / typecheck 23/23 / lint 0 errors. Part of #56 (PR #64).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@kateebonner

Copy link
Copy Markdown
ContributorAuthor

Live design-tuning batch (Kate, 2026-07-25) — commit 69ebf7e

The design evolved significantly beyond the original slices through a live review session. Landed:

  • Glass — now purely blur + tint + radius: dark derives to fully transparent (brightness 0.8), no border, no top sheen, no box-shadow. AA kept for light, waived+recorded for dark standard (the landing constellation is yellow-free).
  • Composer — one uniform glass surface (two-tone fixed); full-bleed bottom dock, ~35% viewport height, edge-to-edge; wordmark + project/folder picker removed.
  • Landing — starter-chip wall removed; discovery moved into the composer as a rotating typewriter placeholder (types the real starters letter-by-letter, blinking caret, Tab-to-accept, reduced-motion static). Constellation contrast bumped.
  • Session parity — the 3D constellation is now the background in-session too (not the sparse 2D graph); launch + session are one surface.

Queued (next): live-thought node pulsing over the constellation (data-true layer), card width containment, and folding the effort/variant selector into the model dropdown.

Gates: ui 438 / app 473 / typecheck 23/23 / lint 0 errors.

🤖 Generated with Claude Code

…lass sweep
Overnight batch 2 (Kate 2026-07-25), three asks:
1. Live thought over the constellation — the '+ live thought' half of
'constellation + live thought': real session touches flare their node
in css.thought (#fff676 dark / #8f8000 light) over the latent web —
rise 150ms, ease-out decay ~1.6s, expanding ring, incident-edge
glints, touched label beside the flare (fg ink + halo). Labels hash
deterministically into their category lobe with a visible-node walk
(a flare the user can't see isn't thought). Replays restore silently;
re-touches refresh instead of stacking; capped at 24; reduced motion
holds ONE statically lit node. Dev hook window.__amicoBrainTouch
(mirrors __amicoBrainStats) previews flares without a real turn.
+7 tests incl. byte-determinism under touches and the color-law
boundary (latent web ink stays yellow-free with zero touches).
2. Thinking effort folded INTO the model surface — the standalone
Default/None/High footer Select is gone (both composer paths). New
ModelVariantRow renders in the paid ModelSelectorPopover AND the
unpaid dialog (Kate's dev path): chips on --accent-fill-soft /
--accent-edge, keeps the menu open on pick; the collapsed trigger
reads 'Model · High' so effort stays visible at rest.
3. Session glass sweep to the launch-composer feel — glass is
blur+tint+radius ONLY, now enforced in-session: dock-prompt ring +
permission/question footer border-top scoped off-glass; composer
focus ring removed; comment chips borderless; dock radius 10px →
var(--radius-lg). Width containment: tool collapsibles, diffs group,
reasoning-part, error-card all share the prose measure
(min(88%, 72ch)) — floating cards on the Brain, never full-width
bands.
Gate: ui 445 / app 473 / typecheck 23 projects / lint 0 errors.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@kateebonner

Copy link
Copy Markdown
ContributorAuthor

Overnight batch 2 — 05fa001d0

All three queued items from the live-tuning session, plus the new ask (session components on the launch-composer feel):

1. Live thought over the constellation ✨

The "+ live thought" half of constellation + live thought is in. As amico works, each real touch flares its constellation node in the thought color (#fff676 dark / #8f8000 light — the brand law holds per scheme): fast rise, ~1.6s ease-out decay, an expanding ring, glints down the node's incident edges, and the touched label ("session.tsx", "amico-vault") named beside the flare.

  • Labels hash deterministically into their category lobe (file work lights the code lobe, skills the skills lobe…), then walk to a visible node — a flare you can't see isn't thought.
  • History replays silently on mount; re-touches refresh their flare instead of stacking; capped at 24 so a torrent stays a shimmer.
  • Reduced motion: the tableau holds one statically lit node — where amico is now.
  • Dev preview without a real turn: window.__amicoBrainTouch({label:"x.ts", type:"resource"}) in the console (the ?-param pattern doesn't survive the router redirect, so this rides the __amicoBrainStats hook pattern instead).
  • +7 tests: flare paint, light-scheme ink, silent replay, refresh-not-stack, decay-to-rest, reduced-motion tableau, and byte-determinism under touches. The latent-web color law tests still pin zero yellow with zero touches.

2. Thinking effort lives in the model menu

The standalone Default/None/High Select is gone (both composer paths). A ModelVariantRow renders inside the paid popover and the unpaid dialog (the dev/free path — it would otherwise have lost the control entirely): chips on --accent-fill-soft/--accent-edge, picking one keeps the menu open. The collapsed trigger now reads "DeepSeek V4 Fl… · High" so effort stays visible at rest.

3. Session glass sweep — the launch-composer feel everywhere

Glass = blur + tint + radius, nothing else, now enforced in-session too:

  • dock-prompt (permission/question card): 1px ring removed, footer border-top removed (one surface, same law as the composer footer), radius 10px → --radius-lg.
  • In-session composer: focus-within ring removed (the caret carries focus; drag keeps its dashed dropzone).
  • Comment chips: borderless dense tint.
  • Width containment: tool collapsibles ("Explored · 2 searches"), the diffs group, reasoning, and error cards all share the prose measure — min(88%, 72ch) — so the thread reads as floating cards over the Brain, never full-width bands.

Verified live in both themes on real sessions (silent replay ✓, live flare mid-session ✓, permission card ✓).

Gate: ui 445 / app 473 / typecheck / lint 0 errors.

kateebonnerand others added 4 commits July 26, 2026 12:38
… session composer = launch dock
Live review with Kate (2026-07-26), three asks:
1. 'I don't see the flares' — thought was landing behind the message
column's glass. The engine now takes an occlusion set (occlude());
session.tsx measures the real layout (timeline column band + composer
dock) and BrainAtmosphere feeds it fresh before every event flush, so
flares land in the GUTTERS where the Brain is actually visible
(fallback: merely-visible beats nothing). While the session works,
the NEWEST flare holds lit as a sustained 'amico is HERE' cursor and
decays out when the turn ends. +3 tests (gutter avoidance, hold/decay,
fully-occluded fallback).
2. Cards hug their contents — tool collapsibles and the diffs group are
width: fit-content up to the prose measure, never a padded-out band.
3. The session composer IS the launch composer — same full-bleed bottom
dock (~35% of the pane, edge-to-edge one-surface glass) via
placement='inline'; starter/typewriter suggestions stay gated to the
EMPTY LANDING (params.id gates on rotation, typing, Tab-accept,
placeholder). Legacy layout keeps the floating column card.
Gate: ui 448 / app 473 / typecheck / lint 0 errors.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ttom-stacked flow + full-width header
Live review with Kate (2026-07-26), second batch:
- Thought-tracking camera v2: rotation eases to a stop while flares are
alive and the view zooms (1.6x) + glides the newest thought to the
CENTER of the frame (Kate's call — replaces the gutter stage). All 6
confirmed findings from the adversarial review workflow fixed:
(1) conPulses is RECENCY-ordered — a re-touch splices to the end, so
the camera + busy-hold follow the re-fired concept, never a stale
array-last pulse; (2) ignite() no longer spins the stopped web back up
mid-dissolve (conRotK frozen during ignite) and the camera fast-eases
home (tau 200ms) before the live layer co-paints; (3) an OS
reduced-motion flip mid-track snaps the camera home instantly;
(4) edges/glints/ring/bloom scale with the zoom — a camera dolly, not
dots inflating over a hairline web; (5) flare seating is computed in
AMBIENT space so the zoomed viewport never funnels subsequent flares
into one slice; (6) the busy-hold is budgeted (~30s) so a wedged
active signal or ?brainForceActive cannot freeze the camera forever.
+2 tests (hold budget, seat-vs-camera split); 452 ui tests green.
- Session header: full-width band, bottom padding tight unless the
entity-chips rail rendered (CSS :has), and the band now lives OUTSIDE
the scroller, pinned at the pane top.
- Messages: rows span the pane — user messages justify RIGHT, amico's
justify LEFT (each card keeps its reading measure); the Brain owns the
middle where the camera stages thought.
- Bottom-stacked flow (messenger law): the SCROLLER's height is
content-driven up to the space the header leaves and anchors to the
bottom, so a short thread sits just above the composer; inside it
scrolling stays classic top-anchored — virtua's geometry is untouched
(an mt-auto-in-viewport variant starved virtua's visible range and
was abandoned). startMargin 0, sticky-accordion offsets updated.
Gate: ui 452 / app 473 / typecheck / lint 0 errors.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Kate 2026-07-26 (component audit): the collapsed 'edit · Failed' chip was
banding across the pane — width: fit-content capped at the prose measure,
matching the width law every timeline card now follows.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…erity
Kate 2026-07-26: glass is blur+tint+radius; the 2px Card accent rail read
as a border on the failed/error cards. content:none on the ::before for
tool-error-card and .error-card — the danger tint, icon, and ink alone
mark severity.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@kateebonner
kateebonner marked this pull request as draft July 26, 2026 23:19
@kateebonner

Copy link
Copy Markdown
ContributorAuthor

Parked 2026-07-26 — converting to draft. Aaron's call: not pursuing this UI direction right now. Everything through 83d070ae4 is on the branch (living-chat glass redesign, thought-tracking camera, bottom-stacked edge-justified flow, effort-in-model-menu, component audit + width law). The branch is the complete archive of the direction if we return to it; the component library artifact documents every surface.

@kateebonner
kateebonner marked this pull request as ready for review July 29, 2026 00:21
@kateebonner
kateebonner marked this pull request as draft July 29, 2026 00:23
@jack-champagne

Copy link
Copy Markdown
Member

@kateebonner — question before this ages further: is anything here still worth keeping?

Asking because ADR 0002, which this implements, is marked superseded on mainline:

Status: Superseded by ADR 0003 (direction parked 2026-07-26; the Brain moved to the context-tree top panel instead of becoming the chat background)

and ADR 0003 (Accepted, 2026-07-27, on Aaron's 2026-07-26 feedback) is explicit:

Supersedes: ADR 0002 (Brain as chat background — direction parked)
… Aaron's feedback reframed what the graph is for: not ambience, but orientationThe graph moves out of the timeline into a pinned top panel … the ambient background direction is parked.

The ADR-0003 replacement has fully landed

All of this is on local/amicode and shipped in v1.17.3-amicode.11:

So the top-panel + first-class vault surface direction is done and released.

What's still unique to this branch

brain-engine.ts and context-tree-engine.ts are already on main — the graph engine itself made it across. What has no counterpart is the presentation layer for the parked direction:

only in #64
glass.css (778 lines), glass-tokens.ts, script/generate-glass.ts
brain-atmosphere.tsx / .css
brain-constellation.ts
brain-perf-governor.test.ts, brain-events.ts, e2e/perf/brain-governor-trace.spec.ts

16 added files, 54 modified, 1 deleted.

Why I'm asking rather than just closing

Two things in there look potentially valuable independent of the parked background direction:

  1. The legibility machineryglass-tokens.ts plus the WCAG-AA-floored tint derivation. ADR 0002 records that the earlier attempt failed exactly one AA check (muted grey on the most translucent tier), so this encodes a real lesson. Worth salvaging if any surface still layers text on translucency — the session header's backdrop-blur comes to mind, given fix(session): header backdrop-blur off while the context-tree band is open #97 just had to switch it off over the context-tree band.
  2. brain-perf-governor + the e2e perf trace — frame-budget governance for the graph. The organic context tree that did land has the same cost profile, so a perf governor may be wanted regardless of where the graph renders.

If neither is worth extracting, this is a clean close — the direction is parked and the replacement is released. If either is, they'd be small standalone PRs rather than resurrecting 71 files.

For context on the state: it is still a draft, CONFLICTING/DIRTY, 72 commits behind mainline, and its checks are all CANCELLED from before #2 fixed the runner labels — so CI has never actually evaluated this branch.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Make the Brain the Chat's living background; float components on legibility-floored Glass

2 participants

@kateebonner@jack-champagne
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Make the Brain the Chat's living background; float components on legibility-floored Glass - #64

Closed
kateebonner wants to merge 34 commits into
local/amicodefrom
amico/issue-56-living-chat
Closed

Make the Brain the Chat's living background; float components on legibility-floored Glass#64
kateebonner wants to merge 34 commits into
local/amicodefrom
amico/issue-56-living-chat

Conversation

@kateebonner

@kateebonnerkateebonner commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Closes#56

Integration branch for the Living Chat redesign, built slice-by-slice from the sub-issue DAG (#59#60#61#62#63; design-of-record: ADR 0002, merged via #58).

Landed:

Final gate on this branch: ui 402 pass / 0 fail · app 464 pass / 0 fail · typecheck 23/23 · lint 0 errors.

Honest pre-gate evidence (headless, dev build — NOT the gate): forced full tempo + 11s continuous scroll of a 144-message thread → dark p95 25.4ms / light 25.2ms, mean ≈16.3ms, 11–15 frames >33ms. The tail misses the 16.7ms budget in that proxy environment (dev-mode Solid, headless vsync, sampler riding the measured loop) — which is exactly what the pre-agreed governor valve is for. The real call happens on the reference laptop (checklist below).

Known follow-up candidates (from #61's browser pass, non-blocking): composer placeholder hint and reasoning-part still composite on standard/bare over the Brain.

🤖 Generated with Claude Code

kateebonnerand others added 19 commits July 25, 2026 02:26
The full-bleed Brain background component, ported from the old
kate/chat-brain-atmosphere branch and retargeted to the native engine on
this branch: suspend()->pause(), refreshTokens()->setTheme(scheme) read
from data-color-scheme, the requestRender font-ready hook degraded to a
resize() repaint, and the old-engine-only setActive/setReducedMotion
dropped (tempo work is slice #62). Environment plumbing carried over
verbatim: ResizeObserver->resize, theme MutationObserver, document
visibility + IntersectionObserver hard-pause, amicode:brain-hover
glances, and the diff-by-id event flush with a silent first restore.
The live feed is the inline strip's event derivation extracted to a
pure, session-scoped deriveBrainEvents(messages, getParts) so it is
unit-testable headless and shared by the mount: touches in message
order via the tool->brain-ref map, a chart after each completed
assistant turn with >=2 commits, replay=true for completed turns,
ids never repeated.
Tests: new brain-events derivation suite (9 cases) pinning the AC-4
contract; brain-engine suite extended with the background-mount driving
case (derived-stream growth, quiet replay-only first flush with nothing
queued, lossless theme swap over a restored atlas).
Part of #56 (ADR 0002 - the Brain becomes the Chat's background).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
One full-bleed BrainAtmosphere per Chat window, mounted as the first
child of the session pane card (now relative isolate) at -z-10: above
the pane's surface fill, below the conversation timeline, landing, and
composer, pointer-events none. Keyed on the active session id so a
titlebar tab swap remounts to that session's atlas with exactly one
engine/render loop alive; empty on the landing. The standalone
new-session draft page gets the same layer (no events - sparse seed).
The inline brain-strip timeline row is deleted: the Brain member is
dropped from the TimelineRow union, forcing out its key branch, the
timelineRows append, the keepMounted special-case, the render case, and
the framed-row exclusion. The working-indicator shimmer (Thinking row)
is untouched, guarded by a new row-model suite; the strip's
click-to-expand is obviated (the engine has no node hit-testing).
Part of #56 (ADR 0002 - the Brain becomes the Chat's background).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Two-tier Glass token system over the Brain background (ADR 0002):
standard (prose/bubbles/composer) and dense (code/diffs/run-plots),
one shared 18px blur, tint carries all contrast. Each tier's alpha is
DERIVED per theme+mode — the least alpha clearing WCAG-AA with a +0.3
safety margin (target 4.8) over that mode's reference frame, read from
the brain engine's own PALETTES (dark: peak-bloom #fff676; light:
#8f8000 — the light brain never paints #fff676). Dense additionally
converges every graphical mark (syntax tokens, diff fills, run-plot
strokes) to within 0.2 of native and holds WCAG 1.4.11's 3:1.
- glass-tokens.ts: WCAG math (ported from the old branch), pure
deriveGlassTiers(tokens, frame) — no blur argument by design —
collectMarks, and the generateGlassCss emitter for every bundled
theme, scoped html[data-theme][data-color-scheme] with a
@supports-not near-opaque fallback (alpha >= 0.95)
- glass.css: committed generated output, registered in styles index;
exposes only [data-glass="standard"|"dense"] surfaces — no component
opts in within this slice, rendered output unchanged
- generate:glass script mirrors generate:tailwind wiring
- brain-engine.ts: export PALETTES (data seam only, no behavior change)
- glass-tokens.test.ts: headless contrast certification for oc-2
light+dark — body/code text floors + margin, mark rule, strict tier
ordering, blur-never-a-term guard, keying purity, fallback floor,
byte-for-byte drift guard, and the muted-grey-rides-dense invariant
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…st cadence) (#62)
One draw-gate honored by both the rAF loop and the manual tick(): full
musical tempo while active / in-flight / unfurling, ~8fps breathing at
rest (REST_FRAME_MS ported from the atmosphere branch engine). touch/
chart/highlight/resize/resume/setTheme beat the throttle via
requestRender so feedback stays immediate. BrainEngineStats gains
active + scale.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Boot is the amico core alone — the vault-skeleton preload, its
force-settle layout, and the demo-trace thought-edges are gone (ADR
0002 rejects the breathing skeleton atlas). The graph grows only from
real touches; two engines share no state (all state closure-local).
The camera is a constant core-centered zoom: no per-frame
fit-to-farthest, no close-up follow, no glance steering — growth
densifies in place. stats().scale exposes the fixed zoom; ambient
ghost picks tolerate an empty edge set.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The cap is the whole graph (core + GRAFT_CAP), not just live-* grafts:
eviction picks the least-recently-touched node — recency stamped by a
monotonic touch counter, not the beat clock (which stalls at rest).
Only the current live node and in-flight pulse endpoints are exempt;
atlas keep / charting / replay grant no immunity, so marathon sessions
can never grow the node set or per-frame draw cost without limit.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…rest (#62)
With prefers-reduced-motion set the engine never breathes at idle: once
the post-event nudge window (NUDGE_MS, rebased onto the frame timebase,
never performance.now()) elapses with nothing in flight, ticks draw
nothing and the rAF chain ends — a touch/chart/highlight/resume re-arms
one bounded burst. This is the accessibility terminal (ADR 0002),
independent of slice #63's frame-time ease. pause() clears any
scheduled frame; the lifecycle suite now pins zero-draws-while-hidden.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…#62)
Re-add the `active` output that #59's createBrainEvents dropped:
deriveBrainActive (pure, headless-tested — non-idle means busy or
retrying) feeds a memo that session.tsx passes to <BrainAtmosphere
active>, which plumbs it to engine.setActive. The draft page keeps the
default at-rest Brain (no session, no busy signal). Test helpers
(drive/clears) consolidated at file scope.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Everything floats over the mounted Brain (ADR 0002): the seven content
archetypes opt into slice #60's tier tokens — STANDARD on the user
bubble, assistant prose (which gains its first card), and the composer;
DENSE on code blocks, diffs, run-plots/run-windows, and tool cards (the
tool-collapsible root, so trigger + expanded output float as one unit
across single tools and context/shell groups). The tier token owns
fill/edge/radius/shadow everywhere — the opaque --surface-base bubble
fill, the composer's layer-01 fill + raised shadow, and the dock band's
background-stronger tiling are gone, so the Brain stays live in the
gaps (session-turn row frames and column wrappers stay transparent).
Muted/secondary ink never composites against the ultra-transparent
standard tint (certified to fail AA by #60): the prose meta, user-
message meta, composer footer controls, prose blockquotes, the child-
session stub, and the bubble's file/agent highlights all ride dense-
backed inline zones styled with --glass-dense-bg — the #60 token, no
new tint/blur literal anywhere. Shiki's inlined theme surface defers
to the dense card; the diff card's sticky header occludes with the
dense token instead of opaque chrome. The ghost-collapsible reset is
scoped :not([data-glass]) so the tier fill survives specificity.
Tests extend #60's certified surface onto the components:
- glass-float.test.ts (ui): the 7-archetype tier map as a table test —
body→standard ≥4.8 (AA + margin), code/diff→dense ≥4.5, marks→dense
≥3:1 (1.4.11) without native drift, muted-role never on standard —
measured with #60's exported validator math over the running-brain
reference frame in both oc-2 modes; plus source contracts (tier
attributes on the real markup, no ad-hoc literals in the restyled
card rules, repo-wide data-glass allowlist: two tier values only,
never on Rail/titlebar/Panels chrome).
- glass-float.test.ts (app): composer/diff/child-stub tier contracts,
gaps-stay-live (no glass, no fill on session-turn + containers), and
the sticky session-title header's pre-existing chrome blur untouched.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The sparse-seed boot (#62) removed the last importer; the latent skeleton
atlas was the superseded design's raw material (flagged by the #62 engineer,
removed at integration).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ver blur (#63)
A frame-time state machine observing the ONE Brain render loop: rolling-p95
over the 16.7ms budget for a sustained ~2s window steps motion down the
tempo ladder (allegro -> andante -> largo) with eased paint-cadence caps,
then to a motion full-stop, then terminally hard-pauses the canvas to a
static blurred field. Dual-guard hysteresis (13ms restore threshold + a ~2x
clear window, one level per window) prevents oscillation; the sample window
resets on every step so a stale regime never cascades an unearned step.
Measurement pauses with the engine (hidden / off-screen / reduced-motion):
stalled gaps are discarded, never fed as phantom over-budget frames. The
governor is independent of the reduced-motion accessibility terminal (#62)
and is bypassed entirely under it. Its only levers are tempo and the
terminal pause — no path writes a glass token, a style, or any CSS; stats()
now emits the discrete motion level. governed:false (the dev
force-full-tempo hook's engine seam) disables it for un-eased worst-case
perf capture.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…isables the governor (#63)
Ported from the old branch's perf-capture hook and extended per the issue:
the param now ALSO disables the perf governor (governed:false), so a gated
run — headless proxy or the reference laptop — measures the un-eased worst
case. DEV-gated, inert in prod. Also DEV-only window.__amicoBrainStats for
the trace harness and the manual gate checklist to read engine stats live.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…h themes (#63)
Playwright spec over the real app on the e2e mock-server harness: boots the
144-message fixture thread with the dev force-full-tempo hook (Brain pinned
busy, governor disabled — the un-eased worst case), scrolls continuously
for >=11s per theme inside the SAME rAF loop that samples frame intervals,
and emits a p95 / max / frames>33ms report per theme.
Labeled and asserted as the PRE-GATE PROXY only: the spec pins that the
harness runs and reports (shape, duration, theme coverage, forced state) —
it asserts NO numeric frame-time outcome. The release gate stays the manual
sign-off on the pinned reference laptop (issue #63, HITL).
Run: cd packages/app && bunx playwright test e2e/perf/brain-governor-trace.spec.ts
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…re-emptively eases (#63)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@kateebonner

Copy link
Copy Markdown
ContributorAuthor

HITL sign-off checklist — reference-laptop 60fps gate (#63)

The one open acceptance criterion on this PR. Run on the reference laptop, battery-powered:

  • Pin the machine: model, OS, battery %, VS Code + webview (Chromium) version — write them here.
  • Launch the dev lane: opencode serve --port 4099 + bun --cwd packages/app dev --port 5990 with VITE_OPENCODE_SERVER_PORT=4099 (the force hook is DEV-gated by design).
  • Open the Chat in the VS Code webview on a real thread of ≥40 cards with ?brainForceActive appended; verify in devtools: window.__amicoBrainStats()active: true, motion: "full".
  • Record a ≥10s continuous scroll (devtools Performance panel, or the rAF sampler in Add the perf governor (ease motion, never blur) and gate 60fps on the reference laptop #63's notes ~600 frames).
  • Pass = p95 ≤ 16.7ms AND zero frames > 33ms. Repeat in both themes (flip the chat scheme mid-session — Brain/Glass re-key losslessly).
  • Write the numbers here and sign off.

If the gate fails: remove ?brainForceActive and confirm the governor engages under load — watch __amicoBrainStats().motion step eased-1 → eased-2 → full-stop → hard-paused with the frosted look intact — then decide accept-with-valve vs iterate. (Headless dev-proxy already suggests the tail will need the valve; see PR body.)

🤖 Generated with Claude Code

@kateebonner
kateebonner marked this pull request as ready for review July 25, 2026 16:28
kateebonnerand others added 8 commits July 25, 2026 16:30
…sed question dock
Live design-review iteration with Kate (2026-07-25) on the Living Chat:
- Glass is ONE recipe everywhere: blur 8px + per-mode tint (dark: 4% white
frost + backdrop brightness(0.4); light: 5% near-white). The dark tint's
direction flips to a frost veil (lighter than ground, classic glass) with
the brightness term modeled honestly in the contrast derivation.
- The marks law (WCAG 1.4.11 dense certification) is WAIVED by design
decision; dense==standard. Muted ink is recorded as not-certified.
Tests rewritten to record the waiver rather than certify the old law.
- Cards no longer span the thread: prose fit-content ≤ min(88%,72ch),
user bubbles ≤ min(82%,64ch), tool cards ≤ 92%.
- The question dock floats on glass (8th archetype); its muted hint and
answers summary ride dense-backed zones; opaque fill scoped to
:not([data-glass]).
Part of #56 (PR #64); supersedes the #60/#61 tier law per Kate's call.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…cipe
Receipt chip, ask card (+options), run window (hover regression fixed),
inline entity card, entity rail chips, widget-preview shell, entity-view
inner atoms (tier/skeleton/formula/badge/seq/status pills), and the classic
in-chat landing (one standard card; starter buttons on dense-zone fills,
accent-edge instead of a yellow border on light). Semantic error state is a
danger tint over the glass, never an opaque surface. No !important fills.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Permission dock joins the question dock on the unified glass card (dock-prompt
generalized across kinds, permission footer flattened the same way); todo /
followup / revert trays carry the standard hook (opaque tray fill loses to
glass.css by import order); todo scroll-fade rides the glass tint; question
option tiles become dense-zone fills with the accent-soft hover, never an
opaque layer.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Opaque bands inside glassed cards defer to the dense-zone token (edit/write/
apply-patch sticky triggers, accordion header+expanded body inside any glassed
card, StickyAccordionHeader, timeline diff expanded view); the task/subagent
card is a dense zone with the accent-soft hover; diagnostics become a critical
tint over the frost; error/retry/assistant-error cards ride glass with a danger
tint; bare-muted-ink rows get their #60 backing (thinking indicator, reasoning
part, tool-loaded-file rows, turn divider label, comment-strip chips); user
attachment chips carry the dense hook; jump-to-bottom converts its hand-rolled
near-glass to the single recipe; the sticky session-title band converts its
chrome gradient/blur literals to the glass vars; inline-code chips ride the
dense token.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…cipe
Dialogs (one dialog.css edit covers delete-session/entity/fork/MCP/file/model/
unpaid/usage-exceeded launch sites), ImagePreview lightbox, popovers, dropdown
menus, shared Select menus, slash/@ autocomplete, project picker, model
selector, toast v2 — all ride the glass vars (tint + shared blur/brightness +
edge) with the legacy token as no-theme fallback; item highlights move to the
accent-soft state fill. Tooltips, the markdown code-fence copy tooltip and the
legacy toast keep their deliberate INVERSE ink on a HEAVIER glass (denser
float-token tint + shared blur/edge, never a raw opaque token); the copy
button itself rides the dense token. Drag overlay and the legacy composer
clip-mask stay heavier by function (masking), now token-mix + blur; composer
attachment tiles/pills and the theme-blind bg-black/50 name bar move to token
tints; legacy composer path gets the standard hook; composer loading stub and
review-tab header/diff surfaces convert to the glass tokens; classic landing
metadata gets a dense-zone chip.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ll audit
ui: allowlist covers every swept file (+ pre-allowed entries for the parallel
draft-landing rebuild: pages/new-session.tsx, session-new-design-view, and the
work-order's pages/session/new-session.tsx alias); new assertions pin the
AMICO family hooks + no-opaque-layer fills, dock unification across kinds,
question-option dense tiles, no-opaque-band-inside-glass (sticky triggers,
accordion, task card, diagnostics tint, diff view, inline code), muted-ink
backings, floating-chrome recipes (dialog/popover/menu/select/toast-v2/
ImagePreview), heavier inverse glass for tooltip/toast/copy-tooltip, review
surfaces, and error-tint-over-glass replacing the old no-glass error ruling.
app: sticky title band asserted on the glass vars (chrome literals banned),
timeline data-glass census, dock/composer chrome coverage, drag-overlay and
legacy clip-mask pinned as heavier-by-function token mixes.
These fail if any fix is reverted.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…st Brain
The empty landing shows the full latent network ("everything amico could
think") as a clustered ellipsoid cloud rotating in 3D, projected inside the
existing canvas engine (new constellation mode; reuses the rAF loop, governor,
pause/resume, theme re-key, reduced-motion). Curated core + seeded procedural
densification → identical constellation every launch. Dim monochrome + whisper
cluster tints, ZERO #fff676 (yellow stays exclusive to live thought). Twinkle +
breath micro-motion; static ¾ tableau under reduced-motion. First prompt →
ignition dissolve → live session graph. Removes the opaque new-session hero
wrapper that was occluding the Brain entirely, and glasses the draft-landing
chips + metadata. DEV knobs: ?constellationSpeed/Density/Tint/Fog.
Design of record: grilled with Kate 2026-07-25 (landing-only; clustered cloud;
canvas projection; mono+cluster-tint; ignition dissolve; twinkle+breath; static
tableau; uniform full-bleed). Part of #56 (PR #64).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
kateebonnerand others added 2 commits July 25, 2026 17:16
# Conflicts:
#	packages/app/src/components/session/session-new-view.tsx
#	packages/ui/src/amicode/getting-started.tsx
…k composer, typewriter placeholder, 3D constellation in-session
Live design-review iteration with Kate (2026-07-25) on the Living Chat:
Glass
- Max transparency: dark tint derives to fully transparent (backdrop
brightness 0.4 -> 0.8; less darkening lets the constellation read through).
AA retained for LIGHT, waived-and-recorded for DARK standard (the landing
constellation is yellow-free, so it reads there). Tests record the trade.
- The glass tier is now JUST blur + tint + radius — no border outline, no top
sheen/inset line, no box-shadow (Kate: "no border, no top line, no shadow").
Composer
- One background: dock-surface shell/tray opaque fills scoped to :not([data-glass])
so the glass wins as one uniform surface; footer inset fill removed (was a
visible second background).
- Full-bleed bottom dock: full width, stuck to the bottom, ~35% viewport height
(ui-ux-pro-max: primary CTA without eclipsing the hero), edge-to-edge (radius/
border/shadow zeroed). Fixed the flex height-chain so it fills to the bottom.
- Removed the model-provider H-mark/AMICODE wordmark and the project/folder
picker from the landing.
Landing
- Starter chip wall removed (competed with the constellation + composer).
Discovery now lives in the composer as a rotating TYPEWRITER placeholder that
types out the real starter prompts letter-by-letter with a blinking caret;
freezes on focus (Tab accepts the shown one), static under reduced motion.
- Constellation contrast bumped (edge alpha 0.10 -> 0.17, nodes x1.4).
Session parity
- The 3D constellation is now the background EVERYWHERE (session too), not the
sparse 2D live graph — the launch and session are one surface. (Live-thought
node pulsing is the next layer.)
Gates: ui 438 / app 473 / typecheck 23/23 / lint 0 errors. Part of #56 (PR #64).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@kateebonner

Copy link
Copy Markdown
ContributorAuthor

Live design-tuning batch (Kate, 2026-07-25) — commit 69ebf7e

The design evolved significantly beyond the original slices through a live review session. Landed:

  • Glass — now purely blur + tint + radius: dark derives to fully transparent (brightness 0.8), no border, no top sheen, no box-shadow. AA kept for light, waived+recorded for dark standard (the landing constellation is yellow-free).
  • Composer — one uniform glass surface (two-tone fixed); full-bleed bottom dock, ~35% viewport height, edge-to-edge; wordmark + project/folder picker removed.
  • Landing — starter-chip wall removed; discovery moved into the composer as a rotating typewriter placeholder (types the real starters letter-by-letter, blinking caret, Tab-to-accept, reduced-motion static). Constellation contrast bumped.
  • Session parity — the 3D constellation is now the background in-session too (not the sparse 2D graph); launch + session are one surface.

Queued (next): live-thought node pulsing over the constellation (data-true layer), card width containment, and folding the effort/variant selector into the model dropdown.

Gates: ui 438 / app 473 / typecheck 23/23 / lint 0 errors.

🤖 Generated with Claude Code

…lass sweep
Overnight batch 2 (Kate 2026-07-25), three asks:
1. Live thought over the constellation — the '+ live thought' half of
'constellation + live thought': real session touches flare their node
in css.thought (#fff676 dark / #8f8000 light) over the latent web —
rise 150ms, ease-out decay ~1.6s, expanding ring, incident-edge
glints, touched label beside the flare (fg ink + halo). Labels hash
deterministically into their category lobe with a visible-node walk
(a flare the user can't see isn't thought). Replays restore silently;
re-touches refresh instead of stacking; capped at 24; reduced motion
holds ONE statically lit node. Dev hook window.__amicoBrainTouch
(mirrors __amicoBrainStats) previews flares without a real turn.
+7 tests incl. byte-determinism under touches and the color-law
boundary (latent web ink stays yellow-free with zero touches).
2. Thinking effort folded INTO the model surface — the standalone
Default/None/High footer Select is gone (both composer paths). New
ModelVariantRow renders in the paid ModelSelectorPopover AND the
unpaid dialog (Kate's dev path): chips on --accent-fill-soft /
--accent-edge, keeps the menu open on pick; the collapsed trigger
reads 'Model · High' so effort stays visible at rest.
3. Session glass sweep to the launch-composer feel — glass is
blur+tint+radius ONLY, now enforced in-session: dock-prompt ring +
permission/question footer border-top scoped off-glass; composer
focus ring removed; comment chips borderless; dock radius 10px →
var(--radius-lg). Width containment: tool collapsibles, diffs group,
reasoning-part, error-card all share the prose measure
(min(88%, 72ch)) — floating cards on the Brain, never full-width
bands.
Gate: ui 445 / app 473 / typecheck 23 projects / lint 0 errors.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@kateebonner

Copy link
Copy Markdown
ContributorAuthor

Overnight batch 2 — 05fa001d0

All three queued items from the live-tuning session, plus the new ask (session components on the launch-composer feel):

1. Live thought over the constellation ✨

The "+ live thought" half of constellation + live thought is in. As amico works, each real touch flares its constellation node in the thought color (#fff676 dark / #8f8000 light — the brand law holds per scheme): fast rise, ~1.6s ease-out decay, an expanding ring, glints down the node's incident edges, and the touched label ("session.tsx", "amico-vault") named beside the flare.

  • Labels hash deterministically into their category lobe (file work lights the code lobe, skills the skills lobe…), then walk to a visible node — a flare you can't see isn't thought.
  • History replays silently on mount; re-touches refresh their flare instead of stacking; capped at 24 so a torrent stays a shimmer.
  • Reduced motion: the tableau holds one statically lit node — where amico is now.
  • Dev preview without a real turn: window.__amicoBrainTouch({label:"x.ts", type:"resource"}) in the console (the ?-param pattern doesn't survive the router redirect, so this rides the __amicoBrainStats hook pattern instead).
  • +7 tests: flare paint, light-scheme ink, silent replay, refresh-not-stack, decay-to-rest, reduced-motion tableau, and byte-determinism under touches. The latent-web color law tests still pin zero yellow with zero touches.

2. Thinking effort lives in the model menu

The standalone Default/None/High Select is gone (both composer paths). A ModelVariantRow renders inside the paid popover and the unpaid dialog (the dev/free path — it would otherwise have lost the control entirely): chips on --accent-fill-soft/--accent-edge, picking one keeps the menu open. The collapsed trigger now reads "DeepSeek V4 Fl… · High" so effort stays visible at rest.

3. Session glass sweep — the launch-composer feel everywhere

Glass = blur + tint + radius, nothing else, now enforced in-session too:

  • dock-prompt (permission/question card): 1px ring removed, footer border-top removed (one surface, same law as the composer footer), radius 10px → --radius-lg.
  • In-session composer: focus-within ring removed (the caret carries focus; drag keeps its dashed dropzone).
  • Comment chips: borderless dense tint.
  • Width containment: tool collapsibles ("Explored · 2 searches"), the diffs group, reasoning, and error cards all share the prose measure — min(88%, 72ch) — so the thread reads as floating cards over the Brain, never full-width bands.

Verified live in both themes on real sessions (silent replay ✓, live flare mid-session ✓, permission card ✓).

Gate: ui 445 / app 473 / typecheck / lint 0 errors.

kateebonnerand others added 4 commits July 26, 2026 12:38
… session composer = launch dock
Live review with Kate (2026-07-26), three asks:
1. 'I don't see the flares' — thought was landing behind the message
column's glass. The engine now takes an occlusion set (occlude());
session.tsx measures the real layout (timeline column band + composer
dock) and BrainAtmosphere feeds it fresh before every event flush, so
flares land in the GUTTERS where the Brain is actually visible
(fallback: merely-visible beats nothing). While the session works,
the NEWEST flare holds lit as a sustained 'amico is HERE' cursor and
decays out when the turn ends. +3 tests (gutter avoidance, hold/decay,
fully-occluded fallback).
2. Cards hug their contents — tool collapsibles and the diffs group are
width: fit-content up to the prose measure, never a padded-out band.
3. The session composer IS the launch composer — same full-bleed bottom
dock (~35% of the pane, edge-to-edge one-surface glass) via
placement='inline'; starter/typewriter suggestions stay gated to the
EMPTY LANDING (params.id gates on rotation, typing, Tab-accept,
placeholder). Legacy layout keeps the floating column card.
Gate: ui 448 / app 473 / typecheck / lint 0 errors.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ttom-stacked flow + full-width header
Live review with Kate (2026-07-26), second batch:
- Thought-tracking camera v2: rotation eases to a stop while flares are
alive and the view zooms (1.6x) + glides the newest thought to the
CENTER of the frame (Kate's call — replaces the gutter stage). All 6
confirmed findings from the adversarial review workflow fixed:
(1) conPulses is RECENCY-ordered — a re-touch splices to the end, so
the camera + busy-hold follow the re-fired concept, never a stale
array-last pulse; (2) ignite() no longer spins the stopped web back up
mid-dissolve (conRotK frozen during ignite) and the camera fast-eases
home (tau 200ms) before the live layer co-paints; (3) an OS
reduced-motion flip mid-track snaps the camera home instantly;
(4) edges/glints/ring/bloom scale with the zoom — a camera dolly, not
dots inflating over a hairline web; (5) flare seating is computed in
AMBIENT space so the zoomed viewport never funnels subsequent flares
into one slice; (6) the busy-hold is budgeted (~30s) so a wedged
active signal or ?brainForceActive cannot freeze the camera forever.
+2 tests (hold budget, seat-vs-camera split); 452 ui tests green.
- Session header: full-width band, bottom padding tight unless the
entity-chips rail rendered (CSS :has), and the band now lives OUTSIDE
the scroller, pinned at the pane top.
- Messages: rows span the pane — user messages justify RIGHT, amico's
justify LEFT (each card keeps its reading measure); the Brain owns the
middle where the camera stages thought.
- Bottom-stacked flow (messenger law): the SCROLLER's height is
content-driven up to the space the header leaves and anchors to the
bottom, so a short thread sits just above the composer; inside it
scrolling stays classic top-anchored — virtua's geometry is untouched
(an mt-auto-in-viewport variant starved virtua's visible range and
was abandoned). startMargin 0, sticky-accordion offsets updated.
Gate: ui 452 / app 473 / typecheck / lint 0 errors.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Kate 2026-07-26 (component audit): the collapsed 'edit · Failed' chip was
banding across the pane — width: fit-content capped at the prose measure,
matching the width law every timeline card now follows.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…erity
Kate 2026-07-26: glass is blur+tint+radius; the 2px Card accent rail read
as a border on the failed/error cards. content:none on the ::before for
tool-error-card and .error-card — the danger tint, icon, and ink alone
mark severity.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@kateebonner
kateebonner marked this pull request as draft July 26, 2026 23:19
@kateebonner

Copy link
Copy Markdown
ContributorAuthor

Parked 2026-07-26 — converting to draft. Aaron's call: not pursuing this UI direction right now. Everything through 83d070ae4 is on the branch (living-chat glass redesign, thought-tracking camera, bottom-stacked edge-justified flow, effort-in-model-menu, component audit + width law). The branch is the complete archive of the direction if we return to it; the component library artifact documents every surface.

@kateebonner
kateebonner marked this pull request as ready for review July 29, 2026 00:21
@kateebonner
kateebonner marked this pull request as draft July 29, 2026 00:23
@jack-champagne

Copy link
Copy Markdown
Member

@kateebonner — question before this ages further: is anything here still worth keeping?

Asking because ADR 0002, which this implements, is marked superseded on mainline:

Status: Superseded by ADR 0003 (direction parked 2026-07-26; the Brain moved to the context-tree top panel instead of becoming the chat background)

and ADR 0003 (Accepted, 2026-07-27, on Aaron's 2026-07-26 feedback) is explicit:

Supersedes: ADR 0002 (Brain as chat background — direction parked)
… Aaron's feedback reframed what the graph is for: not ambience, but orientationThe graph moves out of the timeline into a pinned top panel … the ambient background direction is parked.

The ADR-0003 replacement has fully landed

All of this is on local/amicode and shipped in v1.17.3-amicode.11:

So the top-panel + first-class vault surface direction is done and released.

What's still unique to this branch

brain-engine.ts and context-tree-engine.ts are already on main — the graph engine itself made it across. What has no counterpart is the presentation layer for the parked direction:

only in #64
glass.css (778 lines), glass-tokens.ts, script/generate-glass.ts
brain-atmosphere.tsx / .css
brain-constellation.ts
brain-perf-governor.test.ts, brain-events.ts, e2e/perf/brain-governor-trace.spec.ts

16 added files, 54 modified, 1 deleted.

Why I'm asking rather than just closing

Two things in there look potentially valuable independent of the parked background direction:

  1. The legibility machineryglass-tokens.ts plus the WCAG-AA-floored tint derivation. ADR 0002 records that the earlier attempt failed exactly one AA check (muted grey on the most translucent tier), so this encodes a real lesson. Worth salvaging if any surface still layers text on translucency — the session header's backdrop-blur comes to mind, given fix(session): header backdrop-blur off while the context-tree band is open #97 just had to switch it off over the context-tree band.
  2. brain-perf-governor + the e2e perf trace — frame-budget governance for the graph. The organic context tree that did land has the same cost profile, so a perf governor may be wanted regardless of where the graph renders.

If neither is worth extracting, this is a clean close — the direction is parked and the replacement is released. If either is, they'd be small standalone PRs rather than resurrecting 71 files.

For context on the state: it is still a draft, CONFLICTING/DIRTY, 72 commits behind mainline, and its checks are all CANCELLED from before #2 fixed the runner labels — so CI has never actually evaluated this branch.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Make the Brain the Chat's living background; float components on legibility-floored Glass

2 participants

@kateebonner@jack-champagne
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Make the Brain the Chat's living background; float components on legibility-floored Glass - #64

Closed
kateebonner wants to merge 34 commits into
local/amicodefrom
amico/issue-56-living-chat
Closed

Make the Brain the Chat's living background; float components on legibility-floored Glass#64
kateebonner wants to merge 34 commits into
local/amicodefrom
amico/issue-56-living-chat

Conversation

@kateebonner

@kateebonnerkateebonner commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Closes#56

Integration branch for the Living Chat redesign, built slice-by-slice from the sub-issue DAG (#59#60#61#62#63; design-of-record: ADR 0002, merged via #58).

Landed:

Final gate on this branch: ui 402 pass / 0 fail · app 464 pass / 0 fail · typecheck 23/23 · lint 0 errors.

Honest pre-gate evidence (headless, dev build — NOT the gate): forced full tempo + 11s continuous scroll of a 144-message thread → dark p95 25.4ms / light 25.2ms, mean ≈16.3ms, 11–15 frames >33ms. The tail misses the 16.7ms budget in that proxy environment (dev-mode Solid, headless vsync, sampler riding the measured loop) — which is exactly what the pre-agreed governor valve is for. The real call happens on the reference laptop (checklist below).

Known follow-up candidates (from #61's browser pass, non-blocking): composer placeholder hint and reasoning-part still composite on standard/bare over the Brain.

🤖 Generated with Claude Code

kateebonnerand others added 19 commits July 25, 2026 02:26
The full-bleed Brain background component, ported from the old
kate/chat-brain-atmosphere branch and retargeted to the native engine on
this branch: suspend()->pause(), refreshTokens()->setTheme(scheme) read
from data-color-scheme, the requestRender font-ready hook degraded to a
resize() repaint, and the old-engine-only setActive/setReducedMotion
dropped (tempo work is slice #62). Environment plumbing carried over
verbatim: ResizeObserver->resize, theme MutationObserver, document
visibility + IntersectionObserver hard-pause, amicode:brain-hover
glances, and the diff-by-id event flush with a silent first restore.
The live feed is the inline strip's event derivation extracted to a
pure, session-scoped deriveBrainEvents(messages, getParts) so it is
unit-testable headless and shared by the mount: touches in message
order via the tool->brain-ref map, a chart after each completed
assistant turn with >=2 commits, replay=true for completed turns,
ids never repeated.
Tests: new brain-events derivation suite (9 cases) pinning the AC-4
contract; brain-engine suite extended with the background-mount driving
case (derived-stream growth, quiet replay-only first flush with nothing
queued, lossless theme swap over a restored atlas).
Part of #56 (ADR 0002 - the Brain becomes the Chat's background).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
One full-bleed BrainAtmosphere per Chat window, mounted as the first
child of the session pane card (now relative isolate) at -z-10: above
the pane's surface fill, below the conversation timeline, landing, and
composer, pointer-events none. Keyed on the active session id so a
titlebar tab swap remounts to that session's atlas with exactly one
engine/render loop alive; empty on the landing. The standalone
new-session draft page gets the same layer (no events - sparse seed).
The inline brain-strip timeline row is deleted: the Brain member is
dropped from the TimelineRow union, forcing out its key branch, the
timelineRows append, the keepMounted special-case, the render case, and
the framed-row exclusion. The working-indicator shimmer (Thinking row)
is untouched, guarded by a new row-model suite; the strip's
click-to-expand is obviated (the engine has no node hit-testing).
Part of #56 (ADR 0002 - the Brain becomes the Chat's background).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Two-tier Glass token system over the Brain background (ADR 0002):
standard (prose/bubbles/composer) and dense (code/diffs/run-plots),
one shared 18px blur, tint carries all contrast. Each tier's alpha is
DERIVED per theme+mode — the least alpha clearing WCAG-AA with a +0.3
safety margin (target 4.8) over that mode's reference frame, read from
the brain engine's own PALETTES (dark: peak-bloom #fff676; light:
#8f8000 — the light brain never paints #fff676). Dense additionally
converges every graphical mark (syntax tokens, diff fills, run-plot
strokes) to within 0.2 of native and holds WCAG 1.4.11's 3:1.
- glass-tokens.ts: WCAG math (ported from the old branch), pure
deriveGlassTiers(tokens, frame) — no blur argument by design —
collectMarks, and the generateGlassCss emitter for every bundled
theme, scoped html[data-theme][data-color-scheme] with a
@supports-not near-opaque fallback (alpha >= 0.95)
- glass.css: committed generated output, registered in styles index;
exposes only [data-glass="standard"|"dense"] surfaces — no component
opts in within this slice, rendered output unchanged
- generate:glass script mirrors generate:tailwind wiring
- brain-engine.ts: export PALETTES (data seam only, no behavior change)
- glass-tokens.test.ts: headless contrast certification for oc-2
light+dark — body/code text floors + margin, mark rule, strict tier
ordering, blur-never-a-term guard, keying purity, fallback floor,
byte-for-byte drift guard, and the muted-grey-rides-dense invariant
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…st cadence) (#62)
One draw-gate honored by both the rAF loop and the manual tick(): full
musical tempo while active / in-flight / unfurling, ~8fps breathing at
rest (REST_FRAME_MS ported from the atmosphere branch engine). touch/
chart/highlight/resize/resume/setTheme beat the throttle via
requestRender so feedback stays immediate. BrainEngineStats gains
active + scale.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Boot is the amico core alone — the vault-skeleton preload, its
force-settle layout, and the demo-trace thought-edges are gone (ADR
0002 rejects the breathing skeleton atlas). The graph grows only from
real touches; two engines share no state (all state closure-local).
The camera is a constant core-centered zoom: no per-frame
fit-to-farthest, no close-up follow, no glance steering — growth
densifies in place. stats().scale exposes the fixed zoom; ambient
ghost picks tolerate an empty edge set.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The cap is the whole graph (core + GRAFT_CAP), not just live-* grafts:
eviction picks the least-recently-touched node — recency stamped by a
monotonic touch counter, not the beat clock (which stalls at rest).
Only the current live node and in-flight pulse endpoints are exempt;
atlas keep / charting / replay grant no immunity, so marathon sessions
can never grow the node set or per-frame draw cost without limit.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…rest (#62)
With prefers-reduced-motion set the engine never breathes at idle: once
the post-event nudge window (NUDGE_MS, rebased onto the frame timebase,
never performance.now()) elapses with nothing in flight, ticks draw
nothing and the rAF chain ends — a touch/chart/highlight/resume re-arms
one bounded burst. This is the accessibility terminal (ADR 0002),
independent of slice #63's frame-time ease. pause() clears any
scheduled frame; the lifecycle suite now pins zero-draws-while-hidden.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…#62)
Re-add the `active` output that #59's createBrainEvents dropped:
deriveBrainActive (pure, headless-tested — non-idle means busy or
retrying) feeds a memo that session.tsx passes to <BrainAtmosphere
active>, which plumbs it to engine.setActive. The draft page keeps the
default at-rest Brain (no session, no busy signal). Test helpers
(drive/clears) consolidated at file scope.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Everything floats over the mounted Brain (ADR 0002): the seven content
archetypes opt into slice #60's tier tokens — STANDARD on the user
bubble, assistant prose (which gains its first card), and the composer;
DENSE on code blocks, diffs, run-plots/run-windows, and tool cards (the
tool-collapsible root, so trigger + expanded output float as one unit
across single tools and context/shell groups). The tier token owns
fill/edge/radius/shadow everywhere — the opaque --surface-base bubble
fill, the composer's layer-01 fill + raised shadow, and the dock band's
background-stronger tiling are gone, so the Brain stays live in the
gaps (session-turn row frames and column wrappers stay transparent).
Muted/secondary ink never composites against the ultra-transparent
standard tint (certified to fail AA by #60): the prose meta, user-
message meta, composer footer controls, prose blockquotes, the child-
session stub, and the bubble's file/agent highlights all ride dense-
backed inline zones styled with --glass-dense-bg — the #60 token, no
new tint/blur literal anywhere. Shiki's inlined theme surface defers
to the dense card; the diff card's sticky header occludes with the
dense token instead of opaque chrome. The ghost-collapsible reset is
scoped :not([data-glass]) so the tier fill survives specificity.
Tests extend #60's certified surface onto the components:
- glass-float.test.ts (ui): the 7-archetype tier map as a table test —
body→standard ≥4.8 (AA + margin), code/diff→dense ≥4.5, marks→dense
≥3:1 (1.4.11) without native drift, muted-role never on standard —
measured with #60's exported validator math over the running-brain
reference frame in both oc-2 modes; plus source contracts (tier
attributes on the real markup, no ad-hoc literals in the restyled
card rules, repo-wide data-glass allowlist: two tier values only,
never on Rail/titlebar/Panels chrome).
- glass-float.test.ts (app): composer/diff/child-stub tier contracts,
gaps-stay-live (no glass, no fill on session-turn + containers), and
the sticky session-title header's pre-existing chrome blur untouched.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The sparse-seed boot (#62) removed the last importer; the latent skeleton
atlas was the superseded design's raw material (flagged by the #62 engineer,
removed at integration).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ver blur (#63)
A frame-time state machine observing the ONE Brain render loop: rolling-p95
over the 16.7ms budget for a sustained ~2s window steps motion down the
tempo ladder (allegro -> andante -> largo) with eased paint-cadence caps,
then to a motion full-stop, then terminally hard-pauses the canvas to a
static blurred field. Dual-guard hysteresis (13ms restore threshold + a ~2x
clear window, one level per window) prevents oscillation; the sample window
resets on every step so a stale regime never cascades an unearned step.
Measurement pauses with the engine (hidden / off-screen / reduced-motion):
stalled gaps are discarded, never fed as phantom over-budget frames. The
governor is independent of the reduced-motion accessibility terminal (#62)
and is bypassed entirely under it. Its only levers are tempo and the
terminal pause — no path writes a glass token, a style, or any CSS; stats()
now emits the discrete motion level. governed:false (the dev
force-full-tempo hook's engine seam) disables it for un-eased worst-case
perf capture.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…isables the governor (#63)
Ported from the old branch's perf-capture hook and extended per the issue:
the param now ALSO disables the perf governor (governed:false), so a gated
run — headless proxy or the reference laptop — measures the un-eased worst
case. DEV-gated, inert in prod. Also DEV-only window.__amicoBrainStats for
the trace harness and the manual gate checklist to read engine stats live.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…h themes (#63)
Playwright spec over the real app on the e2e mock-server harness: boots the
144-message fixture thread with the dev force-full-tempo hook (Brain pinned
busy, governor disabled — the un-eased worst case), scrolls continuously
for >=11s per theme inside the SAME rAF loop that samples frame intervals,
and emits a p95 / max / frames>33ms report per theme.
Labeled and asserted as the PRE-GATE PROXY only: the spec pins that the
harness runs and reports (shape, duration, theme coverage, forced state) —
it asserts NO numeric frame-time outcome. The release gate stays the manual
sign-off on the pinned reference laptop (issue #63, HITL).
Run: cd packages/app && bunx playwright test e2e/perf/brain-governor-trace.spec.ts
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…re-emptively eases (#63)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@kateebonner

Copy link
Copy Markdown
ContributorAuthor

HITL sign-off checklist — reference-laptop 60fps gate (#63)

The one open acceptance criterion on this PR. Run on the reference laptop, battery-powered:

  • Pin the machine: model, OS, battery %, VS Code + webview (Chromium) version — write them here.
  • Launch the dev lane: opencode serve --port 4099 + bun --cwd packages/app dev --port 5990 with VITE_OPENCODE_SERVER_PORT=4099 (the force hook is DEV-gated by design).
  • Open the Chat in the VS Code webview on a real thread of ≥40 cards with ?brainForceActive appended; verify in devtools: window.__amicoBrainStats()active: true, motion: "full".
  • Record a ≥10s continuous scroll (devtools Performance panel, or the rAF sampler in Add the perf governor (ease motion, never blur) and gate 60fps on the reference laptop #63's notes ~600 frames).
  • Pass = p95 ≤ 16.7ms AND zero frames > 33ms. Repeat in both themes (flip the chat scheme mid-session — Brain/Glass re-key losslessly).
  • Write the numbers here and sign off.

If the gate fails: remove ?brainForceActive and confirm the governor engages under load — watch __amicoBrainStats().motion step eased-1 → eased-2 → full-stop → hard-paused with the frosted look intact — then decide accept-with-valve vs iterate. (Headless dev-proxy already suggests the tail will need the valve; see PR body.)

🤖 Generated with Claude Code

@kateebonner
kateebonner marked this pull request as ready for review July 25, 2026 16:28
kateebonnerand others added 8 commits July 25, 2026 16:30
…sed question dock
Live design-review iteration with Kate (2026-07-25) on the Living Chat:
- Glass is ONE recipe everywhere: blur 8px + per-mode tint (dark: 4% white
frost + backdrop brightness(0.4); light: 5% near-white). The dark tint's
direction flips to a frost veil (lighter than ground, classic glass) with
the brightness term modeled honestly in the contrast derivation.
- The marks law (WCAG 1.4.11 dense certification) is WAIVED by design
decision; dense==standard. Muted ink is recorded as not-certified.
Tests rewritten to record the waiver rather than certify the old law.
- Cards no longer span the thread: prose fit-content ≤ min(88%,72ch),
user bubbles ≤ min(82%,64ch), tool cards ≤ 92%.
- The question dock floats on glass (8th archetype); its muted hint and
answers summary ride dense-backed zones; opaque fill scoped to
:not([data-glass]).
Part of #56 (PR #64); supersedes the #60/#61 tier law per Kate's call.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…cipe
Receipt chip, ask card (+options), run window (hover regression fixed),
inline entity card, entity rail chips, widget-preview shell, entity-view
inner atoms (tier/skeleton/formula/badge/seq/status pills), and the classic
in-chat landing (one standard card; starter buttons on dense-zone fills,
accent-edge instead of a yellow border on light). Semantic error state is a
danger tint over the glass, never an opaque surface. No !important fills.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Permission dock joins the question dock on the unified glass card (dock-prompt
generalized across kinds, permission footer flattened the same way); todo /
followup / revert trays carry the standard hook (opaque tray fill loses to
glass.css by import order); todo scroll-fade rides the glass tint; question
option tiles become dense-zone fills with the accent-soft hover, never an
opaque layer.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Opaque bands inside glassed cards defer to the dense-zone token (edit/write/
apply-patch sticky triggers, accordion header+expanded body inside any glassed
card, StickyAccordionHeader, timeline diff expanded view); the task/subagent
card is a dense zone with the accent-soft hover; diagnostics become a critical
tint over the frost; error/retry/assistant-error cards ride glass with a danger
tint; bare-muted-ink rows get their #60 backing (thinking indicator, reasoning
part, tool-loaded-file rows, turn divider label, comment-strip chips); user
attachment chips carry the dense hook; jump-to-bottom converts its hand-rolled
near-glass to the single recipe; the sticky session-title band converts its
chrome gradient/blur literals to the glass vars; inline-code chips ride the
dense token.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…cipe
Dialogs (one dialog.css edit covers delete-session/entity/fork/MCP/file/model/
unpaid/usage-exceeded launch sites), ImagePreview lightbox, popovers, dropdown
menus, shared Select menus, slash/@ autocomplete, project picker, model
selector, toast v2 — all ride the glass vars (tint + shared blur/brightness +
edge) with the legacy token as no-theme fallback; item highlights move to the
accent-soft state fill. Tooltips, the markdown code-fence copy tooltip and the
legacy toast keep their deliberate INVERSE ink on a HEAVIER glass (denser
float-token tint + shared blur/edge, never a raw opaque token); the copy
button itself rides the dense token. Drag overlay and the legacy composer
clip-mask stay heavier by function (masking), now token-mix + blur; composer
attachment tiles/pills and the theme-blind bg-black/50 name bar move to token
tints; legacy composer path gets the standard hook; composer loading stub and
review-tab header/diff surfaces convert to the glass tokens; classic landing
metadata gets a dense-zone chip.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ll audit
ui: allowlist covers every swept file (+ pre-allowed entries for the parallel
draft-landing rebuild: pages/new-session.tsx, session-new-design-view, and the
work-order's pages/session/new-session.tsx alias); new assertions pin the
AMICO family hooks + no-opaque-layer fills, dock unification across kinds,
question-option dense tiles, no-opaque-band-inside-glass (sticky triggers,
accordion, task card, diagnostics tint, diff view, inline code), muted-ink
backings, floating-chrome recipes (dialog/popover/menu/select/toast-v2/
ImagePreview), heavier inverse glass for tooltip/toast/copy-tooltip, review
surfaces, and error-tint-over-glass replacing the old no-glass error ruling.
app: sticky title band asserted on the glass vars (chrome literals banned),
timeline data-glass census, dock/composer chrome coverage, drag-overlay and
legacy clip-mask pinned as heavier-by-function token mixes.
These fail if any fix is reverted.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…st Brain
The empty landing shows the full latent network ("everything amico could
think") as a clustered ellipsoid cloud rotating in 3D, projected inside the
existing canvas engine (new constellation mode; reuses the rAF loop, governor,
pause/resume, theme re-key, reduced-motion). Curated core + seeded procedural
densification → identical constellation every launch. Dim monochrome + whisper
cluster tints, ZERO #fff676 (yellow stays exclusive to live thought). Twinkle +
breath micro-motion; static ¾ tableau under reduced-motion. First prompt →
ignition dissolve → live session graph. Removes the opaque new-session hero
wrapper that was occluding the Brain entirely, and glasses the draft-landing
chips + metadata. DEV knobs: ?constellationSpeed/Density/Tint/Fog.
Design of record: grilled with Kate 2026-07-25 (landing-only; clustered cloud;
canvas projection; mono+cluster-tint; ignition dissolve; twinkle+breath; static
tableau; uniform full-bleed). Part of #56 (PR #64).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
kateebonnerand others added 2 commits July 25, 2026 17:16
# Conflicts:
#	packages/app/src/components/session/session-new-view.tsx
#	packages/ui/src/amicode/getting-started.tsx
…k composer, typewriter placeholder, 3D constellation in-session
Live design-review iteration with Kate (2026-07-25) on the Living Chat:
Glass
- Max transparency: dark tint derives to fully transparent (backdrop
brightness 0.4 -> 0.8; less darkening lets the constellation read through).
AA retained for LIGHT, waived-and-recorded for DARK standard (the landing
constellation is yellow-free, so it reads there). Tests record the trade.
- The glass tier is now JUST blur + tint + radius — no border outline, no top
sheen/inset line, no box-shadow (Kate: "no border, no top line, no shadow").
Composer
- One background: dock-surface shell/tray opaque fills scoped to :not([data-glass])
so the glass wins as one uniform surface; footer inset fill removed (was a
visible second background).
- Full-bleed bottom dock: full width, stuck to the bottom, ~35% viewport height
(ui-ux-pro-max: primary CTA without eclipsing the hero), edge-to-edge (radius/
border/shadow zeroed). Fixed the flex height-chain so it fills to the bottom.
- Removed the model-provider H-mark/AMICODE wordmark and the project/folder
picker from the landing.
Landing
- Starter chip wall removed (competed with the constellation + composer).
Discovery now lives in the composer as a rotating TYPEWRITER placeholder that
types out the real starter prompts letter-by-letter with a blinking caret;
freezes on focus (Tab accepts the shown one), static under reduced motion.
- Constellation contrast bumped (edge alpha 0.10 -> 0.17, nodes x1.4).
Session parity
- The 3D constellation is now the background EVERYWHERE (session too), not the
sparse 2D live graph — the launch and session are one surface. (Live-thought
node pulsing is the next layer.)
Gates: ui 438 / app 473 / typecheck 23/23 / lint 0 errors. Part of #56 (PR #64).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@kateebonner

Copy link
Copy Markdown
ContributorAuthor

Live design-tuning batch (Kate, 2026-07-25) — commit 69ebf7e

The design evolved significantly beyond the original slices through a live review session. Landed:

  • Glass — now purely blur + tint + radius: dark derives to fully transparent (brightness 0.8), no border, no top sheen, no box-shadow. AA kept for light, waived+recorded for dark standard (the landing constellation is yellow-free).
  • Composer — one uniform glass surface (two-tone fixed); full-bleed bottom dock, ~35% viewport height, edge-to-edge; wordmark + project/folder picker removed.
  • Landing — starter-chip wall removed; discovery moved into the composer as a rotating typewriter placeholder (types the real starters letter-by-letter, blinking caret, Tab-to-accept, reduced-motion static). Constellation contrast bumped.
  • Session parity — the 3D constellation is now the background in-session too (not the sparse 2D graph); launch + session are one surface.

Queued (next): live-thought node pulsing over the constellation (data-true layer), card width containment, and folding the effort/variant selector into the model dropdown.

Gates: ui 438 / app 473 / typecheck 23/23 / lint 0 errors.

🤖 Generated with Claude Code

…lass sweep
Overnight batch 2 (Kate 2026-07-25), three asks:
1. Live thought over the constellation — the '+ live thought' half of
'constellation + live thought': real session touches flare their node
in css.thought (#fff676 dark / #8f8000 light) over the latent web —
rise 150ms, ease-out decay ~1.6s, expanding ring, incident-edge
glints, touched label beside the flare (fg ink + halo). Labels hash
deterministically into their category lobe with a visible-node walk
(a flare the user can't see isn't thought). Replays restore silently;
re-touches refresh instead of stacking; capped at 24; reduced motion
holds ONE statically lit node. Dev hook window.__amicoBrainTouch
(mirrors __amicoBrainStats) previews flares without a real turn.
+7 tests incl. byte-determinism under touches and the color-law
boundary (latent web ink stays yellow-free with zero touches).
2. Thinking effort folded INTO the model surface — the standalone
Default/None/High footer Select is gone (both composer paths). New
ModelVariantRow renders in the paid ModelSelectorPopover AND the
unpaid dialog (Kate's dev path): chips on --accent-fill-soft /
--accent-edge, keeps the menu open on pick; the collapsed trigger
reads 'Model · High' so effort stays visible at rest.
3. Session glass sweep to the launch-composer feel — glass is
blur+tint+radius ONLY, now enforced in-session: dock-prompt ring +
permission/question footer border-top scoped off-glass; composer
focus ring removed; comment chips borderless; dock radius 10px →
var(--radius-lg). Width containment: tool collapsibles, diffs group,
reasoning-part, error-card all share the prose measure
(min(88%, 72ch)) — floating cards on the Brain, never full-width
bands.
Gate: ui 445 / app 473 / typecheck 23 projects / lint 0 errors.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@kateebonner

Copy link
Copy Markdown
ContributorAuthor

Overnight batch 2 — 05fa001d0

All three queued items from the live-tuning session, plus the new ask (session components on the launch-composer feel):

1. Live thought over the constellation ✨

The "+ live thought" half of constellation + live thought is in. As amico works, each real touch flares its constellation node in the thought color (#fff676 dark / #8f8000 light — the brand law holds per scheme): fast rise, ~1.6s ease-out decay, an expanding ring, glints down the node's incident edges, and the touched label ("session.tsx", "amico-vault") named beside the flare.

  • Labels hash deterministically into their category lobe (file work lights the code lobe, skills the skills lobe…), then walk to a visible node — a flare you can't see isn't thought.
  • History replays silently on mount; re-touches refresh their flare instead of stacking; capped at 24 so a torrent stays a shimmer.
  • Reduced motion: the tableau holds one statically lit node — where amico is now.
  • Dev preview without a real turn: window.__amicoBrainTouch({label:"x.ts", type:"resource"}) in the console (the ?-param pattern doesn't survive the router redirect, so this rides the __amicoBrainStats hook pattern instead).
  • +7 tests: flare paint, light-scheme ink, silent replay, refresh-not-stack, decay-to-rest, reduced-motion tableau, and byte-determinism under touches. The latent-web color law tests still pin zero yellow with zero touches.

2. Thinking effort lives in the model menu

The standalone Default/None/High Select is gone (both composer paths). A ModelVariantRow renders inside the paid popover and the unpaid dialog (the dev/free path — it would otherwise have lost the control entirely): chips on --accent-fill-soft/--accent-edge, picking one keeps the menu open. The collapsed trigger now reads "DeepSeek V4 Fl… · High" so effort stays visible at rest.

3. Session glass sweep — the launch-composer feel everywhere

Glass = blur + tint + radius, nothing else, now enforced in-session too:

  • dock-prompt (permission/question card): 1px ring removed, footer border-top removed (one surface, same law as the composer footer), radius 10px → --radius-lg.
  • In-session composer: focus-within ring removed (the caret carries focus; drag keeps its dashed dropzone).
  • Comment chips: borderless dense tint.
  • Width containment: tool collapsibles ("Explored · 2 searches"), the diffs group, reasoning, and error cards all share the prose measure — min(88%, 72ch) — so the thread reads as floating cards over the Brain, never full-width bands.

Verified live in both themes on real sessions (silent replay ✓, live flare mid-session ✓, permission card ✓).

Gate: ui 445 / app 473 / typecheck / lint 0 errors.

kateebonnerand others added 4 commits July 26, 2026 12:38
… session composer = launch dock
Live review with Kate (2026-07-26), three asks:
1. 'I don't see the flares' — thought was landing behind the message
column's glass. The engine now takes an occlusion set (occlude());
session.tsx measures the real layout (timeline column band + composer
dock) and BrainAtmosphere feeds it fresh before every event flush, so
flares land in the GUTTERS where the Brain is actually visible
(fallback: merely-visible beats nothing). While the session works,
the NEWEST flare holds lit as a sustained 'amico is HERE' cursor and
decays out when the turn ends. +3 tests (gutter avoidance, hold/decay,
fully-occluded fallback).
2. Cards hug their contents — tool collapsibles and the diffs group are
width: fit-content up to the prose measure, never a padded-out band.
3. The session composer IS the launch composer — same full-bleed bottom
dock (~35% of the pane, edge-to-edge one-surface glass) via
placement='inline'; starter/typewriter suggestions stay gated to the
EMPTY LANDING (params.id gates on rotation, typing, Tab-accept,
placeholder). Legacy layout keeps the floating column card.
Gate: ui 448 / app 473 / typecheck / lint 0 errors.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ttom-stacked flow + full-width header
Live review with Kate (2026-07-26), second batch:
- Thought-tracking camera v2: rotation eases to a stop while flares are
alive and the view zooms (1.6x) + glides the newest thought to the
CENTER of the frame (Kate's call — replaces the gutter stage). All 6
confirmed findings from the adversarial review workflow fixed:
(1) conPulses is RECENCY-ordered — a re-touch splices to the end, so
the camera + busy-hold follow the re-fired concept, never a stale
array-last pulse; (2) ignite() no longer spins the stopped web back up
mid-dissolve (conRotK frozen during ignite) and the camera fast-eases
home (tau 200ms) before the live layer co-paints; (3) an OS
reduced-motion flip mid-track snaps the camera home instantly;
(4) edges/glints/ring/bloom scale with the zoom — a camera dolly, not
dots inflating over a hairline web; (5) flare seating is computed in
AMBIENT space so the zoomed viewport never funnels subsequent flares
into one slice; (6) the busy-hold is budgeted (~30s) so a wedged
active signal or ?brainForceActive cannot freeze the camera forever.
+2 tests (hold budget, seat-vs-camera split); 452 ui tests green.
- Session header: full-width band, bottom padding tight unless the
entity-chips rail rendered (CSS :has), and the band now lives OUTSIDE
the scroller, pinned at the pane top.
- Messages: rows span the pane — user messages justify RIGHT, amico's
justify LEFT (each card keeps its reading measure); the Brain owns the
middle where the camera stages thought.
- Bottom-stacked flow (messenger law): the SCROLLER's height is
content-driven up to the space the header leaves and anchors to the
bottom, so a short thread sits just above the composer; inside it
scrolling stays classic top-anchored — virtua's geometry is untouched
(an mt-auto-in-viewport variant starved virtua's visible range and
was abandoned). startMargin 0, sticky-accordion offsets updated.
Gate: ui 452 / app 473 / typecheck / lint 0 errors.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Kate 2026-07-26 (component audit): the collapsed 'edit · Failed' chip was
banding across the pane — width: fit-content capped at the prose measure,
matching the width law every timeline card now follows.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…erity
Kate 2026-07-26: glass is blur+tint+radius; the 2px Card accent rail read
as a border on the failed/error cards. content:none on the ::before for
tool-error-card and .error-card — the danger tint, icon, and ink alone
mark severity.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@kateebonner
kateebonner marked this pull request as draft July 26, 2026 23:19
@kateebonner

Copy link
Copy Markdown
ContributorAuthor

Parked 2026-07-26 — converting to draft. Aaron's call: not pursuing this UI direction right now. Everything through 83d070ae4 is on the branch (living-chat glass redesign, thought-tracking camera, bottom-stacked edge-justified flow, effort-in-model-menu, component audit + width law). The branch is the complete archive of the direction if we return to it; the component library artifact documents every surface.

@kateebonner
kateebonner marked this pull request as ready for review July 29, 2026 00:21
@kateebonner
kateebonner marked this pull request as draft July 29, 2026 00:23
@jack-champagne

Copy link
Copy Markdown
Member

@kateebonner — question before this ages further: is anything here still worth keeping?

Asking because ADR 0002, which this implements, is marked superseded on mainline:

Status: Superseded by ADR 0003 (direction parked 2026-07-26; the Brain moved to the context-tree top panel instead of becoming the chat background)

and ADR 0003 (Accepted, 2026-07-27, on Aaron's 2026-07-26 feedback) is explicit:

Supersedes: ADR 0002 (Brain as chat background — direction parked)
… Aaron's feedback reframed what the graph is for: not ambience, but orientationThe graph moves out of the timeline into a pinned top panel … the ambient background direction is parked.

The ADR-0003 replacement has fully landed

All of this is on local/amicode and shipped in v1.17.3-amicode.11:

So the top-panel + first-class vault surface direction is done and released.

What's still unique to this branch

brain-engine.ts and context-tree-engine.ts are already on main — the graph engine itself made it across. What has no counterpart is the presentation layer for the parked direction:

only in #64
glass.css (778 lines), glass-tokens.ts, script/generate-glass.ts
brain-atmosphere.tsx / .css
brain-constellation.ts
brain-perf-governor.test.ts, brain-events.ts, e2e/perf/brain-governor-trace.spec.ts

16 added files, 54 modified, 1 deleted.

Why I'm asking rather than just closing

Two things in there look potentially valuable independent of the parked background direction:

  1. The legibility machineryglass-tokens.ts plus the WCAG-AA-floored tint derivation. ADR 0002 records that the earlier attempt failed exactly one AA check (muted grey on the most translucent tier), so this encodes a real lesson. Worth salvaging if any surface still layers text on translucency — the session header's backdrop-blur comes to mind, given fix(session): header backdrop-blur off while the context-tree band is open #97 just had to switch it off over the context-tree band.
  2. brain-perf-governor + the e2e perf trace — frame-budget governance for the graph. The organic context tree that did land has the same cost profile, so a perf governor may be wanted regardless of where the graph renders.

If neither is worth extracting, this is a clean close — the direction is parked and the replacement is released. If either is, they'd be small standalone PRs rather than resurrecting 71 files.

For context on the state: it is still a draft, CONFLICTING/DIRTY, 72 commits behind mainline, and its checks are all CANCELLED from before #2 fixed the runner labels — so CI has never actually evaluated this branch.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Make the Brain the Chat's living background; float components on legibility-floored Glass

2 participants

@kateebonner@jack-champagne
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Make the Brain the Chat's living background; float components on legibility-floored Glass - #64

Closed
kateebonner wants to merge 34 commits into
local/amicodefrom
amico/issue-56-living-chat
Closed

Make the Brain the Chat's living background; float components on legibility-floored Glass#64
kateebonner wants to merge 34 commits into
local/amicodefrom
amico/issue-56-living-chat

Conversation

@kateebonner

@kateebonnerkateebonner commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Closes#56

Integration branch for the Living Chat redesign, built slice-by-slice from the sub-issue DAG (#59#60#61#62#63; design-of-record: ADR 0002, merged via #58).

Landed:

Final gate on this branch: ui 402 pass / 0 fail · app 464 pass / 0 fail · typecheck 23/23 · lint 0 errors.

Honest pre-gate evidence (headless, dev build — NOT the gate): forced full tempo + 11s continuous scroll of a 144-message thread → dark p95 25.4ms / light 25.2ms, mean ≈16.3ms, 11–15 frames >33ms. The tail misses the 16.7ms budget in that proxy environment (dev-mode Solid, headless vsync, sampler riding the measured loop) — which is exactly what the pre-agreed governor valve is for. The real call happens on the reference laptop (checklist below).

Known follow-up candidates (from #61's browser pass, non-blocking): composer placeholder hint and reasoning-part still composite on standard/bare over the Brain.

🤖 Generated with Claude Code

kateebonnerand others added 19 commits July 25, 2026 02:26
The full-bleed Brain background component, ported from the old
kate/chat-brain-atmosphere branch and retargeted to the native engine on
this branch: suspend()->pause(), refreshTokens()->setTheme(scheme) read
from data-color-scheme, the requestRender font-ready hook degraded to a
resize() repaint, and the old-engine-only setActive/setReducedMotion
dropped (tempo work is slice #62). Environment plumbing carried over
verbatim: ResizeObserver->resize, theme MutationObserver, document
visibility + IntersectionObserver hard-pause, amicode:brain-hover
glances, and the diff-by-id event flush with a silent first restore.
The live feed is the inline strip's event derivation extracted to a
pure, session-scoped deriveBrainEvents(messages, getParts) so it is
unit-testable headless and shared by the mount: touches in message
order via the tool->brain-ref map, a chart after each completed
assistant turn with >=2 commits, replay=true for completed turns,
ids never repeated.
Tests: new brain-events derivation suite (9 cases) pinning the AC-4
contract; brain-engine suite extended with the background-mount driving
case (derived-stream growth, quiet replay-only first flush with nothing
queued, lossless theme swap over a restored atlas).
Part of #56 (ADR 0002 - the Brain becomes the Chat's background).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
One full-bleed BrainAtmosphere per Chat window, mounted as the first
child of the session pane card (now relative isolate) at -z-10: above
the pane's surface fill, below the conversation timeline, landing, and
composer, pointer-events none. Keyed on the active session id so a
titlebar tab swap remounts to that session's atlas with exactly one
engine/render loop alive; empty on the landing. The standalone
new-session draft page gets the same layer (no events - sparse seed).
The inline brain-strip timeline row is deleted: the Brain member is
dropped from the TimelineRow union, forcing out its key branch, the
timelineRows append, the keepMounted special-case, the render case, and
the framed-row exclusion. The working-indicator shimmer (Thinking row)
is untouched, guarded by a new row-model suite; the strip's
click-to-expand is obviated (the engine has no node hit-testing).
Part of #56 (ADR 0002 - the Brain becomes the Chat's background).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Two-tier Glass token system over the Brain background (ADR 0002):
standard (prose/bubbles/composer) and dense (code/diffs/run-plots),
one shared 18px blur, tint carries all contrast. Each tier's alpha is
DERIVED per theme+mode — the least alpha clearing WCAG-AA with a +0.3
safety margin (target 4.8) over that mode's reference frame, read from
the brain engine's own PALETTES (dark: peak-bloom #fff676; light:
#8f8000 — the light brain never paints #fff676). Dense additionally
converges every graphical mark (syntax tokens, diff fills, run-plot
strokes) to within 0.2 of native and holds WCAG 1.4.11's 3:1.
- glass-tokens.ts: WCAG math (ported from the old branch), pure
deriveGlassTiers(tokens, frame) — no blur argument by design —
collectMarks, and the generateGlassCss emitter for every bundled
theme, scoped html[data-theme][data-color-scheme] with a
@supports-not near-opaque fallback (alpha >= 0.95)
- glass.css: committed generated output, registered in styles index;
exposes only [data-glass="standard"|"dense"] surfaces — no component
opts in within this slice, rendered output unchanged
- generate:glass script mirrors generate:tailwind wiring
- brain-engine.ts: export PALETTES (data seam only, no behavior change)
- glass-tokens.test.ts: headless contrast certification for oc-2
light+dark — body/code text floors + margin, mark rule, strict tier
ordering, blur-never-a-term guard, keying purity, fallback floor,
byte-for-byte drift guard, and the muted-grey-rides-dense invariant
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…st cadence) (#62)
One draw-gate honored by both the rAF loop and the manual tick(): full
musical tempo while active / in-flight / unfurling, ~8fps breathing at
rest (REST_FRAME_MS ported from the atmosphere branch engine). touch/
chart/highlight/resize/resume/setTheme beat the throttle via
requestRender so feedback stays immediate. BrainEngineStats gains
active + scale.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Boot is the amico core alone — the vault-skeleton preload, its
force-settle layout, and the demo-trace thought-edges are gone (ADR
0002 rejects the breathing skeleton atlas). The graph grows only from
real touches; two engines share no state (all state closure-local).
The camera is a constant core-centered zoom: no per-frame
fit-to-farthest, no close-up follow, no glance steering — growth
densifies in place. stats().scale exposes the fixed zoom; ambient
ghost picks tolerate an empty edge set.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The cap is the whole graph (core + GRAFT_CAP), not just live-* grafts:
eviction picks the least-recently-touched node — recency stamped by a
monotonic touch counter, not the beat clock (which stalls at rest).
Only the current live node and in-flight pulse endpoints are exempt;
atlas keep / charting / replay grant no immunity, so marathon sessions
can never grow the node set or per-frame draw cost without limit.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…rest (#62)
With prefers-reduced-motion set the engine never breathes at idle: once
the post-event nudge window (NUDGE_MS, rebased onto the frame timebase,
never performance.now()) elapses with nothing in flight, ticks draw
nothing and the rAF chain ends — a touch/chart/highlight/resume re-arms
one bounded burst. This is the accessibility terminal (ADR 0002),
independent of slice #63's frame-time ease. pause() clears any
scheduled frame; the lifecycle suite now pins zero-draws-while-hidden.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…#62)
Re-add the `active` output that #59's createBrainEvents dropped:
deriveBrainActive (pure, headless-tested — non-idle means busy or
retrying) feeds a memo that session.tsx passes to <BrainAtmosphere
active>, which plumbs it to engine.setActive. The draft page keeps the
default at-rest Brain (no session, no busy signal). Test helpers
(drive/clears) consolidated at file scope.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Everything floats over the mounted Brain (ADR 0002): the seven content
archetypes opt into slice #60's tier tokens — STANDARD on the user
bubble, assistant prose (which gains its first card), and the composer;
DENSE on code blocks, diffs, run-plots/run-windows, and tool cards (the
tool-collapsible root, so trigger + expanded output float as one unit
across single tools and context/shell groups). The tier token owns
fill/edge/radius/shadow everywhere — the opaque --surface-base bubble
fill, the composer's layer-01 fill + raised shadow, and the dock band's
background-stronger tiling are gone, so the Brain stays live in the
gaps (session-turn row frames and column wrappers stay transparent).
Muted/secondary ink never composites against the ultra-transparent
standard tint (certified to fail AA by #60): the prose meta, user-
message meta, composer footer controls, prose blockquotes, the child-
session stub, and the bubble's file/agent highlights all ride dense-
backed inline zones styled with --glass-dense-bg — the #60 token, no
new tint/blur literal anywhere. Shiki's inlined theme surface defers
to the dense card; the diff card's sticky header occludes with the
dense token instead of opaque chrome. The ghost-collapsible reset is
scoped :not([data-glass]) so the tier fill survives specificity.
Tests extend #60's certified surface onto the components:
- glass-float.test.ts (ui): the 7-archetype tier map as a table test —
body→standard ≥4.8 (AA + margin), code/diff→dense ≥4.5, marks→dense
≥3:1 (1.4.11) without native drift, muted-role never on standard —
measured with #60's exported validator math over the running-brain
reference frame in both oc-2 modes; plus source contracts (tier
attributes on the real markup, no ad-hoc literals in the restyled
card rules, repo-wide data-glass allowlist: two tier values only,
never on Rail/titlebar/Panels chrome).
- glass-float.test.ts (app): composer/diff/child-stub tier contracts,
gaps-stay-live (no glass, no fill on session-turn + containers), and
the sticky session-title header's pre-existing chrome blur untouched.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The sparse-seed boot (#62) removed the last importer; the latent skeleton
atlas was the superseded design's raw material (flagged by the #62 engineer,
removed at integration).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ver blur (#63)
A frame-time state machine observing the ONE Brain render loop: rolling-p95
over the 16.7ms budget for a sustained ~2s window steps motion down the
tempo ladder (allegro -> andante -> largo) with eased paint-cadence caps,
then to a motion full-stop, then terminally hard-pauses the canvas to a
static blurred field. Dual-guard hysteresis (13ms restore threshold + a ~2x
clear window, one level per window) prevents oscillation; the sample window
resets on every step so a stale regime never cascades an unearned step.
Measurement pauses with the engine (hidden / off-screen / reduced-motion):
stalled gaps are discarded, never fed as phantom over-budget frames. The
governor is independent of the reduced-motion accessibility terminal (#62)
and is bypassed entirely under it. Its only levers are tempo and the
terminal pause — no path writes a glass token, a style, or any CSS; stats()
now emits the discrete motion level. governed:false (the dev
force-full-tempo hook's engine seam) disables it for un-eased worst-case
perf capture.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…isables the governor (#63)
Ported from the old branch's perf-capture hook and extended per the issue:
the param now ALSO disables the perf governor (governed:false), so a gated
run — headless proxy or the reference laptop — measures the un-eased worst
case. DEV-gated, inert in prod. Also DEV-only window.__amicoBrainStats for
the trace harness and the manual gate checklist to read engine stats live.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…h themes (#63)
Playwright spec over the real app on the e2e mock-server harness: boots the
144-message fixture thread with the dev force-full-tempo hook (Brain pinned
busy, governor disabled — the un-eased worst case), scrolls continuously
for >=11s per theme inside the SAME rAF loop that samples frame intervals,
and emits a p95 / max / frames>33ms report per theme.
Labeled and asserted as the PRE-GATE PROXY only: the spec pins that the
harness runs and reports (shape, duration, theme coverage, forced state) —
it asserts NO numeric frame-time outcome. The release gate stays the manual
sign-off on the pinned reference laptop (issue #63, HITL).
Run: cd packages/app && bunx playwright test e2e/perf/brain-governor-trace.spec.ts
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…re-emptively eases (#63)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@kateebonner

Copy link
Copy Markdown
ContributorAuthor

HITL sign-off checklist — reference-laptop 60fps gate (#63)

The one open acceptance criterion on this PR. Run on the reference laptop, battery-powered:

  • Pin the machine: model, OS, battery %, VS Code + webview (Chromium) version — write them here.
  • Launch the dev lane: opencode serve --port 4099 + bun --cwd packages/app dev --port 5990 with VITE_OPENCODE_SERVER_PORT=4099 (the force hook is DEV-gated by design).
  • Open the Chat in the VS Code webview on a real thread of ≥40 cards with ?brainForceActive appended; verify in devtools: window.__amicoBrainStats()active: true, motion: "full".
  • Record a ≥10s continuous scroll (devtools Performance panel, or the rAF sampler in Add the perf governor (ease motion, never blur) and gate 60fps on the reference laptop #63's notes ~600 frames).
  • Pass = p95 ≤ 16.7ms AND zero frames > 33ms. Repeat in both themes (flip the chat scheme mid-session — Brain/Glass re-key losslessly).
  • Write the numbers here and sign off.

If the gate fails: remove ?brainForceActive and confirm the governor engages under load — watch __amicoBrainStats().motion step eased-1 → eased-2 → full-stop → hard-paused with the frosted look intact — then decide accept-with-valve vs iterate. (Headless dev-proxy already suggests the tail will need the valve; see PR body.)

🤖 Generated with Claude Code

@kateebonner
kateebonner marked this pull request as ready for review July 25, 2026 16:28
kateebonnerand others added 8 commits July 25, 2026 16:30
…sed question dock
Live design-review iteration with Kate (2026-07-25) on the Living Chat:
- Glass is ONE recipe everywhere: blur 8px + per-mode tint (dark: 4% white
frost + backdrop brightness(0.4); light: 5% near-white). The dark tint's
direction flips to a frost veil (lighter than ground, classic glass) with
the brightness term modeled honestly in the contrast derivation.
- The marks law (WCAG 1.4.11 dense certification) is WAIVED by design
decision; dense==standard. Muted ink is recorded as not-certified.
Tests rewritten to record the waiver rather than certify the old law.
- Cards no longer span the thread: prose fit-content ≤ min(88%,72ch),
user bubbles ≤ min(82%,64ch), tool cards ≤ 92%.
- The question dock floats on glass (8th archetype); its muted hint and
answers summary ride dense-backed zones; opaque fill scoped to
:not([data-glass]).
Part of #56 (PR #64); supersedes the #60/#61 tier law per Kate's call.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…cipe
Receipt chip, ask card (+options), run window (hover regression fixed),
inline entity card, entity rail chips, widget-preview shell, entity-view
inner atoms (tier/skeleton/formula/badge/seq/status pills), and the classic
in-chat landing (one standard card; starter buttons on dense-zone fills,
accent-edge instead of a yellow border on light). Semantic error state is a
danger tint over the glass, never an opaque surface. No !important fills.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Permission dock joins the question dock on the unified glass card (dock-prompt
generalized across kinds, permission footer flattened the same way); todo /
followup / revert trays carry the standard hook (opaque tray fill loses to
glass.css by import order); todo scroll-fade rides the glass tint; question
option tiles become dense-zone fills with the accent-soft hover, never an
opaque layer.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Opaque bands inside glassed cards defer to the dense-zone token (edit/write/
apply-patch sticky triggers, accordion header+expanded body inside any glassed
card, StickyAccordionHeader, timeline diff expanded view); the task/subagent
card is a dense zone with the accent-soft hover; diagnostics become a critical
tint over the frost; error/retry/assistant-error cards ride glass with a danger
tint; bare-muted-ink rows get their #60 backing (thinking indicator, reasoning
part, tool-loaded-file rows, turn divider label, comment-strip chips); user
attachment chips carry the dense hook; jump-to-bottom converts its hand-rolled
near-glass to the single recipe; the sticky session-title band converts its
chrome gradient/blur literals to the glass vars; inline-code chips ride the
dense token.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…cipe
Dialogs (one dialog.css edit covers delete-session/entity/fork/MCP/file/model/
unpaid/usage-exceeded launch sites), ImagePreview lightbox, popovers, dropdown
menus, shared Select menus, slash/@ autocomplete, project picker, model
selector, toast v2 — all ride the glass vars (tint + shared blur/brightness +
edge) with the legacy token as no-theme fallback; item highlights move to the
accent-soft state fill. Tooltips, the markdown code-fence copy tooltip and the
legacy toast keep their deliberate INVERSE ink on a HEAVIER glass (denser
float-token tint + shared blur/edge, never a raw opaque token); the copy
button itself rides the dense token. Drag overlay and the legacy composer
clip-mask stay heavier by function (masking), now token-mix + blur; composer
attachment tiles/pills and the theme-blind bg-black/50 name bar move to token
tints; legacy composer path gets the standard hook; composer loading stub and
review-tab header/diff surfaces convert to the glass tokens; classic landing
metadata gets a dense-zone chip.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ll audit
ui: allowlist covers every swept file (+ pre-allowed entries for the parallel
draft-landing rebuild: pages/new-session.tsx, session-new-design-view, and the
work-order's pages/session/new-session.tsx alias); new assertions pin the
AMICO family hooks + no-opaque-layer fills, dock unification across kinds,
question-option dense tiles, no-opaque-band-inside-glass (sticky triggers,
accordion, task card, diagnostics tint, diff view, inline code), muted-ink
backings, floating-chrome recipes (dialog/popover/menu/select/toast-v2/
ImagePreview), heavier inverse glass for tooltip/toast/copy-tooltip, review
surfaces, and error-tint-over-glass replacing the old no-glass error ruling.
app: sticky title band asserted on the glass vars (chrome literals banned),
timeline data-glass census, dock/composer chrome coverage, drag-overlay and
legacy clip-mask pinned as heavier-by-function token mixes.
These fail if any fix is reverted.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…st Brain
The empty landing shows the full latent network ("everything amico could
think") as a clustered ellipsoid cloud rotating in 3D, projected inside the
existing canvas engine (new constellation mode; reuses the rAF loop, governor,
pause/resume, theme re-key, reduced-motion). Curated core + seeded procedural
densification → identical constellation every launch. Dim monochrome + whisper
cluster tints, ZERO #fff676 (yellow stays exclusive to live thought). Twinkle +
breath micro-motion; static ¾ tableau under reduced-motion. First prompt →
ignition dissolve → live session graph. Removes the opaque new-session hero
wrapper that was occluding the Brain entirely, and glasses the draft-landing
chips + metadata. DEV knobs: ?constellationSpeed/Density/Tint/Fog.
Design of record: grilled with Kate 2026-07-25 (landing-only; clustered cloud;
canvas projection; mono+cluster-tint; ignition dissolve; twinkle+breath; static
tableau; uniform full-bleed). Part of #56 (PR #64).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
kateebonnerand others added 2 commits July 25, 2026 17:16
# Conflicts:
#	packages/app/src/components/session/session-new-view.tsx
#	packages/ui/src/amicode/getting-started.tsx
…k composer, typewriter placeholder, 3D constellation in-session
Live design-review iteration with Kate (2026-07-25) on the Living Chat:
Glass
- Max transparency: dark tint derives to fully transparent (backdrop
brightness 0.4 -> 0.8; less darkening lets the constellation read through).
AA retained for LIGHT, waived-and-recorded for DARK standard (the landing
constellation is yellow-free, so it reads there). Tests record the trade.
- The glass tier is now JUST blur + tint + radius — no border outline, no top
sheen/inset line, no box-shadow (Kate: "no border, no top line, no shadow").
Composer
- One background: dock-surface shell/tray opaque fills scoped to :not([data-glass])
so the glass wins as one uniform surface; footer inset fill removed (was a
visible second background).
- Full-bleed bottom dock: full width, stuck to the bottom, ~35% viewport height
(ui-ux-pro-max: primary CTA without eclipsing the hero), edge-to-edge (radius/
border/shadow zeroed). Fixed the flex height-chain so it fills to the bottom.
- Removed the model-provider H-mark/AMICODE wordmark and the project/folder
picker from the landing.
Landing
- Starter chip wall removed (competed with the constellation + composer).
Discovery now lives in the composer as a rotating TYPEWRITER placeholder that
types out the real starter prompts letter-by-letter with a blinking caret;
freezes on focus (Tab accepts the shown one), static under reduced motion.
- Constellation contrast bumped (edge alpha 0.10 -> 0.17, nodes x1.4).
Session parity
- The 3D constellation is now the background EVERYWHERE (session too), not the
sparse 2D live graph — the launch and session are one surface. (Live-thought
node pulsing is the next layer.)
Gates: ui 438 / app 473 / typecheck 23/23 / lint 0 errors. Part of #56 (PR #64).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@kateebonner

Copy link
Copy Markdown
ContributorAuthor

Live design-tuning batch (Kate, 2026-07-25) — commit 69ebf7e

The design evolved significantly beyond the original slices through a live review session. Landed:

  • Glass — now purely blur + tint + radius: dark derives to fully transparent (brightness 0.8), no border, no top sheen, no box-shadow. AA kept for light, waived+recorded for dark standard (the landing constellation is yellow-free).
  • Composer — one uniform glass surface (two-tone fixed); full-bleed bottom dock, ~35% viewport height, edge-to-edge; wordmark + project/folder picker removed.
  • Landing — starter-chip wall removed; discovery moved into the composer as a rotating typewriter placeholder (types the real starters letter-by-letter, blinking caret, Tab-to-accept, reduced-motion static). Constellation contrast bumped.
  • Session parity — the 3D constellation is now the background in-session too (not the sparse 2D graph); launch + session are one surface.

Queued (next): live-thought node pulsing over the constellation (data-true layer), card width containment, and folding the effort/variant selector into the model dropdown.

Gates: ui 438 / app 473 / typecheck 23/23 / lint 0 errors.

🤖 Generated with Claude Code

…lass sweep
Overnight batch 2 (Kate 2026-07-25), three asks:
1. Live thought over the constellation — the '+ live thought' half of
'constellation + live thought': real session touches flare their node
in css.thought (#fff676 dark / #8f8000 light) over the latent web —
rise 150ms, ease-out decay ~1.6s, expanding ring, incident-edge
glints, touched label beside the flare (fg ink + halo). Labels hash
deterministically into their category lobe with a visible-node walk
(a flare the user can't see isn't thought). Replays restore silently;
re-touches refresh instead of stacking; capped at 24; reduced motion
holds ONE statically lit node. Dev hook window.__amicoBrainTouch
(mirrors __amicoBrainStats) previews flares without a real turn.
+7 tests incl. byte-determinism under touches and the color-law
boundary (latent web ink stays yellow-free with zero touches).
2. Thinking effort folded INTO the model surface — the standalone
Default/None/High footer Select is gone (both composer paths). New
ModelVariantRow renders in the paid ModelSelectorPopover AND the
unpaid dialog (Kate's dev path): chips on --accent-fill-soft /
--accent-edge, keeps the menu open on pick; the collapsed trigger
reads 'Model · High' so effort stays visible at rest.
3. Session glass sweep to the launch-composer feel — glass is
blur+tint+radius ONLY, now enforced in-session: dock-prompt ring +
permission/question footer border-top scoped off-glass; composer
focus ring removed; comment chips borderless; dock radius 10px →
var(--radius-lg). Width containment: tool collapsibles, diffs group,
reasoning-part, error-card all share the prose measure
(min(88%, 72ch)) — floating cards on the Brain, never full-width
bands.
Gate: ui 445 / app 473 / typecheck 23 projects / lint 0 errors.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@kateebonner

Copy link
Copy Markdown
ContributorAuthor

Overnight batch 2 — 05fa001d0

All three queued items from the live-tuning session, plus the new ask (session components on the launch-composer feel):

1. Live thought over the constellation ✨

The "+ live thought" half of constellation + live thought is in. As amico works, each real touch flares its constellation node in the thought color (#fff676 dark / #8f8000 light — the brand law holds per scheme): fast rise, ~1.6s ease-out decay, an expanding ring, glints down the node's incident edges, and the touched label ("session.tsx", "amico-vault") named beside the flare.

  • Labels hash deterministically into their category lobe (file work lights the code lobe, skills the skills lobe…), then walk to a visible node — a flare you can't see isn't thought.
  • History replays silently on mount; re-touches refresh their flare instead of stacking; capped at 24 so a torrent stays a shimmer.
  • Reduced motion: the tableau holds one statically lit node — where amico is now.
  • Dev preview without a real turn: window.__amicoBrainTouch({label:"x.ts", type:"resource"}) in the console (the ?-param pattern doesn't survive the router redirect, so this rides the __amicoBrainStats hook pattern instead).
  • +7 tests: flare paint, light-scheme ink, silent replay, refresh-not-stack, decay-to-rest, reduced-motion tableau, and byte-determinism under touches. The latent-web color law tests still pin zero yellow with zero touches.

2. Thinking effort lives in the model menu

The standalone Default/None/High Select is gone (both composer paths). A ModelVariantRow renders inside the paid popover and the unpaid dialog (the dev/free path — it would otherwise have lost the control entirely): chips on --accent-fill-soft/--accent-edge, picking one keeps the menu open. The collapsed trigger now reads "DeepSeek V4 Fl… · High" so effort stays visible at rest.

3. Session glass sweep — the launch-composer feel everywhere

Glass = blur + tint + radius, nothing else, now enforced in-session too:

  • dock-prompt (permission/question card): 1px ring removed, footer border-top removed (one surface, same law as the composer footer), radius 10px → --radius-lg.
  • In-session composer: focus-within ring removed (the caret carries focus; drag keeps its dashed dropzone).
  • Comment chips: borderless dense tint.
  • Width containment: tool collapsibles ("Explored · 2 searches"), the diffs group, reasoning, and error cards all share the prose measure — min(88%, 72ch) — so the thread reads as floating cards over the Brain, never full-width bands.

Verified live in both themes on real sessions (silent replay ✓, live flare mid-session ✓, permission card ✓).

Gate: ui 445 / app 473 / typecheck / lint 0 errors.

kateebonnerand others added 4 commits July 26, 2026 12:38
… session composer = launch dock
Live review with Kate (2026-07-26), three asks:
1. 'I don't see the flares' — thought was landing behind the message
column's glass. The engine now takes an occlusion set (occlude());
session.tsx measures the real layout (timeline column band + composer
dock) and BrainAtmosphere feeds it fresh before every event flush, so
flares land in the GUTTERS where the Brain is actually visible
(fallback: merely-visible beats nothing). While the session works,
the NEWEST flare holds lit as a sustained 'amico is HERE' cursor and
decays out when the turn ends. +3 tests (gutter avoidance, hold/decay,
fully-occluded fallback).
2. Cards hug their contents — tool collapsibles and the diffs group are
width: fit-content up to the prose measure, never a padded-out band.
3. The session composer IS the launch composer — same full-bleed bottom
dock (~35% of the pane, edge-to-edge one-surface glass) via
placement='inline'; starter/typewriter suggestions stay gated to the
EMPTY LANDING (params.id gates on rotation, typing, Tab-accept,
placeholder). Legacy layout keeps the floating column card.
Gate: ui 448 / app 473 / typecheck / lint 0 errors.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ttom-stacked flow + full-width header
Live review with Kate (2026-07-26), second batch:
- Thought-tracking camera v2: rotation eases to a stop while flares are
alive and the view zooms (1.6x) + glides the newest thought to the
CENTER of the frame (Kate's call — replaces the gutter stage). All 6
confirmed findings from the adversarial review workflow fixed:
(1) conPulses is RECENCY-ordered — a re-touch splices to the end, so
the camera + busy-hold follow the re-fired concept, never a stale
array-last pulse; (2) ignite() no longer spins the stopped web back up
mid-dissolve (conRotK frozen during ignite) and the camera fast-eases
home (tau 200ms) before the live layer co-paints; (3) an OS
reduced-motion flip mid-track snaps the camera home instantly;
(4) edges/glints/ring/bloom scale with the zoom — a camera dolly, not
dots inflating over a hairline web; (5) flare seating is computed in
AMBIENT space so the zoomed viewport never funnels subsequent flares
into one slice; (6) the busy-hold is budgeted (~30s) so a wedged
active signal or ?brainForceActive cannot freeze the camera forever.
+2 tests (hold budget, seat-vs-camera split); 452 ui tests green.
- Session header: full-width band, bottom padding tight unless the
entity-chips rail rendered (CSS :has), and the band now lives OUTSIDE
the scroller, pinned at the pane top.
- Messages: rows span the pane — user messages justify RIGHT, amico's
justify LEFT (each card keeps its reading measure); the Brain owns the
middle where the camera stages thought.
- Bottom-stacked flow (messenger law): the SCROLLER's height is
content-driven up to the space the header leaves and anchors to the
bottom, so a short thread sits just above the composer; inside it
scrolling stays classic top-anchored — virtua's geometry is untouched
(an mt-auto-in-viewport variant starved virtua's visible range and
was abandoned). startMargin 0, sticky-accordion offsets updated.
Gate: ui 452 / app 473 / typecheck / lint 0 errors.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Kate 2026-07-26 (component audit): the collapsed 'edit · Failed' chip was
banding across the pane — width: fit-content capped at the prose measure,
matching the width law every timeline card now follows.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…erity
Kate 2026-07-26: glass is blur+tint+radius; the 2px Card accent rail read
as a border on the failed/error cards. content:none on the ::before for
tool-error-card and .error-card — the danger tint, icon, and ink alone
mark severity.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@kateebonner
kateebonner marked this pull request as draft July 26, 2026 23:19
@kateebonner

Copy link
Copy Markdown
ContributorAuthor

Parked 2026-07-26 — converting to draft. Aaron's call: not pursuing this UI direction right now. Everything through 83d070ae4 is on the branch (living-chat glass redesign, thought-tracking camera, bottom-stacked edge-justified flow, effort-in-model-menu, component audit + width law). The branch is the complete archive of the direction if we return to it; the component library artifact documents every surface.

@kateebonner
kateebonner marked this pull request as ready for review July 29, 2026 00:21
@kateebonner
kateebonner marked this pull request as draft July 29, 2026 00:23
@jack-champagne

Copy link
Copy Markdown
Member

@kateebonner — question before this ages further: is anything here still worth keeping?

Asking because ADR 0002, which this implements, is marked superseded on mainline:

Status: Superseded by ADR 0003 (direction parked 2026-07-26; the Brain moved to the context-tree top panel instead of becoming the chat background)

and ADR 0003 (Accepted, 2026-07-27, on Aaron's 2026-07-26 feedback) is explicit:

Supersedes: ADR 0002 (Brain as chat background — direction parked)
… Aaron's feedback reframed what the graph is for: not ambience, but orientationThe graph moves out of the timeline into a pinned top panel … the ambient background direction is parked.

The ADR-0003 replacement has fully landed

All of this is on local/amicode and shipped in v1.17.3-amicode.11:

So the top-panel + first-class vault surface direction is done and released.

What's still unique to this branch

brain-engine.ts and context-tree-engine.ts are already on main — the graph engine itself made it across. What has no counterpart is the presentation layer for the parked direction:

only in #64
glass.css (778 lines), glass-tokens.ts, script/generate-glass.ts
brain-atmosphere.tsx / .css
brain-constellation.ts
brain-perf-governor.test.ts, brain-events.ts, e2e/perf/brain-governor-trace.spec.ts

16 added files, 54 modified, 1 deleted.

Why I'm asking rather than just closing

Two things in there look potentially valuable independent of the parked background direction:

  1. The legibility machineryglass-tokens.ts plus the WCAG-AA-floored tint derivation. ADR 0002 records that the earlier attempt failed exactly one AA check (muted grey on the most translucent tier), so this encodes a real lesson. Worth salvaging if any surface still layers text on translucency — the session header's backdrop-blur comes to mind, given fix(session): header backdrop-blur off while the context-tree band is open #97 just had to switch it off over the context-tree band.
  2. brain-perf-governor + the e2e perf trace — frame-budget governance for the graph. The organic context tree that did land has the same cost profile, so a perf governor may be wanted regardless of where the graph renders.

If neither is worth extracting, this is a clean close — the direction is parked and the replacement is released. If either is, they'd be small standalone PRs rather than resurrecting 71 files.

For context on the state: it is still a draft, CONFLICTING/DIRTY, 72 commits behind mainline, and its checks are all CANCELLED from before #2 fixed the runner labels — so CI has never actually evaluated this branch.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Make the Brain the Chat's living background; float components on legibility-floored Glass

2 participants

@kateebonner@jack-champagne
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Make the Brain the Chat's living background; float components on legibility-floored Glass - #64

Closed
kateebonner wants to merge 34 commits into
local/amicodefrom
amico/issue-56-living-chat
Closed

Make the Brain the Chat's living background; float components on legibility-floored Glass#64
kateebonner wants to merge 34 commits into
local/amicodefrom
amico/issue-56-living-chat

Conversation

@kateebonner

@kateebonnerkateebonner commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Closes#56

Integration branch for the Living Chat redesign, built slice-by-slice from the sub-issue DAG (#59#60#61#62#63; design-of-record: ADR 0002, merged via #58).

Landed:

Final gate on this branch: ui 402 pass / 0 fail · app 464 pass / 0 fail · typecheck 23/23 · lint 0 errors.

Honest pre-gate evidence (headless, dev build — NOT the gate): forced full tempo + 11s continuous scroll of a 144-message thread → dark p95 25.4ms / light 25.2ms, mean ≈16.3ms, 11–15 frames >33ms. The tail misses the 16.7ms budget in that proxy environment (dev-mode Solid, headless vsync, sampler riding the measured loop) — which is exactly what the pre-agreed governor valve is for. The real call happens on the reference laptop (checklist below).

Known follow-up candidates (from #61's browser pass, non-blocking): composer placeholder hint and reasoning-part still composite on standard/bare over the Brain.

🤖 Generated with Claude Code

kateebonnerand others added 19 commits July 25, 2026 02:26
The full-bleed Brain background component, ported from the old
kate/chat-brain-atmosphere branch and retargeted to the native engine on
this branch: suspend()->pause(), refreshTokens()->setTheme(scheme) read
from data-color-scheme, the requestRender font-ready hook degraded to a
resize() repaint, and the old-engine-only setActive/setReducedMotion
dropped (tempo work is slice #62). Environment plumbing carried over
verbatim: ResizeObserver->resize, theme MutationObserver, document
visibility + IntersectionObserver hard-pause, amicode:brain-hover
glances, and the diff-by-id event flush with a silent first restore.
The live feed is the inline strip's event derivation extracted to a
pure, session-scoped deriveBrainEvents(messages, getParts) so it is
unit-testable headless and shared by the mount: touches in message
order via the tool->brain-ref map, a chart after each completed
assistant turn with >=2 commits, replay=true for completed turns,
ids never repeated.
Tests: new brain-events derivation suite (9 cases) pinning the AC-4
contract; brain-engine suite extended with the background-mount driving
case (derived-stream growth, quiet replay-only first flush with nothing
queued, lossless theme swap over a restored atlas).
Part of #56 (ADR 0002 - the Brain becomes the Chat's background).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
One full-bleed BrainAtmosphere per Chat window, mounted as the first
child of the session pane card (now relative isolate) at -z-10: above
the pane's surface fill, below the conversation timeline, landing, and
composer, pointer-events none. Keyed on the active session id so a
titlebar tab swap remounts to that session's atlas with exactly one
engine/render loop alive; empty on the landing. The standalone
new-session draft page gets the same layer (no events - sparse seed).
The inline brain-strip timeline row is deleted: the Brain member is
dropped from the TimelineRow union, forcing out its key branch, the
timelineRows append, the keepMounted special-case, the render case, and
the framed-row exclusion. The working-indicator shimmer (Thinking row)
is untouched, guarded by a new row-model suite; the strip's
click-to-expand is obviated (the engine has no node hit-testing).
Part of #56 (ADR 0002 - the Brain becomes the Chat's background).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Two-tier Glass token system over the Brain background (ADR 0002):
standard (prose/bubbles/composer) and dense (code/diffs/run-plots),
one shared 18px blur, tint carries all contrast. Each tier's alpha is
DERIVED per theme+mode — the least alpha clearing WCAG-AA with a +0.3
safety margin (target 4.8) over that mode's reference frame, read from
the brain engine's own PALETTES (dark: peak-bloom #fff676; light:
#8f8000 — the light brain never paints #fff676). Dense additionally
converges every graphical mark (syntax tokens, diff fills, run-plot
strokes) to within 0.2 of native and holds WCAG 1.4.11's 3:1.
- glass-tokens.ts: WCAG math (ported from the old branch), pure
deriveGlassTiers(tokens, frame) — no blur argument by design —
collectMarks, and the generateGlassCss emitter for every bundled
theme, scoped html[data-theme][data-color-scheme] with a
@supports-not near-opaque fallback (alpha >= 0.95)
- glass.css: committed generated output, registered in styles index;
exposes only [data-glass="standard"|"dense"] surfaces — no component
opts in within this slice, rendered output unchanged
- generate:glass script mirrors generate:tailwind wiring
- brain-engine.ts: export PALETTES (data seam only, no behavior change)
- glass-tokens.test.ts: headless contrast certification for oc-2
light+dark — body/code text floors + margin, mark rule, strict tier
ordering, blur-never-a-term guard, keying purity, fallback floor,
byte-for-byte drift guard, and the muted-grey-rides-dense invariant
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…st cadence) (#62)
One draw-gate honored by both the rAF loop and the manual tick(): full
musical tempo while active / in-flight / unfurling, ~8fps breathing at
rest (REST_FRAME_MS ported from the atmosphere branch engine). touch/
chart/highlight/resize/resume/setTheme beat the throttle via
requestRender so feedback stays immediate. BrainEngineStats gains
active + scale.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Boot is the amico core alone — the vault-skeleton preload, its
force-settle layout, and the demo-trace thought-edges are gone (ADR
0002 rejects the breathing skeleton atlas). The graph grows only from
real touches; two engines share no state (all state closure-local).
The camera is a constant core-centered zoom: no per-frame
fit-to-farthest, no close-up follow, no glance steering — growth
densifies in place. stats().scale exposes the fixed zoom; ambient
ghost picks tolerate an empty edge set.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The cap is the whole graph (core + GRAFT_CAP), not just live-* grafts:
eviction picks the least-recently-touched node — recency stamped by a
monotonic touch counter, not the beat clock (which stalls at rest).
Only the current live node and in-flight pulse endpoints are exempt;
atlas keep / charting / replay grant no immunity, so marathon sessions
can never grow the node set or per-frame draw cost without limit.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…rest (#62)
With prefers-reduced-motion set the engine never breathes at idle: once
the post-event nudge window (NUDGE_MS, rebased onto the frame timebase,
never performance.now()) elapses with nothing in flight, ticks draw
nothing and the rAF chain ends — a touch/chart/highlight/resume re-arms
one bounded burst. This is the accessibility terminal (ADR 0002),
independent of slice #63's frame-time ease. pause() clears any
scheduled frame; the lifecycle suite now pins zero-draws-while-hidden.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…#62)
Re-add the `active` output that #59's createBrainEvents dropped:
deriveBrainActive (pure, headless-tested — non-idle means busy or
retrying) feeds a memo that session.tsx passes to <BrainAtmosphere
active>, which plumbs it to engine.setActive. The draft page keeps the
default at-rest Brain (no session, no busy signal). Test helpers
(drive/clears) consolidated at file scope.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Everything floats over the mounted Brain (ADR 0002): the seven content
archetypes opt into slice #60's tier tokens — STANDARD on the user
bubble, assistant prose (which gains its first card), and the composer;
DENSE on code blocks, diffs, run-plots/run-windows, and tool cards (the
tool-collapsible root, so trigger + expanded output float as one unit
across single tools and context/shell groups). The tier token owns
fill/edge/radius/shadow everywhere — the opaque --surface-base bubble
fill, the composer's layer-01 fill + raised shadow, and the dock band's
background-stronger tiling are gone, so the Brain stays live in the
gaps (session-turn row frames and column wrappers stay transparent).
Muted/secondary ink never composites against the ultra-transparent
standard tint (certified to fail AA by #60): the prose meta, user-
message meta, composer footer controls, prose blockquotes, the child-
session stub, and the bubble's file/agent highlights all ride dense-
backed inline zones styled with --glass-dense-bg — the #60 token, no
new tint/blur literal anywhere. Shiki's inlined theme surface defers
to the dense card; the diff card's sticky header occludes with the
dense token instead of opaque chrome. The ghost-collapsible reset is
scoped :not([data-glass]) so the tier fill survives specificity.
Tests extend #60's certified surface onto the components:
- glass-float.test.ts (ui): the 7-archetype tier map as a table test —
body→standard ≥4.8 (AA + margin), code/diff→dense ≥4.5, marks→dense
≥3:1 (1.4.11) without native drift, muted-role never on standard —
measured with #60's exported validator math over the running-brain
reference frame in both oc-2 modes; plus source contracts (tier
attributes on the real markup, no ad-hoc literals in the restyled
card rules, repo-wide data-glass allowlist: two tier values only,
never on Rail/titlebar/Panels chrome).
- glass-float.test.ts (app): composer/diff/child-stub tier contracts,
gaps-stay-live (no glass, no fill on session-turn + containers), and
the sticky session-title header's pre-existing chrome blur untouched.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The sparse-seed boot (#62) removed the last importer; the latent skeleton
atlas was the superseded design's raw material (flagged by the #62 engineer,
removed at integration).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ver blur (#63)
A frame-time state machine observing the ONE Brain render loop: rolling-p95
over the 16.7ms budget for a sustained ~2s window steps motion down the
tempo ladder (allegro -> andante -> largo) with eased paint-cadence caps,
then to a motion full-stop, then terminally hard-pauses the canvas to a
static blurred field. Dual-guard hysteresis (13ms restore threshold + a ~2x
clear window, one level per window) prevents oscillation; the sample window
resets on every step so a stale regime never cascades an unearned step.
Measurement pauses with the engine (hidden / off-screen / reduced-motion):
stalled gaps are discarded, never fed as phantom over-budget frames. The
governor is independent of the reduced-motion accessibility terminal (#62)
and is bypassed entirely under it. Its only levers are tempo and the
terminal pause — no path writes a glass token, a style, or any CSS; stats()
now emits the discrete motion level. governed:false (the dev
force-full-tempo hook's engine seam) disables it for un-eased worst-case
perf capture.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…isables the governor (#63)
Ported from the old branch's perf-capture hook and extended per the issue:
the param now ALSO disables the perf governor (governed:false), so a gated
run — headless proxy or the reference laptop — measures the un-eased worst
case. DEV-gated, inert in prod. Also DEV-only window.__amicoBrainStats for
the trace harness and the manual gate checklist to read engine stats live.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…h themes (#63)
Playwright spec over the real app on the e2e mock-server harness: boots the
144-message fixture thread with the dev force-full-tempo hook (Brain pinned
busy, governor disabled — the un-eased worst case), scrolls continuously
for >=11s per theme inside the SAME rAF loop that samples frame intervals,
and emits a p95 / max / frames>33ms report per theme.
Labeled and asserted as the PRE-GATE PROXY only: the spec pins that the
harness runs and reports (shape, duration, theme coverage, forced state) —
it asserts NO numeric frame-time outcome. The release gate stays the manual
sign-off on the pinned reference laptop (issue #63, HITL).
Run: cd packages/app && bunx playwright test e2e/perf/brain-governor-trace.spec.ts
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…re-emptively eases (#63)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@kateebonner

Copy link
Copy Markdown
ContributorAuthor

HITL sign-off checklist — reference-laptop 60fps gate (#63)

The one open acceptance criterion on this PR. Run on the reference laptop, battery-powered:

  • Pin the machine: model, OS, battery %, VS Code + webview (Chromium) version — write them here.
  • Launch the dev lane: opencode serve --port 4099 + bun --cwd packages/app dev --port 5990 with VITE_OPENCODE_SERVER_PORT=4099 (the force hook is DEV-gated by design).
  • Open the Chat in the VS Code webview on a real thread of ≥40 cards with ?brainForceActive appended; verify in devtools: window.__amicoBrainStats()active: true, motion: "full".
  • Record a ≥10s continuous scroll (devtools Performance panel, or the rAF sampler in Add the perf governor (ease motion, never blur) and gate 60fps on the reference laptop #63's notes ~600 frames).
  • Pass = p95 ≤ 16.7ms AND zero frames > 33ms. Repeat in both themes (flip the chat scheme mid-session — Brain/Glass re-key losslessly).
  • Write the numbers here and sign off.

If the gate fails: remove ?brainForceActive and confirm the governor engages under load — watch __amicoBrainStats().motion step eased-1 → eased-2 → full-stop → hard-paused with the frosted look intact — then decide accept-with-valve vs iterate. (Headless dev-proxy already suggests the tail will need the valve; see PR body.)

🤖 Generated with Claude Code

@kateebonner
kateebonner marked this pull request as ready for review July 25, 2026 16:28
kateebonnerand others added 8 commits July 25, 2026 16:30
…sed question dock
Live design-review iteration with Kate (2026-07-25) on the Living Chat:
- Glass is ONE recipe everywhere: blur 8px + per-mode tint (dark: 4% white
frost + backdrop brightness(0.4); light: 5% near-white). The dark tint's
direction flips to a frost veil (lighter than ground, classic glass) with
the brightness term modeled honestly in the contrast derivation.
- The marks law (WCAG 1.4.11 dense certification) is WAIVED by design
decision; dense==standard. Muted ink is recorded as not-certified.
Tests rewritten to record the waiver rather than certify the old law.
- Cards no longer span the thread: prose fit-content ≤ min(88%,72ch),
user bubbles ≤ min(82%,64ch), tool cards ≤ 92%.
- The question dock floats on glass (8th archetype); its muted hint and
answers summary ride dense-backed zones; opaque fill scoped to
:not([data-glass]).
Part of #56 (PR #64); supersedes the #60/#61 tier law per Kate's call.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…cipe
Receipt chip, ask card (+options), run window (hover regression fixed),
inline entity card, entity rail chips, widget-preview shell, entity-view
inner atoms (tier/skeleton/formula/badge/seq/status pills), and the classic
in-chat landing (one standard card; starter buttons on dense-zone fills,
accent-edge instead of a yellow border on light). Semantic error state is a
danger tint over the glass, never an opaque surface. No !important fills.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Permission dock joins the question dock on the unified glass card (dock-prompt
generalized across kinds, permission footer flattened the same way); todo /
followup / revert trays carry the standard hook (opaque tray fill loses to
glass.css by import order); todo scroll-fade rides the glass tint; question
option tiles become dense-zone fills with the accent-soft hover, never an
opaque layer.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Opaque bands inside glassed cards defer to the dense-zone token (edit/write/
apply-patch sticky triggers, accordion header+expanded body inside any glassed
card, StickyAccordionHeader, timeline diff expanded view); the task/subagent
card is a dense zone with the accent-soft hover; diagnostics become a critical
tint over the frost; error/retry/assistant-error cards ride glass with a danger
tint; bare-muted-ink rows get their #60 backing (thinking indicator, reasoning
part, tool-loaded-file rows, turn divider label, comment-strip chips); user
attachment chips carry the dense hook; jump-to-bottom converts its hand-rolled
near-glass to the single recipe; the sticky session-title band converts its
chrome gradient/blur literals to the glass vars; inline-code chips ride the
dense token.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…cipe
Dialogs (one dialog.css edit covers delete-session/entity/fork/MCP/file/model/
unpaid/usage-exceeded launch sites), ImagePreview lightbox, popovers, dropdown
menus, shared Select menus, slash/@ autocomplete, project picker, model
selector, toast v2 — all ride the glass vars (tint + shared blur/brightness +
edge) with the legacy token as no-theme fallback; item highlights move to the
accent-soft state fill. Tooltips, the markdown code-fence copy tooltip and the
legacy toast keep their deliberate INVERSE ink on a HEAVIER glass (denser
float-token tint + shared blur/edge, never a raw opaque token); the copy
button itself rides the dense token. Drag overlay and the legacy composer
clip-mask stay heavier by function (masking), now token-mix + blur; composer
attachment tiles/pills and the theme-blind bg-black/50 name bar move to token
tints; legacy composer path gets the standard hook; composer loading stub and
review-tab header/diff surfaces convert to the glass tokens; classic landing
metadata gets a dense-zone chip.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ll audit
ui: allowlist covers every swept file (+ pre-allowed entries for the parallel
draft-landing rebuild: pages/new-session.tsx, session-new-design-view, and the
work-order's pages/session/new-session.tsx alias); new assertions pin the
AMICO family hooks + no-opaque-layer fills, dock unification across kinds,
question-option dense tiles, no-opaque-band-inside-glass (sticky triggers,
accordion, task card, diagnostics tint, diff view, inline code), muted-ink
backings, floating-chrome recipes (dialog/popover/menu/select/toast-v2/
ImagePreview), heavier inverse glass for tooltip/toast/copy-tooltip, review
surfaces, and error-tint-over-glass replacing the old no-glass error ruling.
app: sticky title band asserted on the glass vars (chrome literals banned),
timeline data-glass census, dock/composer chrome coverage, drag-overlay and
legacy clip-mask pinned as heavier-by-function token mixes.
These fail if any fix is reverted.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…st Brain
The empty landing shows the full latent network ("everything amico could
think") as a clustered ellipsoid cloud rotating in 3D, projected inside the
existing canvas engine (new constellation mode; reuses the rAF loop, governor,
pause/resume, theme re-key, reduced-motion). Curated core + seeded procedural
densification → identical constellation every launch. Dim monochrome + whisper
cluster tints, ZERO #fff676 (yellow stays exclusive to live thought). Twinkle +
breath micro-motion; static ¾ tableau under reduced-motion. First prompt →
ignition dissolve → live session graph. Removes the opaque new-session hero
wrapper that was occluding the Brain entirely, and glasses the draft-landing
chips + metadata. DEV knobs: ?constellationSpeed/Density/Tint/Fog.
Design of record: grilled with Kate 2026-07-25 (landing-only; clustered cloud;
canvas projection; mono+cluster-tint; ignition dissolve; twinkle+breath; static
tableau; uniform full-bleed). Part of #56 (PR #64).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
kateebonnerand others added 2 commits July 25, 2026 17:16
# Conflicts:
#	packages/app/src/components/session/session-new-view.tsx
#	packages/ui/src/amicode/getting-started.tsx
…k composer, typewriter placeholder, 3D constellation in-session
Live design-review iteration with Kate (2026-07-25) on the Living Chat:
Glass
- Max transparency: dark tint derives to fully transparent (backdrop
brightness 0.4 -> 0.8; less darkening lets the constellation read through).
AA retained for LIGHT, waived-and-recorded for DARK standard (the landing
constellation is yellow-free, so it reads there). Tests record the trade.
- The glass tier is now JUST blur + tint + radius — no border outline, no top
sheen/inset line, no box-shadow (Kate: "no border, no top line, no shadow").
Composer
- One background: dock-surface shell/tray opaque fills scoped to :not([data-glass])
so the glass wins as one uniform surface; footer inset fill removed (was a
visible second background).
- Full-bleed bottom dock: full width, stuck to the bottom, ~35% viewport height
(ui-ux-pro-max: primary CTA without eclipsing the hero), edge-to-edge (radius/
border/shadow zeroed). Fixed the flex height-chain so it fills to the bottom.
- Removed the model-provider H-mark/AMICODE wordmark and the project/folder
picker from the landing.
Landing
- Starter chip wall removed (competed with the constellation + composer).
Discovery now lives in the composer as a rotating TYPEWRITER placeholder that
types out the real starter prompts letter-by-letter with a blinking caret;
freezes on focus (Tab accepts the shown one), static under reduced motion.
- Constellation contrast bumped (edge alpha 0.10 -> 0.17, nodes x1.4).
Session parity
- The 3D constellation is now the background EVERYWHERE (session too), not the
sparse 2D live graph — the launch and session are one surface. (Live-thought
node pulsing is the next layer.)
Gates: ui 438 / app 473 / typecheck 23/23 / lint 0 errors. Part of #56 (PR #64).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@kateebonner

Copy link
Copy Markdown
ContributorAuthor

Live design-tuning batch (Kate, 2026-07-25) — commit 69ebf7e

The design evolved significantly beyond the original slices through a live review session. Landed:

  • Glass — now purely blur + tint + radius: dark derives to fully transparent (brightness 0.8), no border, no top sheen, no box-shadow. AA kept for light, waived+recorded for dark standard (the landing constellation is yellow-free).
  • Composer — one uniform glass surface (two-tone fixed); full-bleed bottom dock, ~35% viewport height, edge-to-edge; wordmark + project/folder picker removed.
  • Landing — starter-chip wall removed; discovery moved into the composer as a rotating typewriter placeholder (types the real starters letter-by-letter, blinking caret, Tab-to-accept, reduced-motion static). Constellation contrast bumped.
  • Session parity — the 3D constellation is now the background in-session too (not the sparse 2D graph); launch + session are one surface.

Queued (next): live-thought node pulsing over the constellation (data-true layer), card width containment, and folding the effort/variant selector into the model dropdown.

Gates: ui 438 / app 473 / typecheck 23/23 / lint 0 errors.

🤖 Generated with Claude Code

…lass sweep
Overnight batch 2 (Kate 2026-07-25), three asks:
1. Live thought over the constellation — the '+ live thought' half of
'constellation + live thought': real session touches flare their node
in css.thought (#fff676 dark / #8f8000 light) over the latent web —
rise 150ms, ease-out decay ~1.6s, expanding ring, incident-edge
glints, touched label beside the flare (fg ink + halo). Labels hash
deterministically into their category lobe with a visible-node walk
(a flare the user can't see isn't thought). Replays restore silently;
re-touches refresh instead of stacking; capped at 24; reduced motion
holds ONE statically lit node. Dev hook window.__amicoBrainTouch
(mirrors __amicoBrainStats) previews flares without a real turn.
+7 tests incl. byte-determinism under touches and the color-law
boundary (latent web ink stays yellow-free with zero touches).
2. Thinking effort folded INTO the model surface — the standalone
Default/None/High footer Select is gone (both composer paths). New
ModelVariantRow renders in the paid ModelSelectorPopover AND the
unpaid dialog (Kate's dev path): chips on --accent-fill-soft /
--accent-edge, keeps the menu open on pick; the collapsed trigger
reads 'Model · High' so effort stays visible at rest.
3. Session glass sweep to the launch-composer feel — glass is
blur+tint+radius ONLY, now enforced in-session: dock-prompt ring +
permission/question footer border-top scoped off-glass; composer
focus ring removed; comment chips borderless; dock radius 10px →
var(--radius-lg). Width containment: tool collapsibles, diffs group,
reasoning-part, error-card all share the prose measure
(min(88%, 72ch)) — floating cards on the Brain, never full-width
bands.
Gate: ui 445 / app 473 / typecheck 23 projects / lint 0 errors.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@kateebonner

Copy link
Copy Markdown
ContributorAuthor

Overnight batch 2 — 05fa001d0

All three queued items from the live-tuning session, plus the new ask (session components on the launch-composer feel):

1. Live thought over the constellation ✨

The "+ live thought" half of constellation + live thought is in. As amico works, each real touch flares its constellation node in the thought color (#fff676 dark / #8f8000 light — the brand law holds per scheme): fast rise, ~1.6s ease-out decay, an expanding ring, glints down the node's incident edges, and the touched label ("session.tsx", "amico-vault") named beside the flare.

  • Labels hash deterministically into their category lobe (file work lights the code lobe, skills the skills lobe…), then walk to a visible node — a flare you can't see isn't thought.
  • History replays silently on mount; re-touches refresh their flare instead of stacking; capped at 24 so a torrent stays a shimmer.
  • Reduced motion: the tableau holds one statically lit node — where amico is now.
  • Dev preview without a real turn: window.__amicoBrainTouch({label:"x.ts", type:"resource"}) in the console (the ?-param pattern doesn't survive the router redirect, so this rides the __amicoBrainStats hook pattern instead).
  • +7 tests: flare paint, light-scheme ink, silent replay, refresh-not-stack, decay-to-rest, reduced-motion tableau, and byte-determinism under touches. The latent-web color law tests still pin zero yellow with zero touches.

2. Thinking effort lives in the model menu

The standalone Default/None/High Select is gone (both composer paths). A ModelVariantRow renders inside the paid popover and the unpaid dialog (the dev/free path — it would otherwise have lost the control entirely): chips on --accent-fill-soft/--accent-edge, picking one keeps the menu open. The collapsed trigger now reads "DeepSeek V4 Fl… · High" so effort stays visible at rest.

3. Session glass sweep — the launch-composer feel everywhere

Glass = blur + tint + radius, nothing else, now enforced in-session too:

  • dock-prompt (permission/question card): 1px ring removed, footer border-top removed (one surface, same law as the composer footer), radius 10px → --radius-lg.
  • In-session composer: focus-within ring removed (the caret carries focus; drag keeps its dashed dropzone).
  • Comment chips: borderless dense tint.
  • Width containment: tool collapsibles ("Explored · 2 searches"), the diffs group, reasoning, and error cards all share the prose measure — min(88%, 72ch) — so the thread reads as floating cards over the Brain, never full-width bands.

Verified live in both themes on real sessions (silent replay ✓, live flare mid-session ✓, permission card ✓).

Gate: ui 445 / app 473 / typecheck / lint 0 errors.

kateebonnerand others added 4 commits July 26, 2026 12:38
… session composer = launch dock
Live review with Kate (2026-07-26), three asks:
1. 'I don't see the flares' — thought was landing behind the message
column's glass. The engine now takes an occlusion set (occlude());
session.tsx measures the real layout (timeline column band + composer
dock) and BrainAtmosphere feeds it fresh before every event flush, so
flares land in the GUTTERS where the Brain is actually visible
(fallback: merely-visible beats nothing). While the session works,
the NEWEST flare holds lit as a sustained 'amico is HERE' cursor and
decays out when the turn ends. +3 tests (gutter avoidance, hold/decay,
fully-occluded fallback).
2. Cards hug their contents — tool collapsibles and the diffs group are
width: fit-content up to the prose measure, never a padded-out band.
3. The session composer IS the launch composer — same full-bleed bottom
dock (~35% of the pane, edge-to-edge one-surface glass) via
placement='inline'; starter/typewriter suggestions stay gated to the
EMPTY LANDING (params.id gates on rotation, typing, Tab-accept,
placeholder). Legacy layout keeps the floating column card.
Gate: ui 448 / app 473 / typecheck / lint 0 errors.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ttom-stacked flow + full-width header
Live review with Kate (2026-07-26), second batch:
- Thought-tracking camera v2: rotation eases to a stop while flares are
alive and the view zooms (1.6x) + glides the newest thought to the
CENTER of the frame (Kate's call — replaces the gutter stage). All 6
confirmed findings from the adversarial review workflow fixed:
(1) conPulses is RECENCY-ordered — a re-touch splices to the end, so
the camera + busy-hold follow the re-fired concept, never a stale
array-last pulse; (2) ignite() no longer spins the stopped web back up
mid-dissolve (conRotK frozen during ignite) and the camera fast-eases
home (tau 200ms) before the live layer co-paints; (3) an OS
reduced-motion flip mid-track snaps the camera home instantly;
(4) edges/glints/ring/bloom scale with the zoom — a camera dolly, not
dots inflating over a hairline web; (5) flare seating is computed in
AMBIENT space so the zoomed viewport never funnels subsequent flares
into one slice; (6) the busy-hold is budgeted (~30s) so a wedged
active signal or ?brainForceActive cannot freeze the camera forever.
+2 tests (hold budget, seat-vs-camera split); 452 ui tests green.
- Session header: full-width band, bottom padding tight unless the
entity-chips rail rendered (CSS :has), and the band now lives OUTSIDE
the scroller, pinned at the pane top.
- Messages: rows span the pane — user messages justify RIGHT, amico's
justify LEFT (each card keeps its reading measure); the Brain owns the
middle where the camera stages thought.
- Bottom-stacked flow (messenger law): the SCROLLER's height is
content-driven up to the space the header leaves and anchors to the
bottom, so a short thread sits just above the composer; inside it
scrolling stays classic top-anchored — virtua's geometry is untouched
(an mt-auto-in-viewport variant starved virtua's visible range and
was abandoned). startMargin 0, sticky-accordion offsets updated.
Gate: ui 452 / app 473 / typecheck / lint 0 errors.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Kate 2026-07-26 (component audit): the collapsed 'edit · Failed' chip was
banding across the pane — width: fit-content capped at the prose measure,
matching the width law every timeline card now follows.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…erity
Kate 2026-07-26: glass is blur+tint+radius; the 2px Card accent rail read
as a border on the failed/error cards. content:none on the ::before for
tool-error-card and .error-card — the danger tint, icon, and ink alone
mark severity.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@kateebonner
kateebonner marked this pull request as draft July 26, 2026 23:19
@kateebonner

Copy link
Copy Markdown
ContributorAuthor

Parked 2026-07-26 — converting to draft. Aaron's call: not pursuing this UI direction right now. Everything through 83d070ae4 is on the branch (living-chat glass redesign, thought-tracking camera, bottom-stacked edge-justified flow, effort-in-model-menu, component audit + width law). The branch is the complete archive of the direction if we return to it; the component library artifact documents every surface.

@kateebonner
kateebonner marked this pull request as ready for review July 29, 2026 00:21
@kateebonner
kateebonner marked this pull request as draft July 29, 2026 00:23
@jack-champagne

Copy link
Copy Markdown
Member

@kateebonner — question before this ages further: is anything here still worth keeping?

Asking because ADR 0002, which this implements, is marked superseded on mainline:

Status: Superseded by ADR 0003 (direction parked 2026-07-26; the Brain moved to the context-tree top panel instead of becoming the chat background)

and ADR 0003 (Accepted, 2026-07-27, on Aaron's 2026-07-26 feedback) is explicit:

Supersedes: ADR 0002 (Brain as chat background — direction parked)
… Aaron's feedback reframed what the graph is for: not ambience, but orientationThe graph moves out of the timeline into a pinned top panel … the ambient background direction is parked.

The ADR-0003 replacement has fully landed

All of this is on local/amicode and shipped in v1.17.3-amicode.11:

So the top-panel + first-class vault surface direction is done and released.

What's still unique to this branch

brain-engine.ts and context-tree-engine.ts are already on main — the graph engine itself made it across. What has no counterpart is the presentation layer for the parked direction:

only in #64
glass.css (778 lines), glass-tokens.ts, script/generate-glass.ts
brain-atmosphere.tsx / .css
brain-constellation.ts
brain-perf-governor.test.ts, brain-events.ts, e2e/perf/brain-governor-trace.spec.ts

16 added files, 54 modified, 1 deleted.

Why I'm asking rather than just closing

Two things in there look potentially valuable independent of the parked background direction:

  1. The legibility machineryglass-tokens.ts plus the WCAG-AA-floored tint derivation. ADR 0002 records that the earlier attempt failed exactly one AA check (muted grey on the most translucent tier), so this encodes a real lesson. Worth salvaging if any surface still layers text on translucency — the session header's backdrop-blur comes to mind, given fix(session): header backdrop-blur off while the context-tree band is open #97 just had to switch it off over the context-tree band.
  2. brain-perf-governor + the e2e perf trace — frame-budget governance for the graph. The organic context tree that did land has the same cost profile, so a perf governor may be wanted regardless of where the graph renders.

If neither is worth extracting, this is a clean close — the direction is parked and the replacement is released. If either is, they'd be small standalone PRs rather than resurrecting 71 files.

For context on the state: it is still a draft, CONFLICTING/DIRTY, 72 commits behind mainline, and its checks are all CANCELLED from before #2 fixed the runner labels — so CI has never actually evaluated this branch.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Make the Brain the Chat's living background; float components on legibility-floored Glass

2 participants

@kateebonner@jack-champagne
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Make the Brain the Chat's living background; float components on legibility-floored Glass - #64

Closed
kateebonner wants to merge 34 commits into
local/amicodefrom
amico/issue-56-living-chat
Closed

Make the Brain the Chat's living background; float components on legibility-floored Glass#64
kateebonner wants to merge 34 commits into
local/amicodefrom
amico/issue-56-living-chat

Conversation

@kateebonner

@kateebonnerkateebonner commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Closes#56

Integration branch for the Living Chat redesign, built slice-by-slice from the sub-issue DAG (#59#60#61#62#63; design-of-record: ADR 0002, merged via #58).

Landed:

Final gate on this branch: ui 402 pass / 0 fail · app 464 pass / 0 fail · typecheck 23/23 · lint 0 errors.

Honest pre-gate evidence (headless, dev build — NOT the gate): forced full tempo + 11s continuous scroll of a 144-message thread → dark p95 25.4ms / light 25.2ms, mean ≈16.3ms, 11–15 frames >33ms. The tail misses the 16.7ms budget in that proxy environment (dev-mode Solid, headless vsync, sampler riding the measured loop) — which is exactly what the pre-agreed governor valve is for. The real call happens on the reference laptop (checklist below).

Known follow-up candidates (from #61's browser pass, non-blocking): composer placeholder hint and reasoning-part still composite on standard/bare over the Brain.

🤖 Generated with Claude Code

kateebonnerand others added 19 commits July 25, 2026 02:26
The full-bleed Brain background component, ported from the old
kate/chat-brain-atmosphere branch and retargeted to the native engine on
this branch: suspend()->pause(), refreshTokens()->setTheme(scheme) read
from data-color-scheme, the requestRender font-ready hook degraded to a
resize() repaint, and the old-engine-only setActive/setReducedMotion
dropped (tempo work is slice #62). Environment plumbing carried over
verbatim: ResizeObserver->resize, theme MutationObserver, document
visibility + IntersectionObserver hard-pause, amicode:brain-hover
glances, and the diff-by-id event flush with a silent first restore.
The live feed is the inline strip's event derivation extracted to a
pure, session-scoped deriveBrainEvents(messages, getParts) so it is
unit-testable headless and shared by the mount: touches in message
order via the tool->brain-ref map, a chart after each completed
assistant turn with >=2 commits, replay=true for completed turns,
ids never repeated.
Tests: new brain-events derivation suite (9 cases) pinning the AC-4
contract; brain-engine suite extended with the background-mount driving
case (derived-stream growth, quiet replay-only first flush with nothing
queued, lossless theme swap over a restored atlas).
Part of #56 (ADR 0002 - the Brain becomes the Chat's background).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
One full-bleed BrainAtmosphere per Chat window, mounted as the first
child of the session pane card (now relative isolate) at -z-10: above
the pane's surface fill, below the conversation timeline, landing, and
composer, pointer-events none. Keyed on the active session id so a
titlebar tab swap remounts to that session's atlas with exactly one
engine/render loop alive; empty on the landing. The standalone
new-session draft page gets the same layer (no events - sparse seed).
The inline brain-strip timeline row is deleted: the Brain member is
dropped from the TimelineRow union, forcing out its key branch, the
timelineRows append, the keepMounted special-case, the render case, and
the framed-row exclusion. The working-indicator shimmer (Thinking row)
is untouched, guarded by a new row-model suite; the strip's
click-to-expand is obviated (the engine has no node hit-testing).
Part of #56 (ADR 0002 - the Brain becomes the Chat's background).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Two-tier Glass token system over the Brain background (ADR 0002):
standard (prose/bubbles/composer) and dense (code/diffs/run-plots),
one shared 18px blur, tint carries all contrast. Each tier's alpha is
DERIVED per theme+mode — the least alpha clearing WCAG-AA with a +0.3
safety margin (target 4.8) over that mode's reference frame, read from
the brain engine's own PALETTES (dark: peak-bloom #fff676; light:
#8f8000 — the light brain never paints #fff676). Dense additionally
converges every graphical mark (syntax tokens, diff fills, run-plot
strokes) to within 0.2 of native and holds WCAG 1.4.11's 3:1.
- glass-tokens.ts: WCAG math (ported from the old branch), pure
deriveGlassTiers(tokens, frame) — no blur argument by design —
collectMarks, and the generateGlassCss emitter for every bundled
theme, scoped html[data-theme][data-color-scheme] with a
@supports-not near-opaque fallback (alpha >= 0.95)
- glass.css: committed generated output, registered in styles index;
exposes only [data-glass="standard"|"dense"] surfaces — no component
opts in within this slice, rendered output unchanged
- generate:glass script mirrors generate:tailwind wiring
- brain-engine.ts: export PALETTES (data seam only, no behavior change)
- glass-tokens.test.ts: headless contrast certification for oc-2
light+dark — body/code text floors + margin, mark rule, strict tier
ordering, blur-never-a-term guard, keying purity, fallback floor,
byte-for-byte drift guard, and the muted-grey-rides-dense invariant
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…st cadence) (#62)
One draw-gate honored by both the rAF loop and the manual tick(): full
musical tempo while active / in-flight / unfurling, ~8fps breathing at
rest (REST_FRAME_MS ported from the atmosphere branch engine). touch/
chart/highlight/resize/resume/setTheme beat the throttle via
requestRender so feedback stays immediate. BrainEngineStats gains
active + scale.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Boot is the amico core alone — the vault-skeleton preload, its
force-settle layout, and the demo-trace thought-edges are gone (ADR
0002 rejects the breathing skeleton atlas). The graph grows only from
real touches; two engines share no state (all state closure-local).
The camera is a constant core-centered zoom: no per-frame
fit-to-farthest, no close-up follow, no glance steering — growth
densifies in place. stats().scale exposes the fixed zoom; ambient
ghost picks tolerate an empty edge set.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The cap is the whole graph (core + GRAFT_CAP), not just live-* grafts:
eviction picks the least-recently-touched node — recency stamped by a
monotonic touch counter, not the beat clock (which stalls at rest).
Only the current live node and in-flight pulse endpoints are exempt;
atlas keep / charting / replay grant no immunity, so marathon sessions
can never grow the node set or per-frame draw cost without limit.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…rest (#62)
With prefers-reduced-motion set the engine never breathes at idle: once
the post-event nudge window (NUDGE_MS, rebased onto the frame timebase,
never performance.now()) elapses with nothing in flight, ticks draw
nothing and the rAF chain ends — a touch/chart/highlight/resume re-arms
one bounded burst. This is the accessibility terminal (ADR 0002),
independent of slice #63's frame-time ease. pause() clears any
scheduled frame; the lifecycle suite now pins zero-draws-while-hidden.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…#62)
Re-add the `active` output that #59's createBrainEvents dropped:
deriveBrainActive (pure, headless-tested — non-idle means busy or
retrying) feeds a memo that session.tsx passes to <BrainAtmosphere
active>, which plumbs it to engine.setActive. The draft page keeps the
default at-rest Brain (no session, no busy signal). Test helpers
(drive/clears) consolidated at file scope.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Everything floats over the mounted Brain (ADR 0002): the seven content
archetypes opt into slice #60's tier tokens — STANDARD on the user
bubble, assistant prose (which gains its first card), and the composer;
DENSE on code blocks, diffs, run-plots/run-windows, and tool cards (the
tool-collapsible root, so trigger + expanded output float as one unit
across single tools and context/shell groups). The tier token owns
fill/edge/radius/shadow everywhere — the opaque --surface-base bubble
fill, the composer's layer-01 fill + raised shadow, and the dock band's
background-stronger tiling are gone, so the Brain stays live in the
gaps (session-turn row frames and column wrappers stay transparent).
Muted/secondary ink never composites against the ultra-transparent
standard tint (certified to fail AA by #60): the prose meta, user-
message meta, composer footer controls, prose blockquotes, the child-
session stub, and the bubble's file/agent highlights all ride dense-
backed inline zones styled with --glass-dense-bg — the #60 token, no
new tint/blur literal anywhere. Shiki's inlined theme surface defers
to the dense card; the diff card's sticky header occludes with the
dense token instead of opaque chrome. The ghost-collapsible reset is
scoped :not([data-glass]) so the tier fill survives specificity.
Tests extend #60's certified surface onto the components:
- glass-float.test.ts (ui): the 7-archetype tier map as a table test —
body→standard ≥4.8 (AA + margin), code/diff→dense ≥4.5, marks→dense
≥3:1 (1.4.11) without native drift, muted-role never on standard —
measured with #60's exported validator math over the running-brain
reference frame in both oc-2 modes; plus source contracts (tier
attributes on the real markup, no ad-hoc literals in the restyled
card rules, repo-wide data-glass allowlist: two tier values only,
never on Rail/titlebar/Panels chrome).
- glass-float.test.ts (app): composer/diff/child-stub tier contracts,
gaps-stay-live (no glass, no fill on session-turn + containers), and
the sticky session-title header's pre-existing chrome blur untouched.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The sparse-seed boot (#62) removed the last importer; the latent skeleton
atlas was the superseded design's raw material (flagged by the #62 engineer,
removed at integration).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ver blur (#63)
A frame-time state machine observing the ONE Brain render loop: rolling-p95
over the 16.7ms budget for a sustained ~2s window steps motion down the
tempo ladder (allegro -> andante -> largo) with eased paint-cadence caps,
then to a motion full-stop, then terminally hard-pauses the canvas to a
static blurred field. Dual-guard hysteresis (13ms restore threshold + a ~2x
clear window, one level per window) prevents oscillation; the sample window
resets on every step so a stale regime never cascades an unearned step.
Measurement pauses with the engine (hidden / off-screen / reduced-motion):
stalled gaps are discarded, never fed as phantom over-budget frames. The
governor is independent of the reduced-motion accessibility terminal (#62)
and is bypassed entirely under it. Its only levers are tempo and the
terminal pause — no path writes a glass token, a style, or any CSS; stats()
now emits the discrete motion level. governed:false (the dev
force-full-tempo hook's engine seam) disables it for un-eased worst-case
perf capture.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…isables the governor (#63)
Ported from the old branch's perf-capture hook and extended per the issue:
the param now ALSO disables the perf governor (governed:false), so a gated
run — headless proxy or the reference laptop — measures the un-eased worst
case. DEV-gated, inert in prod. Also DEV-only window.__amicoBrainStats for
the trace harness and the manual gate checklist to read engine stats live.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…h themes (#63)
Playwright spec over the real app on the e2e mock-server harness: boots the
144-message fixture thread with the dev force-full-tempo hook (Brain pinned
busy, governor disabled — the un-eased worst case), scrolls continuously
for >=11s per theme inside the SAME rAF loop that samples frame intervals,
and emits a p95 / max / frames>33ms report per theme.
Labeled and asserted as the PRE-GATE PROXY only: the spec pins that the
harness runs and reports (shape, duration, theme coverage, forced state) —
it asserts NO numeric frame-time outcome. The release gate stays the manual
sign-off on the pinned reference laptop (issue #63, HITL).
Run: cd packages/app && bunx playwright test e2e/perf/brain-governor-trace.spec.ts
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…re-emptively eases (#63)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@kateebonner

Copy link
Copy Markdown
ContributorAuthor

HITL sign-off checklist — reference-laptop 60fps gate (#63)

The one open acceptance criterion on this PR. Run on the reference laptop, battery-powered:

  • Pin the machine: model, OS, battery %, VS Code + webview (Chromium) version — write them here.
  • Launch the dev lane: opencode serve --port 4099 + bun --cwd packages/app dev --port 5990 with VITE_OPENCODE_SERVER_PORT=4099 (the force hook is DEV-gated by design).
  • Open the Chat in the VS Code webview on a real thread of ≥40 cards with ?brainForceActive appended; verify in devtools: window.__amicoBrainStats()active: true, motion: "full".
  • Record a ≥10s continuous scroll (devtools Performance panel, or the rAF sampler in Add the perf governor (ease motion, never blur) and gate 60fps on the reference laptop #63's notes ~600 frames).
  • Pass = p95 ≤ 16.7ms AND zero frames > 33ms. Repeat in both themes (flip the chat scheme mid-session — Brain/Glass re-key losslessly).
  • Write the numbers here and sign off.

If the gate fails: remove ?brainForceActive and confirm the governor engages under load — watch __amicoBrainStats().motion step eased-1 → eased-2 → full-stop → hard-paused with the frosted look intact — then decide accept-with-valve vs iterate. (Headless dev-proxy already suggests the tail will need the valve; see PR body.)

🤖 Generated with Claude Code

@kateebonner
kateebonner marked this pull request as ready for review July 25, 2026 16:28
kateebonnerand others added 8 commits July 25, 2026 16:30
…sed question dock
Live design-review iteration with Kate (2026-07-25) on the Living Chat:
- Glass is ONE recipe everywhere: blur 8px + per-mode tint (dark: 4% white
frost + backdrop brightness(0.4); light: 5% near-white). The dark tint's
direction flips to a frost veil (lighter than ground, classic glass) with
the brightness term modeled honestly in the contrast derivation.
- The marks law (WCAG 1.4.11 dense certification) is WAIVED by design
decision; dense==standard. Muted ink is recorded as not-certified.
Tests rewritten to record the waiver rather than certify the old law.
- Cards no longer span the thread: prose fit-content ≤ min(88%,72ch),
user bubbles ≤ min(82%,64ch), tool cards ≤ 92%.
- The question dock floats on glass (8th archetype); its muted hint and
answers summary ride dense-backed zones; opaque fill scoped to
:not([data-glass]).
Part of #56 (PR #64); supersedes the #60/#61 tier law per Kate's call.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…cipe
Receipt chip, ask card (+options), run window (hover regression fixed),
inline entity card, entity rail chips, widget-preview shell, entity-view
inner atoms (tier/skeleton/formula/badge/seq/status pills), and the classic
in-chat landing (one standard card; starter buttons on dense-zone fills,
accent-edge instead of a yellow border on light). Semantic error state is a
danger tint over the glass, never an opaque surface. No !important fills.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Permission dock joins the question dock on the unified glass card (dock-prompt
generalized across kinds, permission footer flattened the same way); todo /
followup / revert trays carry the standard hook (opaque tray fill loses to
glass.css by import order); todo scroll-fade rides the glass tint; question
option tiles become dense-zone fills with the accent-soft hover, never an
opaque layer.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Opaque bands inside glassed cards defer to the dense-zone token (edit/write/
apply-patch sticky triggers, accordion header+expanded body inside any glassed
card, StickyAccordionHeader, timeline diff expanded view); the task/subagent
card is a dense zone with the accent-soft hover; diagnostics become a critical
tint over the frost; error/retry/assistant-error cards ride glass with a danger
tint; bare-muted-ink rows get their #60 backing (thinking indicator, reasoning
part, tool-loaded-file rows, turn divider label, comment-strip chips); user
attachment chips carry the dense hook; jump-to-bottom converts its hand-rolled
near-glass to the single recipe; the sticky session-title band converts its
chrome gradient/blur literals to the glass vars; inline-code chips ride the
dense token.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…cipe
Dialogs (one dialog.css edit covers delete-session/entity/fork/MCP/file/model/
unpaid/usage-exceeded launch sites), ImagePreview lightbox, popovers, dropdown
menus, shared Select menus, slash/@ autocomplete, project picker, model
selector, toast v2 — all ride the glass vars (tint + shared blur/brightness +
edge) with the legacy token as no-theme fallback; item highlights move to the
accent-soft state fill. Tooltips, the markdown code-fence copy tooltip and the
legacy toast keep their deliberate INVERSE ink on a HEAVIER glass (denser
float-token tint + shared blur/edge, never a raw opaque token); the copy
button itself rides the dense token. Drag overlay and the legacy composer
clip-mask stay heavier by function (masking), now token-mix + blur; composer
attachment tiles/pills and the theme-blind bg-black/50 name bar move to token
tints; legacy composer path gets the standard hook; composer loading stub and
review-tab header/diff surfaces convert to the glass tokens; classic landing
metadata gets a dense-zone chip.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ll audit
ui: allowlist covers every swept file (+ pre-allowed entries for the parallel
draft-landing rebuild: pages/new-session.tsx, session-new-design-view, and the
work-order's pages/session/new-session.tsx alias); new assertions pin the
AMICO family hooks + no-opaque-layer fills, dock unification across kinds,
question-option dense tiles, no-opaque-band-inside-glass (sticky triggers,
accordion, task card, diagnostics tint, diff view, inline code), muted-ink
backings, floating-chrome recipes (dialog/popover/menu/select/toast-v2/
ImagePreview), heavier inverse glass for tooltip/toast/copy-tooltip, review
surfaces, and error-tint-over-glass replacing the old no-glass error ruling.
app: sticky title band asserted on the glass vars (chrome literals banned),
timeline data-glass census, dock/composer chrome coverage, drag-overlay and
legacy clip-mask pinned as heavier-by-function token mixes.
These fail if any fix is reverted.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…st Brain
The empty landing shows the full latent network ("everything amico could
think") as a clustered ellipsoid cloud rotating in 3D, projected inside the
existing canvas engine (new constellation mode; reuses the rAF loop, governor,
pause/resume, theme re-key, reduced-motion). Curated core + seeded procedural
densification → identical constellation every launch. Dim monochrome + whisper
cluster tints, ZERO #fff676 (yellow stays exclusive to live thought). Twinkle +
breath micro-motion; static ¾ tableau under reduced-motion. First prompt →
ignition dissolve → live session graph. Removes the opaque new-session hero
wrapper that was occluding the Brain entirely, and glasses the draft-landing
chips + metadata. DEV knobs: ?constellationSpeed/Density/Tint/Fog.
Design of record: grilled with Kate 2026-07-25 (landing-only; clustered cloud;
canvas projection; mono+cluster-tint; ignition dissolve; twinkle+breath; static
tableau; uniform full-bleed). Part of #56 (PR #64).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
kateebonnerand others added 2 commits July 25, 2026 17:16
# Conflicts:
#	packages/app/src/components/session/session-new-view.tsx
#	packages/ui/src/amicode/getting-started.tsx
…k composer, typewriter placeholder, 3D constellation in-session
Live design-review iteration with Kate (2026-07-25) on the Living Chat:
Glass
- Max transparency: dark tint derives to fully transparent (backdrop
brightness 0.4 -> 0.8; less darkening lets the constellation read through).
AA retained for LIGHT, waived-and-recorded for DARK standard (the landing
constellation is yellow-free, so it reads there). Tests record the trade.
- The glass tier is now JUST blur + tint + radius — no border outline, no top
sheen/inset line, no box-shadow (Kate: "no border, no top line, no shadow").
Composer
- One background: dock-surface shell/tray opaque fills scoped to :not([data-glass])
so the glass wins as one uniform surface; footer inset fill removed (was a
visible second background).
- Full-bleed bottom dock: full width, stuck to the bottom, ~35% viewport height
(ui-ux-pro-max: primary CTA without eclipsing the hero), edge-to-edge (radius/
border/shadow zeroed). Fixed the flex height-chain so it fills to the bottom.
- Removed the model-provider H-mark/AMICODE wordmark and the project/folder
picker from the landing.
Landing
- Starter chip wall removed (competed with the constellation + composer).
Discovery now lives in the composer as a rotating TYPEWRITER placeholder that
types out the real starter prompts letter-by-letter with a blinking caret;
freezes on focus (Tab accepts the shown one), static under reduced motion.
- Constellation contrast bumped (edge alpha 0.10 -> 0.17, nodes x1.4).
Session parity
- The 3D constellation is now the background EVERYWHERE (session too), not the
sparse 2D live graph — the launch and session are one surface. (Live-thought
node pulsing is the next layer.)
Gates: ui 438 / app 473 / typecheck 23/23 / lint 0 errors. Part of #56 (PR #64).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@kateebonner

Copy link
Copy Markdown
ContributorAuthor

Live design-tuning batch (Kate, 2026-07-25) — commit 69ebf7e

The design evolved significantly beyond the original slices through a live review session. Landed:

  • Glass — now purely blur + tint + radius: dark derives to fully transparent (brightness 0.8), no border, no top sheen, no box-shadow. AA kept for light, waived+recorded for dark standard (the landing constellation is yellow-free).
  • Composer — one uniform glass surface (two-tone fixed); full-bleed bottom dock, ~35% viewport height, edge-to-edge; wordmark + project/folder picker removed.
  • Landing — starter-chip wall removed; discovery moved into the composer as a rotating typewriter placeholder (types the real starters letter-by-letter, blinking caret, Tab-to-accept, reduced-motion static). Constellation contrast bumped.
  • Session parity — the 3D constellation is now the background in-session too (not the sparse 2D graph); launch + session are one surface.

Queued (next): live-thought node pulsing over the constellation (data-true layer), card width containment, and folding the effort/variant selector into the model dropdown.

Gates: ui 438 / app 473 / typecheck 23/23 / lint 0 errors.

🤖 Generated with Claude Code

…lass sweep
Overnight batch 2 (Kate 2026-07-25), three asks:
1. Live thought over the constellation — the '+ live thought' half of
'constellation + live thought': real session touches flare their node
in css.thought (#fff676 dark / #8f8000 light) over the latent web —
rise 150ms, ease-out decay ~1.6s, expanding ring, incident-edge
glints, touched label beside the flare (fg ink + halo). Labels hash
deterministically into their category lobe with a visible-node walk
(a flare the user can't see isn't thought). Replays restore silently;
re-touches refresh instead of stacking; capped at 24; reduced motion
holds ONE statically lit node. Dev hook window.__amicoBrainTouch
(mirrors __amicoBrainStats) previews flares without a real turn.
+7 tests incl. byte-determinism under touches and the color-law
boundary (latent web ink stays yellow-free with zero touches).
2. Thinking effort folded INTO the model surface — the standalone
Default/None/High footer Select is gone (both composer paths). New
ModelVariantRow renders in the paid ModelSelectorPopover AND the
unpaid dialog (Kate's dev path): chips on --accent-fill-soft /
--accent-edge, keeps the menu open on pick; the collapsed trigger
reads 'Model · High' so effort stays visible at rest.
3. Session glass sweep to the launch-composer feel — glass is
blur+tint+radius ONLY, now enforced in-session: dock-prompt ring +
permission/question footer border-top scoped off-glass; composer
focus ring removed; comment chips borderless; dock radius 10px →
var(--radius-lg). Width containment: tool collapsibles, diffs group,
reasoning-part, error-card all share the prose measure
(min(88%, 72ch)) — floating cards on the Brain, never full-width
bands.
Gate: ui 445 / app 473 / typecheck 23 projects / lint 0 errors.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@kateebonner

Copy link
Copy Markdown
ContributorAuthor

Overnight batch 2 — 05fa001d0

All three queued items from the live-tuning session, plus the new ask (session components on the launch-composer feel):

1. Live thought over the constellation ✨

The "+ live thought" half of constellation + live thought is in. As amico works, each real touch flares its constellation node in the thought color (#fff676 dark / #8f8000 light — the brand law holds per scheme): fast rise, ~1.6s ease-out decay, an expanding ring, glints down the node's incident edges, and the touched label ("session.tsx", "amico-vault") named beside the flare.

  • Labels hash deterministically into their category lobe (file work lights the code lobe, skills the skills lobe…), then walk to a visible node — a flare you can't see isn't thought.
  • History replays silently on mount; re-touches refresh their flare instead of stacking; capped at 24 so a torrent stays a shimmer.
  • Reduced motion: the tableau holds one statically lit node — where amico is now.
  • Dev preview without a real turn: window.__amicoBrainTouch({label:"x.ts", type:"resource"}) in the console (the ?-param pattern doesn't survive the router redirect, so this rides the __amicoBrainStats hook pattern instead).
  • +7 tests: flare paint, light-scheme ink, silent replay, refresh-not-stack, decay-to-rest, reduced-motion tableau, and byte-determinism under touches. The latent-web color law tests still pin zero yellow with zero touches.

2. Thinking effort lives in the model menu

The standalone Default/None/High Select is gone (both composer paths). A ModelVariantRow renders inside the paid popover and the unpaid dialog (the dev/free path — it would otherwise have lost the control entirely): chips on --accent-fill-soft/--accent-edge, picking one keeps the menu open. The collapsed trigger now reads "DeepSeek V4 Fl… · High" so effort stays visible at rest.

3. Session glass sweep — the launch-composer feel everywhere

Glass = blur + tint + radius, nothing else, now enforced in-session too:

  • dock-prompt (permission/question card): 1px ring removed, footer border-top removed (one surface, same law as the composer footer), radius 10px → --radius-lg.
  • In-session composer: focus-within ring removed (the caret carries focus; drag keeps its dashed dropzone).
  • Comment chips: borderless dense tint.
  • Width containment: tool collapsibles ("Explored · 2 searches"), the diffs group, reasoning, and error cards all share the prose measure — min(88%, 72ch) — so the thread reads as floating cards over the Brain, never full-width bands.

Verified live in both themes on real sessions (silent replay ✓, live flare mid-session ✓, permission card ✓).

Gate: ui 445 / app 473 / typecheck / lint 0 errors.

kateebonnerand others added 4 commits July 26, 2026 12:38
… session composer = launch dock
Live review with Kate (2026-07-26), three asks:
1. 'I don't see the flares' — thought was landing behind the message
column's glass. The engine now takes an occlusion set (occlude());
session.tsx measures the real layout (timeline column band + composer
dock) and BrainAtmosphere feeds it fresh before every event flush, so
flares land in the GUTTERS where the Brain is actually visible
(fallback: merely-visible beats nothing). While the session works,
the NEWEST flare holds lit as a sustained 'amico is HERE' cursor and
decays out when the turn ends. +3 tests (gutter avoidance, hold/decay,
fully-occluded fallback).
2. Cards hug their contents — tool collapsibles and the diffs group are
width: fit-content up to the prose measure, never a padded-out band.
3. The session composer IS the launch composer — same full-bleed bottom
dock (~35% of the pane, edge-to-edge one-surface glass) via
placement='inline'; starter/typewriter suggestions stay gated to the
EMPTY LANDING (params.id gates on rotation, typing, Tab-accept,
placeholder). Legacy layout keeps the floating column card.
Gate: ui 448 / app 473 / typecheck / lint 0 errors.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ttom-stacked flow + full-width header
Live review with Kate (2026-07-26), second batch:
- Thought-tracking camera v2: rotation eases to a stop while flares are
alive and the view zooms (1.6x) + glides the newest thought to the
CENTER of the frame (Kate's call — replaces the gutter stage). All 6
confirmed findings from the adversarial review workflow fixed:
(1) conPulses is RECENCY-ordered — a re-touch splices to the end, so
the camera + busy-hold follow the re-fired concept, never a stale
array-last pulse; (2) ignite() no longer spins the stopped web back up
mid-dissolve (conRotK frozen during ignite) and the camera fast-eases
home (tau 200ms) before the live layer co-paints; (3) an OS
reduced-motion flip mid-track snaps the camera home instantly;
(4) edges/glints/ring/bloom scale with the zoom — a camera dolly, not
dots inflating over a hairline web; (5) flare seating is computed in
AMBIENT space so the zoomed viewport never funnels subsequent flares
into one slice; (6) the busy-hold is budgeted (~30s) so a wedged
active signal or ?brainForceActive cannot freeze the camera forever.
+2 tests (hold budget, seat-vs-camera split); 452 ui tests green.
- Session header: full-width band, bottom padding tight unless the
entity-chips rail rendered (CSS :has), and the band now lives OUTSIDE
the scroller, pinned at the pane top.
- Messages: rows span the pane — user messages justify RIGHT, amico's
justify LEFT (each card keeps its reading measure); the Brain owns the
middle where the camera stages thought.
- Bottom-stacked flow (messenger law): the SCROLLER's height is
content-driven up to the space the header leaves and anchors to the
bottom, so a short thread sits just above the composer; inside it
scrolling stays classic top-anchored — virtua's geometry is untouched
(an mt-auto-in-viewport variant starved virtua's visible range and
was abandoned). startMargin 0, sticky-accordion offsets updated.
Gate: ui 452 / app 473 / typecheck / lint 0 errors.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Kate 2026-07-26 (component audit): the collapsed 'edit · Failed' chip was
banding across the pane — width: fit-content capped at the prose measure,
matching the width law every timeline card now follows.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…erity
Kate 2026-07-26: glass is blur+tint+radius; the 2px Card accent rail read
as a border on the failed/error cards. content:none on the ::before for
tool-error-card and .error-card — the danger tint, icon, and ink alone
mark severity.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@kateebonner
kateebonner marked this pull request as draft July 26, 2026 23:19
@kateebonner

Copy link
Copy Markdown
ContributorAuthor

Parked 2026-07-26 — converting to draft. Aaron's call: not pursuing this UI direction right now. Everything through 83d070ae4 is on the branch (living-chat glass redesign, thought-tracking camera, bottom-stacked edge-justified flow, effort-in-model-menu, component audit + width law). The branch is the complete archive of the direction if we return to it; the component library artifact documents every surface.

@kateebonner
kateebonner marked this pull request as ready for review July 29, 2026 00:21
@kateebonner
kateebonner marked this pull request as draft July 29, 2026 00:23
@jack-champagne

Copy link
Copy Markdown
Member

@kateebonner — question before this ages further: is anything here still worth keeping?

Asking because ADR 0002, which this implements, is marked superseded on mainline:

Status: Superseded by ADR 0003 (direction parked 2026-07-26; the Brain moved to the context-tree top panel instead of becoming the chat background)

and ADR 0003 (Accepted, 2026-07-27, on Aaron's 2026-07-26 feedback) is explicit:

Supersedes: ADR 0002 (Brain as chat background — direction parked)
… Aaron's feedback reframed what the graph is for: not ambience, but orientationThe graph moves out of the timeline into a pinned top panel … the ambient background direction is parked.

The ADR-0003 replacement has fully landed

All of this is on local/amicode and shipped in v1.17.3-amicode.11:

So the top-panel + first-class vault surface direction is done and released.

What's still unique to this branch

brain-engine.ts and context-tree-engine.ts are already on main — the graph engine itself made it across. What has no counterpart is the presentation layer for the parked direction:

only in #64
glass.css (778 lines), glass-tokens.ts, script/generate-glass.ts
brain-atmosphere.tsx / .css
brain-constellation.ts
brain-perf-governor.test.ts, brain-events.ts, e2e/perf/brain-governor-trace.spec.ts

16 added files, 54 modified, 1 deleted.

Why I'm asking rather than just closing

Two things in there look potentially valuable independent of the parked background direction:

  1. The legibility machineryglass-tokens.ts plus the WCAG-AA-floored tint derivation. ADR 0002 records that the earlier attempt failed exactly one AA check (muted grey on the most translucent tier), so this encodes a real lesson. Worth salvaging if any surface still layers text on translucency — the session header's backdrop-blur comes to mind, given fix(session): header backdrop-blur off while the context-tree band is open #97 just had to switch it off over the context-tree band.
  2. brain-perf-governor + the e2e perf trace — frame-budget governance for the graph. The organic context tree that did land has the same cost profile, so a perf governor may be wanted regardless of where the graph renders.

If neither is worth extracting, this is a clean close — the direction is parked and the replacement is released. If either is, they'd be small standalone PRs rather than resurrecting 71 files.

For context on the state: it is still a draft, CONFLICTING/DIRTY, 72 commits behind mainline, and its checks are all CANCELLED from before #2 fixed the runner labels — so CI has never actually evaluated this branch.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Make the Brain the Chat's living background; float components on legibility-floored Glass

2 participants

@kateebonner@jack-champagne
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Make the Brain the Chat's living background; float components on legibility-floored Glass - #64

Closed
kateebonner wants to merge 34 commits into
local/amicodefrom
amico/issue-56-living-chat
Closed

Make the Brain the Chat's living background; float components on legibility-floored Glass#64
kateebonner wants to merge 34 commits into
local/amicodefrom
amico/issue-56-living-chat

Conversation

@kateebonner

@kateebonnerkateebonner commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Closes#56

Integration branch for the Living Chat redesign, built slice-by-slice from the sub-issue DAG (#59#60#61#62#63; design-of-record: ADR 0002, merged via #58).

Landed:

Final gate on this branch: ui 402 pass / 0 fail · app 464 pass / 0 fail · typecheck 23/23 · lint 0 errors.

Honest pre-gate evidence (headless, dev build — NOT the gate): forced full tempo + 11s continuous scroll of a 144-message thread → dark p95 25.4ms / light 25.2ms, mean ≈16.3ms, 11–15 frames >33ms. The tail misses the 16.7ms budget in that proxy environment (dev-mode Solid, headless vsync, sampler riding the measured loop) — which is exactly what the pre-agreed governor valve is for. The real call happens on the reference laptop (checklist below).

Known follow-up candidates (from #61's browser pass, non-blocking): composer placeholder hint and reasoning-part still composite on standard/bare over the Brain.

🤖 Generated with Claude Code

kateebonnerand others added 19 commits July 25, 2026 02:26
The full-bleed Brain background component, ported from the old
kate/chat-brain-atmosphere branch and retargeted to the native engine on
this branch: suspend()->pause(), refreshTokens()->setTheme(scheme) read
from data-color-scheme, the requestRender font-ready hook degraded to a
resize() repaint, and the old-engine-only setActive/setReducedMotion
dropped (tempo work is slice #62). Environment plumbing carried over
verbatim: ResizeObserver->resize, theme MutationObserver, document
visibility + IntersectionObserver hard-pause, amicode:brain-hover
glances, and the diff-by-id event flush with a silent first restore.
The live feed is the inline strip's event derivation extracted to a
pure, session-scoped deriveBrainEvents(messages, getParts) so it is
unit-testable headless and shared by the mount: touches in message
order via the tool->brain-ref map, a chart after each completed
assistant turn with >=2 commits, replay=true for completed turns,
ids never repeated.
Tests: new brain-events derivation suite (9 cases) pinning the AC-4
contract; brain-engine suite extended with the background-mount driving
case (derived-stream growth, quiet replay-only first flush with nothing
queued, lossless theme swap over a restored atlas).
Part of #56 (ADR 0002 - the Brain becomes the Chat's background).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
One full-bleed BrainAtmosphere per Chat window, mounted as the first
child of the session pane card (now relative isolate) at -z-10: above
the pane's surface fill, below the conversation timeline, landing, and
composer, pointer-events none. Keyed on the active session id so a
titlebar tab swap remounts to that session's atlas with exactly one
engine/render loop alive; empty on the landing. The standalone
new-session draft page gets the same layer (no events - sparse seed).
The inline brain-strip timeline row is deleted: the Brain member is
dropped from the TimelineRow union, forcing out its key branch, the
timelineRows append, the keepMounted special-case, the render case, and
the framed-row exclusion. The working-indicator shimmer (Thinking row)
is untouched, guarded by a new row-model suite; the strip's
click-to-expand is obviated (the engine has no node hit-testing).
Part of #56 (ADR 0002 - the Brain becomes the Chat's background).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Two-tier Glass token system over the Brain background (ADR 0002):
standard (prose/bubbles/composer) and dense (code/diffs/run-plots),
one shared 18px blur, tint carries all contrast. Each tier's alpha is
DERIVED per theme+mode — the least alpha clearing WCAG-AA with a +0.3
safety margin (target 4.8) over that mode's reference frame, read from
the brain engine's own PALETTES (dark: peak-bloom #fff676; light:
#8f8000 — the light brain never paints #fff676). Dense additionally
converges every graphical mark (syntax tokens, diff fills, run-plot
strokes) to within 0.2 of native and holds WCAG 1.4.11's 3:1.
- glass-tokens.ts: WCAG math (ported from the old branch), pure
deriveGlassTiers(tokens, frame) — no blur argument by design —
collectMarks, and the generateGlassCss emitter for every bundled
theme, scoped html[data-theme][data-color-scheme] with a
@supports-not near-opaque fallback (alpha >= 0.95)
- glass.css: committed generated output, registered in styles index;
exposes only [data-glass="standard"|"dense"] surfaces — no component
opts in within this slice, rendered output unchanged
- generate:glass script mirrors generate:tailwind wiring
- brain-engine.ts: export PALETTES (data seam only, no behavior change)
- glass-tokens.test.ts: headless contrast certification for oc-2
light+dark — body/code text floors + margin, mark rule, strict tier
ordering, blur-never-a-term guard, keying purity, fallback floor,
byte-for-byte drift guard, and the muted-grey-rides-dense invariant
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…st cadence) (#62)
One draw-gate honored by both the rAF loop and the manual tick(): full
musical tempo while active / in-flight / unfurling, ~8fps breathing at
rest (REST_FRAME_MS ported from the atmosphere branch engine). touch/
chart/highlight/resize/resume/setTheme beat the throttle via
requestRender so feedback stays immediate. BrainEngineStats gains
active + scale.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Boot is the amico core alone — the vault-skeleton preload, its
force-settle layout, and the demo-trace thought-edges are gone (ADR
0002 rejects the breathing skeleton atlas). The graph grows only from
real touches; two engines share no state (all state closure-local).
The camera is a constant core-centered zoom: no per-frame
fit-to-farthest, no close-up follow, no glance steering — growth
densifies in place. stats().scale exposes the fixed zoom; ambient
ghost picks tolerate an empty edge set.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The cap is the whole graph (core + GRAFT_CAP), not just live-* grafts:
eviction picks the least-recently-touched node — recency stamped by a
monotonic touch counter, not the beat clock (which stalls at rest).
Only the current live node and in-flight pulse endpoints are exempt;
atlas keep / charting / replay grant no immunity, so marathon sessions
can never grow the node set or per-frame draw cost without limit.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…rest (#62)
With prefers-reduced-motion set the engine never breathes at idle: once
the post-event nudge window (NUDGE_MS, rebased onto the frame timebase,
never performance.now()) elapses with nothing in flight, ticks draw
nothing and the rAF chain ends — a touch/chart/highlight/resume re-arms
one bounded burst. This is the accessibility terminal (ADR 0002),
independent of slice #63's frame-time ease. pause() clears any
scheduled frame; the lifecycle suite now pins zero-draws-while-hidden.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…#62)
Re-add the `active` output that #59's createBrainEvents dropped:
deriveBrainActive (pure, headless-tested — non-idle means busy or
retrying) feeds a memo that session.tsx passes to <BrainAtmosphere
active>, which plumbs it to engine.setActive. The draft page keeps the
default at-rest Brain (no session, no busy signal). Test helpers
(drive/clears) consolidated at file scope.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Everything floats over the mounted Brain (ADR 0002): the seven content
archetypes opt into slice #60's tier tokens — STANDARD on the user
bubble, assistant prose (which gains its first card), and the composer;
DENSE on code blocks, diffs, run-plots/run-windows, and tool cards (the
tool-collapsible root, so trigger + expanded output float as one unit
across single tools and context/shell groups). The tier token owns
fill/edge/radius/shadow everywhere — the opaque --surface-base bubble
fill, the composer's layer-01 fill + raised shadow, and the dock band's
background-stronger tiling are gone, so the Brain stays live in the
gaps (session-turn row frames and column wrappers stay transparent).
Muted/secondary ink never composites against the ultra-transparent
standard tint (certified to fail AA by #60): the prose meta, user-
message meta, composer footer controls, prose blockquotes, the child-
session stub, and the bubble's file/agent highlights all ride dense-
backed inline zones styled with --glass-dense-bg — the #60 token, no
new tint/blur literal anywhere. Shiki's inlined theme surface defers
to the dense card; the diff card's sticky header occludes with the
dense token instead of opaque chrome. The ghost-collapsible reset is
scoped :not([data-glass]) so the tier fill survives specificity.
Tests extend #60's certified surface onto the components:
- glass-float.test.ts (ui): the 7-archetype tier map as a table test —
body→standard ≥4.8 (AA + margin), code/diff→dense ≥4.5, marks→dense
≥3:1 (1.4.11) without native drift, muted-role never on standard —
measured with #60's exported validator math over the running-brain
reference frame in both oc-2 modes; plus source contracts (tier
attributes on the real markup, no ad-hoc literals in the restyled
card rules, repo-wide data-glass allowlist: two tier values only,
never on Rail/titlebar/Panels chrome).
- glass-float.test.ts (app): composer/diff/child-stub tier contracts,
gaps-stay-live (no glass, no fill on session-turn + containers), and
the sticky session-title header's pre-existing chrome blur untouched.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The sparse-seed boot (#62) removed the last importer; the latent skeleton
atlas was the superseded design's raw material (flagged by the #62 engineer,
removed at integration).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ver blur (#63)
A frame-time state machine observing the ONE Brain render loop: rolling-p95
over the 16.7ms budget for a sustained ~2s window steps motion down the
tempo ladder (allegro -> andante -> largo) with eased paint-cadence caps,
then to a motion full-stop, then terminally hard-pauses the canvas to a
static blurred field. Dual-guard hysteresis (13ms restore threshold + a ~2x
clear window, one level per window) prevents oscillation; the sample window
resets on every step so a stale regime never cascades an unearned step.
Measurement pauses with the engine (hidden / off-screen / reduced-motion):
stalled gaps are discarded, never fed as phantom over-budget frames. The
governor is independent of the reduced-motion accessibility terminal (#62)
and is bypassed entirely under it. Its only levers are tempo and the
terminal pause — no path writes a glass token, a style, or any CSS; stats()
now emits the discrete motion level. governed:false (the dev
force-full-tempo hook's engine seam) disables it for un-eased worst-case
perf capture.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…isables the governor (#63)
Ported from the old branch's perf-capture hook and extended per the issue:
the param now ALSO disables the perf governor (governed:false), so a gated
run — headless proxy or the reference laptop — measures the un-eased worst
case. DEV-gated, inert in prod. Also DEV-only window.__amicoBrainStats for
the trace harness and the manual gate checklist to read engine stats live.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…h themes (#63)
Playwright spec over the real app on the e2e mock-server harness: boots the
144-message fixture thread with the dev force-full-tempo hook (Brain pinned
busy, governor disabled — the un-eased worst case), scrolls continuously
for >=11s per theme inside the SAME rAF loop that samples frame intervals,
and emits a p95 / max / frames>33ms report per theme.
Labeled and asserted as the PRE-GATE PROXY only: the spec pins that the
harness runs and reports (shape, duration, theme coverage, forced state) —
it asserts NO numeric frame-time outcome. The release gate stays the manual
sign-off on the pinned reference laptop (issue #63, HITL).
Run: cd packages/app && bunx playwright test e2e/perf/brain-governor-trace.spec.ts
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…re-emptively eases (#63)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@kateebonner

Copy link
Copy Markdown
ContributorAuthor

HITL sign-off checklist — reference-laptop 60fps gate (#63)

The one open acceptance criterion on this PR. Run on the reference laptop, battery-powered:

  • Pin the machine: model, OS, battery %, VS Code + webview (Chromium) version — write them here.
  • Launch the dev lane: opencode serve --port 4099 + bun --cwd packages/app dev --port 5990 with VITE_OPENCODE_SERVER_PORT=4099 (the force hook is DEV-gated by design).
  • Open the Chat in the VS Code webview on a real thread of ≥40 cards with ?brainForceActive appended; verify in devtools: window.__amicoBrainStats()active: true, motion: "full".
  • Record a ≥10s continuous scroll (devtools Performance panel, or the rAF sampler in Add the perf governor (ease motion, never blur) and gate 60fps on the reference laptop #63's notes ~600 frames).
  • Pass = p95 ≤ 16.7ms AND zero frames > 33ms. Repeat in both themes (flip the chat scheme mid-session — Brain/Glass re-key losslessly).
  • Write the numbers here and sign off.

If the gate fails: remove ?brainForceActive and confirm the governor engages under load — watch __amicoBrainStats().motion step eased-1 → eased-2 → full-stop → hard-paused with the frosted look intact — then decide accept-with-valve vs iterate. (Headless dev-proxy already suggests the tail will need the valve; see PR body.)

🤖 Generated with Claude Code

@kateebonner
kateebonner marked this pull request as ready for review July 25, 2026 16:28
kateebonnerand others added 8 commits July 25, 2026 16:30
…sed question dock
Live design-review iteration with Kate (2026-07-25) on the Living Chat:
- Glass is ONE recipe everywhere: blur 8px + per-mode tint (dark: 4% white
frost + backdrop brightness(0.4); light: 5% near-white). The dark tint's
direction flips to a frost veil (lighter than ground, classic glass) with
the brightness term modeled honestly in the contrast derivation.
- The marks law (WCAG 1.4.11 dense certification) is WAIVED by design
decision; dense==standard. Muted ink is recorded as not-certified.
Tests rewritten to record the waiver rather than certify the old law.
- Cards no longer span the thread: prose fit-content ≤ min(88%,72ch),
user bubbles ≤ min(82%,64ch), tool cards ≤ 92%.
- The question dock floats on glass (8th archetype); its muted hint and
answers summary ride dense-backed zones; opaque fill scoped to
:not([data-glass]).
Part of #56 (PR #64); supersedes the #60/#61 tier law per Kate's call.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…cipe
Receipt chip, ask card (+options), run window (hover regression fixed),
inline entity card, entity rail chips, widget-preview shell, entity-view
inner atoms (tier/skeleton/formula/badge/seq/status pills), and the classic
in-chat landing (one standard card; starter buttons on dense-zone fills,
accent-edge instead of a yellow border on light). Semantic error state is a
danger tint over the glass, never an opaque surface. No !important fills.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Permission dock joins the question dock on the unified glass card (dock-prompt
generalized across kinds, permission footer flattened the same way); todo /
followup / revert trays carry the standard hook (opaque tray fill loses to
glass.css by import order); todo scroll-fade rides the glass tint; question
option tiles become dense-zone fills with the accent-soft hover, never an
opaque layer.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Opaque bands inside glassed cards defer to the dense-zone token (edit/write/
apply-patch sticky triggers, accordion header+expanded body inside any glassed
card, StickyAccordionHeader, timeline diff expanded view); the task/subagent
card is a dense zone with the accent-soft hover; diagnostics become a critical
tint over the frost; error/retry/assistant-error cards ride glass with a danger
tint; bare-muted-ink rows get their #60 backing (thinking indicator, reasoning
part, tool-loaded-file rows, turn divider label, comment-strip chips); user
attachment chips carry the dense hook; jump-to-bottom converts its hand-rolled
near-glass to the single recipe; the sticky session-title band converts its
chrome gradient/blur literals to the glass vars; inline-code chips ride the
dense token.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…cipe
Dialogs (one dialog.css edit covers delete-session/entity/fork/MCP/file/model/
unpaid/usage-exceeded launch sites), ImagePreview lightbox, popovers, dropdown
menus, shared Select menus, slash/@ autocomplete, project picker, model
selector, toast v2 — all ride the glass vars (tint + shared blur/brightness +
edge) with the legacy token as no-theme fallback; item highlights move to the
accent-soft state fill. Tooltips, the markdown code-fence copy tooltip and the
legacy toast keep their deliberate INVERSE ink on a HEAVIER glass (denser
float-token tint + shared blur/edge, never a raw opaque token); the copy
button itself rides the dense token. Drag overlay and the legacy composer
clip-mask stay heavier by function (masking), now token-mix + blur; composer
attachment tiles/pills and the theme-blind bg-black/50 name bar move to token
tints; legacy composer path gets the standard hook; composer loading stub and
review-tab header/diff surfaces convert to the glass tokens; classic landing
metadata gets a dense-zone chip.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ll audit
ui: allowlist covers every swept file (+ pre-allowed entries for the parallel
draft-landing rebuild: pages/new-session.tsx, session-new-design-view, and the
work-order's pages/session/new-session.tsx alias); new assertions pin the
AMICO family hooks + no-opaque-layer fills, dock unification across kinds,
question-option dense tiles, no-opaque-band-inside-glass (sticky triggers,
accordion, task card, diagnostics tint, diff view, inline code), muted-ink
backings, floating-chrome recipes (dialog/popover/menu/select/toast-v2/
ImagePreview), heavier inverse glass for tooltip/toast/copy-tooltip, review
surfaces, and error-tint-over-glass replacing the old no-glass error ruling.
app: sticky title band asserted on the glass vars (chrome literals banned),
timeline data-glass census, dock/composer chrome coverage, drag-overlay and
legacy clip-mask pinned as heavier-by-function token mixes.
These fail if any fix is reverted.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…st Brain
The empty landing shows the full latent network ("everything amico could
think") as a clustered ellipsoid cloud rotating in 3D, projected inside the
existing canvas engine (new constellation mode; reuses the rAF loop, governor,
pause/resume, theme re-key, reduced-motion). Curated core + seeded procedural
densification → identical constellation every launch. Dim monochrome + whisper
cluster tints, ZERO #fff676 (yellow stays exclusive to live thought). Twinkle +
breath micro-motion; static ¾ tableau under reduced-motion. First prompt →
ignition dissolve → live session graph. Removes the opaque new-session hero
wrapper that was occluding the Brain entirely, and glasses the draft-landing
chips + metadata. DEV knobs: ?constellationSpeed/Density/Tint/Fog.
Design of record: grilled with Kate 2026-07-25 (landing-only; clustered cloud;
canvas projection; mono+cluster-tint; ignition dissolve; twinkle+breath; static
tableau; uniform full-bleed). Part of #56 (PR #64).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
kateebonnerand others added 2 commits July 25, 2026 17:16
# Conflicts:
#	packages/app/src/components/session/session-new-view.tsx
#	packages/ui/src/amicode/getting-started.tsx
…k composer, typewriter placeholder, 3D constellation in-session
Live design-review iteration with Kate (2026-07-25) on the Living Chat:
Glass
- Max transparency: dark tint derives to fully transparent (backdrop
brightness 0.4 -> 0.8; less darkening lets the constellation read through).
AA retained for LIGHT, waived-and-recorded for DARK standard (the landing
constellation is yellow-free, so it reads there). Tests record the trade.
- The glass tier is now JUST blur + tint + radius — no border outline, no top
sheen/inset line, no box-shadow (Kate: "no border, no top line, no shadow").
Composer
- One background: dock-surface shell/tray opaque fills scoped to :not([data-glass])
so the glass wins as one uniform surface; footer inset fill removed (was a
visible second background).
- Full-bleed bottom dock: full width, stuck to the bottom, ~35% viewport height
(ui-ux-pro-max: primary CTA without eclipsing the hero), edge-to-edge (radius/
border/shadow zeroed). Fixed the flex height-chain so it fills to the bottom.
- Removed the model-provider H-mark/AMICODE wordmark and the project/folder
picker from the landing.
Landing
- Starter chip wall removed (competed with the constellation + composer).
Discovery now lives in the composer as a rotating TYPEWRITER placeholder that
types out the real starter prompts letter-by-letter with a blinking caret;
freezes on focus (Tab accepts the shown one), static under reduced motion.
- Constellation contrast bumped (edge alpha 0.10 -> 0.17, nodes x1.4).
Session parity
- The 3D constellation is now the background EVERYWHERE (session too), not the
sparse 2D live graph — the launch and session are one surface. (Live-thought
node pulsing is the next layer.)
Gates: ui 438 / app 473 / typecheck 23/23 / lint 0 errors. Part of #56 (PR #64).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@kateebonner

Copy link
Copy Markdown
ContributorAuthor

Live design-tuning batch (Kate, 2026-07-25) — commit 69ebf7e

The design evolved significantly beyond the original slices through a live review session. Landed:

  • Glass — now purely blur + tint + radius: dark derives to fully transparent (brightness 0.8), no border, no top sheen, no box-shadow. AA kept for light, waived+recorded for dark standard (the landing constellation is yellow-free).
  • Composer — one uniform glass surface (two-tone fixed); full-bleed bottom dock, ~35% viewport height, edge-to-edge; wordmark + project/folder picker removed.
  • Landing — starter-chip wall removed; discovery moved into the composer as a rotating typewriter placeholder (types the real starters letter-by-letter, blinking caret, Tab-to-accept, reduced-motion static). Constellation contrast bumped.
  • Session parity — the 3D constellation is now the background in-session too (not the sparse 2D graph); launch + session are one surface.

Queued (next): live-thought node pulsing over the constellation (data-true layer), card width containment, and folding the effort/variant selector into the model dropdown.

Gates: ui 438 / app 473 / typecheck 23/23 / lint 0 errors.

🤖 Generated with Claude Code

…lass sweep
Overnight batch 2 (Kate 2026-07-25), three asks:
1. Live thought over the constellation — the '+ live thought' half of
'constellation + live thought': real session touches flare their node
in css.thought (#fff676 dark / #8f8000 light) over the latent web —
rise 150ms, ease-out decay ~1.6s, expanding ring, incident-edge
glints, touched label beside the flare (fg ink + halo). Labels hash
deterministically into their category lobe with a visible-node walk
(a flare the user can't see isn't thought). Replays restore silently;
re-touches refresh instead of stacking; capped at 24; reduced motion
holds ONE statically lit node. Dev hook window.__amicoBrainTouch
(mirrors __amicoBrainStats) previews flares without a real turn.
+7 tests incl. byte-determinism under touches and the color-law
boundary (latent web ink stays yellow-free with zero touches).
2. Thinking effort folded INTO the model surface — the standalone
Default/None/High footer Select is gone (both composer paths). New
ModelVariantRow renders in the paid ModelSelectorPopover AND the
unpaid dialog (Kate's dev path): chips on --accent-fill-soft /
--accent-edge, keeps the menu open on pick; the collapsed trigger
reads 'Model · High' so effort stays visible at rest.
3. Session glass sweep to the launch-composer feel — glass is
blur+tint+radius ONLY, now enforced in-session: dock-prompt ring +
permission/question footer border-top scoped off-glass; composer
focus ring removed; comment chips borderless; dock radius 10px →
var(--radius-lg). Width containment: tool collapsibles, diffs group,
reasoning-part, error-card all share the prose measure
(min(88%, 72ch)) — floating cards on the Brain, never full-width
bands.
Gate: ui 445 / app 473 / typecheck 23 projects / lint 0 errors.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@kateebonner

Copy link
Copy Markdown
ContributorAuthor

Overnight batch 2 — 05fa001d0

All three queued items from the live-tuning session, plus the new ask (session components on the launch-composer feel):

1. Live thought over the constellation ✨

The "+ live thought" half of constellation + live thought is in. As amico works, each real touch flares its constellation node in the thought color (#fff676 dark / #8f8000 light — the brand law holds per scheme): fast rise, ~1.6s ease-out decay, an expanding ring, glints down the node's incident edges, and the touched label ("session.tsx", "amico-vault") named beside the flare.

  • Labels hash deterministically into their category lobe (file work lights the code lobe, skills the skills lobe…), then walk to a visible node — a flare you can't see isn't thought.
  • History replays silently on mount; re-touches refresh their flare instead of stacking; capped at 24 so a torrent stays a shimmer.
  • Reduced motion: the tableau holds one statically lit node — where amico is now.
  • Dev preview without a real turn: window.__amicoBrainTouch({label:"x.ts", type:"resource"}) in the console (the ?-param pattern doesn't survive the router redirect, so this rides the __amicoBrainStats hook pattern instead).
  • +7 tests: flare paint, light-scheme ink, silent replay, refresh-not-stack, decay-to-rest, reduced-motion tableau, and byte-determinism under touches. The latent-web color law tests still pin zero yellow with zero touches.

2. Thinking effort lives in the model menu

The standalone Default/None/High Select is gone (both composer paths). A ModelVariantRow renders inside the paid popover and the unpaid dialog (the dev/free path — it would otherwise have lost the control entirely): chips on --accent-fill-soft/--accent-edge, picking one keeps the menu open. The collapsed trigger now reads "DeepSeek V4 Fl… · High" so effort stays visible at rest.

3. Session glass sweep — the launch-composer feel everywhere

Glass = blur + tint + radius, nothing else, now enforced in-session too:

  • dock-prompt (permission/question card): 1px ring removed, footer border-top removed (one surface, same law as the composer footer), radius 10px → --radius-lg.
  • In-session composer: focus-within ring removed (the caret carries focus; drag keeps its dashed dropzone).
  • Comment chips: borderless dense tint.
  • Width containment: tool collapsibles ("Explored · 2 searches"), the diffs group, reasoning, and error cards all share the prose measure — min(88%, 72ch) — so the thread reads as floating cards over the Brain, never full-width bands.

Verified live in both themes on real sessions (silent replay ✓, live flare mid-session ✓, permission card ✓).

Gate: ui 445 / app 473 / typecheck / lint 0 errors.

kateebonnerand others added 4 commits July 26, 2026 12:38
… session composer = launch dock
Live review with Kate (2026-07-26), three asks:
1. 'I don't see the flares' — thought was landing behind the message
column's glass. The engine now takes an occlusion set (occlude());
session.tsx measures the real layout (timeline column band + composer
dock) and BrainAtmosphere feeds it fresh before every event flush, so
flares land in the GUTTERS where the Brain is actually visible
(fallback: merely-visible beats nothing). While the session works,
the NEWEST flare holds lit as a sustained 'amico is HERE' cursor and
decays out when the turn ends. +3 tests (gutter avoidance, hold/decay,
fully-occluded fallback).
2. Cards hug their contents — tool collapsibles and the diffs group are
width: fit-content up to the prose measure, never a padded-out band.
3. The session composer IS the launch composer — same full-bleed bottom
dock (~35% of the pane, edge-to-edge one-surface glass) via
placement='inline'; starter/typewriter suggestions stay gated to the
EMPTY LANDING (params.id gates on rotation, typing, Tab-accept,
placeholder). Legacy layout keeps the floating column card.
Gate: ui 448 / app 473 / typecheck / lint 0 errors.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ttom-stacked flow + full-width header
Live review with Kate (2026-07-26), second batch:
- Thought-tracking camera v2: rotation eases to a stop while flares are
alive and the view zooms (1.6x) + glides the newest thought to the
CENTER of the frame (Kate's call — replaces the gutter stage). All 6
confirmed findings from the adversarial review workflow fixed:
(1) conPulses is RECENCY-ordered — a re-touch splices to the end, so
the camera + busy-hold follow the re-fired concept, never a stale
array-last pulse; (2) ignite() no longer spins the stopped web back up
mid-dissolve (conRotK frozen during ignite) and the camera fast-eases
home (tau 200ms) before the live layer co-paints; (3) an OS
reduced-motion flip mid-track snaps the camera home instantly;
(4) edges/glints/ring/bloom scale with the zoom — a camera dolly, not
dots inflating over a hairline web; (5) flare seating is computed in
AMBIENT space so the zoomed viewport never funnels subsequent flares
into one slice; (6) the busy-hold is budgeted (~30s) so a wedged
active signal or ?brainForceActive cannot freeze the camera forever.
+2 tests (hold budget, seat-vs-camera split); 452 ui tests green.
- Session header: full-width band, bottom padding tight unless the
entity-chips rail rendered (CSS :has), and the band now lives OUTSIDE
the scroller, pinned at the pane top.
- Messages: rows span the pane — user messages justify RIGHT, amico's
justify LEFT (each card keeps its reading measure); the Brain owns the
middle where the camera stages thought.
- Bottom-stacked flow (messenger law): the SCROLLER's height is
content-driven up to the space the header leaves and anchors to the
bottom, so a short thread sits just above the composer; inside it
scrolling stays classic top-anchored — virtua's geometry is untouched
(an mt-auto-in-viewport variant starved virtua's visible range and
was abandoned). startMargin 0, sticky-accordion offsets updated.
Gate: ui 452 / app 473 / typecheck / lint 0 errors.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Kate 2026-07-26 (component audit): the collapsed 'edit · Failed' chip was
banding across the pane — width: fit-content capped at the prose measure,
matching the width law every timeline card now follows.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…erity
Kate 2026-07-26: glass is blur+tint+radius; the 2px Card accent rail read
as a border on the failed/error cards. content:none on the ::before for
tool-error-card and .error-card — the danger tint, icon, and ink alone
mark severity.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@kateebonner
kateebonner marked this pull request as draft July 26, 2026 23:19
@kateebonner

Copy link
Copy Markdown
ContributorAuthor

Parked 2026-07-26 — converting to draft. Aaron's call: not pursuing this UI direction right now. Everything through 83d070ae4 is on the branch (living-chat glass redesign, thought-tracking camera, bottom-stacked edge-justified flow, effort-in-model-menu, component audit + width law). The branch is the complete archive of the direction if we return to it; the component library artifact documents every surface.

@kateebonner
kateebonner marked this pull request as ready for review July 29, 2026 00:21
@kateebonner
kateebonner marked this pull request as draft July 29, 2026 00:23
@jack-champagne

Copy link
Copy Markdown
Member

@kateebonner — question before this ages further: is anything here still worth keeping?

Asking because ADR 0002, which this implements, is marked superseded on mainline:

Status: Superseded by ADR 0003 (direction parked 2026-07-26; the Brain moved to the context-tree top panel instead of becoming the chat background)

and ADR 0003 (Accepted, 2026-07-27, on Aaron's 2026-07-26 feedback) is explicit:

Supersedes: ADR 0002 (Brain as chat background — direction parked)
… Aaron's feedback reframed what the graph is for: not ambience, but orientationThe graph moves out of the timeline into a pinned top panel … the ambient background direction is parked.

The ADR-0003 replacement has fully landed

All of this is on local/amicode and shipped in v1.17.3-amicode.11:

So the top-panel + first-class vault surface direction is done and released.

What's still unique to this branch

brain-engine.ts and context-tree-engine.ts are already on main — the graph engine itself made it across. What has no counterpart is the presentation layer for the parked direction:

only in #64
glass.css (778 lines), glass-tokens.ts, script/generate-glass.ts
brain-atmosphere.tsx / .css
brain-constellation.ts
brain-perf-governor.test.ts, brain-events.ts, e2e/perf/brain-governor-trace.spec.ts

16 added files, 54 modified, 1 deleted.

Why I'm asking rather than just closing

Two things in there look potentially valuable independent of the parked background direction:

  1. The legibility machineryglass-tokens.ts plus the WCAG-AA-floored tint derivation. ADR 0002 records that the earlier attempt failed exactly one AA check (muted grey on the most translucent tier), so this encodes a real lesson. Worth salvaging if any surface still layers text on translucency — the session header's backdrop-blur comes to mind, given fix(session): header backdrop-blur off while the context-tree band is open #97 just had to switch it off over the context-tree band.
  2. brain-perf-governor + the e2e perf trace — frame-budget governance for the graph. The organic context tree that did land has the same cost profile, so a perf governor may be wanted regardless of where the graph renders.

If neither is worth extracting, this is a clean close — the direction is parked and the replacement is released. If either is, they'd be small standalone PRs rather than resurrecting 71 files.

For context on the state: it is still a draft, CONFLICTING/DIRTY, 72 commits behind mainline, and its checks are all CANCELLED from before #2 fixed the runner labels — so CI has never actually evaluated this branch.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Make the Brain the Chat's living background; float components on legibility-floored Glass

2 participants

@kateebonner@jack-champagne