diff --git a/.dependency-cruiser.cjs b/.dependency-cruiser.cjs index 35f5dd564..88fb383e6 100644 --- a/.dependency-cruiser.cjs +++ b/.dependency-cruiser.cjs @@ -16,12 +16,14 @@ module.exports = { // - electron/mcp/validation.ts — string-only branch/UUID validators; the renderer // shares them so it never offers a branch the IPC layer would reject // - electron/shared/ — renderer-safe constants/pure helpers (no Node/Electron imports) + // - electron/documents/shared.ts — agent ids/labels the document workspace shows pathNot: [ '^electron/ipc/channels\\.ts', '^electron/mcp/prompt-detect\\.ts', '^electron/mcp/validation\\.ts', '^electron/agent-hooks/status\\.ts', '^electron/shared/', + '^electron/documents/shared\\.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..41629961b --- /dev/null +++ b/docs/document-workspaces.md @@ -0,0 +1,187 @@ +# 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 to 3 of the plan below are built (the loop, comparison, annotations); HTML is 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…**. Type or browse to a + folder and name the document. Neither has to exist: type a new name onto the end of the + path and that folder is the project. The dialog says what it will do — create the + folder, `git init`, create the file, make the first commit — and does it on confirm. +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. +7. **Annotations.** The same composer offers **Note** and **Ask** beside **Task**. A note + is a bubble under the passage. A question is a bubble an agent answers into, running + read-only in the checkout; question and answer stay visible together. Resolve (`r`) + collapses a bubble to one line, Delete removes it with an Undo in the toolbar, and + **Make task** reopens the composer on the passage with the bubble's text (and answer) + as the instruction; the bubble then collapses as `task`. + +### 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. Only tracked files count as pending edits: untracked scratch files + and everything under `.parallel/` stay 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` (the sandbox blocks writes outside the worktree), + `gemini -p --output-format json --approval-mode auto_edit` (`plan`, Gemini's read-only + mode, for annotation questions). Process exit means the + proposal is ready. Cancelling kills the CLI's whole process group. OpenCode and Copilot + expose an unrestricted shell in print mode and are not offered until they can be + restricted. +- **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. While + the main session is working, a new run can only use alternates. +- **Scope is enforced, not trusted.** Files the agent touched or staged outside the + document are reverted before the proposal commit and listed on the candidate; the + proposal commit is verified to contain the document alone. 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/-