leads-cli 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. company_discovery/__init__.py +4 -0
  2. company_discovery/adapters/__init__.py +5 -0
  3. company_discovery/adapters/apollo.py +189 -0
  4. company_discovery/adapters/exa.py +112 -0
  5. company_discovery/adapters/llm.py +118 -0
  6. company_discovery/adapters/protocols.py +58 -0
  7. company_discovery/adapters/website.py +154 -0
  8. company_discovery/bundled_skills/__init__.py +1 -0
  9. company_discovery/bundled_skills/company-discovery-operator/SKILL.md +72 -0
  10. company_discovery/bundled_skills/company-discovery-operator/agents/openai.yaml +4 -0
  11. company_discovery/bundled_skills/company-enrichment-operator/SKILL.md +94 -0
  12. company_discovery/bundled_skills/company-enrichment-operator/agents/openai.yaml +4 -0
  13. company_discovery/bundled_skills/company-search-spec-writer/SKILL.md +109 -0
  14. company_discovery/bundled_skills/company-search-spec-writer/agents/openai.yaml +4 -0
  15. company_discovery/bundled_skills/contact-discovery-operator/SKILL.md +80 -0
  16. company_discovery/bundled_skills/contact-discovery-operator/agents/openai.yaml +4 -0
  17. company_discovery/bundled_skills/contact-enrichment-operator/SKILL.md +86 -0
  18. company_discovery/bundled_skills/contact-enrichment-operator/agents/openai.yaml +4 -0
  19. company_discovery/bundled_skills/contact-search-spec-writer/SKILL.md +86 -0
  20. company_discovery/bundled_skills/contact-search-spec-writer/agents/openai.yaml +4 -0
  21. company_discovery/bundled_skills/leads-update-operator/SKILL.md +60 -0
  22. company_discovery/bundled_skills/leads-update-operator/agents/openai.yaml +4 -0
  23. company_discovery/cli.py +1789 -0
  24. company_discovery/db/__init__.py +5 -0
  25. company_discovery/db/contact_enrichment_repository.py +268 -0
  26. company_discovery/db/contact_repository.py +366 -0
  27. company_discovery/db/enrichment_repository.py +207 -0
  28. company_discovery/db/models.py +324 -0
  29. company_discovery/db/repository.py +363 -0
  30. company_discovery/db/session.py +48 -0
  31. company_discovery/domain/__init__.py +24 -0
  32. company_discovery/domain/contact_models.py +178 -0
  33. company_discovery/domain/contact_spec.py +86 -0
  34. company_discovery/domain/models.py +287 -0
  35. company_discovery/domain/spec.py +263 -0
  36. company_discovery/migrations.py +190 -0
  37. company_discovery/prompts/__init__.py +8 -0
  38. company_discovery/prompts/candidate_evaluation/system.md +13 -0
  39. company_discovery/prompts/company_enrichment/system.md +42 -0
  40. company_discovery/prompts/contact_evaluation/system.md +18 -0
  41. company_discovery/prompts/query_generation/system.md +10 -0
  42. company_discovery/release_manifest.json +7 -0
  43. company_discovery/reports/__init__.py +4 -0
  44. company_discovery/reports/contact_enrichment_exporter.py +108 -0
  45. company_discovery/reports/contact_exporter.py +132 -0
  46. company_discovery/reports/enrichment_exporter.py +125 -0
  47. company_discovery/reports/exporter.py +135 -0
  48. company_discovery/runtime.py +336 -0
  49. company_discovery/services/__init__.py +4 -0
  50. company_discovery/services/contact_enrichment_pipeline.py +344 -0
  51. company_discovery/services/contact_enrichment_progress.py +37 -0
  52. company_discovery/services/contact_evaluator.py +110 -0
  53. company_discovery/services/contact_pipeline.py +295 -0
  54. company_discovery/services/contact_progress.py +38 -0
  55. company_discovery/services/enrichment_extractor.py +61 -0
  56. company_discovery/services/enrichment_pipeline.py +526 -0
  57. company_discovery/services/enrichment_progress.py +20 -0
  58. company_discovery/services/enrichment_resolver.py +148 -0
  59. company_discovery/services/evaluator.py +40 -0
  60. company_discovery/services/hygiene.py +51 -0
  61. company_discovery/services/memory.py +150 -0
  62. company_discovery/services/normalization.py +98 -0
  63. company_discovery/services/pipeline.py +628 -0
  64. company_discovery/services/progress.py +48 -0
  65. company_discovery/services/query_planner.py +47 -0
  66. company_discovery/settings.py +152 -0
  67. company_discovery/skill_installer.py +197 -0
  68. company_discovery/update_plan.py +79 -0
  69. leads_cli-0.1.0.dist-info/METADATA +277 -0
  70. leads_cli-0.1.0.dist-info/RECORD +72 -0
  71. leads_cli-0.1.0.dist-info/WHEEL +4 -0
  72. leads_cli-0.1.0.dist-info/entry_points.txt +2 -0
