tandem-editor 0.8.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -7,10 +7,58 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## \[Unreleased]
9
9
 
10
+ ## \[0.9.0] - 2026-04-28
11
+
12
+ ### Breaking Changes (MCP)
13
+
14
+ This is the last breaking-change window before semver lock. MCP tool count: 31 → 28.
15
+
16
+ - **`tandem_suggest` deprecated (#259)** — returns a structured error stub pointing to `tandem_comment` with `suggestedText`. Hard-remove in v0.10.0.
17
+ - **`tandem_getContent` removed (#259)** — superseded by `tandem_getTextContent`.
18
+ - **`tandem_getSelections` removed (#259)** — superseded by `tandem_checkInbox`.
19
+ - **`tandem_setStatus` merged into `tandem_status` (#259)** — `tandem_status` now accepts optional write params (`text`, `focusParagraph`, `focusOffset`). When params are present it writes to awareness; when absent it reads.
20
+
21
+ ### Added
22
+
23
+ - **`/api/info` endpoint (#441)** — returns app version, MCP SDK version, tool count, data directory, and platform. Serves the Settings panel About footer.
24
+ - **Tabbed-left layout variant (#445)** — new `"tabbed-left"` layout mode places the side panel on the left and editor on the right. Three layout modes total: `tabbed`, `tabbed-left`, `three-panel`.
25
+ - **App version in Settings (#435)** — `useAppInfo` hook fetches `/api/info` and displays version + MCP SDK version in the Settings popover footer.
26
+ - **View Changelog button (#437)** — Settings panel button opens `CHANGELOG.md` as a read-only document tab via `POST /api/open` with `readOnly: true`.
27
+ - **Authorship `data-tandem-author` attributes (#443)** — authorship decorations switched from CSS classes (`.tandem-authorship--user`) to data attributes (`[data-tandem-author="user"]`), per ADR-026. Enables future attribute-based styling without class proliferation.
28
+ - **Schema foundations (#440, #442, #444, #450)** — `heldInSolo` field on `AnnotationBase`; 7 new `TandemSettings` fields (`accentHue`, `editorFont`, `density`, `defaultMode`, `highContrast`, `annotationPatterns`, `selectionToolbar`); `showAuthorship` default flipped to `true`; editor width minimum lowered from 50% to 40%.
29
+ - **Highlight palette migration (#450)** — palette switched from 5 colors to 4 (yellow/green/blue/pink). `LEGACY_COLOR_MAP` migrates `red` → `yellow`, `purple` → `blue` on annotation load.
30
+ - **CI stdio smoke test (#341)** — GitHub Actions step validates the Cowork stdio bridge (`scripts/ci/stdio-smoke.mjs`) on every push.
31
+ - **`__MCP_SDK_VERSION__` build-time injection** — tsup reads the real SDK version from the package root (not the CJS type marker) and injects it at build time.
32
+
33
+ ### Fixed
34
+
35
+ - **Cross-element edit merging (#456)** — canonical Y.js length + delta-walking merge for edits spanning multiple inline elements.
36
+ - **Annotation decoration initial-sync race** — Y.Map observers firing before y-prosemirror sync no longer produce empty decoration sets.
37
+ - **Channel checkpoint timing** — checkpoint advances after MCP notification delivery, not before, preventing event loss on reconnect.
38
+ - **Auto-save spurious tab switches** — auto-save no longer triggers `document:switched` events that confuse tab state.
39
+ - **Annotation recovery guard hardening** — narrowed guard scope for edge cases in session restore.
40
+ - **Event-bridge error handling** — uncaught errors in SSE delivery no longer crash the event loop.
41
+ - **MCP SDK version resolution** — `require("@modelcontextprotocol/sdk/package.json")` resolves to `dist/cjs/package.json` (a CJS type marker without `version`); build now walks back past `dist/` to find the real version.
42
+
43
+ ### Changed
44
+
45
+ - **Redesign gap audit resolved (#439)** — 7 product decisions documented in ADR-026. Design response prompt at `docs/claude-design-response-prompt.md`.
46
+ - **Distribution items deferred** — #316 (macOS/Linux Cowork auto-setup), #317 (cross-platform firewall scoping), #322 (network-type detection) moved to v0.13.0. Requires macOS/Linux validation hardware.
47
+
48
+ ### Internal
49
+
50
+ - Annotation schema Zod validation with `LEGACY_COLOR_MAP` migration path.
51
+ - `ResizeHandle` and `TabbedPanelContainer` shared components extracted for layout code reuse.
52
+ - `useAppInfo` hook with exponential backoff retry for `/api/info` fetch.
53
+ - `file-opener` read-only mode support for changelog viewing.
54
+ - 900+ lines of new test coverage: authorship decorations, annotation decorations, panel layout, app info hook, settings fields, schema migration, info route, document edit edge cases.
55
+
10
56
  ## \[0.8.0] - 2026-04-26
11
57
 
12
58
  ### Added
13
59
 
60
+ - **NSIS pre-install sidecar kill (#434)** — the NSIS installer now kills the running `node-sidecar.exe` process before file replacement, preventing "Error opening file for writing" failures during upgrade installs. Uses `nsis_tauri_utils::KillProcessCurrentUser` for user-scoped process termination. Tauri's built-in `CheckIfAppIsRunning` already handles the main binary.
61
+
14
62
  - **Semantic token lint enforcement (#356)** — `npm run check:tokens` scans `src/client/` for raw hex and non-neutral `rgba()` violations. Runs on pre-commit via lint-staged, blocking merges that introduce unsanctioned color literals.
15
63
  - **`--tandem-suggestion-*` token family (#340)** — violet semantic tokens for replacement/suggestion annotations (`--tandem-suggestion`, `-fg-strong`, `-bg`, `-border`), visually distinct from the indigo accent family.
16
64
  - **Annotation drop count surfacing (#351)** — `normalizeAnnotation` now returns drop counts in snapshot metadata so callers can detect lossy session migrations.
package/README.md CHANGED
@@ -6,8 +6,6 @@ Have you ever been working on a piece of writing with an LLM and caught yourself
6
6
 
7
7
  And because Tandem hooks into Claude as an MCP server, you're not stuck in some stripped-down document-editing silo. It's the full Claude — with all its knowledge, your conversation context, and every tool it has access to — just now it can also see and edit your document.
8
8
 
9
- ![Tandem editor showing a document with annotations, side panel, and Claude's presence](docs/screenshots/01-editor-overview.png)
10
-
11
9
  ## Why Tandem?
12
10
 
13
11
  - **No more copy-paste ping-pong.** Select text in the editor, and Claude reads your selection directly. Ask "what do you think of this?" or "make this more concise" — Claude knows exactly which text you mean.
@@ -154,20 +152,14 @@ Everything in Tandem is built around one idea: you work in the document, Claude
154
152
 
155
153
  ### Chat
156
154
 
157
- ![Chat sidebar showing messages, typing indicator, and panel toggle](docs/screenshots/02-chat-sidebar.png)
158
-
159
155
  Send messages to Claude alongside your document. Select text before sending to attach it as context — Claude sees exactly what you mean. Clicking an anchored selection later scrolls back to that passage.
160
156
 
161
157
  ### Annotations
162
158
 
163
- ![Side panel showing annotation cards with filtering, bulk actions, and text previews](docs/screenshots/03-side-panel.png)
164
-
165
159
  This is how Claude's feedback shows up in the document. Claude adds highlights, comments, suggestions, and flags directly on the text. Suggestion cards show a visual diff — original text in red strikethrough, replacement in green. The side panel lists all annotations with filtering by type, author, and status. Accept, dismiss, or edit each one individually — or use bulk actions to process them in batches.
166
160
 
167
161
  ### Review Mode
168
162
 
169
- ![Review mode with dimmed editor and active annotation highlighted](docs/screenshots/05-review-mode.png)
170
-
171
163
  Press **Ctrl+Shift+R** to enter keyboard review mode. Navigate with **Tab**, accept with **Y**, dismiss with **N**, examine with **E**. A 10-second undo window with a visual countdown lets you reverse accidental accepts. Shortcut hints appear below the Review button.
172
164
 
173
165
  ### More
@@ -193,7 +185,7 @@ Press **Ctrl+Shift+R** to enter keyboard review mode. Navigate with **Tab**, acc
193
185
 
194
186
  ## Where Tandem is headed
195
187
 
196
- Since the v0.4.0 desktop app launch, Tandem has added auth tokens for LAN exposure (v0.7.0), a Claude Code plugin bridge for Cowork and Claude Desktop (v0.6.0+), durable annotation persistence, settings with Light/Dark/System theming, and authorship text coloring. A few directions on the radar for later releases:
188
+ Since the v0.4.0 desktop app launch, Tandem has added auth tokens for LAN exposure (v0.7.0), a Claude Code plugin bridge for Cowork and Claude Desktop (v0.6.0+), durable annotation persistence, settings with Light/Dark/System theming, authorship text coloring, and coordinate system correctness fixes with semantic token enforcement (v0.8.0). A few directions on the radar for later releases:
197
189
 
198
190
  - **High-fidelity .docx round-trip** — current `.docx` support is review-only; production export is planned so you can stay in Tandem through the final draft.
199
191
  - **Exportable annotated documents** — PDF (and eventually `.docx`) with annotations baked in, so you can share reviewed drafts outside Tandem.
@@ -205,12 +197,12 @@ See the full [Roadmap](docs/roadmap.md) and [Known Limitations](docs/roadmap.md#
205
197
  ## Documentation
206
198
 
207
199
  - **[User Guide](docs/user-guide.md)** — How to use Tandem: editor UI, annotations, chat, review mode, keyboard shortcuts
208
- - [MCP Tool Reference](docs/mcp-tools.md) — 31 MCP tools + channel API endpoints
200
+ - [MCP Tool Reference](docs/mcp-tools.md) — 28 MCP tools + channel API endpoints
209
201
  - [Architecture](docs/architecture.md) — System design, data flows, coordinate systems, channel push
210
202
  - [Workflows](docs/workflows.md) — Claude Code usage patterns: text iteration, cross-referencing, multi-model
211
203
  - [Roadmap](docs/roadmap.md) — Phase 2+ roadmap, known issues, future extensions
212
204
  - [Design Decisions](docs/decisions.md) — ADR-001 through ADR-024
213
- - [Lessons Learned](docs/lessons-learned.md) — 44 implementation lessons
205
+ - [Lessons Learned](docs/lessons-learned.md) — 48 implementation lessons
214
206
 
215
207
  ## CLI Commands
216
208
 
@@ -228,7 +220,7 @@ See the full [Roadmap](docs/roadmap.md) and [Known Limitations](docs/roadmap.md#
228
220
 
229
221
  ## MCP Configuration
230
222
 
231
- Tandem registers two MCP connections: **HTTP** for document tools (31 tools including annotation editing — always on), and a **channel shim** for real-time push notifications. The channel shim is what enables the live-collaborator experience described in [Connect Claude Code](#connect-claude-code) and is recommended; it activates when you start Claude Code with `--dangerously-load-development-channels server:tandem-channel`. If you'd rather not pass that experimental flag, the entry sits idle and everything still works through polling on the HTTP connection — you just lose spontaneous reactions.
223
+ Tandem registers two MCP connections: **HTTP** for document tools (28 tools including annotation editing — always on), and a **channel shim** for real-time push notifications. The channel shim is what enables the live-collaborator experience described in [Connect Claude Code](#connect-claude-code) and is recommended; it activates when you start Claude Code with `--dangerously-load-development-channels server:tandem-channel`. If you'd rather not pass that experimental flag, the entry sits idle and everything still works through polling on the HTTP connection — you just lose spontaneous reactions.
232
224
 
233
225
  **Global install** (`tandem setup`): Automatically writes both entries to `~/.claude/mcp_settings.json` (Claude Code) and/or `claude_desktop_config.json` (Claude Desktop) with absolute paths. No manual configuration needed.
234
226
 
@@ -18105,7 +18105,11 @@ async function connectAndStream(mcp, tandemUrl, lastEventId, onEventId) {
18105
18105
  status: "idle",
18106
18106
  active: false
18107
18107
  })
18108
- }).catch(() => {
18108
+ }).catch((err) => {
18109
+ console.error(
18110
+ "[Channel] clearAwareness failed (non-fatal):",
18111
+ err instanceof Error ? err.message : err
18112
+ );
18109
18113
  });
18110
18114
  }
18111
18115
  function flushAwareness() {
@@ -18151,11 +18155,21 @@ async function connectAndStream(mcp, tandemUrl, lastEventId, onEventId) {
18151
18155
  try {
18152
18156
  event = parseTandemEvent(JSON.parse(data));
18153
18157
  } catch {
18154
- console.error("[Channel] Malformed SSE event data (skipping):", data.slice(0, 200));
18158
+ console.error(
18159
+ "[Channel] Malformed SSE event data (skipping), eventId=%s:",
18160
+ eventId,
18161
+ data.slice(0, 200)
18162
+ );
18163
+ if (eventId) onEventId(eventId);
18155
18164
  continue;
18156
18165
  }
18157
18166
  if (!event) {
18158
- console.error("[Channel] Received invalid SSE event, skipping");
18167
+ console.error(
18168
+ "[Channel] Invalid SSE event structure (skipping), eventId=%s:",
18169
+ eventId,
18170
+ data.slice(0, 200)
18171
+ );
18172
+ if (eventId) onEventId(eventId);
18159
18173
  continue;
18160
18174
  }
18161
18175
  if (event.type !== "chat:message") {
@@ -18166,7 +18180,6 @@ async function connectAndStream(mcp, tandemUrl, lastEventId, onEventId) {
18166
18180
  continue;
18167
18181
  }
18168
18182
  }
18169
- if (eventId) onEventId(eventId);
18170
18183
  try {
18171
18184
  await mcp.notification({
18172
18185
  method: "notifications/claude/channel",
@@ -18179,6 +18192,7 @@ async function connectAndStream(mcp, tandemUrl, lastEventId, onEventId) {
18179
18192
  console.error("[Channel] MCP notification failed (transport broken?):", err);
18180
18193
  throw err;
18181
18194
  }
18195
+ if (eventId) onEventId(eventId);
18182
18196
  scheduleAwareness(event);
18183
18197
  }
18184
18198
  }