Skip to content

fix(send): explain why notes were skipped instead of just counting them - #9

Merged
anusbutt merged 2 commits into
mainfrom
fix/send-skip-reasons
Jul 27, 2026
Merged

fix(send): explain why notes were skipped instead of just counting them#9
anusbutt merged 2 commits into
mainfrom
fix/send-skip-reasons

Conversation

@anusbutt

Copy link
Copy Markdown
Owner

What & why

Running prospector send against a real vault produced this:

Prospector send [WOULD SEND (dry-run)]
  today's cap: 30   already sent today: 0
  to send: 0   deferred (cap): 0   skipped: 47   failed: 0

That reads as a malfunction. It wasn't: 46 of those notes had already been emailed and the ledger was doing exactly its job, and the 47th just needed a subject line. But nothing in the output said so, and there was no flag to make it say so.

Every skip already carried a precise reason — "already in ledger", "draft has no subject", "not an email-channel note". The report simply filtered them out: it printed rows only for SENT, FAILED and DEFERRED_CAP. Skipped was the single most confusing outcome and the only one with no explanation attached.

After

  skipped:
     46  already in ledger  (already emailed — the ledger prevents a repeat)
         a-z-air-duct, ace-duct-cleaning-inc, air-central, air-duct-cleaning-miami,
         air-duct-dynasty-air-duct-cleaning-philadelphia, air-duct-pros-inc, and 40 more
      1  draft has no subject  (add a **Subject:** line, or re-draft the note)
         monster-vac

  Nothing to send: every approved note was skipped for a reason above.

Design points:

  • Grouped by reason, most common first — the shape of the problem is the useful information, not 47 individual lines.
  • Slugs are named, so a one-off (monster-vac) is immediately actionable rather than hidden in a count.
  • Truncated after six slugs per group, so a 46-note group cannot bury the summary above it.
  • Plain-language hints translate an internal reason into what it means for the operator's list. "already in ledger" is accurate but tells you nothing about whether to worry.
  • A run that selects nothing says so outright — that's the case most likely to be mistaken for a bug.

How it was verified

  • pytest -q597 passed (4 new).
  • Ran against the real 115-note vault; that's the output above.

New tests cover: reasons and slugs both appear; the all-skipped run states "Nothing to send"; a 9-note group truncates to "and 3 more"; and a clean run prints no skip block at all.

One test needed tightening during review — asserting "skipped:" not in output was wrong, because the summary line always contains skipped: 0. It now asserts on the block header specifically.

Notes for reviewers

No behavior change to what is sent or skipped — only to what is reported. The selection logic, ledger dedupe, cap arithmetic and sendability checks are untouched.

Worth noting how this surfaced: the guarantee worked perfectly and the reporting made it look like a failure. A safety mechanism that can't explain itself gets overridden by the person it's protecting — the tempting next move on seeing skipped: 47 is to find a way to force the send, which here would have meant a duplicate cold email to 46 real businesses.

🤖 Generated with Claude Code

anusbutt and others added 2 commits July 27, 2026 14:10
`prospector send` reported skips as a bare number. On a real vault that came
out as "to send: 0 ... skipped: 47", which reads as a malfunction — while the
truth was that 46 of those notes had already been emailed and the ledger was
doing exactly its job, and the 47th simply needed a subject line.

Every skip already carried a reason; the report just filtered them out, and
they were the only outcome the operator got no explanation for.

Now grouped by reason, most common first, with the affected slugs named and a
plain-language hint for what each reason means:

    skipped:
       46  already in ledger  (already emailed — the ledger prevents a repeat)
           a-z-air-duct, ace-duct-cleaning-inc, air-central, and 43 more
        1  draft has no subject  (add a **Subject:** line, or re-draft the note)
           monster-vac

Long groups are truncated after six slugs so a 46-note group cannot bury the
summary. A run that selects nothing now says so outright, because that is the
case most likely to be mistaken for a bug.

No behavior change to what is sent or skipped — only to what is reported.
@anusbutt
anusbutt merged commit db0358f into main Jul 27, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant