feat: forum-style dashboard redesign (Epic #339)#362
Merged
CalebisGross merged 75 commits intomainfrom Mar 29, 2026
Merged
Conversation
Change go:embed directive from `static/*` to `static` to support recursive subdirectory embedding. Create css/, css/pages/, js/, js/pages/ directories for the ES module migration. Part of #342 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Extract 5 theme definitions to css/tokens.css with forum-specific semantic variables (--bg-row, --link, --decision, --insight, etc.) - Remove D3.js CDN script tag (breaks air-gap, replaced in Phase 4) - Archive 10 design mockups, keep design-forum-v3.html as reference - Add between-phases recall rule to mnemonic-usage.md - index.html drops from 5829 to 5704 lines Part of #343 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Write split-dashboard.py to auto-extract CSS sections from monolith - Extract 10 CSS files: base, nav, drawer, components, + 6 page files - Create forum component library (components.css) with full vBulletin- inspired design system: forum blocks, rows, type icons, expand zones, thread posts, quote blocks, timeline rows, recall results - Generate JS function map (135 functions categorized for migration) - Extract HTML body for reference - Link components.css from index.html Part of #344 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Delete ~828 lines: Mind view CSS (105 lines), HTML (37 lines), and JS (558 lines including D3 force graph, color scales, search, detail panel, neighborhood highlight, all mind-* functions). Remove Mind nav tab. Renumber keyboard shortcuts (1-6). Associations will be shown as quoted posts in thread view instead. Part of #345 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace card-style nav with vBulletin-inspired forum chrome: - Top bar with brand, version, theme select, activity bell - Sticky navbar with Search/Forum/Timeline/SDK/LLM/Tools tabs - Breadcrumb bar - Fixed footer status bar (version, active/fading/archived counts, encoding status, last consolidation time) - loadStats() populates footer on 30s refresh - switchView() handles both old nav-tab and new ntab classes - forum-transform.py script for reproducible transformation Part of #344, #345 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Transform JS render functions to emit forum-style HTML: - loadEpisodes: forum rows with EP icon, column headers, expandable nested zones, episode stats (memory count, file count, last activity) - loadMemories: forum rows with type icons (IN/DE/LE/ER), salience %, link count, expandable detail with content + metadata - renderResults: forum table with score column, type icons, column headers, recall info bar (count, latency, spread activation hops) - Add toggle() function for forum expand zones - Update toggleExpand() to handle .expand-zone class Part of #345, #347 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Transform renderTimelineCard to emit .tlr forum rows: - Time column, colored type dot, text with inline concept tags, salience % - Preserve data-concepts attribute for tag hover/click filtering - Tag interaction handlers (toggleTimelineTag, hoverTimelineTag, unhoverTimelineTag) remain intact - Date group headers now use .tl-head sticky headers - Expandable detail on click (summary, narrative, files) - Remove card-based layout (timeline-date-group, timeline-rail) Part of #348 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implement a ~200-line D3 API shim that provides the subset of D3 used by our charts: select, scaleBand, scaleLinear, scalePoint, axisBottom, axisLeft, max, stack, area, line, extent, format, pointer, curveMonotoneX (stub — uses straight lines). This means ALL existing chart functions (renderLLMChart, renderToolChart, renderLifecycleChart, renderSignalChart, renderRecallChart, renderSDKCostChart, renderTimelineSparkline, _renderSparkline) work without any code changes — they call d3.select(), d3.scaleBand(), etc. and hit the shim instead of the CDN library. Zero external dependencies. Zero CDN calls. Everything embedded. Part of #346 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
loadStats() referenced old 'navHealth' element ID but forum nav uses 'healthDot'. The null reference threw before version text could be set. Now gracefully handles both IDs and null-checks all DOM lookups. Part of #344 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Change navVersion from <small> to <a> with href to the release page. Hover underline now works as expected. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Missing d3.scaleSqrt caused JS crash that prevented SDK/LLM/Tools pages from loading. Charts render empty containers (shim needs debugging for bar/line rendering) but stat cards, tables, and data loading all work correctly. Part of #346 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fix chart bars not rendering: selectAll() now passes parent element to wrapAll so enter().append() can find the correct parent container for new SVG elements. Previously, empty selectAll results had null parent so appended elements were lost. Also add tickValues(), tickFormat(), ticks() chainable methods to axisBottom and axisLeft. Add domain baseline lines. Add style() and classed() to wrapAll return object. Part of #346 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Two bugs from the nav migration: 1. switchView() queried old .nav-tab selector instead of .ntab, crashing before lazy-load triggers — SDK/LLM/Tools needed manual Refresh to load data 2. loadLLMUsage() wrote to navTokenCount which was removed from the forum nav — null reference crashed the function, catch block showed ERR in REQUESTS card Both fixed with null-safe lookups. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Thread view: click "View full thread" on any episode to see its
memories as vBulletin-style forum posts. Each memory shows a left
sidebar (type badge, salience, links, source, time) and right
content area (summary, full content, concept tags). Episode
narrative shown at bottom. Hash routing: #thread/{episodeId}.
Breadcrumbs update to show navigation path.
SDK/LLM/Tools: replace card-style headers with .fblock-title
for visual consistency with forum design.
Part of #345, #349
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…se 8) Remove: - css/pages/mind.css (mind view was deleted) - .gitkeep files (directories now have real files) - BODY_HTML.txt and FUNCTION_MAP.txt (extraction reference files) Part of #350 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Thread view was fetching by raw_memory_ids which don't resolve via
/memories/{id}. Now uses /memories?episode_id={id} which correctly
returns all encoded memories belonging to the episode.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
GET /episodes/{id} returns {episode: {...}} not the episode directly.
loadThread now unwraps correctly, fixing "Untitled Episode" title
and missing metadata (mood, duration, files).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The /memories?episode_id= param doesn't filter server-side. Now fetches all active memories and filters client-side to show only those belonging to the episode. Shows correct memory count instead of always 50. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
HandleListMemories now reads ?episode_id= query param and filters results server-side. Previously the param was ignored, forcing the thread view to fetch all memories and filter client-side (slow). Reverts client-side workaround in loadThread. Part of #345 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Source event types (FILE_CREATED, REPO_CHANGED) now map to 'general' for display. Cognitive types (decision, insight, learning, error) pass through. Salience capped at 100% (was showing 196% for values >1.0). Added shared helpers: memoryType(), memoryTypeAbbr(), memoryTypeIcon(), safeSalience() to eliminate duplication across forum view, recall results, and thread view renderers. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Rewrite components.css and all render functions to use phpBB prosilver semantic HTML patterns: CSS: - ul.topiclist > li.row > dl.row-item > dt + dd column layout - dt uses negative margin trick for flexible first column - dd columns float with fixed widths and border-left separators - bg1/bg2 alternating row classes (not :nth-child) - .post with .postprofile (dl sidebar) + .postbody (content area) - blockquote.quote for associated memories - .forabg category containers with gradient headers - .status-icon type badges (EP/IN/DE/LE/ER) JS render functions rewritten (4 of 8): - loadEpisodes: ul.topiclist with dl/dt/dd columns - loadMemories: same structure with sal/links/lastpost columns - renderResults: forum table inside .forabg with score column - loadThread: posts with dl.postprofile sidebar (avatar, rank, salience, links, project, join date) + div.postbody content Studied phpBB prosilver templates at /tmp/phpbb/ for structural reference. Bespoke implementation, not a clone. Part of #339 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Rewrite remaining render functions to phpBB dl/dt/dd layout: - renderTimelineCard: li.row with dl/dt/dd + concept tags preserving tl-source/tl-concept classes for tag filtering compatibility - renderTimelineItems: date groups wrapped in .forabg containers - loadPatterns: forum rows with sticky class, archive button - loadAbstractions: forum rows with announce class, level badges Replace Explore tabbed layout with collapsible .forabg blocks: - Episodes, Recent Memories, Discovered Patterns, Abstractions shown simultaneously as forum categories - Click category header to collapse/expand (.collapsed class) - All 4 sections load in parallel on first visit - Welcome panel placeholder with stats Update filterExplore to query li.row elements. Part of #339 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Welcome panel shows active/fading/archived counts from /stats endpoint. Tracks last visit timestamp in localStorage and shows "Last visit: date" or "Welcome to mnemonic" for first-time visitors. Timestamps stored for future "new since last visit" feature. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fix research analytics charts not rendering:
- stack() now supports .value(fn) method and attaches .data property
to each stack point (D3 convention for accessing original data row)
- datum(d) now stores data on element and returns wrapper for chaining
- attr(name, fn) now calls fn(datum) when value is a function, matching
D3's behavior for things like .attr('d', areaGenerator)
- Individual try/catch around each chart render for isolated debugging
Part of #346
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
switchView() now updates #breadcrumbs with view-specific text: Search, Forum, Timeline, SDK, LLM Usage, Tools. Previously only the thread view updated breadcrumbs. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
d3.area().y0(h) passes a number, not a function. The shim's y0/y1/x setters now wrap constants in functions automatically, matching D3's API. Same fix for d3.line().x() and .y(). Root cause of _renderSparkline crash: "TypeError: _y0 is not a function" — y0 was set to the number 24 (container height) but called as _y0(d, i). Part of #346 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Timeline: - Rewrite renderTimelineCard to use flexbox rows (.tl-row) instead of dl/dt/dd which broke layout and caused text overflow - Fix invalid HTML: expand-zone was a div sibling inside ul.topiclist - Proper text-overflow:ellipsis on titles - Time and salience columns fixed-width and right-aligned Thread view: - Add missing CSS: .thread-wrap, .thread-top, .thread-title-big, .thread-meta were used in HTML but had no CSS definitions (lost during migration from inline styles to components.css) - .thread-meta now has display:flex with gap:14px fixing the "Mood: satisfyingDuration:" spacing bug Tag filtering: - Preserved .tl-card, .tl-source, .tl-concept, data-concepts classes for compatibility with highlightTimelineCards() Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove old card-based CSS rules that are no longer used after the forum structural rewrite: - .result-card, .score-high/mid/low (now uses .forabg + dl/dt/dd) - .episode-card, .episode-header/title/summary/meta (now li.row) - .memory-card, .memory-header/type-badge/stats-row (now li.row) - .tl-card border-left type colors (now .tl-row with status-icon) - .timeline-date-group/label/rail (now .tl-head + .forabg) - .timeline-empty (kept .timeline-empty text, removed structural) index.html: 5574 → 5447 lines (-127 lines) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The old .tl-card rule added border-left, margin-left:20px, padding, position:relative, and ::before/::after pseudo-elements to every timeline row. This caused the huge gap at top and broke the flexbox layout. Kept only .tl-card.dimmed and .tl-card.highlighted which are needed for tag hover/click filtering. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Each memory included a 3072-dimension embedding vector serialized as 42KB of JSON. For 50 memories that's 2.1MB of data the dashboard never uses. Now nil-ing embeddings before JSON serialization. Response size: 2,007,710 → 49,557 bytes (40x reduction) Note: query time still ~2.5s due to SQLite scanning 33K+ rows. DB query optimization tracked separately. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Quote button: use data-attributes instead of inline JSON to avoid escaping issues. Reads author/content from data-author/data-content on the post element. - Clickable @tags: clicking an agent's @tag in the sidebar inserts @agentkey into the reply box and focuses it. - Dropdown: insert before textarea (not after), use --bg-primary background, wider width, no absolute bottom positioning. - Blank replies: guard against empty LLM responses with fallback text. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…cation Gemini 3 Flash (thinking model) was consuming most of the max_tokens budget on reasoning tokens, leaving only ~100-150 tokens for the actual response. A 512 token limit with reasoning enabled produced truncated replies every time. Fix: add DisableThinking field to CompletionRequest. When set, the LM Studio provider sends reasoning_effort=none to thinking models. Forum mention responses now use DisableThinking:true since conversational replies don't need chain-of-thought. This is a general-purpose fix — any LLM call that expects short output on a thinking model should consider DisableThinking. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Mnemonic's LLM calls are short, structured tasks (encoding, retrieval synthesis, forum replies) where chain-of-thought wastes token budget and causes truncation. Always set reasoning_effort=none when a thinking model (Gemini 2.5+/3+) is detected. Previously this was only applied to JSON schema requests and explicit DisableThinking=true calls. Now it's the default for all requests. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Lines starting with > are now parsed into styled blockquote elements with a left accent border, dimmed background, and smaller font — like phpBB quote blocks. @mentions within quotes are still highlighted. The compose box still uses > prefix format (plain text input), but the rendered output shows proper visual quote boxes. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add a category system to the forum with a classic phpBB-style index: Data layer: - forum_categories table with id, name, slug, description, icon, color, type (system/project/agent/custom), sort_order - category_id column on forum_posts for thread-to-category mapping - 11 default categories seeded on startup: 3 system (Discussions, Announcements, System Reports) + 8 agent (@consolidation, @dreaming, @episoding, @abstraction, @Metacognition, @encoding, @perception, @Retrieval) API: - GET /api/v1/forum/categories — returns all categories with thread counts, post counts, and last post per category - GET /api/v1/forum/threads?category=ID — filter threads by category - POST /api/v1/forum/posts now accepts category_id Agent routing: - Agent autonomous posts route to per-agent sub-forums by default (e.g., consolidation → @consolidation) - Configurable via forum.per_agent_subforums (false = shared System Reports category) - Human posts default to Discussions category Frontend: - Forum index page grouped by type (General, Projects, Agents, Custom) - Each category shows icon, name, description, thread count, post count, last post info - Click category to see its threads - New thread form includes category selector - Hash routing for forum-category/ID URLs Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Improve the forum index layout to better communicate the parent/child relationship between category groups and sub-forums: - Add column headers (Sub-forum, Threads, Posts, Last post) to each group for scannability - Show total thread/post counts in group header bar - Last post shows @tag for agents instead of full name - Tighter spacing between groups (margin-bottom:2px) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Update CSS column widths to match phpBB prosilver's proven proportions: - dt margin-right: -345px (phpBB uses -440px for wider layouts) - dd.posts/topics: 80px centered with line-height:2 (phpBB: 95px) - dd.lastpost: 185px right-aligned (phpBB: 250px) - list-inner margin-right: 345px to match Use proper li.header class for column headers instead of inline styles. phpBB's prosilver template reference: forumlist_body.html structure with ul.topiclist > li.header + ul.topiclist.forums > li.row pattern. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Existing posts created before the category system had empty category_id.
Backfill on startup: agent posts get 'agent-{author_key}', human posts
get 'discussions'. Idempotent — only updates rows with empty category_id.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…post Restructure the forum index to match phpBB's hierarchical navigation: Level 1 - Forum Index: shows top-level category groups (General, Agents, Projects, Custom) as clickable rows with aggregate thread/post counts and inline sub-forum links. Level 2 - Category Group: clicking a group (e.g., "Agents") navigates to a sub-forum listing showing all sub-forums in that group with individual thread/post counts and last post info. Level 3 - Sub-forum: clicking a sub-forum (e.g., "@consolidation") shows threads within that sub-forum. Level 4 - Thread: clicking a thread shows posts with compose box. Each level has proper breadcrumb navigation and hash routing (forum-group/type, forum-category/id, forum-thread/id). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…m section
Restructure the Forum page into a single cohesive index:
1. Merged Welcome Back + Live Activity into one compact header panel
with inline event feed (collapsible, max 150px).
2. Removed separate Episodes, Memories, Patterns, Abstractions forabg
blocks. These are now rows in a "Memory System" group in the forum
index, alongside General, Agents, and Projects.
3. Clicking a Memory System row (e.g., "Episodes") navigates to a
detail view showing that section's content with proper breadcrumbs.
4. The explore data sections are now hidden containers — their content
is loaded on demand and rendered in the thread view when navigated to.
Navigation flow:
Forum Index → General/Agents/Projects/Memory System
→ Sub-forums → Threads → Posts
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… thread subscriptions Four unique features that phpBB can't do: 1. Project auto-detection: SyncProjectCategories() runs on startup, discovers all known projects via ListProjects(), and auto-creates forum categories for each. New projects get sub-forums automatically. 2. Data-aware @mention responses: each agent now injects real system data into the LLM context before generating replies: - @Retrieval: search results with scores and salience - @Metacognition: live stats (memory counts, storage, observations) - @consolidation: last run stats (processed, decayed, merged) - @episoding: recent episodes with mood and memory counts - @abstraction: active patterns with strength, abstractions with confidence - @dreaming: memory system state and recent autonomous actions - @encoding: source distribution and encoding stats - @perception: observation counts by source 3. Agent-to-agent conversations: when an agent's @mention response contains @mentions of other agents, those trigger new mention events. Self-mentions are blocked to prevent infinite loops. Chain-level cooldowns (10s) gate rapid back-and-forth. 4. Thread subscriptions: posting in a thread auto-subscribes you. When an agent replies to a subscribed thread and you're not viewing it, a notification badge appears on the Forum tab and a toast shows. Subscriptions persist in localStorage. Viewing a thread clears its unread count. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…episode project tagging
Make the whole forum functional end-to-end:
Memory System sections now fetch and render real data:
- Episodes: clickable rows that open the episode thread view via
loadThread(), showing title, summary, memory count, file count
- Recent Memories: rows with salience, type badge, concepts preview
- Discovered Patterns: rows with strength, evidence count, description
- Abstractions: rows with confidence, level (principle/axiom)
Project routing:
- Agent posts with project context (pattern discoveries, episode
closures) route to project-{name} sub-forums instead of agent subs
- EpisodeClosed event now carries Project field from the episode
- ComposePost returns project hint for category routing
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ssues The onclick handler for Memory System rows (Recent Memories, Patterns, Abstractions) was breaking due to special characters in names. Switch to data-section/data-section-name attributes read via getAttribute(). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…nclick
Inline onclick in dynamically generated HTML wasn't firing for Memory
System rows. Switch to addEventListener bound after innerHTML is set.
Each row gets a unique ID (memsec-{id}) and the click handler is
attached via addEventListener in the loadForumIndex callback.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The inline onclick in generated HTML couldn't find loadMemorySection because it was defined in a script scope, not global/window scope. Expose window._loadMemSec as a bridge that calls loadMemorySection. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
All rows in Memory System sections are now interactive: - Memories: click to expand full content, source, project, and episode thread link - Patterns: click to expand type, full description, concepts, evidence count - Abstractions: click to expand level, description, source counts - Episodes: already clickable (opens thread view) Uses the existing .expand-zone CSS toggle pattern — click to expand, click again to collapse. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…S class
Inline style="display:none" has higher specificity than the CSS class
.expand-zone.open { display: block }, so toggling the 'open' class had
no visible effect. The .expand-zone CSS rule already sets display:none
by default — the inline style was redundant and blocking the toggle.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… count The episode list was showing raw_memory_ids count labeled as "Memories", but the thread view showed encoded memory count (often 0 since encoding is async). This created a confusing discrepancy. Fix: episode list column renamed to "Obs" (observations) and shows raw count. Thread header shows "Memories: 0 (13 observations)" when encoded count differs from raw count, making the async encoding gap visible. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…artup Root cause: encoding agent (5s poll) runs before episoding agent (10s poll), so memories get encoded with empty episode_id. No backfill existed to fix the linkage after episoding assigns raw observations. Fix: 1. Episoding agent now backfills episode_id on encoded memories when closing an episode — iterates raw_memory_ids, looks up encoded memories via GetMemoryByRawID, updates their episode_id. 2. Also populates episode.memory_ids (reverse link) which was always empty. 3. One-time BackfillEpisodeMemoryLinks() runs in a goroutine on startup — iterates all episodes (small set) and fixes any orphaned linkages from before this fix. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ng about When you @mention an agent from within an episode thread view, the agent now receives the full episode context: title, summary, narrative, concepts, files, mood, duration, and all encoded memories linked to that episode. This works for ALL agents, not just @episoding. Implementation: - CreateForumPostRequest gains episode_id field - ForumMentionDetected event carries episode_id - buildAgentContext() prepends episode detail (title, narrative, concepts, files, linked memories) when episode_id is present - Frontend: loadThread() sets state.currentEpisodeId, submitThreadReply passes it to the API, compose box shown in episode threads - Breadcrumbs link back to Episodes section Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
# Conflicts: # internal/store/sqlite/schema.go
…ions, D3 removal - Add daily digest threads: agent posts batch into one thread per category per day instead of flooding with individual threads. New GetDailyDigestThread store method + DigestPosting config flag. - Add associations as quoted posts: new GET /api/v1/associations endpoint with enriched summaries, rendered as blockquote elements in episode thread view. - Replace D3 shim with hand-rolled SVG/CSS: all 8 charts rewritten using svgEl/linScale helpers, ~300-line shim deleted. Zero external dependencies. - Frontend quality fixes: forumFetch helper with HTTP status checks, visible error states, null guards, data-attribute onclick delegation, auto-subscribe on thread view. - Fix pre-existing TestWriteMemoryDuplicateRawID FK failure. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove 7 dead mind* state variables and updateMindColors() call - Remove leftover "mind view removed" comments - Archive design-forum-v3.html to mockups/archive/ - Zero external URLs remain (verified: only GitHub releases link and SVG namespace string) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move the entire 4564-line inline <script> block from index.html into a separate js/app.js file served via go:embed. index.html is now a pure HTML/CSS shell with a single <script src="/js/app.js"> tag. Zero behavior change — same code, just in its own cacheable file. The browser can now cache the JS independently of HTML changes. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Split the monolithic 4564-line app.js into 12 ES modules: - state.js (35 lines) — shared state, config, constants - utils.js (182) — fetch helpers, escapeHtml, SVG chart helpers, agent profiles - nav.js (89) — view switching, hash routing, keyboard shortcuts - recall.js (119) — recall search, remember panel - explore.js (398) — explore tabs, episode thread view - timeline.js (483) — timeline with filters, sparkline, tags - forum.js (885) — forum communication layer, @mentions, subscriptions - drawer.js (294) — activity drawer, insights, stats, projects - ws.js (61) — WebSocket connection - llm.js (1227) — LLM usage, tool analytics, research analytics - agent.js (785) — agent dashboard, chat, self-update - app.js (88) — entry point, imports, window bindings, init index.html uses <script type="module"> with an inline theme script to prevent FOUC. Cross-module calls use window.* bindings set up by app.js. No build step — go:embed serves modules natively. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove formatBytes, renderMarkdown, and relativeTime from import lines where they were both imported from utils.js and declared locally. Fix relativeTime imports in explore.js and drawer.js to import from forum.js where the function actually lives. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Completes the forum-style dashboard redesign (Epic #339) — a full rewrite of the web dashboard from card-based layout to phpBB-inspired forum UI with hierarchical navigation.
/api/v1/associationsendpoint, rendered as blockquote elements in episode thread viewindex.htmlreduced to 1,601 linesforumFetchwith HTTP status checks, visible error states, null guards, data-attribute onclick delegation, thread auto-subscribeCloses #339. Closes #349. Closes #350.
Test plan
make checkpasses (go fmt + go vet)make testpasses (all packages)make buildsucceeds🤖 Generated with Claude Code