diff --git a/ROADMAP.md b/ROADMAP.md index 0674320..58ae6f7 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -291,19 +291,124 @@ Zero platform special-casing. Proves the full extension stack E2E. | Import .md | ✅ | Import button in topbar. File picker for `.md`/`.markdown`/`.txt`. Parses YAML frontmatter for title and tags. Creates note via API with tags. | | Notes package v0.5.0 | ✅ | Manifest version bumped from 0.4.0 → 0.5.0. | -## v0.5.0 — MVP +### v0.4.5 — Editor Modes + Document Outline (planned) -Extension and operations tracks converge. First externally usable release. +| Step | Status | Description | +|------|--------|-------------| +| Default-rendered mode | | Preview is the initial state on note open. "Edit" button enters CM6. Save exits back to rendered view. | +| Split view | | Side-by-side layout: CM6 left, rendered preview right. New `viewMode` state: `rendered` / `edit` / `split`. CSS grid two-column in `.notes-editor__body`. | +| Synced scroll | | Split mode scroll sync. CM6 `scrollDOM` scroll listener maps position ratio to preview `scrollTop`. Linear mapping. | +| View mode setting | | Add `editor_mode` to manifest `settings` (rendered / split / edit). Persist preference. Toolbar cycles modes. | +| Document outline | | Parse headings from body. Render as collapsible TOC panel adjacent to editor. Click heading → scroll CM6 or preview to target. Updates on body change via debounced parse. | -- Package registry (browse, install, update, uninstall) -- Package distribution model (no auto-install; explicit install only) -- Health monitoring dashboard -- Backup/restore tooling -- Documentation site +### v0.4.6 — Sidebar Restructure (planned) + +| Step | Status | Description | +|------|--------|-------------| +| Sidebar tabs | | Two-tab header at top of sidebar: "Notes" (folders → tags → search → list) and "Outline" (heading tree for active note). Outline tab enabled only when a note is selected. | +| Heading tree | | Nested heading hierarchy (H1 → H2 → H3) with depth indentation. Click → scroll to heading in editor/preview. Current heading highlighted based on scroll position. | + +### v0.4.7 — Note Graph (planned) + +| Step | Status | Description | +|------|--------|-------------| +| Graph API | | `GET /graph` endpoint in Starlark — `{ nodes: [{id, title, folder_id}], edges: [{source, target, text}] }`. Full notes + links in one payload. | +| Graph renderer | | Canvas force-directed layout. Minimal force simulation (repulsion + attraction + damping). Nodes = circles with title labels, edges = lines. Zoom/pan via wheel + drag. | +| Click → focus + filter | | Single click a node: dims unconnected nodes/edges to ~15% opacity. Clicked node + direct neighbors stay full brightness. Edges highlighted in accent color. Click empty space to reset. | +| Shift+click → chain | | Shift+click adds a second node to the focus set — union of both neighborhoods visible. Trace thought paths across two hops without losing context. | +| Double-click → open | | Double-click navigates to the note. Graph view stays active — back returns to graph with previous focus state preserved. | +| Hover → tooltip | | Hover shows note title + tag pills + edge count. No API call — all data in graph payload. | +| Folder/tag coloring | | Nodes colored by folder. Tag filter dropdown — select tag, unmatched nodes dim. Stacks with click focus. | +| Orphan highlighting | | Zero-edge nodes rendered with dashed stroke. Optional toggle to hide entirely. | +| Entry point | | "Graph" button in topbar. Replaces editor pane with full graph canvas. Note selection in graph populates sidebar, switching back to editor shows that note. | + +## v0.5.x — Realtime + Chat + +Communication primitive track. The kernel gains one generic realtime +module. Everything else — conversations, messages, participants — is +pure extension code. Human-to-human chat ships pre-MVP; LLM +participation is post-MVP. + +### v0.5.0 — Realtime Primitive + Dialog System (planned) + +| Step | Status | Description | +|------|--------|-------------| +| `realtime.publish()` | | Starlark module: `realtime.publish(channel, event, data)`. Publishes JSON event to WebSocket hub scoped to channel (e.g. `conversation:{id}`). Hub handles fan-out and cross-replica broadcast. | +| `sw.realtime.subscribe()` | | SDK method: `sw.realtime.subscribe(channel, callback)`. Client-side WebSocket listener filtered by channel. Returns unsubscribe handle. | +| `sw.ui.Dialog` | | SDK modal primitive: configurable title, body, action buttons. Replaces native `alert()`. Promise-based API. | +| `sw.ui.Confirm` | | SDK confirm primitive: question + confirm/cancel buttons. Replaces native `confirm()`. Returns promise resolving to boolean. | +| `sw.ui.Prompt` | | SDK prompt primitive: label + text input + confirm/cancel. Replaces native `prompt()`. Returns promise resolving to string or null. | +| Native dialog audit | | Sweep all surfaces (notes, tasks, schedules, admin, settings). Replace every `prompt()`, `confirm()`, `alert()` with SDK equivalents. | + +### v0.5.1 — Chat Core Library (planned) + +| Step | Status | Description | +|------|--------|-------------| +| Library package | | `chat-core` library with `permissions: ["db.write"]`. Private ext_data tables, exported Starlark functions, REST endpoints. | +| Conversations table | | `conversations` — title, type (direct/group), created_by, updated_at. | +| Participants table | | `participants` — conversation_id, participant_id, participant_type (user/bot), display_name, role (member/admin), joined_at. | +| Messages table | | `messages` — conversation_id, participant_id, content, content_type (text/system/file), edited_at. | +| Read cursors table | | `read_cursors` — conversation_id, participant_id, last_read_message_id. | +| Exported Starlark API | | `chat.create()`, `chat.send()`, `chat.history()`, `chat.add_participant()`, `chat.remove_participant()`, `chat.mark_read()`. | +| REST endpoints | | Full CRUD for conversations, messages, participants. Paginated message history. Unread counts. | +| Realtime integration | | On `chat.send()`: insert message, emit `chat.message.created` event, call `realtime.publish("conversation:{id}", "message", data)`. | + +### v0.5.2 — Chat Surface (planned) + +| Step | Status | Description | +|------|--------|-------------| +| Conversation list | | Sidebar: conversation list with last message preview, unread badge, timestamp. Create conversation button. | +| Message thread | | Main pane: message history with participant avatars, timestamps, content. Virtual scroll for long threads. | +| Compose bar | | Text input with Enter-to-send, Shift+Enter for newline. Markdown support via existing inline renderer. | +| Participant sidebar | | Collapsible right panel: participant list with online status (via kernel presence hub). Add/remove participants using `sw.ui.Dialog`. | +| 1:1 and group | | Direct messages (two participants) and group conversations. Type field on conversation. | +| Typing indicators | | `realtime.publish("conversation:{id}", "typing", {participant_id})` on keypress with debounce. Surface shows "X is typing…" with auto-expire. | +| Read receipts | | Mark-read on scroll/focus via `chat.mark_read()`. Unread count in conversation list. | +| Message editing | | Edit own messages. `edited_at` timestamp displayed. Edit via `PUT /messages/:id`. | +| Message deletion | | Soft-delete own messages. Replaced with "message deleted" placeholder. | + +### v0.5.3 — Chat Polish + Integration Testing (planned) + +| Step | Status | Description | +|------|--------|-------------| +| Conversation search | | Search across conversation titles and message content. | +| Message pagination | | Cursor-based pagination on message history. Scroll-to-load-more in thread view. | +| Multi-user E2E | | Docker compose test: multiple browser sessions, verify real-time message delivery, presence indicators, cross-replica broadcast. | +| Workflow integration | | Verify: workflow stage with `audience: team` can create a conversation via `chat.create()`, add assigned members as participants. Conversation scoped to instance. | + +### v0.5.4 — Package Updates (planned) + +| Step | Status | Description | +|------|--------|-------------| +| Version comparison | | Compare installed package version against incoming `.pkg` version. Semantic version parsing. Skip if same or older. | +| Schema migration on update | | Diff declared `db_tables` against existing ext_data schema. Add new columns, add new tables. No destructive changes (no column drops, no type changes). | +| Data preservation | | ext_data tables survive update. Only additive schema changes applied. Settings merged (new keys added, existing preserved). | +| Update API | | `PUT /api/v1/packages/:id/update` — accepts `.pkg` archive, validates version bump, applies schema diff, replaces code (JS/CSS/Starlark). | +| Admin UI | | Update button on package card when newer version available. Version comparison badge. Update confirmation via `sw.ui.Confirm`. | +| Rollback story | | Export package before update (existing export). Document manual rollback: re-install old `.pkg`. No automatic rollback — KISS. | + +### v0.5.5 — Upgrade Testing (planned) + +| Step | Status | Description | +|------|--------|-------------| +| Test harness | | Docker compose environment: build v(current) image, seed data (notes, conversations, tasks, workflows), then upgrade to v(next) image. Verify data integrity post-upgrade. | +| Schema edge cases | | Force upgrade scenarios: add column to existing table, add new table, add new index. Verify ext_data migrations apply cleanly without data loss. Throwaway changes — not committed, only bug fixes. | +| Settings migration | | Verify settings cascade survives upgrade: global → team → user overrides preserved. New settings keys appear with defaults. Removed keys ignored. | +| Package compatibility | | Install older package version, upgrade kernel, verify package still loads. Install newer package version on older kernel, verify graceful failure. | +| Multi-replica upgrade | | Rolling upgrade in K8s: old and new replicas coexist briefly. Verify WebSocket hub handoff, no message loss, no split-brain on ext_data writes. | + +## v0.6.0 — MVP + +Extension, communication, and operations tracks converge. First +externally usable release. + +- Health monitoring (extension package wrapping kernel `/health`) +- Backup/restore tooling (ext_data export/import, admin surface) +- Documentation site (extension authoring guide, API reference, deployment guide) ## Post-MVP -- Chat extension (provider registry, streaming, personas, tool system) +- LLM participation (`llm-bridge` extension: subscribes to `chat.message.created`, calls `provider.complete()`, streams response via `realtime.publish`, posts via `chat.send()`. Bot participants with persona config. Multi-model conversations.) - Rich media extensions: image generation, code sandbox, STT/TTS - Desktop app (Tauri or Electron) - Sidecar tier: container-based extensions @@ -327,6 +432,6 @@ Extension and operations tracks converge. First externally usable release. | No new migrations pre-MVP | Edit existing migration SQL files in place. No migration chains until schema is in production. | | Notes over Editor | First surface is Obsidian-style notes (rich text, folders, backlinks) instead of a code editor. Notes is a stronger E2E proof — it exercises ext_data, storage, and the SDK more fully than a pure-browser CM6 editor. | | No built-in auto-install | Extensions ship in the repo but are not auto-installed. Distribution model TBD — explicit install only. Keeps the kernel clean and avoids opinionated defaults. | -| Chat → post-MVP | Chat extension (providers, streaming, personas) is valuable but not MVP-critical. The platform must prove itself with simpler surfaces first. Chat moves to post-MVP track. | +| Chat as extension, not kernel | Human-to-human chat built entirely as library + surface packages. Zero kernel awareness of conversations, messages, or participants. Kernel gains one generic `realtime` module. Proves near-infinite extensibility. LLM participation layers on top via a separate bridge extension — the chat system doesn't know or care whether a participant is human or AI. | | Two trigger tiers | Event + webhook triggers are extension-declared (manifest contract, full sandbox). Scheduled tasks are user-created ad-hoc (restricted sandbox — no raw HTTP, no DB table creation, connections-only outbound). Separation keeps extension contracts static and user automation safe. | -| Scheduled task identity | Tasks run as their creator (RBAC-scoped). Admin-created tasks can opt into system context. Creator deactivation pauses the schedule. Ensures audit trail and permission boundaries. | +| Scheduled task identity | Tasks run as their creator (RBAC-scoped). Admin-created tasks can opt into system context. Creator deactivation pauses the schedule. Ensures audit trail and permission boundaries. | \ No newline at end of file