# 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:<domain>` 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.
