Replaces the read-only stats dashboard with a three-pane wiki: a
navigator tree (group by folder/type/tag/entity), a reader/editor with
bare-slug auto-linking and revision history + diff, and a context rail
for backlinks and related notes. Adds a Cleanup mode for the drift
tools (duplicates, tag manager, orphans, trash) and a Cmd+K quick-open.
Also:
- Adds a real landing view (hero count, KPI row, Nomos-share meter,
recently-updated, busiest tags) in place of the old "Select a note"
empty state, and extends the design pass across the tree/reader/rail
(kind icons instead of repeated text badges, accent-bar selection,
constrained prose measure).
- Guards every note-selection path behind a confirm when there's an
unsaved edit in progress, so switching notes can no longer silently
discard a draft.
- Extracts the markdown-rendering CSS duplicated across ChatThread,
EntityDetailContent, and the new WikiReader into a shared
.markdown-body class in app.css, with ChatThread keeping only its
decorative deltas.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
.prettierrc.json was missing "semi": false, so prettier wanted to add
semicolons to a codebase written without them (763 semicolon-free
statements vs. 150 with, in hand-written .ts; zero hand-written .svelte
files use them at all). That's why prettier --check failed on 249 files
— not because the code was unformatted, but because the config didn't
match the actual house style. Added "semi": false; left printWidth/etc
as configured (printWidth barely moves the failure count: 218/213/212
files at 100/120/140).
Ran `prettier --write .` with the corrected config. Verified
semantics-preserving before and after:
- eslint: 142 problems both before and after, byte-identical
- build passes, 38/38 tests pass
- token-stream diff (whitespace/semicolons/quotes normalized) on all
218 changed files: only 52 had any remaining token change, all either
trailing-comma removal (matching trailingComma: "none") or import/
ternary reflow — no semantic changes
- live smoke test: Knowledge, Tasks, Fleet map, and a chat window
(AgentTrace, markdown, Scope graph, activity rail) all render
correctly, no console errors
Most of the diff is shadcn/ui vendor files (lib/components/ui/) moving
from the CLI's own style (double quotes, tabs, semicolons) to house
style; re-running `shadcn-svelte add` on a component will need a
follow-up format pass.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The chat rendered one card per tool call, so a 20-call turn buried the
answer under 20 stacked cards. Merge them with the "thinking" indicator
into a single collapsible strip above the answer:
- collapsed: the live activity while running, a count once finished
- expanded: the turn's work in humanized language (reuses the activity
log's toolActivityLabel, so ten identical "run · target: host:strong"
rows now read as what they actually did)
- per row: the raw args/result, one more click in
Also flip the Activity rail to newest-first with the current step on top:
- follow-mode/auto-scroll re-anchored to the top to match, or it would
jump to the oldest entry on every new event
- pending plan steps park at the tail rather than sorting above the
running step and pushing it off the top; the goal anchors the bottom
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
text-primary instead of text-success — keeps the "done" state on-brand
with the rest of the UI (buttons, focus rings) rather than introducing
a separate green that only really worked well on the dark theme.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
text-success/50 and /60 washed out to almost nothing against the light
theme's cream card background — full-opacity text-success still reads
as a calm, muted green (not alarming) but is actually visible on both
themes.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The pending operator-question card now renders inline in ChatThread (the
newest thing in the conversation) instead of in the context rail — it's
part of the chat, not a separate side panel, and the panel's hasContext
gate no longer needs to special-case it.
The desktop mascot's reactions are now entirely about whichever task
window has focus, not fleet-wide events: thinking/talking is a new
continuous `busy` behavior that tracks the focused session's own
streaming state (thinking before any text arrives, talking once it
does — using the previously-unwired peep/talk sprite), eureka fires with
the actual knowledge title that was recorded, happy fires with the
task's own completion summary, and alarmed now means "this task needs
your OK" (an operator question was raised) rather than a fleet-wide
critical/signal event.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
New Task now opens directly as an empty ChatThread (NewTaskChat) instead of
a separate compose screen, sized like a real task window. The Scope/Activity
context rail in a task window no longer renders until there's actually
something to show (touched entities, activity, or an open question),
avoiding an empty-placeholder sidebar on every new task. Also fixes the
chat input defaulting to several lines tall on window open, centers the
empty-chat greeting vertically, and gives floating windows the same
frosted-glass look as the desktop's task launcher card.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Replace hand-rolled pointer-resize logic (TaskContextPanel's 3-way vertical
split, SessionChatWindow's rail, ChatThread's message/input split) with
svelte-splitpanes, themed onto the app's existing border/primary tokens.
- TaskContextPanel: Scope/Plan/Event-log sections collapse to a fixed header
height and restore their last size on reopen.
- ChatThread: input area is now a separate resizable pane, clamped to a
measured one-line minimum and a 45% max, instead of a fixed max-h textarea.
- Send button restyled to sit inside the input's corner (Claude-style),
swapping the up-arrow for a corner-down-left return icon.
- Adds a $app/environment shim + optimizeDeps exclude, since
svelte-splitpanes assumes SvelteKit and this is a plain Vite app.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Clicking a task now opens it as a wmkit floating window (like entity
windows already do) instead of navigating away from wherever you were.
Several task windows can be open and actively streaming at once, each
fully independent — no "which one's on screen" guard needed, since
each window owns its own store bundle:
- chat.ts: chatFor(sessionId)/loadSessionChat/sendSessionMessage give
each window its own messages/streaming/connectionState, alongside
the existing singleton path the main Chat page still uses unchanged.
- workspace.ts: same split for plan/questions/touched/health-diffs
(workspaceFor/startSessionWorkspace), each with its own live-event
watermark since several windows can watch the same event stream.
- activity.ts: activityLogFor(sessionId) mirrors the global derivation.
SessionGraph.svelte, OperatorQuestion.svelte, and ActivityTimeline.svelte
were converted from store-importing to prop-driven (matching the new
ChatThread.svelte, extracted from Chat.svelte's transcript/input so both
the main page and task windows share one implementation instead of
duplicating markup/styling) so each can render either the global
"current session" or a specific window's session.
Also: minimized-window taskbar chips now cap at a max width with
middle-ellipsis truncation instead of growing unbounded, and the
window header's title/action-button row is fixed to genuinely match
heights (not just share a center point) for more robust alignment.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>