Send a lone CR through the newline transform, and say what pinned is

`toClaudePayload` matched `/\r?\n/`, so a bare CR that is not part of a
CRLF went through verbatim — and a bare CR *submits* in a Claude prompt
and *runs* the line in a shell, which is the terminator the function's
own contract says it never appends. A `<textarea>` cannot produce one,
but `load_in` returns whatever a hand-edited or externally written notes
file holds, so the guarantee has to cover that rather than only what the
editor can type.

`Note.pinned` is persisted and sorted on, but nothing in the app sets
it: there is no pin control and no indicator. The spec stated the
ordering rule as though pinning existed and §8 did not list it, so the
spec is amended to say `pinned` is reserved and inert in v1, and pinning
is added to the out-of-scope list. No UI is added — a user-facing
affordance does not belong in a fix wave.

Also renamed NotesPanel.test.tsx's "deletes the selected note and falls
back to another": `useNotes` is mocked in that file and the mocked list
never changes, so the fallback was never exercised. A name that claims
coverage which is absent is worse than an absent test, because it makes
the gap invisible. The real assertion now lives against the real hook in
NotesPanel.shared.test.tsx.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HjL1E2JFNctUqCYotUwqqb
This commit is contained in:
2026-09-01 13:47:01 -07:00
co-authored by Claude Opus 5
parent 5c47656444
commit 436b6dd470
4 changed files with 38 additions and 2 deletions
@@ -85,6 +85,13 @@ struct ProjectNotes { version: u32, notes: Vec<Note> }
Order is pinned-first then `updated_at` descending. Manual reordering is deliberately out.
**`pinned` is reserved, and nothing in v1 sets it.** The field is persisted and sorted on, but
there is no pin control and no pinned indicator anywhere in the UI, so in v1 every note sorts
by `updated_at` descending and the pinned-first half of the rule is inert. It is carried from
the start because it is a field in a file: adding one later means every reader has to tolerate
its absence forever, while an unused `bool` with a serde default costs nothing. Pinning itself
is out of scope — see §8.
### Why not a field on `Project`
`projects.json` is written on **every blur** by the debounced `useProjectSave` path
@@ -339,6 +346,9 @@ that — but anything touching real key handling needs a manual check in Chromiu
generic write-a-file-to-container command today (only `write_file_to_container` for image
paste and `upload_bytes_to_container` for migration), and a second storage path with a
sync direction is a v2 conversation.
- Pinning. `Note.pinned` exists on both sides of the IPC boundary and the backend sorts on
it, but no UI sets it and none indicates it — see §1. A pin control is a user-facing
affordance and belongs in the change that adds it, not in the storage that anticipates it.
- Tags, full-text search, manual reordering, note history.
- Any change to `claude_instructions`. The two features stay distinct: ambient context
versus fired-on-demand items.