# TODO Open items for mailctl. The three original feature gaps (`--max-messages`, `senders`, `subjects`) are implemented and were removed from this list on 2026-08-01. The list of concrete senders that warrant a `post-new` hook rule is personal data, so it lives in a local-only `HOOK-RULES.md` rather than in the repo. The method for deriving it is below. ## 1. `--actor` audit tag (not urgent) Already noted in the module docstring. Distinguish agent-run from user-run mutations in `~/.local/state/mailctl/audit.log`. Matters for trust; has not slowed any session's work so far. ## Method notes for writing hook rules These are the traps found while sweeping a large backlog. They cost real mis-tagging when skipped, so they are worth keeping even though the senders that produced them are not recorded here. - **Verify every predicate with `mailctl count` before acting on it.** `from:` matches whole tokens, and local parts split on punctuation, so per-sender probes silently undercount: one bucket of 24 messages returned 16 across ten probed addresses. - **Scope vendor rules to local parts, not domains.** A domain that sends marketing usually also sends order confirmations and password resets from other local parts on the same domain. A `from:` rule sweeps those into promo. - **Check for transactional terms before any bulk promo tag.** Marketing senders hide real order, shipping, and billing mail in the same bucket. This caught genuine transactional messages in five separate batches; the one batch where it was skipped produced the only mis-tagging that reached the index. - **A sender is not always one rule.** Forum and mailing-list senders mix bulletins, automated notices, and real replies to threads you posted in. Split by subject, or a blanket rule buries correspondence. - **Subject substring tests overmatch.** A common word in a subject test can pull in unrelated threads that merely discuss the topic. - **Dead senders need no rule.** Most backlog volume comes from senders that stopped mailing years ago. A rule for a dead sender is dead code that whoever edits the hook next still has to read and trust. Check last-seen dates first. - **Join multiple `id:` terms in Python, not the shell.** `paste -sd' or '` cycles the two delimiter characters between lines and glues message-ids together, failing silently with a plausible-looking match count. Always assert the match count equals the number of ids.