tandem-editor 0.12.0 → 0.13.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.
Files changed (37) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CHANGELOG.md +69 -10
  4. package/README.md +141 -238
  5. package/dist/channel/index.js +158 -69
  6. package/dist/channel/index.js.map +1 -1
  7. package/dist/cli/index.js +656 -148
  8. package/dist/cli/index.js.map +1 -1
  9. package/dist/client/assets/CoworkSettings-BOYbyKul.js +3 -0
  10. package/dist/client/assets/index-D8uS4cj7.css +1 -0
  11. package/dist/client/assets/index-Dm_QtxGQ.js +1 -0
  12. package/dist/client/assets/index-g-KwmRn9.js +271 -0
  13. package/dist/client/assets/webview-KiZyy_pC.js +1 -0
  14. package/dist/client/fonts/OFL-Hanuman.txt +93 -0
  15. package/dist/client/fonts/OFL-InterTight.txt +93 -0
  16. package/dist/client/fonts/OFL-JetBrainsMono.txt +93 -0
  17. package/dist/client/fonts/OFL-SNPro.txt +93 -0
  18. package/dist/client/fonts/OFL-Sono.txt +93 -0
  19. package/dist/client/fonts/OFL-SourceSerif4.txt +93 -0
  20. package/dist/client/fonts/hanuman-latin.woff2 +0 -0
  21. package/dist/client/fonts/jetbrains-mono-latin.woff2 +0 -0
  22. package/dist/client/fonts/sn-pro-latin.woff2 +0 -0
  23. package/dist/client/fonts/sono-latin.woff2 +0 -0
  24. package/dist/client/fonts/source-serif-4-latin.woff2 +0 -0
  25. package/dist/client/index.html +204 -17
  26. package/dist/client/logo.png +0 -0
  27. package/dist/monitor/index.js +235 -161
  28. package/dist/monitor/index.js.map +1 -1
  29. package/dist/server/index.js +54900 -51788
  30. package/dist/server/index.js.map +1 -1
  31. package/package.json +6 -2
  32. package/sample/welcome.md +6 -6
  33. package/skills/tandem/SKILL.md +15 -0
  34. package/dist/client/assets/CoworkSettings-C0cS9R7L.js +0 -3
  35. package/dist/client/assets/index-Dn5JwXA3.css +0 -1
  36. package/dist/client/assets/index-n-vFW5By.js +0 -299
  37. package/dist/client/assets/webview-Bhf-n_os.js +0 -1
@@ -4,7 +4,7 @@
4
4
  "name": "Tandem"
5
5
  },
6
6
  "metadata": {
7
- "description": "Tandem — collaborative AI-human document editor"
7
+ "description": "Tandem — collaborative AI-human document editor (MCP-first; Claude is the default integration)"
8
8
  },
9
9
  "plugins": [
10
10
  {
@@ -13,7 +13,7 @@
13
13
  "source": "github",
14
14
  "repo": "bloknayrb/tandem"
15
15
  },
16
- "description": "Edit and iterate on documents with Claude no copy-paste, real-time push via plugin monitor"
16
+ "description": "Edit and iterate on documents with any MCP-capable AI. Claude is the default and best-supported client today."
17
17
  }
18
18
  ]
19
19
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "tandem",
3
3
  "version": "0.8.0",
4
- "description": "Edit and iterate on documents with Claude no copy-paste, real-time push via plugin monitor",
4
+ "description": "Edit and iterate on documents with any MCP-capable AI. Claude is the default and best-supported client today.",
5
5
  "author": {
6
6
  "name": "Tandem"
7
7
  },
