From 73c0bfccc42625ef30072c9910d8a011fe3fc09f Mon Sep 17 00:00:00 2001 From: Codeman maintainer Date: Thu, 1 Oct 2026 11:19:00 +0200 Subject: [PATCH] fix(files): keep attachment markdown refs from resolving into the workspace, and render files without chat line breaks (#503 review) - A markdown preview opened by attachment id under a bare file name (attachment cards, history drawer) no longer resolves relative refs against the workspace root: filePreviewText carries attachmentId, and the rebase pass turns those images into their alt text and unwraps those links. Absolute-path and workspace previews are unchanged. - _renderMarkdown(text, { breaks = true } = {}): the File Viewer passes breaks: false, so a hard-wrapped paragraph renders as one paragraph; the Response Viewer keeps a
per newline. - Absolute paths linkified inside a rendered document now carry the preview's data-session-id. - CLAUDE.md, architecture-invariants and the Working-With-Files wiki page now say that only an in-workspace path clicked in the terminal keeps the tail viewer. - Tests in test/file-preview-markdown.test.ts for all three fixes, including an end-to-end run of the shipping app.js + marked + DOMPurify. Co-Authored-By: Claude Opus 5.5 (1M context) --- CLAUDE.md | 2 +- docs/architecture-invariants.md | 6 +- docs/wiki/Working-With-Files.md | 7 +- src/web/public/app.js | 11 +- src/web/public/panels-ui.js | 31 ++++- test/file-preview-markdown.test.ts | 177 ++++++++++++++++++++++++++--- 6 files changed, 205 insertions(+), 29 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 450bfcbe..380559ae 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -295,7 +295,7 @@ Codeman is a Claude Code session manager with web interface and autonomous Ralph **File Viewer edit mode** (issue #212): the file-preview overlay edits workspace text files in place — `GET .../file-content?edit=1` + `PUT /api/sessions/:id/file-content`, policy in `src/config/file-editing.ts`. This is a **third file surface and the only one that WRITES**: read-path confinement (realpath + workspace + ownership) plus sensitive/blocked/`.git` denies and an extension **allowlist**; writes are `wx`-temp + rename (no `O_CREAT` anywhere = edit-in-place is structural); optimistic concurrency via sha256 `baseHash` → 409. ⚠️ `edit=1` never truncates and the client must never save a plain-preview buffer (the 500-line truncation would silently delete the rest). ⚠️ CRLF/UTF-8 guards: EOL re-applied server-side, non-UTF-8 refused via round-trip compare. → [architecture-invariants#file-viewer-edit-mode](docs/architecture-invariants.md#file-viewer-edit-mode), `docs/file-viewer-edit-plan.md` -**File Viewer text view: rendered markdown + Lines/Wrap toggles** (`_renderFilePreviewText()` in panels-ui.js): a `.md`/`.markdown` opens RENDERED by default with an `MD` pill back to source; the plain-text view has `Lines` (CSS-counter gutter) and `Wrap` toggles. ⚠️ ONE markdown pipeline: the viewer calls `_renderMarkdown()` (marked + the DOMPurify allowlist, the Response Viewer's) and binds the Response Viewer's click delegate (`_bindResponseViewerInteractions`) on the preview body for code-copy buttons and path links; never a second parser or handler. ⚠️ The document is built inside a `