docs(viewer): fix round 1 — fallback trap, tracked checklist, residual-risk framing

- CLAUDE.md: document the viewer.html fallback trap (missing/broken Vite entry
  silently serves index.html into the viewer window) and point at the Rust test
  that pins it.
- Give the manual verification checklist a durable, tracked home: append it as
  a markdown task list to the terminal-file-viewer design spec, including the
  file-path hover key-hint wording check and the CRLF/BOM round-trip save check.
- default.json: state the app-command residual risk and the pending AppManifest
  lockdown directly in the capability file's own description, not only in
  CLAUDE.md, since this file is the reviewed threat model of record.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-22 21:36:15 -07:00
co-authored by Claude Opus 5.5
parent 90991fee32
commit 398281c8b5
4 changed files with 56 additions and 3 deletions
+5 -1
View File
@@ -78,7 +78,11 @@ docker exec stdout → tokio task → emit("terminal-output-{sessionId}") → li
`components/terminal/filePathLinkProvider.ts` registers it with xterm. The OSC 8 handler now `components/terminal/filePathLinkProvider.ts` registers it with xterm. The OSC 8 handler now
runs with `allowNonHttpProtocols` on and dispatches `file:` to the viewer, so every other scheme runs with `allowNonHttpProtocols` on and dispatches `file:` to the viewer, so every other scheme
must be refused *there*. `viewer.html` must never carry an inline `<style>` — Tauri would add a must be refused *there*. `viewer.html` must never carry an inline `<style>` — Tauri would add a
style nonce and CodeMirror's injected styles would stop applying. style nonce and CodeMirror's injected styles would stop applying. A missing or broken
`viewer.html` Vite entry is not caught by Tauri at build time — both Vite dev and Tauri's asset
lookup silently fall back to `index.html`, so the window just opens the *main app*, full UI and
all, with no error anywhere; `file_viewer::tests::the_viewer_entry_exists_and_is_a_vite_input`
in `file_viewer/mod.rs` is the only thing pinning this.
- **`components/layout/`** — TopBar, MainTabs (the unified tab strip), Sidebar, StatusBar - **`components/layout/`** — TopBar, MainTabs (the unified tab strip), Sidebar, StatusBar
- **`components/projects/`** — `ProjectRow` (select-only list row), `ProjectList`, `AddProjectDialog`, - **`components/projects/`** — `ProjectRow` (select-only list row), `ProjectList`, `AddProjectDialog`,
and the editors reused by Project Home and the editors reused by Project Home
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -345,3 +345,52 @@ click, editable, CodeMirror 6, probe-roots resolution, 2 s polling, no autosave,
10. **Event delivery (§3).** `emit_to(label, …)` still reaches a bare `listen()` in the main 10. **Event delivery (§3).** `emit_to(label, …)` still reaches a bare `listen()` in the main
window, so the viewer subscribes via `getCurrentWindow().listen` and the main window has no window, so the viewer subscribes via `getCurrentWindow().listen` and the main window has no
listener for viewer event names. listener for viewer event names.
## Manual verification checklist
Not runnable inside the planning/implementation container: it needs `npx tauri dev` on a machine
with a display, plus a running project container. Run this after every task on this feature has
landed, including any review fix rounds (in particular Task 11's CRLF/BOM save fix, item 16
below).
- [ ] 1. In a Claude session, ask for a file listing; click `src/…` paths, `/workspace/...`
absolute paths, a `path:line` and a `path:start-end`. Each opens its own window titled
`<basename> — <project>`, scrolled to and highlighting the line/range.
- [ ] 2. Click the same path again → the existing window is focused and re-highlights; no
duplicate.
- [ ] 3. Open 20 windows; the 21st click shows the "20 file windows are already open" toast.
- [ ] 4. Edit, `Ctrl+S`: file changes in the container (`cat` it in a bash tab); mode preserved
(`stat -c %a`); owner is the container user.
- [ ] 5. While a window is open, have Claude edit the file: clean window reloads with "Reloaded";
a dirty window shows "Changed on disk" with both buttons; "Overwrite on save" then Save
succeeds; "Reload (discard mine)" drops the edits.
- [ ] 6. Save while the file changed between polls → "Changed on disk" banner, no data written.
- [ ] 7. Delete the file in a bash tab → "File no longer exists", text still copyable, Save
disabled.
- [ ] 8. Stop the project with a window open → "Container not running" banner; start it → banner
clears, polling resumes.
- [ ] 9. Click a path under `/etc` or a `file:///etc/hosts` OSC 8 link → read-only badge with the
write-roots reason.
- [ ] 10. Close a dirty window with the X → Save / Discard / Cancel bar; Cancel keeps it open;
Discard closes.
- [ ] 11. Close the *main* window with viewers open → app exits, viewers close.
- [ ] 12. Ctrl/Cmd+Shift+I opens devtools in a viewer in dev; in a release build the CSP console
shows no violations (CodeMirror styles apply).
- [ ] 13. A wrapped long path (narrow the terminal) underlines across the wrap and opens.
- [ ] 14. Image (`.png`) opens read-only; a `.bin`/binary shows "not text".
- [ ] 15. **File-path hover key-hint wording.** Hover a plain-text file-path link in the terminal
(not an OSC 8 hyperlink) while a foreground program is holding the mouse (e.g. an
interactive TUI like `vim`/`htop`/`claude`'s own REPL) and confirm the hover card's key hint
reads correctly for the platform/mode: "Shift+click to open" on non-Mac while the program
tracks the mouse, "Click to open" when nothing tracks the mouse, "Option+click to open" on
Mac with `macOptionClickForcesSelection`, or "Not clickable while a program holds the mouse"
on Mac without it (`openHintLabel` / `fillFileCard` in `TerminalView.tsx`). Then confirm the
*click itself* is held to whatever the card promised — the modifier actually required to
activate the link matches the hint shown, even if the program changes its mouse-tracking
mode between the hover and the click.
- [ ] 16. **CRLF/BOM file round-trip save.** Open a file in the container that has Windows line
endings (CRLF) and/or a UTF-8 BOM (e.g.
`printf '\xEF\xBB\xBF\r\nfoo\r\nbar\r\n' > /workspace/<project>/crlf.txt` in a bash tab),
open it in the viewer, make a small text edit, and Save. Then `cat -A` (or `xxd`) the file
in the container and confirm the CRLF line endings and the BOM are still present/unchanged
apart from the edit — i.e. the save did not silently normalize them to LF or strip the BOM.