Repository navigation
feat(notes): keep todos, ideas and notes per project - #45
Merged
Merged
Conversation
Add a project_notes table to kriyon.db and three commands to list, save and delete notes. A note is a todo, an idea or a plain note that belongs to a project, not a session. kriyon-core checks every note from the webview before it is written: ids are bounded, text is trimmed and capped, and only a todo can carry a done mark. An update never moves a note to another project. Co-Authored-By: Claude Opus 5.5 <[email protected]>
The Details rail gets a third tab, Notes, that lists the todos, ideas and notes of the active session's project. Every session in the project sees the same list, and nothing in it is sent to Claude. - A capture box adds a note of the picked kind on Enter. - Filters show one kind at a time; done todos fold away under Done. - Opening a note edits its text, a longer body, its kind and pin. Edits save on blur, on Back and when the view closes. Delete asks first. - The project menu gains "Open notes", which shows that project's notes without opening a session, and a project header counts open todos. The store shows a change at once and rolls it back with a toast when the save fails, so a note never vanishes quietly. Co-Authored-By: Claude Opus 5.5 <[email protected]>
A small overlay takes a todo, idea or note without leaving what you are doing. It files under the project the Notes tab would show, can be pointed at another project, and closes with a toast naming where the note went. The chord is reserved so a focused terminal passes it to the app, and the command palette offers "Add a note…" once a project exists. Co-Authored-By: Claude Opus 5.5 <[email protected]>
The pin button's class was built as a string expression, which the hover-seam check cannot see and the formatter rewrote. The reveal now sits on a wrapper span, so the button carries a plain kr-hover-surface. Co-Authored-By: Claude Opus 5.5 <[email protected]>
ADR 0053 records why notes are one list with three kinds, why they live in the app database rather than the repository, and where they show. The glossary gains Project note and Note capture. Co-Authored-By: Claude Opus 5.5 <[email protected]>
A save looked up nothing: an id already kept under one project could be saved under another and overwrite that note, and the command returned the webview's copy even where the store kept a different project or creation time. The save now refuses an id owned by another project (kriyon-core check_owner) and returns the row as read back from the store, so the frontend holds what the database holds. Co-Authored-By: Claude Opus 5.5 <[email protected]>
A failed save put back the copy from before that edit, whatever had happened since. With two saves in flight it could undo a later edit, restore a copy that was never saved, or bring back a note deleted meanwhile. The store now remembers the last copy known to be stored and only touches a note while it still shows that save's own copy; tests cover saves that settle out of order. An edit with a cleared title was dropped whole, so a body typed under it was lost without a word. A blank title now keeps the stored one, the detail view puts it back in the field, and the rest of the edit saves. Co-Authored-By: Claude Opus 5.5 <[email protected]>
The project picked with "Open notes" was kept with the session active at the time and came back whenever that session was opened again, so the Notes tab and Cmd+Shift+N could show the wrong project. The pick is now a plain project id that installNotesPickReset clears as soon as another session becomes active. With no session open, the Notes view showed the tab strip, but Details then had no strip at all, leaving no way back to Notes. Details keeps the strip while there are notes to show. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Cmd+Shift+N was written twice, in the capture overlay and in the chords a terminal lets through, so a rebind in one would leave a focused terminal swallowing it. Both now use isNoteCaptureChord. On a Mac it is Cmd only, like every chord a terminal passes on; Ctrl stays with the shell. "Add a project first" was checked by each caller rather than by openNoteCapture, so a new entry point could open a panel with no project to file under. The opener now checks and explains, and the palette entry relies on it. Co-Authored-By: Claude Opus 5.5 <[email protected]>
The frontend's text limit was a second copy of kriyon-core's with nothing tying them, and the detail body had no limit at all, so a long paste failed on save. Both limits now sit beside each other with a test that reads them from the Rust module, and the body field is capped too. Co-Authored-By: Claude Opus 5.5 <[email protected]>
The Notes tab header copied the sidebar's project square. It now lives in theme/projectColor.ts as projectSquareStyle, used by both. Co-Authored-By: Claude Opus 5.5 <[email protected]>
The detail view repeated the store's blank-title rule before calling it, so the store's own rule never ran for that caller and a change to it would not reach the view. update() now returns the note as it stands and skips edits that change nothing; the view sends what was typed and shows what the store kept. Co-Authored-By: Claude Opus 5.5 <[email protected]>
update() compared text, body, kind and pinned by hand, a second list of the fields NotePatch already names. A field added to NotePatch alone would have been dropped without a word. It now compares only the keys the edit carries. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Member
Author
Review and fix — pass 1Full review of the pull request, then fixes and re-checks over 3 passes. Fixed 11 issues; 0 left open. All local checks and CI are green on the new head.
NotesScored below the bar and left alone: a hand-drawn filter toggle, a blank list for an empty filter, timestamp bounds, newlines in pasted text, and the test-only seeding of the saved-copy map. Fixed this pass
Checked by 3 finders (boundary, contract, saved data, correctness, tests, public text, lifecycle, frontend rules, errors, step 5 re-check of the fixes) · architecture review · scorer: 26 scored, 11 kept. Ready to merge, as far as this review can see. Nothing is open from this pass or any pass before it. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changed
Each project now has its own list of todos, ideas and notes. They are the user's own planning: they belong to the project, not a session, every session in the project sees the same list, and nothing in it is sent to Claude.
project_notestable inkriyon.dbwith a foreign key toprojects.kriyon-corechecks every note from the webview: ids are bounded, text is trimmed and capped at 500 characters, the body at 20,000, and only a todo can be done. An update never moves a note to another project.ADR 0053 records the decisions, including why notes live in the app database rather than in the repository. The glossary gains Project note and Note capture.
Why
People have thoughts while working that are not prompts: a todo for later, an idea to try, a fact worth keeping. Today they go to another app, or into a terminal where they get lost or sent to Claude by mistake. This keeps them next to the work, per project.
How I tested it
project_notesvalidation tests inkriyon-core(checked they fail when validation is removed), store round-trip tests for the new table, and tests for the save command's glue.pnpm checkpasses.Checklist
dev.pnpm checkpasses.🤖 Generated with Claude Code