From 53a6051c1d74e48d9a065ce0765dc49a75c9d711 Mon Sep 17 00:00:00 2001 From: "Danilo M." Date: Fri, 16 Oct 2026 20:46:50 +0200 Subject: notes: in-drawer editor with commit-on-save and git pull The editor, and the write and git path behind it. Save is two clicks and each does one thing: the first writes the note and only then arms the button as 'Commit & push?', so a quick second click cannot commit a note the first has not written yet. The write path refuses when db.json cannot be read as the index. That is not hypothetical: git pull --rebase --autostash resolves a remote db.json change against a local uncommitted one, the stash pop conflicts, git still exits 0, and the file is left full of merge markers. Reading that as 'no notes' and writing it back deleted every title in a probe; Notes.valid now distinguishes it from an empty store and the write reports instead. parse stays tolerant for display. Stamping lastpull also only follows a pull that worked, and only when git is on at all. Db reads that a write is based on go through reload() plus waitForJob(): blockLoading does not make reload() blocking, contrary to the note in AGENTS.md, and reading text() straight after reload() returns the old contents. A body is written with a plain setText, which needs no prior load; only reading text() before a load would. --- docs/superpowers/specs/2026-10-16-notes-design.md | 29 +++++++++++++++++------ 1 file changed, 22 insertions(+), 7 deletions(-) (limited to 'docs/superpowers/specs') diff --git a/docs/superpowers/specs/2026-10-16-notes-design.md b/docs/superpowers/specs/2026-10-16-notes-design.md index 9b460a8..a9f5420 100644 --- a/docs/superpowers/specs/2026-10-16-notes-design.md +++ b/docs/superpowers/specs/2026-10-16-notes-design.md @@ -111,6 +111,15 @@ All index writes go through the module's `db.json` `FileView` with `db.json` for `notes.sh` to trip on. A body is written with a `FileView` on its own path, which creates the file. +**A write is refused when `db.json` cannot be read as the index.** That is not +hypothetical: `git pull --rebase --autostash` resolves a remote `db.json` +change against a local uncommitted one, the stash pop conflicts, git still +exits 0, and the file is left full of merge markers. Reading that as "no notes" +and writing it back would delete every title, so the write instead reports +`db.json could not be read; resolve it in ` and leaves the file for +git to resolve. `Notes.valid` is the check; `Notes.parse` stays tolerant for +display, returning an empty store for the same input. + - **Create**: the first click pulls first (see Git), then re-reads `db.json` so the append is based on what the pull brought in, not on what was read before it; `notes.sh` reads the id after its own pull for the same reason. @@ -163,12 +172,16 @@ clipboard page keeps for its own untrusted text. `git add .` runs from that changed nothing, is not a failure: git has nothing to record and the push still runs. -`git.lastpull` is stamped after the pull, not before. `notes.sh` stamps first -and then pulls, which leaves its own `db.json` dirty for the pull it is about -to run, and it ignores the resulting failure; stamping on return keeps the -field truthful without that. The field is what `notes.sh -l` reads to decide -whether to pull again inside `GITSYNCDELAY`, so a page pull that did not stamp -would make every CLI list pull again. +`git.lastpull` is stamped after the pull, not before, and only when that pull +worked. `notes.sh` stamps first and then pulls, which leaves its own `db.json` +dirty for the pull it is about to run, and it ignores the resulting failure; +stamping on return keeps the field truthful without that. The field is what +`notes.sh -l` reads to decide whether to pull again inside `GITSYNCDELAY`, so a +page pull that did not stamp would make every CLI list pull again. + +A pull that fails without leaving a conflict does not stop a note being saved: +the note is written and the failure is shown, as a note taker that refused to +work offline would be worse. Only an unreadable index stops the write (above). The commit message follows `notes.sh`'s wording but names the page, so history says where a change came from: `quickshell - adding note from @@ -224,7 +237,9 @@ Registering: `import "modules/notes"` and a `NotesModule {}` in `shell.qml`'s `params` and `git.lastpull` intact, and adding does not mutate the input object. - A malformed or truncated `db.json` yields an empty list rather than a - throw, so the page renders "no notes" instead of failing to load. + throw, so the page renders "no notes" instead of failing to load, while + `valid` returns null for the same input so a write refuses instead of + replacing it. Merge markers read the same way. The tests must be shown to fail on a broken input before they are trusted. -- cgit v1.2.3