Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,17 @@ OPENROUTER_API_KEY=
# Optional: Hunter.io email-name enrichment (skipped when absent)
#HUNTER_API_KEY=

# --- Offer profiles (feature 008) ---
# Default profile, so --profile can be omitted. Without either, an interactive
# run lists the available profiles and asks; a non-interactive one fails.
#PROSPECTOR_PROFILE=duct-cleaning
# Extra profile directory, searched BEFORE ./profiles/ and before the profiles
# bundled with the package. Your own directory always wins.
#PROSPECTOR_PROFILES=/path/to/my/profiles

# Optional: vault output folder (default: Vault/Outreach). --vault overrides it.
#PROSPECTOR_VAULT=Vault/Outreach

# --- Approved-send (features 003/004) ---
# Provider: gmail (Gmail API, default) or smtp (authenticated SMTP, e.g. Zoho).
#PROSPECTOR_SEND_PROVIDER=smtp
Expand Down
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ labels: bug
## Command you ran

```bash
# e.g. prospector run companies.csv --limit 3
# e.g. prospector run companies.csv --profile duct-cleaning --limit 3
```

## Expected vs actual
Expand Down
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@ send_ledger.jsonl
Vault/
samples/

# Prospect data must never be committed: these files hold real businesses'
# names, addresses and websites. `candidates.csv` is the default --out of
# `prospector source`, so it appears in the working tree on a normal run.
candidates.csv
*candidates*.csv
dm_ledger.jsonl
*.local.csv

# Internal development method — not part of the public project.
# These stay on the maintainer's machine and are intentionally untracked.
.specify/
Expand Down
5 changes: 5 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,11 @@ fixes should include a test that fails before the fix and passes after.
frameworks or agent/orchestration machinery.
- Never hardcode secrets. Credentials come from the gitignored `.env`; never log
or commit them.
- **Never commit prospect data.** Real company names, addresses, websites and
scraped emails belong to third parties and must stay local. The vault,
`candidates.csv` (the default `--out` of `prospector source`), the send ledger
and `samples/` are all gitignored for this reason. Use fictional data in tests,
fixtures, issues and PR output.

## Commit and PR conventions

Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ Secrets are loaded from the gitignored `.env` file.
| `OPENROUTER_MODEL` | No | Defaults to `anthropic/claude-sonnet-4.5`. |
| `PROSPECTOR_PROFILE` | No | Default profile name, so `--profile` can be omitted. |
| `PROSPECTOR_PROFILES` | No | Extra profile directory, searched before `./profiles/`. |
| `PROSPECTOR_VAULT` | No | Vault output folder; defaults to `Vault/Outreach`. `--vault` overrides it. |
| `GOOGLE_PLACES_API_KEY` | For `source` | Required for discovery. During `run`, its absence enables the DuckDuckGo fallback. |
| `HUNTER_API_KEY` | No | Enables email-name enrichment at medium confidence. |
| `PROSPECTOR_SEND_PROVIDER` | No | `gmail` (default) or `smtp`. |
Expand All @@ -197,6 +198,8 @@ Secrets are loaded from the gitignored `.env` file.
| `PROSPECTOR_SEND_CAPS` | No | Weekly cap ramp; defaults to `15,30,60,100`. |
| `PROSPECTOR_SEND_DELAY` | No | Delay range in seconds; defaults to `30,90`. |
| `PROSPECTOR_LEDGER` | No | Ledger path; defaults to `send_ledger.jsonl`. |
| `PROSPECTOR_GMAIL_CLIENT` | No | Gmail OAuth client secret; defaults to `secrets/gmail_client_secret.json`. |
| `PROSPECTOR_GMAIL_TOKEN` | No | Stored Gmail token; defaults to `secrets/gmail_token.json`. |

Gmail OAuth files live under `secrets/`; the send ledger remains local. Both
locations are excluded from version control.
Expand Down
109 changes: 0 additions & 109 deletions candidates.csv

This file was deleted.

21 changes: 13 additions & 8 deletions prospector/profiles/duct-cleaning/CONSTRAINTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ program owns. If you write a name yourself, the draft is rejected.
`cites` is a list of identifiers, and **it must never be empty**.

You are given an evidence catalogue for this company. Each entry has an `id`
like `about_page_1`, `hook_source_1`, or `fb_link_1`. Those ids are what you
cite.
like `about_page_1`, `hook_source_1`, or `email_published_1`. Those ids are what
you cite. Cite only ids that appear in the catalogue you were given.

- **A block that says something about the prospect** cites the evidence
id(s) that support it. If you write "you have been serving Dallas for 22
Expand Down Expand Up @@ -85,18 +85,23 @@ The word "your" is what turns one into the other:
| "when someone messages **your page** at 9pm" | "when someone messages a business at 9pm" |
| "It watches **your inbox**" | "It watches the page inbox" |

Banned outright unless the evidence catalogue contains an `fb_*` record, you
cite it in that same block, **and** you were told the signal is strong:
**Banned outright — there is no evidence that makes these acceptable:**
"your facebook page", "your fb page", "your page", "your inbox",
"your messenger", "your dms", "your direct messages", "messages your page".

There used to be an exception here for a cited `fb_*` evidence record on a
strong channel signal. **That exception is gone.** The tool no longer researches,
scores, or records anything about a prospect's Facebook usage — there is no
`fb_*` record to cite and no signal to be told about — so a possessive channel
phrase can never be justified. A validator rejects these unconditionally.

A page appearing in search results is not proof they read it. Say what the tool
does. Never say what they own.

- **Never assert they use Facebook** unless you were given `fb_*` evidence and
you cite it. Describing what the *product* does with a Facebook inbox is a
fact about the product and is always fine. Saying *they* are active on
Facebook requires evidence.
- **Never assert they use Facebook.** Not conditionally, not with a hedge.
Describing what the *product* does with a Facebook inbox is a fact about the
product and is always fine. Saying *they* are on Facebook is a claim about the
prospect, and nothing in the evidence catalogue can support it.
- Never invent a problem, a metric, a compliment, or a number.
- Never guarantee bookings, revenue, or replies.

Expand Down
6 changes: 4 additions & 2 deletions prospector/profiles/duct-cleaning/skills/write-cold-email.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,10 @@ before you write anything. Different evidence supports different openings:
and repeat customers, and a dropped message costs more.
- A service area or city supports an opening about their market.
- An about/team page naming the owner supports addressing what they built.
- A Facebook page link supports mentioning that channel, but only as a fact
about where messages arrive, never as a claim about how active they are.

Nothing in the catalogue describes the prospect's own marketing channels, so no
opening can be built on one. Do not reach for Facebook, Messenger, ads, or "where
your leads come from" — you have not been told, and guessing is a fabrication.

**Never open with:**
- "I hope this email finds you well."
Expand Down
Loading