From a46d28f940e58cf4c829ef7fc269dc2d22dea24a Mon Sep 17 00:00:00 2001 From: "Danilo M." Date: Tue, 25 Aug 2026 17:09:26 +0200 Subject: docs: mailctl is retired, the hooks are ours The user has not run mailctl in months and the coupling this document described is gone: the live database.hook_dir symlinks post-new, mailrules.py and qtmaildirconf.py into assets/hooks/ here, where their three suites also live. All three pass. The format discipline survives the move and is kept, because what makes it necessary is two independent readers of one file, not two repositories: src/tagrules.cpp and assets/hooks/mailrules.py still share no code and still agree by test. What changes is the procedure around it, which no longer sends anyone to a sibling checkout, and the round trip, which is now verified by running the hook rather than by a CLI that is retired. Item 166 said the same thing and was filed a day before this was noticed; its row and its two-repo constraint are corrected with it. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01HFuRPtzFrSxCQjFk6tq7gD --- docs/superpowers/plans/2026-08-03-post-0.1.0-usability.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'docs') diff --git a/docs/superpowers/plans/2026-08-03-post-0.1.0-usability.md b/docs/superpowers/plans/2026-08-03-post-0.1.0-usability.md index 5b843a4..6c29fe0 100644 --- a/docs/superpowers/plans/2026-08-03-post-0.1.0-usability.md +++ b/docs/superpowers/plans/2026-08-03-post-0.1.0-usability.md @@ -239,7 +239,7 @@ taking that too literally. | 163 | The message pane shows a stale path, and the composer forks the draft | defect | S | **done, 2026-08-25.** mbsync renames an uploaded file to add its `,U=` infix while the model still holds the name the query returned. `MaildirName::resolveRenamed()` returns the path unchanged when it exists, else finds the file in that one directory whose unique stem matches; it refuses an ambiguous match and yields nothing for a genuinely missing file. Wired into all THREE read sites: the pane, Reply/Forward, and the draft reopen. The reopen was the one that cost data, forking a draft into two files with two Message-IDs, both reaching the server | | 164 | A draft this application saved keeps `inbox` | defect | S | open, 2026-08-25, **cause corrected 2026-08-25**. The first diagnosis blamed a missing drafts helper and was WRONG: `NOT_ARRIVALS` in `qtmaildirconf.py` is `("sent", "drafts")`, the folder list includes every account's drafts folder, and `notmuch count` confirms the carve-out query MATCHES the affected draft. The carve-out is scoped to `tag:new`, and the draft carries `inbox` while `tag:new` is 0, so it was never in scope when the hook ran. Measured separately: an mbsync-style rename does NOT re-add `new.tags`, so the retag theory is out too. What remains unestablished is WHICH pass tagged it; establish that before writing code | | 165 | A draft gets a new Message-ID on every autosave | enhancement | ? | open, 2026-08-25, found while hand-testing 163 and 164. `MessageBuilder::build()` generates an id unconditionally and every autosave calls it, so each revision is a distinct MESSAGE to notmuch and to the server rather than a new version of one. Invisible while the file is replaced correctly, which item 163's fix restores; it is what turned that fork into two messages rather than one duplicated file. Needs a DECISION on what a draft's identity is before any code: a stable id reused at send, a stable id discarded at send, or the status quo. Neither `ComposeContext` nor `OutgoingMessage` has a field to carry an id, so it is not a changed call site | -| 166 | Mail you send to your own other account loses `inbox` | defect | S | open, found 2026-08-25. Two-repo change: the carve-out lives in the `post-new` hook, mirrored in mailctl's `mailrules.py` | +| 166 | Mail you send to your own other account loses `inbox` | defect | S | open, found 2026-08-25. Wholly this repo's: the hooks live in `assets/hooks/` with their own suites, and the live `post-new` symlinks to them | | 167 | No way to tell one build of an unreleased version from another | enhancement | XS | open, found 2026-08-25 from the notes, unrecorded until now. `src/version.h.in` interpolates `PROJECT_VERSION` alone, so every build between two releases reports the same string and a rebuilt binary cannot be told from the one it replaced. The user runs unreleased builds daily, which is when it matters. Needs a DECISION on the source: the git describe/short hash (accurate, needs the build to re-run cmake to pick up a new commit) or a monotonic counter (always moves, means nothing on its own) | Sizes are rough: XS under an hour, S a sitting, M a session. @@ -586,9 +586,9 @@ Option 1 is the one that makes the code true to what it already says it does. **Constraints.** -- **This is a two-repo change.** The carve-out is in this repo's `post-new`, - but the shared rule machinery is mirrored in `../mailctl`. Read "Changing the - shared rule format" in CLAUDE.md before touching it, and run both suites. +- **The hook is this repo's**, `assets/hooks/post-new`, which the live + `database.hook_dir` symlinks to. It has its own suites beside it; run + `./test_post_new.py` and `./test_mailrules.py` from `assets/hooks/`. - The hook **tags real mail unattended, every ten minutes, on the user's live index.** A predicate that is wrong in the other direction would strip `inbox` from arriving mail, which is the failure mode PROTECTED_REMOVALS exists to -- cgit v1.2.3