@@ -0,0 +1,72 @@
1
+ ---
2
+ name: company-discovery-operator
3
+ description: Validate, execute, inspect, rerun, and explain Company Discovery CLI runs from an existing company_search_spec.json. Use when a user asks an agent to run company discovery, find companies from a prepared spec, inspect a discovered domain, export a run, or summarize selected, reserve, and rejected company results. Do not rewrite the ICP or work on contacts.
4
+ ---
5
+
6
+ # Operate Company Discovery
7
+
8
+ Run company discovery from an existing spec without silently changing it.
9
+
10
+ ## Workspace And CLI
11
+
12
+ Use `leads doctor` or `leads version` to confirm the workspace root. The root contains
13
+ `backups/`, `config/`, `data/`, `logs/`, `runs/`, `skills/`, and `specs/`.
14
+
15
+ - Company specs normally live in `specs/companies/`; validate the exact spec path before running.
16
+ - Company discovery artifacts are saved under `runs/<company-discover-id>/` with `selected.csv`,
17
+ `reserve.csv`, `rejected.csv`, `summary.md`, and `run.json`.
18
+ - Config lives in `config/config.toml`; secrets live in `config/secrets.toml`; never expose secret
19
+ values.
20
+ - The memory database is `data/company_memory.db`; treat CLI output and saved artifacts as the
21
+ normal interface.
22
+ - Backups are under `backups/`; CLI diagnostics are in `logs/leads.log`; installed skill metadata
23
+ is under `skills/`.
24
+ - Useful setup/maintenance commands: `leads init`, `leads version`, `leads doctor`,
25
+ `leads update --check`, `leads migrate --check`, and `leads skills status`.
26
+
27
+ ## New discovery
28
+
29
+ 1. Locate the requested `company_search_spec.json`.
30
+ 2. Run `leads companies validate-spec --spec <path>`.
31
+ 3. Report material open modes shown by validation: national geography, no size filter, or no custom exclusions.
32
+ 4. State the novelty policy before running: `unused_memory` searches unused memory first,
33
+ `only_new` bypasses memory candidates and suppresses known domains, and `full_memory` permits
34
+ reuse of previously selected companies. If omitted, the policy is `unused_memory`.
35
+ 5. For multi-vertical specs, report the balance mode and treat each vertical as an independent memory and external-search lane.
36
+ 6. Report the external search budget before running. If omitted, use the normalized defaults:
37
+ `external_search.exa_searches = 8` and `external_search.results_per_search = 5`.
38
+ 7. Run `leads companies discover --spec <path>`. Add `--verbose` only when detailed queries and candidate decisions help diagnose the run. Before launching the command, set a large tool-window timeout, around 10 minutes, so live discovery can finish without being cut off.
39
+ 8. Let the command finish. Do not launch a duplicate while the original process is active.
40
+ 9. Read the final counts and Markdown summary path.
41
+ 10. Summarize memory reuse, known-domain suppression for `only_new`, external-search volume,
42
+ selected/reserve/rejected counts, per-vertical outcomes, and any shortfall.
43
+ 11. Present the results with:
44
+ - one compact count line for all buckets;
45
+ - one table for `selected`;
46
+ - one table for `reserve`.
47
+ Do not show `rejected` rows by default unless the user asks, or unless there are no useful
48
+ results and the failure reasons are the main thing that matters.
49
+ 12. Keep the default tables compact and systematic. Use these columns when they are available:
50
+ `Company | Domain | Vertical | State | Size | Fit | Source | Notes`
51
+ 13. Show at most about 15 rows per table by default. If there are more, say that additional rows
52
+ are available in the exported artifacts.
53
+
54
+ Discovery stops after saving and reporting its run ID. Never start enrichment through a discovery
55
+ flag. When the user also requests enrichment, finish discovery first and pass its saved run ID to
56
+ the separate enrichment workflow.
57
+
58
+ ## Follow-up operations
59
+
60
+ - Inspect a run with `leads companies show-run <run-id>`.
61
+ - Inspect one domain with `leads companies inspect <run-id> --domain <domain>`.
62
+ - Regenerate artifacts with `leads companies export <run-id>`.
63
+ - Repeat the exact prior spec and its novelty policy using `leads companies rerun <run-id>`.
64
+
65
+ ## Guardrails
66
+
67
+ - Do not edit or replace the spec unless the user asks to change the ICP.
68
+ - Do not hide a missing constraint or selected-count shortfall.
69
+ - Do not describe reserve companies as confirmed selections.
70
+ - Explain deterministic hygiene rejections separately from LLM ICP judgments when relevant.
71
+ - Treat the saved run and artifacts as authoritative; do not infer companies from terminal snippets alone.
72
+ - Never expose API keys or raw environment values.
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "Company Discovery Operator"
3
+ short_description: "Run and explain company discovery searches"
4
+ default_prompt: "Use $company-discovery-operator to run this company discovery spec and summarize the results."
@@ -0,0 +1,94 @@
1
+ ---
2
+ name: company-enrichment-operator
3
+ description: Enrich company profiles from a completed Company Discovery run. Use when a user asks to enrich selected or reserve companies, continue from discovery to enrichment, retrieve company phone/address/independence, inspect enrichment evidence, refresh stale enrichment facts, or export ready/review/blocked company results. This skill operates on companies only, never contacts.
4
+ ---
5
+
6
+ # Operate Company Enrichment
7
+
8
+ Consume a completed discovery run. Do not ask the user to restate its ICP or reconstruct input from
9
+ `selected.csv`; the database record is authoritative.
10
+
11
+ ## Workspace And CLI
12
+
13
+ Use `leads doctor` or `leads version` to confirm the workspace root. The root contains
14
+ `backups/`, `config/`, `data/`, `logs/`, `runs/`, `skills/`, and `specs/`.
15
+
16
+ - Company discovery runs live at `runs/<company-discover-id>/`.
17
+ - Company enrichment artifacts live at
18
+ `runs/<company-discover-id>/enrich/<company-enrich-id>/` with `enriched.csv`, `review.csv`,
19
+ `blocked.csv`, `summary.md`, and `run.json`.
20
+ - The database is `data/company_memory.db`; use `leads companies show-run`,
21
+ `show-enrichment`, and inspect commands before direct DB inspection.
22
+ - Config is in `config/config.toml`; secrets are in `config/secrets.toml`; never expose secret
23
+ values.
24
+ - Backups are under `backups/`; CLI diagnostics are in `logs/leads.log`; installed skill metadata
25
+ is under `skills/`; specs live under `specs/companies/` and `specs/contacts/`.
26
+ - Useful setup/maintenance commands: `leads init`, `leads version`, `leads doctor`,
27
+ `leads update --check`, `leads migrate --check`, and `leads skills status`.
28
+
29
+ ## Standard workflow
30
+
31
+ 1. Identify the discovery run ID. Default to its `selected` bucket.
32
+ 2. Run `leads companies show-run <discovery-run-id>` when its status or result count is unclear.
33
+ 3. Explain that name, domain, vertical, geography, employee estimate, and ownership type are retained
34
+ from discovery. Enrichment targets LinkedIn company profile, phone, complete address, and
35
+ independence.
36
+ 4. Run `leads companies enrich <discovery-run-id>`.
37
+ 5. Read the final counts and artifact path. Report inherited facts, memory reuse, website retrieval,
38
+ fallback searches, and ready/review/blocked totals.
39
+ The returned enrichment run ID is random and prefixed, like `company-enrich-a1b2c3d4e5f6`.
40
+ 6. Treat `enriched.csv` as the clean deliverable, `review.csv` as unresolved work, `blocked.csv` as
41
+ conflicts, and `run.json` as the provenance and decision trace.
42
+ 7. Present the results with:
43
+ - one compact count line for all outcomes;
44
+ - one table for `ready`;
45
+ - one table for `review`.
46
+ Do not show `blocked` rows by default unless the user asks, or unless there are no useful
47
+ results and the blocking reasons are what the user needs next.
48
+ 8. Keep the default tables compact and systematic. Use these columns when they are available:
49
+ `Company | Domain | Vertical | Phone | City | State | LinkedIn | Independence | Outcome | Notes`
50
+ 9. Show at most about 15 rows per table by default. If there are more, say that additional rows
51
+ are available in the exported artifacts.
52
+
53
+ For a new search followed by enrichment, always use two separate commands:
54
+
55
+ ```bash
56
+ leads companies discover --spec <spec-path>
57
+ leads companies enrich <discovery-run-id>
58
+ ```
59
+
60
+ Wait for discovery to finish and use the exact run ID it returns. Never represent enrichment as a
61
+ discovery option.
62
+
63
+ ## Options
64
+
65
+ - Use `--bucket reserve` only when the user asks to enrich reserve companies.
66
+ - Use `--limit N` for an explicitly bounded run.
67
+ - Use `--refresh contact` to refetch LinkedIn, phone, and location.
68
+ - Use `--refresh independence` to rerun only the parent/franchise check.
69
+ - Use `--refresh all` to ignore all fresh enrichment memory.
70
+ - Use `--allow-unknown-independence` only when the user accepts complete contact profiles whose
71
+ independence could not be proven. Without it, those companies go to review.
72
+
73
+ ## Follow-up operations
74
+
75
+ - Show a run with `leads companies show-enrichment <company-enrich-id>`.
76
+ - Inspect provenance and trace with
77
+ `leads companies inspect-enrichment <company-enrich-id> --domain <domain>`.
78
+ - Regenerate artifacts with `leads companies export-enrichment <company-enrich-id>`.
79
+
80
+ ## Guardrails
81
+
82
+ - Never treat `private`, `privately held`, LLC, partnership, or corporation as proof of independence.
83
+ - Explicit franchise, parent, subsidiary, division, or acquisition evidence blocks the company.
84
+ - If the discovery spec lists `family_owned` under `exclude.structured.ownership_signals`, explicit
85
+ family-owned evidence blocks the company as a fit conflict. Without that requested exclusion,
86
+ family-owned remains valid positive evidence of independence.
87
+ - Absence of franchise language is not proof; unresolved independence remains `unknown`.
88
+ - Never merge address pieces from separate offices. The selected address must be one complete block
89
+ and, for state-scoped discovery, must be in the inherited state.
90
+ - Save only LinkedIn company profiles under `/company/`. Never save personal profiles, jobs, posts,
91
+ or search pages. Prefer links found directly on the official company website.
92
+ - Do not silently replace discovery facts. Report identity, geography, and fit conflicts.
93
+ - Do not refresh employee data during the default pass; discovery already supplied it.
94
+ - Never expose API keys or raw environment values.
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "Company Enrichment Operator"
3
+ short_description: "Enrich selected companies from a discovery run"
4
+ default_prompt: "Use $company-enrichment-operator to enrich selected companies from this discovery run and summarize ready, review, and blocked results."
@@ -0,0 +1,109 @@
1
+ ---
2
+ name: company-search-spec-writer
3
+ description: Turn natural-language company targeting or ICP requests into strict company_search_spec.json files for the Company Discovery CLI. Use when a user asks to find target companies, define a company ICP, prepare a company search, or translate company criteria such as vertical, geography, employee size, exclusions, and novelty into a runnable spec. Do not use for contact or person searches.
4
+ ---
5
+
6
+ # Write a Company Search Spec
7
+
8
+ Create one `company_search_spec.json` under the Leads workspace unless the user gives another path.
9
+
10
+ ## Workspace And CLI
11
+
12
+ Use `leads doctor` or `leads version` to confirm the workspace root. The root contains
13
+ `backups/`, `config/`, `data/`, `logs/`, `runs/`, `skills/`, and `specs/`.
14
+
15
+ - Write company specs to `specs/companies/`, for example
16
+ `specs/companies/company_search_spec.json`.
17
+ - Contact specs belong in `specs/contacts/`; do not write contact specs here.
18
+ - Runtime config is in `config/config.toml`; secrets are in `config/secrets.toml`; never expose
19
+ secret values.
20
+ - The SQLite memory DB is `data/company_memory.db`; use CLI commands rather than editing it.
21
+ - Run artifacts are saved under `runs/`; backups are saved under `backups/`; CLI diagnostics are in
22
+ `logs/leads.log`; installed skill metadata lives under `skills/`.
23
+ - Useful setup/maintenance commands: `leads init`, `leads version`, `leads doctor`,
24
+ `leads update --check`, `leads migrate --check`, and `leads skills status`.
25
+
26
+ ## Workflow
27
+
28
+ 1. Extract only company-level criteria the user actually supplied.
29
+ 2. Set `version` to `1` and require a positive `count`.
30
+ 3. Use `verticals` for every new spec. Add one entry per requested vertical; multiple entries mean
31
+ OR (separate company groups), never companies that must match every vertical.
32
+ 4. Each vertical should always use one simple shape: `key`, `label`, and optional query hints.
33
+ Use a lowercase stable key.
34
+ 5. Add `search_terms` only when the vertical is niche, ambiguous, or user wording needs stronger
35
+ search hints. Add `exclude_terms` only when a few obvious search-time negatives help reduce
36
+ noise. Do not invent ICP constraints.
37
+ 6. Encode broad US geography as `{"country": "US", "states": []}`. Use two-letter uppercase state codes when states are requested.
38
+ 7. Use an empty `company_size` object when no employee range was given. Never invent employee limits.
39
+ 8. Use empty arrays for omitted include/exclude criteria. When the user explicitly excludes family
40
+ businesses, set `exclude.structured.ownership_signals` to `["family_owned"]`. This tells enrichment
41
+ to block a company when official-site or corroborating evidence identifies it as family-owned.
42
+ Never invent this exclusion.
43
+ 9. Default `novelty_mode` to `unused_memory`. This searches memory first but excludes every company
44
+ that has ever been selected. Use `only_new` when the user wants external discovery only; it skips
45
+ memory candidates and excludes known domains returned by search. Use `full_memory` only when the
46
+ user explicitly permits reusing companies selected in prior runs.
47
+ 10. Default `reserve_ratio` to `0.5`; this controls output capacity, not ICP fit.
48
+ 11. Default `balance_mode` to `soft` for multiple verticals. Use `strict` only when equal caps matter more than reaching the requested count, and `none` only when distribution does not matter.
49
+ 12. Add `external_search` to every new spec. Default to `{"exa_searches": 8, "results_per_search": 5}` unless the user asks for a broader or cheaper search. `exa_searches` is the number of Exa searches per active vertical/lane; `results_per_search` is the number of Exa results requested by each search.
50
+ 13. Write JSON, then run `leads companies validate-spec --spec <spec-path>`.
51
+ 14. Fix validation errors before returning. Do not run discovery unless the user asked for it.
52
+
53
+ ## Contract
54
+
55
+ Use this shape and omit no top-level fields except those with documented defaults:
56
+
57
+ ```json
58
+ {
59
+ "version": 1,
60
+ "count": 50,
61
+ "verticals": [
62
+ {"key": "construction", "label": "Construction"},
63
+ {"key": "healthcare", "label": "Healthcare"}
64
+ ],
65
+ "geography": {"country": "US", "states": ["TX"]},
66
+ "company_size": {"employee_min": 20, "employee_max": 100},
67
+ "include": {"keywords": [], "subtypes": []},
68
+ "exclude": {
69
+ "keywords": [],
70
+ "ownership_types": [],
71
+ "company_patterns": [],
72
+ "structured": {"ownership_signals": []}
73
+ },
74
+ "novelty_mode": "unused_memory",
75
+ "reserve_ratio": 0.5,
76
+ "balance_mode": "soft",
77
+ "external_search": {
78
+ "exa_searches": 8,
79
+ "results_per_search": 5
80
+ }
81
+ }
82
+ ```
83
+
84
+ Allowed novelty values are `unused_memory`, `only_new`, and `full_memory`.
85
+
86
+ - `unused_memory` (default): search memory first, but never select a company that was selected before.
87
+ - `only_new`: do not source candidates from memory and discard external results whose domains are already known.
88
+ - `full_memory`: search all matching memory, including companies selected in prior runs.
89
+ Allowed balance values are `soft`, `strict`, and `none`.
90
+ `external_search.exa_searches` may be 1-20. `external_search.results_per_search` may be
91
+ 1-100. Keep the default `8` and `5` unless the user asks to make discovery broader, narrower,
92
+ cheaper, or more exhaustive.
93
+
94
+ For a niche or ambiguous vertical, add query hints like:
95
+
96
+ ```json
97
+ {
98
+ "key": "marine-surveying",
99
+ "label": "Marine Surveying",
100
+ "search_terms": ["marine surveying", "vessel inspection", "cargo survey"],
101
+ "exclude_terms": ["software", "directory", "marketplace"]
102
+ }
103
+ ```
104
+
105
+ Allowed structured ownership signals are `family_owned`, `franchise`, `parent`, `subsidiary`,
106
+ `division`, and `acquired`. When a size bound is one-sided, include only the known bound. When
107
+ exclusions are omitted, keep all exclusion arrays empty. Preserve the user's ambiguity instead of
108
+ silently tightening the ICP. Old specs that still use `mode`, `seed_terms`, or `anti_terms` remain
109
+ valid, but new specs should not emit them.
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "Company Search Spec Writer"
3
+ short_description: "Turn company ICP requests into valid specs"
4
+ default_prompt: "Use $company-search-spec-writer to turn my company targeting request into a validated discovery spec."
@@ -0,0 +1,80 @@
1
+ ---
2
+ name: contact-discovery-operator
3
+ description: Validate, execute, inspect, export, and explain live contact discovery from an existing contact_search_spec.json. Use when a user asks an agent to find current role-matched people at companies from a completed enrichment run or review a prior contact discovery run. Use the separate contact-enrichment-operator skill for Apollo email or phone enrichment.
4
+ ---
5
+
6
+ # Operate Contact Discovery
7
+
8
+ Find current people at already-enriched companies without changing the saved company scope.
9
+
10
+ ## Workspace And CLI
11
+
12
+ Use `leads doctor` or `leads version` to confirm the workspace root. The root contains
13
+ `backups/`, `config/`, `data/`, `logs/`, `runs/`, `skills/`, and `specs/`.
14
+
15
+ - Contact specs normally live in `specs/contacts/`; validate the exact spec path before running.
16
+ - Contact discovery artifacts live at
17
+ `runs/<company-discover-id>/enrich/<company-enrich-id>/contacts/<contact-discover-id>/`
18
+ with `accepted.csv`, `review.csv`, `rejected.csv`, `summary.md`, and `run.json`.
19
+ - The source company enrichment run lives under
20
+ `runs/<company-discover-id>/enrich/<company-enrich-id>/`.
21
+ - Config is in `config/config.toml`; secrets are in `config/secrets.toml`; never expose secret
22
+ values.
23
+ - The memory database is `data/company_memory.db`; use `leads contacts show-run` and inspect
24
+ commands before direct DB inspection.
25
+ - Backups are under `backups/`; CLI diagnostics are in `logs/leads.log`; installed skill metadata
26
+ is under `skills/`.
27
+ - Useful setup/maintenance commands: `leads init`, `leads version`, `leads doctor`,
28
+ `leads update --check`, `leads migrate --check`, and `leads skills status`.
29
+
30
+ ## New Discovery
31
+
32
+ 1. Locate the requested `contact_search_spec.json`.
33
+ 2. Run `leads contacts validate-spec --spec <path>`.
34
+ 3. Confirm the source company enrichment run, bucket, optional domain subset, roles, and caps.
35
+ 4. Run `leads contacts discover --spec <path>`.
36
+ 5. Let the command finish; do not launch a duplicate while it is active.
37
+ 6. Report the contact run ID, companies loaded, memory reuse, live-web queries, and
38
+ accepted/review/rejected counts.
39
+ 7. Read the saved summary or `run.json` when explaining why people were accepted or held for
40
+ review. Terminal progress is not the authoritative record.
41
+ 8. Present the results with:
42
+ - one compact count line for all verdicts;
43
+ - one table for `accepted`;
44
+ - one table for `review`.
45
+ Do not show `rejected` rows by default unless the user asks, or unless there are no useful
46
+ results and the rejection reasons are the important output.
47
+ 9. Keep the default tables compact and systematic. Use these columns when they are available:
48
+ `Company | Contact | Title | Role Key | LinkedIn | Status | Source | Notes`
49
+ 10. Show at most about 15 rows per table by default. If there are more, say that additional rows
50
+ are available in the exported artifacts.
51
+
52
+ The command checks fresh contact memory independently for every company and role. It searches Exa
53
+ only for remaining per-role gaps, then verifies identity, current-company evidence, and title fit.
54
+
55
+ ## Follow-up Operations
56
+
57
+ - Show a run with `leads contacts show-run <contact-run-id>`.
58
+ - Inspect one person with `leads contacts inspect <contact-run-id> --person "Jane Smith"`.
59
+ - Regenerate artifacts with `leads contacts export <contact-run-id>`.
60
+
61
+ ## Interpret Results
62
+
63
+ - `accepted.csv`: clear identity, explicit current-company tie, and explicit requested-role match.
64
+ - `review.csv`: plausible evidence that is not strong enough for automatic acceptance, including
65
+ valid matches beyond a per-company role cap.
66
+ - `rejected.csv`: wrong company, former employee, wrong role, or ambiguous identity.
67
+ - `run.json`: complete role decisions, evidence, source URLs, query results, and memory/live source.
68
+
69
+ The CSV schema intentionally includes blank `email` and `phone` columns so later enrichment can
70
+ fill the same client-facing shape. Never describe those blank fields as failed enrichment.
71
+
72
+ ## Guardrails
73
+
74
+ - Do not edit the spec during execution.
75
+ - Do not search arbitrary companies outside the source enrichment run.
76
+ - Do not describe a review contact as confirmed.
77
+ - Do not infer current employment from Apollo or old databases.
78
+ - Do not silently continue into contact enrichment; invoke the separate operator workflow when the
79
+ user asks for email or phone data.
80
+ - Never expose API keys or raw environment values.
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "Contact Discovery Operator"
3
+ short_description: "Run and explain live contact discovery"
4
+ default_prompt: "Use $contact-discovery-operator to run this contact discovery spec and summarize the results."
@@ -0,0 +1,86 @@
1
+ ---
2
+ name: contact-enrichment-operator
3
+ description: Enrich accepted live-web contact discoveries with Apollo email and phone data, inspect provider mismatches, and export outreach-ready results. Use when a user asks to find contact details, emails, or phone numbers for people in a completed contact discovery run, rerun Apollo enrichment, or review a prior contact enrichment run.
4
+ ---
5
+
6
+ # Operate Contact Enrichment
7
+
8
+ Use Apollo only after contact discovery has established the person's identity, current company,
9
+ and requested-role fit.
10
+
11
+ ## Workspace And CLI
12
+
13
+ Use `leads doctor` or `leads version` to confirm the workspace root. The root contains
14
+ `backups/`, `config/`, `data/`, `logs/`, `runs/`, `skills/`, and `specs/`.
15
+
16
+ - Contact discovery artifacts live under
17
+ `runs/<company-discover-id>/enrich/<company-enrich-id>/contacts/<contact-discover-id>/`.
18
+ - Contact enrichment artifacts live under
19
+ `runs/<company-discover-id>/enrich/<company-enrich-id>/contacts/<contact-discover-id>/enrich/<contact-enrich-id>/`
20
+ with `ready.csv`, `review.csv`, `blocked.csv`, `summary.md`, and `run.json`.
21
+ - Config is in `config/config.toml`; secrets are in `config/secrets.toml`; never expose API keys or
22
+ webhook values.
23
+ - The memory database is `data/company_memory.db`; use `leads contacts show-run`,
24
+ `show-enrichment`, and inspect commands before direct DB inspection.
25
+ - Backups are under `backups/`; CLI diagnostics are in `logs/leads.log`; installed skill metadata
26
+ is under `skills/`; specs live under `specs/companies/` and `specs/contacts/`.
27
+ - Useful setup/maintenance commands: `leads init`, `leads version`, `leads doctor`,
28
+ `leads update --check`, `leads migrate --check`, and `leads skills status`.
29
+
30
+ ## Configure Apollo
31
+
32
+ Require `APOLLO_API_KEY`.
33
+
34
+ For the default email-and-phone flow, also require a public HTTPS `APOLLO_WEBHOOK_URL`; Apollo's
35
+ phone and waterfall enrichment are asynchronous. Never print either environment value.
36
+
37
+ If no webhook endpoint is available, run email-only enrichment with `--no-phone`.
38
+
39
+ ## Run Enrichment
40
+
41
+ 1. Identify the completed `contact-discover-<id>` requested by the user.
42
+ 2. Run `leads contacts show-run <contact-run-id>` to confirm scope and accepted count.
43
+ 3. Run `leads contacts enrich <contact-run-id>` for email and phone.
44
+ 4. Use `--no-phone` only when the user wants email-only enrichment or no webhook is configured.
45
+ 5. Use `--refresh` only when the user explicitly wants to ignore fresh 14-day Apollo memory.
46
+ 6. Report the contact enrichment run ID and ready/review/blocked counts.
47
+ 7. Read `summary.md` or `run.json` before explaining mismatches.
48
+ 8. Present the results with:
49
+ - one compact count line for all outcomes;
50
+ - one table for `ready`;
51
+ - one table for `review`.
52
+ Do not show `blocked` rows by default unless the user asks, or unless there are no useful
53
+ results and the blocking reasons are what the user needs next.
54
+ 9. Keep the default tables compact and systematic. Use these columns when they are available:
55
+ `Company | Contact | Title | Email | Phone | Status | Apollo Match | Notes`
56
+ 10. Show at most about 15 rows per table by default. If there are more, say that additional rows
57
+ are available in the exported artifacts.
58
+
59
+ The command enriches accepted contacts only. It batches up to 10 people per Apollo request, polls
60
+ asynchronous request IDs, and saves `contact-enrich-<id>` below the source contact run.
61
+
62
+ ## Follow-Up Operations
63
+
64
+ - Show a run: `leads contacts show-enrichment <contact-enrich-id>`
65
+ - Inspect a person: `leads contacts inspect-enrichment <run-id> --person "Jane Smith"`
66
+ - Regenerate artifacts: `leads contacts export-enrichment <run-id>`
67
+
68
+ ## Interpret Results
69
+
70
+ - `ready.csv`: identity matches and a work channel is supported by the target company domain.
71
+ - `review.csv`: identity is credible, but Apollo company data, email domain, or channel context is
72
+ stale or ambiguous.
73
+ - `blocked.csv`: no credible Apollo identity match or no usable email/phone was returned.
74
+ - `run.json`: discovery snapshot, Apollo metadata, raw provider record, deterministic checks,
75
+ flags, and outcome.
76
+
77
+ Apollo never overrides the live-web company, title, LinkedIn URL, or role. A stale Apollo employer
78
+ is a review signal, not proof that discovery was wrong.
79
+
80
+ ## Guardrails
81
+
82
+ - Do not enrich review or rejected discovery contacts automatically.
83
+ - Do not describe review rows as outreach-ready.
84
+ - Do not use personal email addresses without explicit human review.
85
+ - Do not expose API keys, webhook secrets, or raw environment values.
86
+ - Do not retry failed paid requests blindly; inspect the stored run and provider error first.
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "Contact Enrichment Operator"
3
+ short_description: "Enrich discovered contacts safely with Apollo"
4
+ default_prompt: "Use $contact-enrichment-operator to enrich accepted contacts from a contact discovery run with Apollo."
@@ -0,0 +1,86 @@
1
+ ---
2
+ name: contact-search-spec-writer
3
+ description: Convert natural-language requests for people at previously enriched companies into a validated contact_search_spec.json for the Leads CLI. Use when a user asks to find managers, owners, estimators, project managers, or other current employees across all or selected companies from a company enrichment run. Do not run discovery or add Apollo enrichment settings.
4
+ ---
5
+
6
+ # Write Contact Search Specs
7
+
8
+ Create one strict JSON input for `leads contacts discover`.
9
+
10
+ ## Workspace And CLI
11
+
12
+ Use `leads doctor` or `leads version` to confirm the workspace root. The root contains
13
+ `backups/`, `config/`, `data/`, `logs/`, `runs/`, `skills/`, and `specs/`.
14
+
15
+ - Write contact specs to `specs/contacts/`, for example
16
+ `specs/contacts/contact_search_spec.json`.
17
+ - Company specs belong in `specs/companies/`; do not write company ICP specs here.
18
+ - Contact specs reference completed company enrichment runs stored under
19
+ `runs/<company-discover-id>/enrich/<company-enrich-id>/`.
20
+ - Config is in `config/config.toml`; secrets are in `config/secrets.toml`; never expose secret
21
+ values.
22
+ - The memory database is `data/company_memory.db`; use CLI commands rather than editing it.
23
+ - Backups are under `backups/`; CLI diagnostics are in `logs/leads.log`; installed skill metadata
24
+ is under `skills/`.
25
+ - Useful setup/maintenance commands: `leads init`, `leads version`, `leads doctor`,
26
+ `leads update --check`, `leads migrate --check`, and `leads skills status`.
27
+
28
+ ## Workflow
29
+
30
+ 1. Identify the completed company enrichment run that supplies the companies.
31
+ 2. Default to its `ready` companies. Use `review` or `all` only when the user explicitly wants
32
+ companies that were not fully ready.
33
+ 3. Resolve company scope:
34
+ - omit `domains` or use `[]` for every company in the chosen bucket;
35
+ - use root domains for a requested subset;
36
+ - never invent domains that are absent from the enrichment run.
37
+ 4. Convert every requested role into a stable snake_case key and a focused list of title labels.
38
+ 5. Default `max_per_company` to `1`. Increase it only when the user requests multiple people per
39
+ company or the role naturally needs broader coverage.
40
+ 6. Keep `current_only` and `require_role_match` true unless the user explicitly requests looser
41
+ research.
42
+ 7. Write JSON, then run `leads contacts validate-spec --spec <spec-path>`.
43
+ 8. Correct validation errors before handing the spec to the discovery operator.
44
+
45
+ ## Contract
46
+
47
+ ```json
48
+ {
49
+ "version": 1,
50
+ "company_source": {
51
+ "enrichment_run_id": "company-enrich-a1b2c3d4e5f6",
52
+ "bucket": "ready",
53
+ "domains": []
54
+ },
55
+ "roles": [
56
+ {
57
+ "key": "project_manager",
58
+ "labels": ["project manager", "senior project manager"],
59
+ "max_per_company": 1
60
+ }
61
+ ],
62
+ "company_limit": null,
63
+ "contact_limit": null,
64
+ "current_only": true,
65
+ "require_role_match": true,
66
+ "memory_freshness_days": 30
67
+ }
68
+ ```
69
+
70
+ ## Role Rules
71
+
72
+ - Keep synonyms semantically close. Do not put `owner`, `estimator`, and `project manager` under
73
+ one broad `manager` role.
74
+ - Preserve distinct user requests as distinct role objects.
75
+ - Use observed business titles, not department keywords alone.
76
+ - If “manager” is genuinely ambiguous and context does not resolve it, ask which management role
77
+ they mean before creating the file.
78
+
79
+ ## Guardrails
80
+
81
+ - JSON is the canonical format; do not produce YAML.
82
+ - Do not include company-discovery ICP fields such as state, vertical, size, or exclusions. The
83
+ company enrichment run already defines company scope.
84
+ - Do not add email, phone, Apollo, or contact-enrichment settings.
85
+ - Do not silently include company enrichment review rows.
86
+ - Never expose API keys or environment values.
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "Contact Search Spec Writer"
3
+ short_description: "Turn contact requests into validated JSON specs"
4
+ default_prompt: "Use $contact-search-spec-writer to create a contact discovery spec from my request."
@@ -0,0 +1,60 @@
1
+ ---
2
+ name: leads-update-operator
3
+ description: Safely guide updates for the Leads CLI, bundled agent skills, local database schema, and workspace backups.
4
+ ---
5
+
6
+ # Operate Leads Updates
7
+
8
+ Use this skill when a user asks to update, upgrade, repair, or check the installed Leads tool.
9
+
10
+ ## Workspace And CLI
11
+
12
+ Use `leads doctor` or `leads version` to confirm the workspace root. The root contains
13
+ `backups/`, `config/`, `data/`, `logs/`, `runs/`, `skills/`, and `specs/`.
14
+
15
+ - `config/config.toml` stores non-secret settings; `config/secrets.toml` stores API keys and
16
+ webhook secrets; `config/runtime.json` stores schema, skill, and install metadata.
17
+ - `data/company_memory.db` is the SQLite memory DB.
18
+ - `runs/` stores discovery, enrichment, contact discovery, and contact enrichment artifacts.
19
+ - `specs/companies/` and `specs/contacts/` store agent-created spec files.
20
+ - `backups/` stores migration and reset backups.
21
+ - `logs/leads.log` stores CLI diagnostics; it is not run evidence and should not be summarized as
22
+ a lead result.
23
+ - `skills/` stores bundled skill copies and install metadata. Use `leads skills ...` commands
24
+ instead of manually editing installed skill files.
25
+
26
+ Core commands to know: `leads init`, `leads version`, `leads doctor`, `leads config show`,
27
+ `leads skills status`, `leads skills install`, `leads skills reinstall`, `leads update --check`,
28
+ `leads migrate --check`, and `leads migrate --apply`.
29
+
30
+ ## Safe Update Flow
31
+
32
+ 1. Run `leads update --check` first.
33
+ 2. Prefer `leads update --check --json` when you need exact fields for an explanation.
34
+ 3. Report CLI, skill bundle, and database schema changes separately.
35
+ 4. Explain whether a backup or migration is required.
36
+ 5. If migration is required, run `leads migrate --check` or `leads migrate --check --json` and
37
+ explain the migration action, backup path behavior, and risk summary.
38
+ 6. Ask the user before applying structural database changes.
39
+ 7. Only run `leads migrate --apply` after explicit user approval. Use a large tool-window timeout,
40
+ around 10 minutes, so backup and migration work can finish.
41
+ 8. Do not assume a migration is harmless just because the command exists.
42
+
43
+ ## Interpretation
44
+
45
+ - `cli_update_required` means the installed package version differs from the release manifest.
46
+ - `skills_update_required` means bundled agent skills should be reinstalled or synced.
47
+ - `migration_required` means the local schema and release manifest disagree, or the release
48
+ explicitly requires migration.
49
+ - `backup_required` means the update plan expects a database backup before structural work.
50
+ - `confirmation_required` means the agent should pause and get explicit user approval.
51
+ - `leads migrate --check` is read-only and reports the local DB migration action.
52
+ - `leads migrate --apply` creates a timestamped backup before supported structural changes and
53
+ refuses unknown migration paths.
54
+
55
+ ## Guardrails
56
+
57
+ - Do not run destructive database operations from a plain update request.
58
+ - Do not hide skill updates inside a generic success message.
59
+ - Do not delete runs, specs, logs, backups, or the database unless the user explicitly confirms.
60
+ - Never expose API keys or raw secret values from the workspace config.
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "Leads Update Operator"
3
+ short_description: "Check and explain safe Leads updates"
4
+ default_prompt: "Use $leads-update-operator to run leads update --check, explain CLI, skill, and database changes separately, and ask before applying structural changes."