Skip to content

feat(leads): show what outreach actually produced - #142

Merged
ralyodio merged 1 commit into
masterfrom
feat/funnel-panel
Jul 28, 2026
Merged

ralyodio merged 1 commit into
masterfrom
feat/funnel-panel

Conversation

@ralyodio

Copy link
Copy Markdown
Contributor

Renders the funnel from #140 at project and campaign level, alongside the per-tick history each campaign already carries — which is where a single run belongs, so it isn't duplicated.

Measured, not projected

Published cold-email benchmarks are someone else's list, someone else's offer, and someone else's year. Dressing one up as a forecast invites a decision the number can't support. This is the project's own data — worth little on day one, more every week.

Two denominators, chosen rather than defaulted

  • Reply rate divides by people contacted, not sends. Follow-ups mean one person can receive three emails; counting them separately understates every campaign that follows up.
  • Close rate divides by people who replied. A deal comes out of a conversation — dividing by silence answers a different question.

Honest about small samples

Rates are withheld below 20 sends, with the reason shown. One reply in three is not a 33% reply rate, and drawing it as one is worse than drawing nothing.

A campaign with sends but no replies is told "no replies yet, so there is no close rate to show" rather than shown 0%, which reads as failure rather than absence.

Outcomes are now recordable

Nothing in the pipeline can observe a reply — a send is visible, a reply isn't. Until something reads the sending mailbox, marking one is the only way the funnel gets a numerator.

The control appears on the lead row only once it has actually been mailed; offering it earlier would invite a reply rate computed over people who were never contacted.

Checks

  • tsc --noEmit clean
  • 852/852 tests pass, 6 new covering the denominators, the small-sample hold-back, and won/lost counting as replies
  • production build compiles

🤖 Generated with Claude Code

The funnel is rendered at project and campaign level, alongside the
per-tick history each campaign already carries — which is where a single
run belongs, so it is not duplicated here.

It reports measured outcomes, never a projection. Published cold-email
benchmarks are someone else's list, someone else's offer and someone
else's year; dressing one up as a forecast invites a decision the number
cannot support. These are the project's own sends, worth little on day
one and more every week.

Two denominators, chosen rather than defaulted. Reply rate divides by
people contacted, not by sends, because follow-ups mean one person can
receive three emails and counting them separately understates every
campaign that follows up. Close rate divides by people who replied,
because a deal comes out of a conversation and dividing by silence
answers a different question.

Rates are withheld below twenty sends and say why. One reply out of three
is not a thirty-three percent reply rate, and drawing it as one is worse
than drawing nothing. A campaign with sends but no replies is told there
is no close rate rather than shown a zero, which reads as failure rather
than as absence.

Outcomes are recordable from the lead row, and only once it has actually
been mailed. Nothing here can observe a reply — a send is visible, a
reply is not — so until something reads the sending mailbox this is the
only way the funnel gets a numerator. Offering the control earlier would
invite a reply rate computed over people who were never contacted.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

vu1nz Security Review

0 finding(s) in PR #?

No security issues found.

@ralyodio
ralyodio merged commit d74b0f7 into master Jul 28, 2026
8 checks passed
@ralyodio
ralyodio deleted the feat/funnel-panel branch July 28, 2026 06:42
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