This repository has been archived on 2026-04-03. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
core/docs/ROADMAP.md
2026-03-01 18:20:01 +00:00

995 lines
51 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Roadmap — Chat Switchboard
**See also:**
- [ARCHITECTURE.md](ARCHITECTURE.md) — Core services design, store layer, scope model
- [EXTENSIONS.md](EXTENSIONS.md) — Extension system spec (Browser/Starlark/Sidecar tiers,
manifests, browser tool bridge, surfaces/modes, model roles)
- [CHANGELOG.md](../CHANGELOG.md) — Detailed release notes for all completed versions
**Versioning (pre-1.0):** `0.<major>.<minor>` — hotfixes use quad: `0.x.y.z`
No compatibility guarantees before 1.0.
---
## Dependency Graph
Features have real dependencies. This ordering respects them.
```
v0.9.x Stability + Quick UX Wins ✅
v0.9.3 Content Visibility & Block Controls ✅
v0.9.4 API Key Encryption + Vault ✅
v0.10.0 Model Roles (utility + embedding) ✅
+ Usage Tracking
v0.10.2 Summarize & Continue ✅
v0.10.3 Frontend Refactor ✅
v0.10.4 Model Type Pipeline + Role Fixes ✅
v0.10.5 UI Primitives + Extension Surfaces ✅
v0.11.0 Extension Foundation (browser tier) ✅
┌───────┴──────────────┐
│ │
v0.12.0 File Handling v0.13.0 Admin Panel
+ Vision ✅ Refactor (fullscreen) ✅
│ │
│ v0.13.1 Web Search
│ + url_fetch ✅
│ │
└───────┬──────────────┘
v0.14.0 Knowledge Bases ✅ (embedding role + file storage + pgvector)
v0.15.0 Compaction ✅ (utility role + background job)
v0.15.1 Context Recall Tools ✅ (attachment_recall, conversation_search)
┌───────┴──────────────┐
│ │
v0.16.0 User Groups v0.17.0 Persona-KB Binding
+ Resource Grants ✅ + Enterprise KB Mode
│ + QOL / UX Wins
└───────┬──────────────┘
┌───────┴──────────────┐
│ │
v0.17.1 SQLite Backend ✅ v0.17.2 CodeMirror 6 ✅
v0.17.3 Notes Graph + Wikilinks ✅
(dual DB) (editor bundle, chat
│ input, ext editor)
└───────┬──────────────┘
v0.18.0 Memory ✅ (user + persona scopes, review pipeline)
v0.18.1 Side Panel Architecture ✅ (single-slot, ctx.ui primitives, mermaid refactor)
v0.19.0 Projects / Workspaces ✅ (project groups, KB resolution, drag-drop sidebar)
v0.19.1 Active Project + System Prompt + Detail Panel ✅
v0.19.2 Project Persona Default + Archive + Reorder ✅
v0.20.0 Notifications + @mention Routing + Multi-model ✅
v0.21.0 Workspace Storage Primitive ✅
┌───────┴──────────────┐
│ │
v0.21.1 Workspace ✅ v0.21.3 Surface Infra ✅
Tools + Bindings + REPL (parallel)
│ │
v0.21.2 Workspace ✅ v0.21.5 Editor Surface
Indexing + Search (Development Mode)
│ │
v0.21.4 Git v0.21.6 Article Surface
Integration + Document Output
└───────┬──────────────┘
v0.22.0 Smart Routing + Provider Extensions
v0.23.0 Multi-Participant Channels + Presence
v0.24.0 Auth Strategy (mTLS/OIDC) + Full RBAC + Group permissions
┌───────┴──────────────┐
│ │
v0.25.0 Workflow v0.26.0 Tasks /
Engine Autonomous Agents
(team-owned, (service channels,
staged processes, scheduler, unattended
human + AI collab) execution)
```
---
## Completed Releases
> Full details for all completed versions are in [CHANGELOG.md](../CHANGELOG.md).
### ✅ v0.9.0 — Schema Consolidation + BYOK
21 migrations → single schema, store layer abstraction, persona-as-trust-boundary,
BYOK with auto-fetch, composite model IDs, journey integration tests.
### ✅ v0.9.1 — Capability Architecture + Docs
Removed static known model table. Resolution chain: catalog → heuristic only.
Frontend relies solely on backend for capabilities. Docs rewrite.
### ✅ v0.9.2 — Quick UX Wins + Hardening
Collapsible code blocks, HTML preview, token counter, context warning, proxy
interception detection, environment injection, team admin audit scoping.
### ✅ v0.9.3 — Content Visibility & Block Controls
Button-driven code collapse, always-rendered thinking blocks, tool call
persistence in history, Notes panel → unified side panel, streaming refactor
(`streamWithToolLoop`), regenerate fix.
### ✅ v0.9.4 — API Key Encryption + Vault
Two-tier AES-256-GCM: env-var key for global/team, per-user UEK (Argon2id)
for personal BYOK. `server/crypto/` package. Migration 003. Startup backfill.
DOMPurify strict allowlist (XSS fix).
### ✅ v0.10.0 — Model Roles + Usage Tracking + Vault Debt
Named role slots (utility, embedding) with fallback. `Provider.Embed()` interface.
`usage_log` + `model_pricing` tables. Streaming token capture. Vault debt:
UEK re-wrap on password change, destruction on admin reset.
### ✅ v0.10.1 — Polish + UX
Admin system prompt injection, Personas tab, Team Management modal extraction,
preview pane enhancements, code download, personal usage scoped to BYOK.
### ✅ v0.10.2 — Summarize & Continue + Role Cleanup
User-triggered conversation compaction via utility role. Summary as tree node
with boundary metadata. BYOK role overrides (personal → team → global).
Utility rate limiting. Generation role removed.
### ✅ v0.10.3 — Frontend Refactor
2 monolith files → 13 domain-scoped files (~544 lines avg). Zero features,
no function renames. Vanilla JS, no build step.
See [REFACTOR-0.10.3.md](REFACTOR-0.10.3.md).
### ✅ v0.10.4 — Model Type Pipeline + Role Fixes
`model_type` (chat/embedding/image) captured end-to-end from provider API
through catalog to frontend. Role dropdowns filter by type.
### ✅ v0.10.5 — UI Primitives + Extension Surfaces
Shared `Providers`/`Roles` registries, 6 consolidated render primitives,
`showConfirm()` replacing native dialogs, `.popup-menu` CSS primitive.
Removed ~400 lines of duplication.
### ✅ v0.11.0 — Extension Foundation (Browser Tier)
Full extension lifecycle: manifest, loader, scoped `ctx.*` API, browser tool
bridge via WebSocket. Custom renderer pipeline. 2 server tools (calculator,
datetime), 6 built-in browser extensions (Mermaid, KaTeX, CSV, Diff, JS
Sandbox, Regex). See [EXTENSIONS.md](EXTENSIONS.md).
### ✅ v0.12.0 — File Handling + Vision
S3/PVC storage backend, image/file upload (📎, drag-drop, paste), multimodal
message assembly, text extraction pipeline (PDF/DOCX/XLSX/PPTX/ODT/RTF),
vault CLI (`rekey`/`status`), per-chat model persistence.
### ✅ v0.13.0 — Admin Panel Refactor
12-tab modal → fullscreen admin panel. 4 categories (People, AI, System,
Monitoring) × section sidebar. URL-based routing, responsive, banner-aware.
CSS design token cleanup.
### ✅ v0.13.1 — Web Search + URL Fetch
`web_search` + `url_fetch` tools. Search provider abstraction (DuckDuckGo,
SearXNG). Tool categories with per-tool toggle UI in chat bar.
### ✅ v0.14.0 — Knowledge Bases
RAG: upload → chunk → embed (pgvector) → `kb_search` tool. Channel KB toggle.
Team/personal KB scopes. Notes semantic search. Admin panel KB management.
See [DESIGN-0.14.0.md](DESIGN-0.14.0.md).
### ✅ v0.15.0 — Compaction
Background scanner with configurable thresholds. Automatic summarization via
utility role. Per-channel opt-in/out. Context budget guard rail (80% ceiling).
### ✅ v0.15.1 — Context Recall Tools
`attachment_recall` (list + read, channel-scoped), `conversation_search`
(full-text via `plainto_tsquery`). Token estimator attachment awareness.
### ✅ v0.16.0 — User Groups + Resource Grants
Groups (global/team-scoped ACLs) decoupled from team membership. Three-way
resource grants (team_only/global/groups) for Personas and KBs. Grant picker
UI. Schema consolidation: 9 migrations → single `001_v016_schema.sql`.
---
## v0.17.0 — Persona-KB Binding + Enterprise KB Mode + QOL ✅
Personas become **gateways** to knowledge. In enterprise deployments,
users don't interact with KBs directly — they talk to Personas that
have KBs attached. Plus quality-of-life improvements: chat rename,
token display, state persistence, utility model auto-naming.
Depends on: knowledge bases (v0.14.0), user groups (v0.16.0).
**Persona-KB Binding**
- [x] `persona_knowledge_bases` table: `persona_id`, `kb_id`, `auto_search` (bool — always search vs tool-only)
- [x] When a channel uses a Persona with bound KBs, `kb_search` is auto-scoped to those KBs
- [x] No user toggle needed — Persona carries its own KB context
- [x] Channel KB toggle becomes "additional KBs" on top of Persona-provided ones
- [x] Persona system prompt auto-includes KB listing hint (reuses `BuildKBHint` pattern)
- [x] Admin/team admin UI: KB picker on Persona create/edit form
**Enterprise KB Mode**
- [x] `discoverable` flag on knowledge_bases: `true` (default — appears in user's KB popup) or `false` (hidden, only accessible through Persona binding)
- [x] Hidden KBs don't appear in `GET /api/v1/knowledge-bases-discoverable` for non-admins
- [x] Hidden KBs still searchable by `kb_search` tool when accessed through a Persona
- [x] Admin panel: toggle discoverability per KB
- [x] Platform policy: `kb_direct_access` — when `false`, disables channel KB popup entirely (strict enterprise mode)
**Access Control Integration**
- [x] Persona grants (v0.16.0 groups) control who can *use* a Persona
- [x] KB grants control who can *manage* a KB (upload/delete docs)
- [x] Persona-KB binding grants implicit *search* access through the Persona
- [x] Users who can use a Persona can search its KBs, even if they can't see those KBs directly
**Team Admin Workflow**
- [x] Team admin creates KB → uploads documents → marks non-discoverable
- [x] Team admin creates Persona → binds KBs → sets access to Team Only or specific Groups
- [x] Team members see the Persona in their preset list, use it, get KB-powered answers
- [x] Team members never see or manage the underlying KBs
**Technical Debt (carried forward)**
- [x] **Security**: KB create handler authorization — team/global scope verified
- [x] **Test hygiene**: stripped DIAG diagnostics from `TestGroupBasedPersonaAccess`
- [x] **Architecture**: `KnowledgeBaseStore.UpdateDocumentStorageKey()` — moved to store layer
- [x] **UX**: Embedding dropdown fix — tolerant type filter, manual model ID fallback, auto-switch on empty _(already implemented in `ui-primitives.js`)_
- [x] **Minor**: Paste-to-file character threshold — synced from backend `PublicSettings` (`storage.paste_to_file_chars`), admin-configurable, default 2000
**Role Fallback Alerts** ([#69](https://git.gobha.me/xcaliber/chat-switchboard/issues/69))
- [x] Audit log entry on fallback fire: `action = "role.fallback"` with primary/fallback model IDs and error string
- [x] `role.fallback` WebSocket event via EventBus (`PublishAsync`, zero latency impact on completion path)
- [x] In-memory cooldown on `Resolver` (per-role, 5-minute TTL) to deduplicate repeated fallback alerts
- [x] Admin UI: persistent alert banner on `role.fallback` event (persists until dismissed)
- [x] Wire `*events.Bus` into `roles.NewResolver` via `.WithBus()` builder
**QOL / UX Wins**
- [x] **Chat rename**: inline edit on sidebar item — dblclick title → input → blur/Enter saves via `API.updateChannel(id, { title })`
- [x] **Chat token count**: display `Tokens.estimateConversation()` in model bar, update on `selectChat` and after each message
- [x] **State restore on refresh**: persist `App.currentChatId` to `sessionStorage` on select, restore on load
- [x] **Utility model auto-naming**: after first assistant response, background utility role request → `POST /channels/:id/generate-title` → re-render sidebar. Fallback to truncation when no utility model configured. Debounced via `_autoNamePending` set
- [x] **SW extension cache fix**: exclude `/extensions/` from service worker fetch handler
- [x] **Mermaid renderer**: promoted enhanced version (v2.0 — pan/zoom, SVG/PNG export, source copy) to `extensions/builtin/mermaid-renderer/`
---
## v0.17.1 — SQLite Backend ✅
Dual-database support. Every subsequent schema change is developed
against both Postgres and SQLite from day one — no retrofit. SQLite
enables single-binary deployment for dev, demo, edge, and single-user.
Depends on: v0.17.0 DB debt cleanup (store layer is sole DB interface).
**Store Layer**
- [x] 19 SQLite store implementations covering all domain interfaces
- [x] `DB_DRIVER` env var: `postgres` (default) | `sqlite`
- [x] Separate migration files per driver (`migrations/sqlite/`)
- [x] WAL mode + single-writer connection pooling for SQLite concurrency
- [x] CI matrix: full handler integration tests against both Postgres and SQLite
**Vector Search**
- [x] App-level cosine similarity in Go (pure Go, no CGO/sqlite-vec required)
- [x] Embeddings stored as JSON text in `kb_chunks.embedding` column
- [x] Full feature parity with pgvector: `SimilaritySearch`, `InsertChunks`
- [x] Graceful: adequate performance for SQLite-scale deployments (single-user, not millions of chunks)
**Schema Compatibility**
- [x] UUID generation: application-side `store.NewID()` (Go `uuid.New()`)
- [x] JSONB → JSON text columns with `ToJSON()`/`ScanJSON()` helpers
- [x] `UUID[]` arrays → JSON arrays with `ToJSONArray()`/`ScanJSONArray()`
- [x] `TIMESTAMPTZ` → SQLite `TEXT` with `datetime('now')`
- [x] `ON CONFLICT excluded.*` pattern (works in both dialects)
- [x] `INSERT RETURNING id` → separate query pattern for SQLite
**Test Infrastructure**
- [x] `dialectSQL()` converts `$N``?` and strips `::jsonb` at runtime
- [x] `database.PH(n)` returns dialect-appropriate placeholder
- [x] `database.TruncateAll()` dialect-aware (DELETE + PRAGMA vs TRUNCATE CASCADE)
- [x] Generic provider config: `PROVIDER`/`PROVIDER_KEY`/`PROVIDER_URL` (replaces `VENICE_API_KEY`)
- [x] Model selection prefers non-reasoning models in live tests
**What SQLite mode skips** (feature-gated, not broken):
- [x] `LISTEN/NOTIFY` — WebSocket event fan-out uses in-process EventBus (already works)
- [x] Full-text search `tsvector` — conversation_search uses LIKE fallback
---
## v0.17.2 — CodeMirror 6 Integration ✅
Rich editor infrastructure for the frontend. CM6 is ESM-native; the build
step runs in Docker (esbuild → single IIFE bundle). No change to dev
experience for non-editor code — the rest of `src/js/` stays vanilla.
Depends on: nothing (frontend-only). Prerequisite for: extension surfaces
(v0.21.5 editor surface). See [DESIGN-CM6.md](DESIGN-CM6.md) for full spec.
**Build Pipeline**
- [x] `src/editor/` directory: `package.json`, `build.mjs`, `index.mjs`, language/theme modules
- [x] `scripts/build-editor.sh`: shared build script for both Dockerfiles and local dev
- [x] New Docker stage (`cm6-build`): `npm ci` + `node build.mjs``vendor/codemirror/`
- [x] Both `Dockerfile.frontend` and `Dockerfile` (unified) use the shared build script
- [x] Bundle output: `codemirror.bundle.js` (~295KB min, ~90KB gzip)
- [x] Graceful degradation: all integration points check `window.CM` — falls back to `<textarea>` if bundle unavailable
**Languages (bundled)**
- [x] Markdown, JavaScript, JSON, SQL, HTML, CSS, YAML, Go, Python, Rust
- [x] Additional modes: one-line import + rebuild
**Phase 1: Extension Editor** (admin panel)
- [x] `CM.codeEditor()` factory: line numbers, bracket matching, auto-indent, search/replace
- [x] Replace manifest `<textarea>` → CM6 JSON mode
- [x] Replace script `<textarea>` → CM6 JavaScript mode
- [x] Remove manual Tab-key handler in `admin-handlers.js` (CM6 handles it)
- [x] Update `saveAdminExtension()` to use `.getValue()`
**Phase 2: Chat Input** (markdown mode)
- [x] `CM.chatInput()` factory: markdown highlighting, minimal chrome (no line numbers, no gutter)
- [x] Enter=send, Shift+Enter=newline keybindings
- [x] Auto-growing height, placeholder text
- [x] Wire `onChange``updateInputTokens()`
- [x] Update `chat.js`, `attachments.js`, `tokens.js` to use CM API
- [x] WYSIWYG fenced code block decorations (visual container matching claude.ai UX)
- [x] Inline code shortcut (Ctrl/Cmd+E)
**Phase 3: Polish**
- [x] Theme integration: CSS variable overrides (`--bg`, `--border`, `--accent`, etc.)
- [x] Dark/light/system mode toggle in appearance settings
- [x] Vim/Emacs keybinding preference in appearance settings (`@replit/codemirror-vim`, `@replit/codemirror-emacs`)
- [x] Vim/Emacs applies to code editor + extension editor only (never chat input)
- [x] SW cache: exclude `vendor/codemirror/` with version bust
- [x] Update `debug.js` snapshot to include CM6 version
- [x] Documentation in ARCHITECTURE.md
**CI/CD**
- [x] Path-based change detection gating (FE-only → skip BE tests, docs-only → skip all)
---
## v0.17.3 — Notes Graph + Wikilinks ✅
Knowledge graph and bi-directional linking for the notes system. Transforms
notes from flat documents into an interconnected knowledge base with
Obsidian-style `[[wikilinks]]`, backlinks, graph visualization, and
transclusion.
Depends on: CodeMirror 6 (v0.17.2), Notes CRUD (v0.13.x). See
[DESIGN-0.17.3.md](DESIGN-0.17.3.md) for full spec.
**Backend: Note Links**
- [x] `note_links` table (Postgres + SQLite migrations)
- [x] `NoteLinkStore` interface + both implementations
- [x] `ExtractWikilinks()` regex parser + tests
- [x] Link extraction on note create/update
- [x] Dangling link resolution on note create
- [x] `notes.source_message_id` column for chat-to-note provenance
**API Endpoints**
- [x] `GET /notes/:id/backlinks` — notes linking to this note
- [x] `GET /notes/search-titles?q=` — lightweight fuzzy search for autocomplete
- [x] `GET /notes/graph` — full graph topology (nodes + edges + unresolved)
**CM6 Note Editor**
- [x] `note-editor.mjs` factory: markdown live preview (heading sizes, blockquotes, code blocks)
- [x] `wikilink.mjs` CM6 extension: parse, decorate as clickable chips, autocomplete on `[[`
- [x] Textarea → CM6 swap in `notes.js` with graceful fallback
- [x] `noteEditorTheme` in `theme.mjs`
**Graph Visualization**
- [x] Canvas-based force-directed graph (~200 lines, no d3 dependency)
- [x] O(n²) Coulomb repulsion + Hooke spring + center gravity
- [x] Pan, zoom (0.154.0x), drag nodes, hover highlight, click to open
- [x] Node sizing by link_count, folder-based coloring
- [x] Ghost nodes for unresolved `[[links]]` with toggle
- [x] Energy-based pause (stop rAF below KE threshold)
- [x] ResizeObserver for responsive canvas
**Note-from-Selection + Daily Notes**
- [x] "Note" button in message action bar
- [x] Selection-aware capture (`window.getSelection()` within message)
- [x] Provenance tracking (`source_channel_id` + `source_message_id`)
- [x] "Today" button → find-or-create daily note in `/daily/`
**Read Mode**
- [x] `[[link]]` rendered as clickable wikilink chips
- [x] `![[embed]]` transclusion with async content fetch, recursion guard
- [x] Backlinks panel (collapsible, with count badge)
---
## v0.18.0 — Memory (User + Persona Scopes) ✅
Long-term memory across conversations, with scope-aware isolation.
Unlike KB (static documents) or compaction (within-conversation), this
captures facts and preferences that persist across channels.
**Key differentiator: Persona-scoped memory.** Each Persona can build
its own memory independently of user memory, preventing cross-context
contamination and enabling specialized knowledge accumulation.
Depends on: compaction (v0.15.0), knowledge bases (v0.14.0), persona-KB binding (v0.17.0), SQLite backend (v0.17.1).
See [DESIGN-0.18.0.md](DESIGN-0.18.0.md) for full spec.
**Memory Scopes**
- [x] `user` — personal facts/preferences, persists across all conversations (current industry standard)
- [x] `persona` — shared across all users of that Persona, accumulated from conversations (differentiator)
- [x] `persona+user` — per-user within a Persona context (e.g. tutoring progress per student)
- [x] Configurable per Persona: which scopes are active, whether user memory is passed through
**Data Model**
- [x] `memories` table: `id`, `scope` (user, persona, persona_user), `owner_id` (user_id or persona_id), `user_id` (nullable — for persona+user scope), `key`, `value`, `source_channel_id`, `confidence` (float), `status` (active, pending_review, archived), `created_at`, `updated_at`
- [x] Index on `(scope, owner_id, user_id)` for fast lookup
- [x] Embedding column (`vector(3072)`) for semantic memory search
**Tools**
- [x] `memory_save` tool: LLM explicitly stores a fact
- Scope-aware: saves to the active memory scope for the current Persona context
- Structured: `key` (short label) + `value` (detail) + `confidence`
- [x] `memory_recall` tool: LLM queries stored facts relevant to current context
- Merges results from applicable scopes (user + persona + persona+user)
- Semantic search via embeddings + keyword fallback
**Automatic Extraction**
- [x] Background job: post-conversation analysis identifies memorable facts (opt-in)
- [x] Configurable extraction prompt per Persona (e.g. "extract FAQ-worthy Q&A pairs")
- [x] Extracted memories start in `pending_review` status
**Review Pipeline**
- [x] Admin/team admin review queue: pending memories with approve/reject/edit
- [x] Persona memory review: team admins see what Personas are "learning"
- [x] User memory review: users see their own memories in Settings
**Memory Injection**
- [x] At completion time: inject relevant memories into system prompt
- [x] Context budget aware: limit injected memory tokens
- [x] Scope priority: persona+user > persona > user (most specific wins on conflicts)
**Use Cases**
- [x] Helpdesk Persona: builds FAQ from repeated questions, human-reviewable
- [x] Roleplay Persona: isolated memory prevents tone/context bleeding from user's other conversations
- [x] Tutoring Persona: tracks per-student progress, common misconceptions
- [x] Sales Persona: accumulates objection responses from real conversations
- [x] Onboarding Persona: learns what new hires commonly struggle with
**User Controls**
- [x] Settings → Memory: view, edit, delete personal memories
- [x] Per-Persona memory toggle: "Allow this persona to remember things about me"
- [x] Admin: enable/disable, retention policies, per-team scoping
- [x] Privacy: user memories never cross team boundaries; persona memories respect group access
---
## v0.18.1 — Side Panel Architecture ✅
Refactored the side panel from a shared-tab layout to independent
single-slot panels. Any action fills the slot, replacing whatever was
there — no tabs, no association between panel types. Extension UI
primitives give browser extensions safe access to host app features.
Depends on: Notes graph + wikilinks (v0.17.3). Prerequisite for: live
collaboration (v0.23.0) where multiple panels need simultaneous visibility.
**Panel System**
- [x] Panel registry: named panels with independent open/close state
- [x] Single-slot model: action-driven, each open replaces the previous
- [x] Dual-view mode: two panels side-by-side (configurable split ratio via drag divider)
- [x] Panel-persistent state: each panel remembers scroll position, open note, etc.
- [x] Header label shows active panel name (replaces tab bar)
- [x] Keyboard shortcut: Ctrl/Cmd+\ cycles panels, Ctrl/Cmd+Shift+\ toggles dual
**Preview Panel**
- [x] Dedicated preview panel (independent of Notes)
- [x] HTML/document preview with iframe sandbox
- [x] Code output preview (extension-rendered blocks via pop-out)
- [x] Live-updating during streaming responses (500ms debounce)
**Extension UI Primitives**
- [x] `ctx.ui.toast()` — toast notifications
- [x] `ctx.ui.openPreview()` — load HTML into side panel preview
- [x] `ctx.ui.isDark()` — theme detection
- [x] `ctx.ui.isMobile()` — viewport width check
- [x] `ctx.ui.isPanelOpen()` — side panel visibility
- [x] `ctx.ui.confirm()` — modal confirm dialog
- [x] Mermaid extension refactored to use primitives exclusively (zero direct globals)
- [x] Context-aware expand: single button, fullscreen or side panel pop-out
**Mobile**
- [x] Swipe navigation between panels
- [x] Tap-to-close overlay
- [x] Graceful collapse to single-panel on narrow viewports
- [x] Enlarged touch targets, fullscreen close button (40px desktop, 48px mobile)
---
## ✅ v0.19.0 — Projects / Workspaces
Organizational containers that group related conversations, KBs, and
notes into a single workspace with shared access controls.
Depends on: user groups (v0.16.0), knowledge bases (v0.14.0).
**Data Model**
- [x] `projects` table: `id`, `name`, `description`, `color`, `icon`, `scope` (personal/team/global), `owner_id`, `team_id`, `is_archived`, `settings` (JSONB)
- [x] `project_channels` junction: ordered membership with UNIQUE `channel_id`, denormalized FK on `channels.project_id`
- [x] `project_knowledge_bases` junction: with `auto_search` flag
- [x] `project_notes` junction
- [x] `resource_grants` CHECK extended to include `'project'`
**Features**
- [x] Channels can belong to a project (optional `project_id` FK)
- [x] KBs can belong to a project → auto-linked to all channels in the project (BuildKBHint + kbsearch)
- [x] Notes can belong to a project → auto-associated when created from project channel
- [x] KB resolution chain: Persona → Project → Channel → Personal
- [x] Project sidebar section: collapsible groups above time-based Recent section
**UI**
- [x] Sidebar: projects as collapsible groups with color dots, counts, options menu
- [x] Right-click context menu: move chat to project / remove / create-and-assign
- [x] Drag-and-drop channels between project groups and Recent
- [x] New Project button in split dropdown
- [x] Channel list `project_id` filter (`?project_id=uuid` or `?project_id=none`)
- [x] Collapse state persisted in localStorage
**Deferred to later versions:**
- Project creation dialog (name, description, default Persona, default KBs) — using prompt() for now
- ~~Project detail panel (KB + note management within a project)~~ → v0.19.1
- ~~Project-level Persona default~~ → v0.19.2
- Folders within projects
- Project templates
- Admin-level team/global project management
- Project-specific files (full project-level upload — deferred for proper architecture)
- Notifications (moved to v0.20.0)
---
## ✅ v0.19.1 — Active Project + Project System Prompt + Detail Panel
Quality-of-life improvements making projects usable for daily workflow.
No migrations.
Depends on: v0.19.0 Projects/Workspaces.
**Active Project**
- [x] Pin a project as active — new chats auto-assign via `addChannelToProject` after channel creation
- [x] `App.activeProjectId` persisted in `localStorage('cs-active-project')`
- [x] Visual indicator: `.project-group.active` accent border + 📌 icon
- [x] Toggle from project ⋯ menu ("Pin as active" / "Unpin project")
- [x] Cleared on project delete
**Project System Prompt**
- [x] Per-project instructions in `projects.settings` JSONB (`system_prompt` key)
- [x] Injected in `loadConversation` between persona/channel prompt and KB hint
- [x] Merge semantics on update: reads existing JSONB, overlays patch keys, writes back
- [x] Both Postgres and SQLite stores updated
**Project Detail Panel**
- [x] Registered with `PanelRegistry` (same pattern as Notes, Preview)
- [x] System prompt textarea with Save button
- [x] KB management: list with names (LEFT JOIN), [+ Add] picker dropdown, [✕] remove
- [x] Notes list with titles (LEFT JOIN), [✕] unbind
- [x] Accessible from project ⋯ menu → "Project settings"
**Bug Fixes**
- [x] `renderChatList` early return prevented project groups from rendering when zero chats
- [x] Recent section drop target: "Drop chats here to unassign" hint with `min-height: 40px`
---
## ✅ v0.19.2 — Project Persona Default + Archive + Channel Reorder
Completes the project management feature set. No migrations.
Depends on: v0.19.1.
**Project Persona Default**
- [x] Bind a persona to a project via detail panel dropdown
- [x] Stored in `projects.settings.persona_id`
- [x] Resolution chain: explicit `req.PresetID` → project persona → none
- [x] Inherits model, provider config, temperature, max tokens, system prompt as defaults
**Project Archive Toggle**
- [x] Checkbox in project detail panel
- [x] Archived projects hidden from sidebar by default
- [x] "▸ Show archived (N)" toggle button below project list
- [x] Chats in hidden-archived projects spill into Recent section (never vanish)
- [x] Dimmed + italic visual treatment for archived groups
**Channel Reorder**
- [x] `loadProjectChannelPositions()` fetches server-persisted positions on startup
- [x] `_getReorderedProjectChats()` sorts project chats by stored position
- [x] Right-click context menu: ↑ Move up / ↓ Move down (optimistic swap + API call)
- [x] Order maintained across add/remove/move operations
---
## v0.20.0 — Notifications + @mention Routing + Multi-model ✅
Notification infrastructure that makes collaboration real-time, plus
multi-model routing for channels. Three-phase delivery: notifications
core (in-app), @mention parsing + fan-out completions, email transport
+ per-user notification preferences.
_(Notifications shifted from v0.19.0; @mention routing shifted from v0.17.0)_
Depends on: v0.19.2 (Projects complete), EventBus + WebSocket hub (v0.9.x),
`channel_models` table (v0.16.0 schema). See
[DESIGN-0.20.0.md](DESIGN-0.20.0.md) for full spec.
**Phase 1 — Notifications Core (in-app)**
- [x] `notifications` table: `id`, `user_id`, `type`, `title`, `body`, `resource_type`, `resource_id`, `is_read`, `created_at` (Postgres + SQLite migrations)
- [x] `NotificationStore` interface + both implementations: Create, ListByUser (paginated), MarkRead, MarkAllRead, Delete, UnreadCount
- [x] `notifications.Service` with `Notify()` / `NotifyMany()` — centralized creation + WebSocket dispatch
- [x] EventBus routes: `notification.new`, `notification.read` (badge sync across tabs)
- [x] API endpoints: list, unread-count, mark-read, mark-all-read, delete (5 endpoints, all user-scoped)
- [x] Initial sources: `role.fallback` (EventBus subscription), `kb.ready`/`kb.error`, `grant.changed`
- [x] Frontend: bell icon + unread badge (capped 9+), notification dropdown (latest 10, click-to-navigate), full panel via PanelRegistry
- [x] WebSocket handler: real-time push + toast for high-priority types
- [x] Background cleanup goroutine (configurable retention, default 90 days)
**Phase 2 — @mention Parsing + Multi-model Routing**
- [x] `mentions.Parse()`: extract @mentions, resolve against channel model roster (case-insensitive, longest-match-first, trailing punctuation tolerant)
- [x] Parser tests: no mentions, unresolved, multiple, overlapping names, punctuation edge cases
- [x] Channel model CRUD handlers (4 endpoints: list, add, remove, update)
- [x] Completion handler: mention extraction → target resolution → sequential fan-out → N assistant messages
- [x] SSE streaming: model attribution in delta events (`model_display` field)
- [x] Frontend: model pills in chat header with add/remove UI
- [x] Frontend: @mention autocomplete via CM6 `mentionCompletion` extension (roster-backed)
- [x] Frontend: model attribution labels on multi-model assistant messages
- [x] Backward compat: channels with no extra `channel_models` rows work exactly as before
**Phase 3 — Email Transport + Notification Preferences**
- [x] `notification_preferences` table (Postgres + SQLite): per-user, per-type in_app/email toggles
- [x] Preference resolution chain: specific type → user wildcard `*` → system default (in_app=true, email=false)
- [x] `EmailTransport`: SMTP with implicit TLS (port 465) and STARTTLS (port 587), multipart MIME (HTML + plaintext)
- [x] Email templates: branded HTML + plaintext, domain-prefixed subjects, Go `html/template`
- [x] Preference CRUD endpoints (3: list, set with partial patch, delete)
- [x] Admin SMTP configuration: enable toggle, host/port/user/password/from/TLS fields, test email button
- [x] User notification preferences UI (Settings → Notifications tab, per-type checkboxes)
- [x] Notification service: preference check before dispatch, async email delivery (goroutine, 30s timeout)
- [x] Tests: preference resolution chain (7 tests), email templates (4 tests)
- [x] Deferred: digest mode (batched email), SMTP password vault encryption
**Hotfix (carried forward from v0.19.2 investigation)**
- [x] `user_model_settings` NULL scan fix: COALESCE on `hidden`/`sort_order` in SELECT + INSERT for both dialects
- [x] Gin release mode: auto-set `gin.ReleaseMode` when `ENVIRONMENT=production`, suppress health check log spam
---
## v0.21.x — Workspace Platform + Extension Surfaces
Seven-release series decomposing workspace storage, tools, indexing, git,
surface infrastructure, and editor/article modes. Full specification in
[DESIGN-0.21.0.md](DESIGN-0.21.0.md).
Depends on: file storage (v0.12.0), extension foundation (v0.11.0),
CodeMirror 6 (v0.17.2), knowledge base embedding pipeline (v0.14.0).
### v0.21.0 — Workspace Storage Primitive ✅
Pure backend foundation. Workspaces as a polymorphic platform primitive
owned by users, projects, channels, or teams. Dual-layer storage: PVC
filesystem (source of truth) + DB metadata index (queryable cache).
- [x] `workspaces` table: polymorphic owner (user/project/channel/team), root_path, max_bytes quota, status
- [x] `workspace_files` table: metadata index (path, MIME type, size, sha256, is_directory)
- [x] `WorkspaceStore` interface: CRUD, file index (upsert/delete/list/prefix), ownership lookup, stats
- [x] Postgres + SQLite store implementations with upsert-on-conflict for file index
- [x] `workspace.FS` package: read, write (atomic via temp+rename), delete, mkdir, stat, list, reconcile (FS→DB sync)
- [x] `workspace.Archive`: zip/tar.gz extract + create with archive bomb protection (10K file limit, 100MB single file, quota enforcement), common-prefix stripping
- [x] Content type detection: extension-based (40+ source code types) with http.DetectContentType fallback
- [x] SHA256 computed during write via tee reader (enables content-addressed skip in v0.21.2)
- [x] Path traversal guards: cleanPath + absPath validation, symlink rejection
- [x] 15 API endpoints: workspace CRUD, file CRUD, archive upload/download, reconcile, stats
- [x] Owner-based authorization: user=self, channel=owner, project=member, team=member
- [x] Unit tests: path cleaning, traversal detection, MIME detection, unsafe path filtering, write/read round-trip, delete, mkdir
### v0.21.1 — Workspace Tools + Channel/Project Binding ✅
Make workspaces useful in chat mode via tool calls.
- [x] Workspace tools (category: workspace): `workspace_ls`, `workspace_read` (50KB soft limit), `workspace_write` (auto-mkdir), `workspace_rm` (recursive guard), `workspace_mv`, `workspace_patch` (find/replace)
- [x] `channels.workspace_id` FK, `projects.workspace_id` FK
- [x] Workspace resolution: channel workspace → project workspace (override pattern)
- [x] Tool injection in completion handler when workspace bound
- [x] Frontend: deferred (channel settings workspace toggle, project Files tab, chat bar workspace indicator)
### v0.21.2 — Workspace Indexing + Semantic Search ✅
Embed text files for semantic search. Reuses `knowledge.SplitText` + `knowledge.Embedder`.
- [x] `workspace_chunks` table (Postgres + SQLite migrations)
- [x] `workspace_files` additions: `index_status`, `chunk_count` columns
- [x] `workspaces.indexing_enabled` boolean (default true)
- [x] Store methods: `InsertChunks`, `DeleteChunksByFile`, `SimilaritySearch`, `UpdateFileIndexStatus`
- [x] Indexable types: text MIME types + 40+ code extensions + special filenames (Makefile, Dockerfile, etc.)
- [x] Code-aware chunking: 1500-char chunks with function/class/type/sub boundary separators
- [x] Content-addressed skip: sha256 comparison before re-chunking/re-embedding
- [x] `workspace.Indexer`: background goroutine with configurable concurrency semaphore
- [x] Single-file indexing via `FS.WriteFile` hook (`SetIndexer`)
- [x] Batch indexing via `ExtractArchive` (sequential within one semaphore slot)
- [x] `workspace_search` tool: semantic search with optional glob filtering, top-K capped at 20
- [x] `GET /api/v1/workspaces/:id/index-status` endpoint (per-status file counts, total chunks)
- [x] Configuration: `WORKSPACE_INDEXING_ENABLED`, `WORKSPACE_INDEX_CONCURRENCY` env vars
- [x] Graceful degradation when no embedding role configured
- [x] Mock store updated for FS unit tests
### v0.21.3 — Surface Infrastructure + REPL ✅
Pure UI architecture. No workspace dependency (parallel development).
- [x] `data-surface-region` attributes on index.html containers (surface-header, surface-main, surface-footer, sidebar-content)
- [x] `surfaces.js` — SurfaceRegistry: register, activate, deactivate, getCurrent, list
- [x] `ctx.ui.replace()` / `ctx.ui.restore()` with DOM preservation (DocumentFragment-based)
- [x] `ctx.surfaces.register()` API for extensions
- [x] Mode selector component in sidebar (`#modeSelectorWrap`, auto-shown when ≥2 surfaces)
- [x] Chat as default surface (implicit, always registered)
- [x] `surface.activated` / `surface.deactivated` / `surface.registered` / `surface.unregistered` EventBus events
- [x] REPL tab: AsyncFunction wrapper, global injection (API, Events, Extensions, Surfaces, DebugLog, Panels, UI, $, $$, sleep)
- [x] REPL tab: pretty-print results (collapsible JSON, type-colored primitives, DOM element summaries)
- [x] REPL tab: command history (sessionStorage, ↑/↓ navigation)
- [x] REPL tab: tab-completion on object graphs, event labels, globals
- [x] REPL tab: event label hints (Events.on/emit completion)
- [x] REPL tab: admin gate (admin role OR ?debug=1 URL param)
- [x] REPL tab: toolbar (clear, copy, help)
- [x] CSS: mode selector + REPL styles
- [x] Documentation in EXTENSIONS.md §6 updated with implementation details
- [ ] Mobile: mode selector collapses to hamburger/bottom nav (deferred — functions via sidebar on mobile)
- [ ] Integration with extension loader (surfaces from manifest — deferred to extension loader update)
### v0.21.4 — Git Integration
Layer git operations onto workspaces.
- [ ] `workspaces` additions: git_remote_url, git_branch, git_credential_id, git_last_sync
- [ ] `git_credentials` table: auth_type (https_pat/https_basic/ssh_key), encrypted_data (AES-256-GCM)
- [ ] Git operations via exec: clone, pull, push, status, diff, commit, log, branch, checkout
- [ ] Workspace tools (git-aware): `git_status`, `git_diff`, `git_commit`, `git_log`, `git_branch`
- [ ] Post-operation hooks: clone/pull/checkout trigger reconcile + re-index changed files
### v0.21.5 — Editor Surface (Development Mode)
IDE-like experience. Browser-tier extension consuming workspace primitives.
- [ ] Layout: file tree (sidebar), code editor (CM6, main), AI chat panel (resizable split), status bar
- [ ] File tree: workspace_ls backed, git status indicators, context menu, drag-drop
- [ ] Code editor: CM6 codeEditor() factory, language auto-detection, tab bar, Ctrl+S save
- [ ] AI chat panel: same channel context, workspace tools auto-injected, live update via EventBus
- [ ] Keyboard shortcuts: Ctrl+P quick open, Ctrl+Shift+F workspace search
### v0.21.6 — Article Surface + Document Output Pipeline
Writing-focused surface. Document is artifact, conversation is secondary.
- [ ] Document output pipeline: write → workspace → export (markdown → HTML/PDF/DOCX via pandoc)
- [ ] Layout: outline (sidebar top), AI assistant (sidebar bottom), rich text editor (CM6 markdown, main)
- [ ] Outline: auto-generated from headings, click-to-scroll, drag to reorder
- [ ] AI assistant: lightweight chat with article-specific tools (suggest_outline, expand_section, check_citations)
- [ ] Rich text editor: CM6 noteEditor() with enhanced live preview, focus mode
- [ ] Export: download as markdown/HTML/PDF, copy to clipboard
---
## v0.22.0 — Smart Routing + Provider Extensions
Depends on: model roles (v0.10.0), usage tracking (v0.10.0).
Rules-based routing engine — policy, not ML. Plus declarative provider
configuration to replace hardcoded provider-specific behavior.
_(Shifted from v0.19.0 — routing content unchanged, provider extensions added)_
**Routing**
- [ ] Admin routing policies: "cheapest model with required capabilities",
"prefer private providers, fallback to cloud", "for team X, use Y"
- [ ] Fallback chains: primary provider down → next with same model
- [ ] Cost-aware: factor pricing into routing decisions
- [ ] Latency-aware: track response times per provider, prefer faster
**Provider Extensions (declarative provider config)**
- [ ] `provider_profiles` table (or JSONB on `api_configs`): per-provider configuration schema
- [ ] System prompt injection: provider-specific preambles (e.g. Venice character system prompt)
- [ ] Thinking mode toggle: per-provider `think` parameter support (Venice `venice_parameters.include_venice_system_prompt`, Anthropic `thinking`, etc.)
- [ ] Request transform hooks: provider-specific parameter mapping before API call
- [ ] Response transform hooks: normalize provider-specific response fields
- [ ] Admin UI: provider profile editor (key-value config per provider type)
- [ ] Preset-level overrides: Persona can override provider-specific settings (e.g. "always enable thinking for this Persona")
- [ ] Provider health: track error rates, latency percentiles, auto-disable unhealthy providers
- [ ] Search/URL fetch rate limiting per provider
- [ ] Capability admin/user override: manual correction for model capabilities (`intrinsic.go` admin override layer)
---
## v0.23.0 — Multi-Participant Channels + Presence
The channel foundation for workflows and real-time collaboration. Today
channels are single-user direct chats. This release makes channels a
shared space that multiple actors can inhabit.
Depends on: extension surfaces (v0.21.3), WebSocket infrastructure (already exists).
_(Shifted from v0.20.0 — no content changes)_
**Channel Participants**
- [ ] `channel_participants` table: `channel_id`, `participant_type` (user, session, persona), `participant_id`, `role` (owner, member, observer), `joined_at`
- [ ] Channel access queries rewritten: `WHERE user_id = $1` → participant-based lookup
- [ ] Backward compatible: existing single-user channels auto-have one participant (owner)
- [ ] Channel `type` column: `direct` (current), `group` (multi-user), `workflow` (staged)
**Presence + Real-time**
- [ ] Typing indicators and presence (who's online, who's in this channel)
- [ ] Participant join/leave events via WebSocket
- [ ] Co-editing for extension surfaces (editor mode, article mode)
- [ ] Cursor sharing, selection highlighting
**Channel-Scoped Notes**
- [ ] Optional `channel_id` FK on notes (NULL = personal notebook, set = channel-attached)
- [ ] Notes created by tool calls within a channel auto-attach to that channel
- [ ] Channel notes visible to all participants (not just creator)
---
## v0.24.0 — Auth Strategy (mTLS/OIDC) + Full RBAC
Enterprise auth modes on top of the teams + groups foundation.
Depends on: vault passphrase support from v0.9.3 (conditional unlock for
personal providers under external auth), user groups (v0.16.0).
_(Shifted from v0.21.0 — enhanced with group-based permissions)_
- [ ] `AUTH_MODE` env var: `builtin` | `mtls` | `oidc`
- [ ] All three resolve to the same internal user model
- [ ] `auth_source` + `external_id` columns on users table
- [ ] mTLS: header trust, auto-provision from cert DN
- [ ] OIDC: Keycloak/Okta token validation, claim extraction, role mapping
- [ ] Per-source auto-activate policy: auto_activate, default_team, default_role
- [ ] Vault passphrase prompt for mTLS/OIDC users (v0.9.3 conditional unlock)
- [ ] Fine-grained permissions: model access, KB write, task create, token budgets
- [ ] Group-based permission sets: assign permissions to groups, users inherit from membership
- [ ] OIDC claim → group mapping: external IdP groups auto-sync to internal groups
**Anonymous / Session Participants**
- [ ] Session-based identity for unauthenticated visitors (workflow intake)
- [ ] mTLS: cert CN/fingerprint as stable session identity (no `users` row required)
- [ ] Non-mTLS: ephemeral session token (cookie or URL token)
- [ ] Session participants can send messages and trigger tool calls within workflow channels
- [ ] Session identity visible to assigned team members (cert DN, display name, or "Anonymous #N")
---
## v0.25.0 — Workflow Engine
Team-owned, stage-based process execution. The channel is the runtime,
personas drive each stage, and the existing tool/notes infrastructure
handles structured data collection. See [ARCHITECTURE.md — Workflow
Architecture](ARCHITECTURE.md#workflow-architecture-future--v0210) for
the conceptual model.
Depends on: multi-participant channels (v0.23.0), anonymous identity (v0.24.0).
_(Shifted from v0.22.0 — no content changes, dependency refs updated)_
**Workflow Definitions**
- [ ] `workflows` table: `team_id` (owner), `name`, `description`, `is_active`, `entry_mode` (public_link, team_internal, api)
- [ ] `workflow_stages` table: `workflow_id`, `ordinal`, `persona_id`, `assignment_team_id`, `form_template` (JSONB, structured note schema), `transition_rules` (JSONB)
- [ ] Team-admin CRUD: create/edit/delete workflows and stages
- [ ] Workflow versioning: edits create new version, active instances continue on their version
**Workflow Instances (Channels)**
- [ ] Workflow-typed channels: `type='workflow'`, `workflow_id`, `current_stage`, `stage_version`
- [ ] Entry point: public link generates workflow channel, adds anonymous participant, binds stage 1 persona
- [ ] Stage transitions: triggered by AI (tool call), team member (button), or rule (form complete)
- [ ] On transition: swap active persona, notify assignment team, update channel metadata
**AI Intake**
- [ ] Stage persona drives structured collection via system prompt
- [ ] Form template → persona system prompt injection ("collect these fields: ...")
- [ ] Tool calls create channel-scoped notes as form responses
- [ ] AI determines readiness: "I have everything needed" → trigger transition
**Assignment + Queue**
- [ ] Assignment queue: unassigned workflow channels visible to team members
- [ ] Claim model: team member claims channel (becomes participant with `member` role)
- [ ] Round-robin / rule-based auto-assignment (optional, per-stage config)
- [ ] Assignment notifications via WebSocket + optional webhook
**Team Member Collaboration**
- [ ] Assigned member sees full history (AI intake + artifacts + notes)
- [ ] Persona remains active — assists both visitor and team member
- [ ] Member can trigger stage transitions, add notes, invoke tools
- [ ] Member can reassign to different team member or escalate to different team
**Frontend**
- [ ] Workflow builder UI in team admin panel (stage list, persona picker, form template editor)
- [ ] Queue view: sidebar section showing unassigned workflow channels for user's teams
- [ ] Channel header: workflow stage indicator, transition controls
- [ ] Anonymous visitor view: minimal UI, persona-driven conversation (public link entry)
---
## v0.26.0 — Tasks / Autonomous Agents
Unattended execution — workflows without a human in the loop.
Depends on: workflow engine (v0.25.0).
_(Shifted from v0.23.0 — no content changes, dependency refs updated)_
- [ ] Scheduler + task runner (cron-like triggers for workflow instantiation)
- [ ] `task_create` tool (AI can spawn sub-workflows)
- [ ] `type: 'service'` channels: workflow instances with no human participants
- [ ] Execution budgets: max tokens, max tool calls, max wall-clock per stage
- [ ] Admin controls for resource limits and kill switches
- [ ] Completion webhooks (notify external systems when workflow completes)
---
## TBD (unscheduled — real features, no immediate need)
Items that are real but don't yet have a version assignment. Pull left
based on need.
**Extension System — Additional Extensions**
- Image generation tool (browser or sidecar, provider-agnostic)
- STT/TTS (browser extension, Web Speech API — personal use case)
- Code execution sandbox (server-side, container isolation)
**Extension System — Server Tiers**
- Starlark runtime integration (Tier 1 — server sandbox)
- Sidecar HTTP tool protocol (Tier 2 — container isolation)
- Server-side tool execution in completion handler
**Desktop + Mobile**
- Desktop app (Tauri)
- Full PWA with offline capability
- Mobile-optimized layouts (beyond current responsive)
**Data + Portability**
- Bulk export/import (account data, conversations, settings)
- ChatGPT/other tool import
- GDPR-style "download my data"
- Backup/restore CronJob manifests
**UX / Multi-Seat**
- "Group" scope badge on model selector / KB list: show access-source annotation so users see _why_ they have access (global, team, group grant). Requires backend to include `access_source` in list responses.
- Per-provider model preferences: `user_model_settings` unique key is `(user_id, model_id)` — same model from different providers shares one visibility toggle. Needs `provider_config_id` dimension in DB constraint, store, API, and frontend `hiddenModels` keying. Frontend composite key (`configId:modelId`) already exists in `App.models[].id`.
**Projects — Future**
- Project-specific files: full project-level upload (own endpoint, storage path, UI surface — not just channel attachment re-linking)
- Project templates: create new projects from predefined configurations (persona, KBs, system prompt)
- Project creation dialog: replace `prompt()` with proper modal (name, description, persona, KB picker)
- Admin-level project management: cross-instance visibility, reassign ownership, enforce team policies (scope: enterprise only, BYOK personal projects stay private)
- Sub-projects / nested hierarchy: child inherits parent KBs, system prompt, persona (deferred until usage patterns clarify need vs tags/labels)
**Knowledge Bases — Future**
- KB auto-injection: top-K chunk prepend to system prompt, context budget aware, per-channel toggle (latency budgeting required)
- Hybrid search: combine vector similarity with full-text `tsvector`, re-rank
- Semantic chunking: embedding-based boundary detection for smarter splits
- HNSW index: better query performance than IVFFlat for large datasets
- Web scraping source: ingest URLs as KB documents (extends url_fetch)
- Scheduled re-indexing: periodic rebuild when source documents update
- ~~Store cleanup: add `UpdateDocumentStorageKey()` to `KnowledgeBaseStore` interface~~ _(done in v0.17.0)_
(currently uses direct `database.DB.ExecContext` in handler — works but bypasses store layer)
**Memory — Future**
- Memory compaction: summarize old memories to save context tokens
- Memory confidence decay: reduce confidence over time, prune low-confidence entries
- Memory export/import: portable memory format across instances
- Cross-persona memory sharing (opt-in): e.g. "coding assistant" can read facts from "project manager"
- Memory analytics: dashboard showing what Personas are learning, memory growth trends
**Platform**
- Rate limiting per user/team/tier (token budgets)
- ~~Provider health monitoring~~ → v0.22.0 + key rotation
- Multi-tenant SaaS mode
- Plugin/extension marketplace
- Virtual scroll for long conversations
- ~~SQLite backend option (single-user / dev)~~ → v0.17.1