From ea36a008c3c5905485c24946ae254a6104577d53 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 3 Sep 2026 23:08:57 +0000 Subject: [PATCH 01/12] feat(documents): add document workspaces behind an experimental flag A new project kind for exploring problems in prose: a Git repository plus one Markdown document. Select a passage, send the same instruction to one or more agents, compare the proposals side by side, accept one as a single readable commit. Backend (electron/ipc/documents.ts): - Dispatch commits pending manual edits, snapshots the base, gives every candidate its own worktree and runs the official CLI headlessly (claude -p stream-json with read/edit tools only, codex exec --json, gemini -p json). Process exit means the proposal is ready. - The main session keeps a persistent worktree so its cwd (and the provider's prompt cache) never changes, resumes by session id, and is handed the diff of the canonical document since it last saw it. - Out-of-scope files are reverted and listed; hunks outside the selected passage are counted. The structured rationale the prompt asks for becomes the proposal commit message with Parallel-* trailers. - Acceptance is one squashed integration commit carrying the run record; a base that moved is merged three-way or marked stale. Rejection commits the record alone so history stays readable. - Document watcher, history with parsed trailers, version and diff at a commit, revert. Renderer (src/documents, src/store/documents.ts): - Full-window workspace with Document, Compare and History tabs. - Block-level rendering with source line mapping (src/lib/markdown-blocks), selection by text, block or heading section, and an in-place composer with agent chips and candidate counts. - Compare view: rationale first, rendered base and candidates, changed blocks marked and navigable, model-blind by default, source diff toggle, per-candidate notes, accept or reject. - Document project creation from the sidebar, flag in Settings. Tests cover the prompt and rationale parsing, CLI launch and output parsers, scope checks, block mapping and diffing, and the full lifecycle against a real temporary repository with a fake agent. An env-gated test drives the real claude CLI through a proposal, acceptance and a resumed follow-up. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_01UP9JjPPAYEBBNe1VbGnSzU --- .gitignore | 1 + docs/document-workspaces.md | 150 +++ electron/ipc/channel-manifest.json | 18 +- electron/ipc/document-agents.test.ts | 170 +++ electron/ipc/document-agents.ts | 295 +++++ electron/ipc/document-prompt.test.ts | 98 ++ electron/ipc/document-prompt.ts | 129 ++ electron/ipc/documents.integration.test.ts | 234 ++++ .../documents.real-claude.integration.test.ts | 150 +++ electron/ipc/documents.test.ts | 70 ++ electron/ipc/documents.ts | 1040 +++++++++++++++++ electron/ipc/register.ts | 110 ++ electron/ipc/shared-types.ts | 123 ++ electron/main.ts | 3 + electron/preload.cjs | 16 + electron/shared/document-agents.ts | 29 + src/App.tsx | 11 + src/components/SettingsDialog.tsx | 9 + src/components/Sidebar.tsx | 37 +- src/documents/CompareView.tsx | 305 +++++ src/documents/DocumentViewer.tsx | 164 +++ src/documents/DocumentWorkspaceOverlay.tsx | 268 +++++ src/documents/HistoryView.tsx | 212 ++++ src/documents/NewDocumentProjectDialog.tsx | 181 +++ src/documents/RunComposer.tsx | 211 ++++ src/documents/RunsRail.tsx | 127 ++ src/documents/SourceDiff.tsx | 43 + src/documents/documents.css | 895 ++++++++++++++ src/documents/use-blocks.ts | 61 + src/ipc/types.ts | 10 + src/lib/markdown-blocks.test.ts | 129 ++ src/lib/markdown-blocks.ts | 220 ++++ src/store/autosave.ts | 1 + src/store/core.ts | 2 + src/store/documents.ts | 441 +++++++ src/store/persistence.ts | 3 + src/store/projects.ts | 31 + src/store/store.ts | 3 + src/store/types.ts | 20 + src/store/ui.ts | 5 + 40 files changed, 6021 insertions(+), 4 deletions(-) create mode 100644 docs/document-workspaces.md create mode 100644 electron/ipc/document-agents.test.ts create mode 100644 electron/ipc/document-agents.ts create mode 100644 electron/ipc/document-prompt.test.ts create mode 100644 electron/ipc/document-prompt.ts create mode 100644 electron/ipc/documents.integration.test.ts create mode 100644 electron/ipc/documents.real-claude.integration.test.ts create mode 100644 electron/ipc/documents.test.ts create mode 100644 electron/ipc/documents.ts create mode 100644 electron/shared/document-agents.ts create mode 100644 src/documents/CompareView.tsx create mode 100644 src/documents/DocumentViewer.tsx create mode 100644 src/documents/DocumentWorkspaceOverlay.tsx create mode 100644 src/documents/HistoryView.tsx create mode 100644 src/documents/NewDocumentProjectDialog.tsx create mode 100644 src/documents/RunComposer.tsx create mode 100644 src/documents/RunsRail.tsx create mode 100644 src/documents/SourceDiff.tsx create mode 100644 src/documents/documents.css create mode 100644 src/documents/use-blocks.ts create mode 100644 src/lib/markdown-blocks.test.ts create mode 100644 src/lib/markdown-blocks.ts create mode 100644 src/store/documents.ts diff --git a/.gitignore b/.gitignore index 7d5ed2181..ff871a58d 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,7 @@ update-test/ # Keep generated docs content ignored, but track the authored architecture overview. docs/* !docs/architecture-overview.html +!docs/document-workspaces.md # Sandbox bind-mount artifacts from user home (not project files). # Root-anchored so legitimate nested files with these names are still tracked. diff --git a/docs/document-workspaces.md b/docs/document-workspaces.md new file mode 100644 index 000000000..71dc0279f --- /dev/null +++ b/docs/document-workspaces.md @@ -0,0 +1,150 @@ +# Document Workspaces + +**A project type in Parallel Code for exploring problems in prose** + +Status: experimental, behind the _Document workspaces_ switch in Settings → Experimental. +Slices 1 and 2 of the plan below are built; annotations and HTML are not. + +Parallel Code already runs several agents against the same codebase and keeps the results +isolated, attributable, and comparable. Document Workspaces applies the same machine to +writing and thinking: architecture notes, specs, ADRs, research. Several agents get the +same passage and the same base version. You read the alternatives and decide what enters +the document. + +``` + ┌────────────── Claude Code ──────────────● accepted + │ \ + ────────● base ─┤ ●────── + │ / + └────────────── Codex ───────────────○ discarded +``` + +## What is built + +### Using it + +1. Enable _Document workspaces_ under Settings → Experimental. +2. Click **+** next to Projects and choose **Document project**. Pick a Git repository and + one tracked Markdown file in it. +3. The workspace opens full-window with three tabs: **Document**, **Compare**, **History**. +4. In the document, select text, click a block, or press **§** next to a heading to select + the section. A composer opens under the selection: type an instruction, pick agents and + candidate counts, press Enter. +5. Proposals appear in the right-hand rail as they finish. **Review** (one candidate) or + **Compare** (several) opens the compare view: base on the left, candidates to the right, + each starting with its rationale. Accept one, or reject all. +6. **History** is `git log` for the document with the `Parallel-*` trailers parsed: + what changed, which agent, which instruction, which base. Show the diff or render the + older version. Revert any entry. + +### How it works + +- **Editing happens in your editor.** The app watches the file and re-renders; an external + change drops any active selection. +- **Dispatch commits pending edits first** as a plain `Manual edits` commit so every run + has a real base. Files under `.parallel/` are left out of that commit. +- **Headless agents.** Each candidate runs the official CLI in print mode inside its own + worktree under `.worktrees/parallel-doc/`: `claude -p --output-format stream-json` + with tools limited to Read/Edit/Write/Glob/Grep, `codex exec --json --sandbox +workspace-write`, `gemini -p --output-format json --approval-mode auto_edit`. + Process exit means the proposal is ready. +- **The main session stays warm.** One agent owns the project's main session (choose it in + the composer). Its worktree is persistent (`.worktrees/parallel-doc-main`) so the working + directory, and with it the provider's prompt cache, never changes; each run resumes the + session by id (`claude --resume`, `codex exec resume`). After the canonical document + moves, the next prompt to that session carries the diff since it last saw the file. + Other agents, and extra candidates from the main agent, are one-shot alternates. +- **Scope is enforced, not trusted.** Files the agent touched outside the document are + reverted before the proposal commit and listed on the candidate. Hunks inside the + document but outside the selected passage are counted and flagged. +- **Structured rationale.** Every prompt asks the agent to end with a JSON block: + summary, changes, assumptions, questions, warnings. It opens each candidate in the + compare view and becomes the commit message. +- **One proposal commit per candidate** on a `parallel-doc/-