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-02-28 18:24:19 +00:00

785 lines
39 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 (independent panels, dual-view)
v0.19.0 Projects / Workspaces + Notifications
v0.20.0 @mention Routing + Multi-model
v0.21.0 Extension Surfaces + Modes (depends on CM6 from v0.17.2)
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.0 editor mode). 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
Refactor the side panel system so Notes, HTML/code previews, and future
panels (knowledge base browser, search results) operate independently
rather than sharing a single slot. Currently, opening Notes hides the
preview panel and vice versa — this is confusing when reviewing AI-
generated HTML/documents while also managing notes.
Depends on: Notes graph + wikilinks (v0.17.3). Prerequisite for: live
collaboration (v0.23.0) where multiple panels need simultaneous visibility.
**Panel System**
- [ ] Panel registry: named panels with independent open/close state
- [ ] Dual-view mode: two panels side-by-side (configurable split ratio)
- [ ] Tab-persistent state: each panel remembers scroll position, open note, etc.
- [ ] Panel priority: when space is tight (mobile), most-recently-opened wins
- [ ] Keyboard shortcut: Ctrl/Cmd+\ cycles panels, Ctrl/Cmd+Shift+\ toggles dual
**Preview Panel**
- [ ] Dedicated preview panel (independent of Notes)
- [ ] HTML/document preview with iframe sandbox
- [ ] Code output preview (extension-rendered blocks)
- [ ] Live-updating during streaming responses
**Mobile**
- [ ] Swipe navigation between panels
- [ ] Bottom sheet mode for secondary panel
- [ ] Graceful collapse to single-panel on narrow viewports
---
## v0.19.0 — Projects / Workspaces + Notifications
Organizational containers that group related conversations, KBs, and
notes into a single workspace with shared access controls. Plus the
notification infrastructure that makes collaboration real-time.
Depends on: user groups (v0.16.0), knowledge bases (v0.14.0).
**Data Model**
- [ ] `projects` table: `id`, `name`, `description`, `scope` (personal, team, global), `owner_id`, `team_id`, `settings` (JSONB), `created_at`, `updated_at`
- [ ] `project_resources` table: `project_id`, `resource_type` (channel, knowledge_base, note), `resource_id`, `added_at`
- [ ] Projects use the same grant model (v0.16.0): team_only / global / groups
**Features**
- [ ] Channels can belong to a project (optional `project_id` FK)
- [ ] KBs can belong to a project → auto-linked to all channels in the project
- [ ] Notes can belong to a project → visible to all project members
- [ ] Project-level Persona default: all new channels in the project start with this Persona
- [ ] Project sidebar section: grouped view of conversations with folder-like nesting
**UI**
- [ ] Sidebar: projects as collapsible groups above/integrated with chat history
- [ ] Project creation dialog (name, description, default Persona, default KBs)
- [ ] Drag channels/notes into projects
- [ ] Folders within projects (lightweight — just a `path` column on project_resources)
- [ ] Project settings: manage resources, access, defaults
**Enterprise Use**
- [ ] Team admins create projects for their teams
- [ ] Project templates: pre-configured with specific Personas, KBs, and settings
- [ ] Cross-team projects via group grants
**Notifications**
- [ ] `notifications` table: `id`, `user_id`, `type`, `title`, `body`, `resource_type`, `resource_id`, `is_read`, `created_at`
- [ ] In-app notification bell (header bar, unread count badge)
- [ ] Notification dropdown: grouped by type, mark read, click-to-navigate
- [ ] WebSocket push: real-time delivery via existing EventBus (`notification.new` event)
- [ ] Notification sources: group membership changes, grant updates, KB processing complete, project invites, team invites
- [ ] Email transport (optional): SMTP config in admin settings, per-user opt-in/out
- [ ] Email templates: HTML + plaintext, branded with instance name
- [ ] Digest mode: batch low-priority notifications into periodic email (hourly/daily)
- [ ] Admin settings: enable/disable email, SMTP config, default notification preferences
- [ ] User preferences: per-type toggles (in-app, email, off)
---
## v0.20.0 — @mention Routing + Multi-model
The channel schema already supports multiple models. This adds routing.
_(Shifted from v0.17.0 — no content changes)_
- [ ] @mention parsing in messages (users and AI models)
- [ ] Resolve mentions against `channel_models`
- [ ] Multi-model channels: fire completions per mentioned model
- [ ] "Add a model" UI per channel
- [ ] Enables: second opinions, cross-model conversations
---
## v0.21.0 — Extension Surfaces + Modes
Depends on: extension foundation (v0.11.0), CodeMirror 6 (v0.17.2).
See [EXTENSIONS.md §6](EXTENSIONS.md#6-surfaces-modes).
_(Shifted from v0.18.0 — no content changes)_
- [ ] Surface registration and activation API
- [ ] Mode selector in sidebar (below brand, above chat history)
- [ ] `ctx.ui.replace()` / `ctx.ui.restore()` for region management
- [ ] `surface.activated` / `surface.deactivated` events
- [ ] Editor mode (extension: file tree + CM6 code editor + AI chat split pane)
- [ ] Article mode (extension: outline + rich text + AI assistant panel)
- [ ] Document generation output storage: extension → attachment → download pipeline _(prerequisite for editor/article output)_
**REPL / Debug Console** ([#70](https://git.gobha.me/xcaliber/chat-switchboard/issues/70))
- [ ] Fourth tab in debug modal (Ctrl+Shift+L): `[ Console | Network | State | REPL ⚠ ]`
- [ ] `AsyncFunction` wrapper for top-level `await` — injects `API`, `Events`, `Extensions`, `DebugLog` as globals
- [ ] Pretty-print results: collapsible JSON (reuse State tab renderer), errors in red with stack
- [ ] Command history: ↑/↓ navigation, `sessionStorage` (not `localStorage` — no stale credentials across sessions)
- [ ] Tab-completion on live object graphs: walk `Object.getOwnPropertyNames` + prototype chain, own-first sort
- [ ] Event label hints: secondary completion when typing `Events.publish('` or `Events.on('` — sourced from routeTable constants
- [ ] Every executed command echoed as `REPL:EXEC` entry in Console tab (trace of what ran)
- [ ] Toolbar: Clear (output only), Copy session (full transcript), Help (available globals guide)
- [ ] Multi-line input: Shift+Enter for newline, Enter to run
- [ ] Access gate: admin-role only (same `isAdmin` check as admin panel) OR `?debug=1` URL param
- [ ] _Nice-to-have_: snippets library dropdown ("List channels", "Show current user", "Ping WebSocket", "List loaded extensions")
- [ ] _Nice-to-have_: method signature tooltip from `fn.toString()` parsing on autocomplete selection
- [ ] Files: `index.html` (tab markup), `debug.js` (ReplRunner object), `debug.css` (output, input, suggestion dropdown)
---
## 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.0), 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`.
**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