package/CHANGELOG.md CHANGED
@@ -5,7 +5,73 @@ All notable changes to Tandem will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),\
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
- ## [Unreleased]
8
+ ## [0.13.0] - 2026-05-25
9
+
10
+ ### Added
11
+
12
+ - **Settings → Models tab + edit modal (Wave 2 PR 8b, #659)** — new tab in `SettingsModal` for managing the Models registry. Provider-grouped list with per-row enable toggle, edit, two-step delete confirm. `ModelEditModal` covers add and edit flows: provider select (Anthropic / OpenAI / Gemini / Ollama / llama.cpp), conditional cloud-vs-local fields, reveal-gated API key (masked `••••${last4}` on edit; "Replace key" button to enter a new value — existing key never round-trips through the DOM). Mandatory in-product disclosure banner about plaintext localStorage storage.
13
+ - **Models registry data model + `useModels` hook (Wave 2 PR 8a, #659)** — `TandemSettings` now carries a `models: ModelRegistryEntry[]` array tracking AI providers Tandem can call out to (Anthropic, OpenAI, Gemini, local Ollama, local llama.cpp). The data layer ships in this PR; the Settings → Models UI ships in PR 8b. Orthogonal to `IntegrationConfig` (#477) — that schema tracks MCP clients connecting INTO Tandem, while this tracks providers Tandem talks OUT to.
14
+ - **Multi-provider Models registry (#659, #784)** — keychain-backed secret storage, per-provider default selection, and a first-run model picker spanning Anthropic / OpenAI / Gemini cloud providers plus local Ollama / llama.cpp endpoints. A legacy-migration banner upgrades pre-registry single-key setups.
15
+ - **Schema v2 → v3 migration with forward-compat read-only mode** — `loadSettings` now walks an explicit migration chain (v1→v2→v3). An on-disk `schemaVersion` greater than v3 loads defensively with `_readOnly: true`, and `createTandemSettings.updateSettings` short-circuits writes on read-only settings. This is the load-bearing defence against a downgraded client clobbering a newer client's Models registry / future fields on first save.
16
+ - **Integration setup wizard + first-run auto-open (#477 PRs 1/3a/3b/3c-i/3c-ii-b — #728, #729, #730, #731, #773)** — a full-screen wizard for connecting MCP clients (Claude Code and other agents) to Tandem. Ships the `IntegrationConfig` schema with atomic storage + v1→v2→v3 migration, a non-mutating reader for existing `~/.claude.json` entries, and an apply path (`POST /api/integrations/apply`) that backs up the target config before rewriting it. On first launch with no `integrations.json` the wizard opens automatically; later launches do not. Enabled by default.
17
+ - **Native OS keychain on the Tauri desktop app (#477 PR 3c-tauri-keychain, #732)** — integration secrets are stored in the platform keychain on desktop, with graceful env-var fallback when the keychain is unavailable.
18
+ - **Auto-launcher for Claude Code (#477 PR 4a/4b, #800)** — Tandem spawns and supervises the Claude Code CLI alongside the server, with a native cross-platform parent-death reaper so the child is reliably cleaned up on exit. Adds command-palette actions "Relaunch Claude in this folder" and "Start fresh Claude conversation", a working-directory picker in Settings → Integrations, and a project-context skill bundled on startup. Enabled by default for users with a configured `claude-code` integration; opt out with `TANDEM_DISABLE_LAUNCHER=1`.
19
+ - **Native file picker + drag-and-drop on the Tauri desktop app (#378)** — open files through the OS-native file dialog and by dragging them onto the window; the File Open dialog is consolidated to a single Browse + Recent panel.
20
+ - **Heading-section collapse (#650)** — collapse everything under a heading via its fold control; collapse state persists per document in localStorage and survives heading-text edits and reloads.
21
+ - **Scratchpad save-to-disk (#827)** — save a scratchpad to a real file via the native dialog (`.md` / `.txt`); Save-As accepts user-chosen locations anywhere on disk while keeping the symlink + UNC guards.
22
+ - **Claude typing-presence indicator (#651)** — a presence cue shows when Claude is actively writing, with monotonic token ownership so overlapping presence updates resolve deterministically.
23
+ - **Warm canvas theme (#738)** — a fourth theme option (System / Light / Dark / Warm) and the foundation for the v7 floating-chrome redesign.
24
+ - **Re-landed D11 bundled fonts (#680)** — re-applied the fontsource Latin variable-axis builds of Source Serif 4, Inter Tight, and JetBrains Mono originally shipped in PR #663 then reverted via #678. The SIL OFL 1.1 license texts (`public/fonts/OFL-*.txt`) ship alongside the binaries per §4. Editor body text renders in Source Serif 4 via the existing `--tandem-editor-font-family` token.
25
+ - **Margin annotation view (#649, #711, #715, #719, #720)** — Word-style margin comment bubbles with breathing-room gaps and leader lines connecting each card to its anchor, action parity with the sidebar, and the annotation filter chip relocated into the panel header.
26
+ - **Margin view auto-collapses on rail open or narrow viewport (#683)** — opening the left rail now hides only the left margin column; opening the right rail hides only the right column. When the viewport gets narrow enough that margin reserve + open rails + readable editor would crowd, both columns hide together. A 32px hysteresis band on the viewport threshold prevents flicker when a user drags through the boundary. New `useViewportWidth` rune store provides the rAF-debounced subscription.
27
+ - **Status-bar word-count cycle + page count (#741, #792)** — the floating status pill cycles through word, character, and page counts.
28
+ - **Inline annotation decoration toggle (#791)** — turn the inline highlight/underline decorations on or off without hiding the annotations themselves.
29
+ - **Knowledge-graph pilot (#769, #771)** — 25 hand-curated concept/rule/ADR nodes with cross-edges, queryable via `npm run kg`.
30
+
31
+ ### Changed
32
+
33
+ - **Network settings split into Connection / Advanced (Wave 2 PR 6)** — connection status, transport, and the restart-sidecar button stay always-visible; loopback port, degraded-banner delay, reconnect strategy, hold-while-offline, and token rotation collapsed under a new "Advanced" disclosure. Disclosure state is ephemeral (resets each time the modal opens). New `CollapsibleSection.svelte` primitive uses native `<details>/<summary>` for free keyboard a11y.
34
+ - **v7 floating-chrome redesign sweep (Waves 1–M)** — a multi-wave reskin that lifts the editor chrome off the canvas:
35
+ - Edge-anchored side rails with inner-rounded corners (Wave 2, #739) and a shared `.tandem-floating-pill` recipe (Wave 3, #740) applied across the formatting bar, status bar (Wave 5, #741), selection popup (Wave C, #762), and slash menu (Wave 10, #757).
36
+ - TitleBar + DocumentTabs reflow: bar seam removed so chrome melts into the canvas (Wave 4a, #746), pill-shaped tabs (Wave 4b, #748), tabs lifted into the TitleBar center cluster with mask-fade overflow and a floating `+` button (Wave 4a/4b maximalist, #752, #755).
37
+ - Left rail locked to outline-only (Wave D, #759); outline rail clears the status pill lane (Wave 6, #742); peek-from-side strips + edge-click panel collapse (Wave E, #764).
38
+ - Narrow-viewport Settings sidebar drawer + hamburger (Wave 9, #745); `.docx` batch-promote with always-visible checkboxes (Wave 8, #756).
39
+ - Native scrollbars hidden with mask-faded overflow edges (Wave B, #761); titlebar/status/right-rail header polish (Wave A, #760); placeholder + margin-card hover affordance (Wave F, #763).
40
+ - Redesign-parity sweep across titlebar, rails, picker teardown, popup, composer (Waves G–L, #765) plus the Wave M titlebar dropdown + solo-mode fade + dark-mode v7 alignment (#776).
41
+ - **README + documentation rewrite (#777, #778)** — README rewritten for a lay reader with technical detail moved below the fold, plus new `docs/cli.md`, `docs/configuration.md`, `docs/troubleshooting.md`, and `docs/security.md`.
42
+ - **MCP-first integration policy; your AI as the default integration (ADR-038, #722)** — documents that Tandem's integration contract is MCP and Claude is the default concrete integration.
43
+
44
+ ### Fixed
45
+
46
+ - **Inline code combined with bold/italic/strikethrough/link no longer loses its `code` formatting on save** — opening a `.md` file in Tandem (editable, not read-only) and letting autosave write it back used to drop the `code` mark on any span that also carried bold/italic/strike, and silently discard the surrounding link for code-in-link. The damage surfaced as doubled asterisks and `&#x20;` entity-spaces — code-heavy docs like `docs/decisions.md` were corrupted just by being viewed. `deltaToPhrasingContent` now treats `code` as a leaf and wraps link/strike/italic/bold unconditionally, and a new coalescing pass merges adjacent same-wrapper phrasing nodes so a bold run holding a code span serializes as one emphasis instead of several. Round-trip verified lossless across the repo's code-heavy docs.
47
+ - **Keyboard tab switch no longer reverts under a stale sync** — a local `Ctrl+1..9` (or click) tab switch is client-only and was being clobbered when a late `documentMeta` re-broadcast re-applied the server's active doc, surfacing as a flaky "Ctrl+N switches to the Nth tab" E2E test. The server now broadcasts a monotonic activation epoch (`activeDocumentEpoch`) alongside the active id; the client applies the server's active only when the epoch advances, so a stale re-sync is ignored while a genuine re-activation (e.g. re-opening the already-active doc) still steals focus.
48
+ - **Selection toolbar places itself clear of fixed chrome (#680)** — the selection BubbleMenu flips below the selection when above-placement would overlap the TitleBar + FormattingBar; selections that straddle the viewport fold pin the toolbar to the viewport bottom rather than clamping onto the chrome; and a 4px hysteresis band at the flip boundary keeps the toolbar from shimmering as a selection drifts across the threshold.
49
+ - **Clicked highlight stays focused over an overlapping comment (#817)** — clicking a highlight that overlaps a comment now collapses the ProseMirror selection so the overlay clears and the click-to-focus ordering resolves to the highlight; unknown annotation types fall back gracefully.
50
+ - **Solo/Tandem mode never auto-flips on a transient error (#822)** — a failed `/api/mode` poll preserves the last-known mode instead of silently reverting to Solo.
51
+ - **Annotation palette remap aligned with the v7 design (Wave 7, #743)**.
52
+ - **Post-wave correctness fixes across 9 sites (#758)** — a cleanup pass over regressions introduced during the redesign sweep.
53
+ - **Kept-tab metadata refreshes on document-list reconcile** — tab titles and state no longer go stale when the open-document list re-syncs.
54
+ - **Unsupported-extension toast names the right extension (#808)** — `extensionAllowed` extracts the basename correctly (handling dot-in-directory and dotfile edge cases) and surfaces `.htm` properly.
55
+ - **`.docx` comment-extraction failures surface via notification (#696, #701)** — instead of failing silently.
56
+
57
+ ### Security
58
+
59
+ - **`IntegrationConfig.url` constrained to loopback only (#753)** — accepts `http://127.0.0.1[:port][/path]` only; rejects `localhost`, IPv6 loopback `[::1]`, other `127.x.x.x` addresses, `https`, and embedded credentials (`http://user:pw@…`). Legacy `http://localhost` entries are normalized to `http://127.0.0.1` on read; any other host shape is surfaced as invalid and re-prompts the wizard.
60
+ - **Windows ACL hardening on `.claude.json` (#643, #795)** — a restrictive DACL is applied to the written config.
61
+ - **`.claude.json` backed up before overwrite (#644, #796)** — backups written under `${appDataDir}/.backups/` with mode `0o600` (POSIX) / restrictive DACL (Windows), capped at `MAX_BACKUPS=3`. Token rotation triggers a backup, so up to 3 superseded bearer tokens may persist on disk per integration; clear the backup folder manually for tighter retention.
62
+ - **Malformed-input matrix + shape gates + BOM strip on integration-config reads (#645, #797)** — broken-JSON backups on Windows also receive a restrictive ACL, with the read-modify-write TOCTOU window closed.
63
+ - **CI guard: harness components must not leak into production client bundle (Wave 2 PR 7)** — new `scripts/ci/verify-harness-stripped.mjs` runs after `npm run build` and greps `dist/client/` for known harness symbols (`UpdateAvailableHarness`, `harness-acknowledge`, etc.). Defends against a future commit accidentally importing a harness component from a production-shipping module, which would expose internal state (e.g. acknowledge buttons, version accessors) to end users. Pairs with the #660 audit confirming every settings-open path routes through the ack-clearing wrapper.
64
+
65
+ ### Internal
66
+
67
+ - **Annotation-lifecycle architecture pass (ADRs 031–037, #695–#714)** — origin-tagged transaction wrappers (ADR-031), a `RefreshResult` tagged variant (ADR-032), `DocumentRegistry` extracted from `document-service` (ADR-033), named file-open entry points (ADR-034), a per-key change-observer factory + `AnnotationLifecycle` module (ADR-035), the `FormatAdapter` capability set + `LoadResult` (ADR-036), and the `LayoutModel` rune store (ADR-037). Includes observer-driven tombstoning that records on every delete.
68
+ - **`#477` Phase 0 spikes (#712, #726, #750)** — session-resume Spike A (GO), plugin-monitor Spike B (NO-GO), marketplace-install spike re-validated NO-GO.
69
+ - **Sidecar-launcher validation spike (#642, #794)** — canonicalize-before-allowlist, Windows reparse-point walk, POSIX hardlink + world-writable-parent rejection, prototyped and tested under `#[cfg(test)]` in `integrations_probe.rs`. Not yet wired into the shipped spawn path.
70
+ - **Test-suite audit (#786)** — ADR-027 privacy bug fix, weak-assertion sweep, ADR-031 gap fill; E2E `waitForTimeout` flake removal (#785); schema-version assertions pinned to `CURRENT_SCHEMA_VERSION` (#789).
71
+ - **Refactors** — `matchShortcut` helper extraction + dead `useSettingsShortcut` removal (#820), shared SSE event-consumer extraction (#822), `THEME_OPTIONS` extracted from TitleBar (#790), typed `RejectionReason` from `extract_file_arg` (#819), dead Solo/Tandem mode plumbing removed.
72
+ - **Tooling / CI** — `check:tokens` extended with a bundle-color blocklist (#826), `claude-review` workflow hardened + auto `/code-review` on new PRs (#830), `block-e2e-port-kill` PreToolUse hook removed (#787).
73
+ - **Dependencies** — `ws` 8.19.0 → 8.20.1 (#772) and `qs` bumped (npm_and_yarn group); no CVE cited.
74
+ - **Docs** — `RelativeRange` invariants documented (#793), roadmap and CLAUDE.md file-map refreshes (#744, #749, #751), design-notes + redesign-review archival (#774, #775), reference-doc consolidation (#852, #854, #856), and AGENTS.md tracked as the cross-agent contributor guide (#858).
9
75
 
10
76
  ## [0.12.0] - 2026-05-15
11
77
 
@@ -144,6 +210,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
144
210
  - **Tauri shell**: reload shortcuts (F5, Ctrl+F5, Shift+F5, Ctrl+R, Ctrl+Shift+R) are now blocked in the desktop app to prevent accidental navigation away from the editor; DevTools, Find, Print, and right-click context menu are preserved (#541)
145
211
  - **Semantic token foundation expanded for redesign wave 2 (#521)** — added radius, font-size, shadow, z-index, editor-font-size, and highlight-color token families in `index.html`, plus checker rules that now flag raw `border-radius: <n>px` and inline `box-shadow: ... rgba(...)` in `src/client/`.
146
212
  - **Read-only/info surfaces now use the shared info token family (#521)** — `ReviewOnlyBanner`, `ConnectionBanner`, `ToastContainer`, `StatusBar`, and related chrome now consume the shared token scales instead of hardcoded radius/text/shadow values.
213
+ - **Monitor and channel honor `CLAUDE_PLUGIN_OPTION_SERVER_URL`** — `resolveTandemUrl()` now checks the `CLAUDE_PLUGIN_OPTION_SERVER_URL` environment variable (exported by Claude Code's plugin host from `plugin.json` `userConfig`) before falling back to `TANDEM_URL` and the localhost default. Both the monitor (`src/monitor/index.ts`) and channel shim (`src/channel/run.ts`) benefit automatically. No change for existing installs that don't use `userConfig`. (Drafted as a standalone v0.10.1 patch that was never tagged; shipped as part of v0.11.0.)
214
+ - **Monitor and channel honor `CLAUDE_PLUGIN_OPTION_AUTH_TOKEN`** — new `resolveAuthToken()` function in `src/shared/cli-runtime.ts` mirrors `resolveTandemUrl()`. Precedence: `CLAUDE_PLUGIN_OPTION_AUTH_TOKEN` → `TANDEM_AUTH_TOKEN`. `authFetch` uses it automatically, so all stdio subcommands gain the new lookup without caller changes.
147
215
 
148
216
  ### Tests
149
217
 
@@ -165,15 +233,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
165
233
  - **Dark annotation highlight colors** — `--tandem-highlight-yellow/green/blue/pink` now have dark-adapted overrides in `[data-theme="dark"]`; the light `rgba(255, 235, 59, 0.3)`-style values were washed out against dark surfaces.
166
234
  - **Forced-colors fallbacks for background-only state surfaces (closes #311)** — StatusBar status dots, toast badge, ModeToggle active button, BulkActions confirm button, AnnotationCard type-badge and Private pill now have `border`/`outline` fallbacks in `@media (forced-colors: active)`.
167
235
 
168
- ## [0.10.1] - Unreleased
169
-
170
- Plugin URL and auth resolution for custom-port and network-remote setups.
171
-
172
- ### Changed
173
-
174
- - \*\*Monitor and channel honor \*\***CLAUDE_PLUGIN_OPTION_SERVER_URL** — `resolveTandemUrl()` now checks the `CLAUDE_PLUGIN_OPTION_SERVER_URL` environment variable (exported by Claude Code's plugin host from `plugin.json` `userConfig`) before falling back to `TANDEM_URL` and the localhost default. Both the monitor (`src/monitor/index.ts`) and channel shim (`src/channel/run.ts`) benefit automatically. No change for existing installs that don't use `userConfig`.
175
- - \*\*Monitor and channel honor \*\***CLAUDE_PLUGIN_OPTION_AUTH_TOKEN** — new `resolveAuthToken()` function in `src/shared/cli-runtime.ts` mirrors `resolveTandemUrl()`. Precedence: `CLAUDE_PLUGIN_OPTION_AUTH_TOKEN` → `TANDEM_AUTH_TOKEN`. `authFetch` uses it automatically, so all stdio subcommands gain the new lookup without caller changes.
176
-
177
236
  ## [0.10.0] - 2026-05-03
178
237
 
179
238
  Complete React → Svelte 5 migration. All 39 client `.tsx` files have been replaced with Svelte 5 rune-based equivalents; `react`, `react-dom`, and `@tiptap/react` are no longer in the bundle. Includes a review-mode correctness fix, accessibility improvements, and follow-on Codex security hardening.