@agent-pattern-labs/leads-rig 0.1.4 → 0.1.5

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.
@@ -1,4 +1,4 @@
1
- # generated by @razroo/iso-route — do not hand-edit
1
+ # generated by @agent-pattern-labs/iso-route — do not hand-edit
2
2
  model = "gpt-5.4"
3
3
  model_provider = "openai"
4
4
 
@@ -9,7 +9,7 @@ Agentic public-web lead discovery harness. It crawls company domains, extracts r
9
9
 
10
10
  ## Hard Limits
11
11
 
12
- - [H1] Only collect public-source business contact data. Do not infer, guess, brute-force, or enrich private email addresses. Every lead needs a source URL and evidence excerpt.
12
+ - [H1] Only collect public-source business contact data. Do not infer, guess, brute-force, or enrich private email addresses. Every lead needs a source URL and evidence excerpt. The primary goal is named people, not generic company inboxes.
13
13
  - [H2] Respect robots.txt, terms, rate limits, and site intent. If a page blocks crawling or is not public, record a warning and move on.
14
14
  - [H3] Never send outreach from this harness. The output is reviewable lead records and ingest-ready artifacts, not email campaigns.
15
15
  - [H4] Use file-backed artifacts before ingest. A subagent prose summary is not enough; write validated JSON/JSONL first, then ingest.
@@ -23,7 +23,7 @@ Agentic public-web lead discovery harness. It crawls company domains, extracts r
23
23
  - [D2] Use deterministic local helpers when they can validate, normalize, manifest, preflight, postflight, or ingest artifacts.
24
24
  - [D3] Read the active mode file before executing. Mode files own output shapes and gates.
25
25
  - [D4] Prefer official company websites and high-signal pages: home, contact, about, team, leadership, people, press, blog, careers, and legal pages.
26
- - [D5] Keep artifacts source-backed. Every emitted lead should include `domain`, `sourceUrl`, `evidence`, `emailType`, `extractionMethod`, `verificationStatus`, and `confidence`.
26
+ - [D5] Keep artifacts source-backed. Every emitted lead should include `domain`, `sourceUrl`, `evidence`, `emailType`, `extractionMethod`, `verificationStatus`, and `confidence`. Reject generic catch-all inboxes such as `info@`, `hello@`, `contact@`, `support@`, `team@`, and similar aliases; if no named person is available, prefer a `contact_path` record instead.
27
27
 
28
28
  ## Procedure
29
29
 
package/AGENTS.md CHANGED
@@ -4,7 +4,7 @@ Agentic public-web lead discovery harness. It crawls company domains, extracts r
4
4
 
5
5
  ## Hard Limits
6
6
 
7
- - [H1] Only collect public-source business contact data. Do not infer, guess, brute-force, or enrich private email addresses. Every lead needs a source URL and evidence excerpt.
7
+ - [H1] Only collect public-source business contact data. Do not infer, guess, brute-force, or enrich private email addresses. Every lead needs a source URL and evidence excerpt. The primary goal is named people, not generic company inboxes.
8
8
  - [H2] Respect robots.txt, terms, rate limits, and site intent. If a page blocks crawling or is not public, record a warning and move on.
9
9
  - [H3] Never send outreach from this harness. The output is reviewable lead records and ingest-ready artifacts, not email campaigns.
10
10
  - [H4] Use file-backed artifacts before ingest. A subagent prose summary is not enough; write validated JSON/JSONL first, then ingest.
@@ -18,7 +18,7 @@ Agentic public-web lead discovery harness. It crawls company domains, extracts r
18
18
  - [D2] Use deterministic local helpers when they can validate, normalize, manifest, preflight, postflight, or ingest artifacts.
19
19
  - [D3] Read the active mode file before executing. Mode files own output shapes and gates.
20
20
  - [D4] Prefer official company websites and high-signal pages: home, contact, about, team, leadership, people, press, blog, careers, and legal pages.
21
- - [D5] Keep artifacts source-backed. Every emitted lead should include `domain`, `sourceUrl`, `evidence`, `emailType`, `extractionMethod`, `verificationStatus`, and `confidence`.
21
+ - [D5] Keep artifacts source-backed. Every emitted lead should include `domain`, `sourceUrl`, `evidence`, `emailType`, `extractionMethod`, `verificationStatus`, and `confidence`. Reject generic catch-all inboxes such as `info@`, `hello@`, `contact@`, `support@`, `team@`, and similar aliases; if no named person is available, prefer a `contact_path` record instead.
22
22
 
23
23
  ## Procedure
24
24
 
package/CLAUDE.md CHANGED
@@ -4,7 +4,7 @@ Agentic public-web lead discovery harness. It crawls company domains, extracts r
4
4
 
5
5
  ## Hard Limits
6
6
 
7
- - [H1] Only collect public-source business contact data. Do not infer, guess, brute-force, or enrich private email addresses. Every lead needs a source URL and evidence excerpt.
7
+ - [H1] Only collect public-source business contact data. Do not infer, guess, brute-force, or enrich private email addresses. Every lead needs a source URL and evidence excerpt. The primary goal is named people, not generic company inboxes.
8
8
  - [H2] Respect robots.txt, terms, rate limits, and site intent. If a page blocks crawling or is not public, record a warning and move on.
9
9
  - [H3] Never send outreach from this harness. The output is reviewable lead records and ingest-ready artifacts, not email campaigns.
10
10
  - [H4] Use file-backed artifacts before ingest. A subagent prose summary is not enough; write validated JSON/JSONL first, then ingest.
@@ -18,7 +18,7 @@ Agentic public-web lead discovery harness. It crawls company domains, extracts r
18
18
  - [D2] Use deterministic local helpers when they can validate, normalize, manifest, preflight, postflight, or ingest artifacts.
19
19
  - [D3] Read the active mode file before executing. Mode files own output shapes and gates.
20
20
  - [D4] Prefer official company websites and high-signal pages: home, contact, about, team, leadership, people, press, blog, careers, and legal pages.
21
- - [D5] Keep artifacts source-backed. Every emitted lead should include `domain`, `sourceUrl`, `evidence`, `emailType`, `extractionMethod`, `verificationStatus`, and `confidence`.
21
+ - [D5] Keep artifacts source-backed. Every emitted lead should include `domain`, `sourceUrl`, `evidence`, `emailType`, `extractionMethod`, `verificationStatus`, and `confidence`. Reject generic catch-all inboxes such as `info@`, `hello@`, `contact@`, `support@`, `team@`, and similar aliases; if no named person is available, prefer a `contact_path` record instead.
22
22
 
23
23
  ## Procedure
24
24
 
package/README.md CHANGED
@@ -6,11 +6,13 @@ Agentic public-web lead discovery harness for portable, source-backed lead artif
6
6
 
7
7
  - Crawls public company websites through agent workflows.
8
8
  - Produces source-backed lead artifacts matching the local lead-ingest contract.
9
- - Validates lead JSON/JSONL before database handoff.
9
+ - Validates lead JSON/JSONL before database handoff and rejects generic catch-all inboxes such as `info@` and `hello@`.
10
10
  - Builds a local manifest for batch auditability.
11
11
  - Submits validated payloads to a configured ingest API.
12
12
  - Ships OpenCode, Claude Code, Cursor, Codex, and Pi harness config from one `iso/` source.
13
13
 
14
+ The harness is optimized to find named people who can actually be contacted. When only a general company contact path exists, it should emit a `contact_path` record rather than a generic organizational inbox.
15
+
14
16
  ## Core Commands
15
17
 
16
18
  ```bash
@@ -23,80 +23,80 @@ const commands = {
23
23
  };
24
24
 
25
25
  const helperAliases = {
26
- 'trace:list': ['@razroo/iso-trace', 'list'],
27
- 'trace:stats': ['@razroo/iso-trace', 'stats'],
28
- 'trace:show': ['@razroo/iso-trace', 'show'],
29
- 'guard:audit': ['@razroo/iso-guard', 'audit'],
30
- 'guard:explain': ['@razroo/iso-guard', 'explain'],
31
- 'ledger:status': ['@razroo/iso-ledger', 'status'],
32
- 'ledger:rebuild': ['@razroo/iso-ledger', 'rebuild'],
33
- 'ledger:verify': ['@razroo/iso-ledger', 'verify'],
34
- 'capabilities:list': ['@razroo/iso-capabilities', 'list'],
35
- 'capabilities:explain': ['@razroo/iso-capabilities', 'explain'],
36
- 'capabilities:check': ['@razroo/iso-capabilities', 'check'],
37
- 'context:list': ['@razroo/iso-context', 'list'],
38
- 'context:explain': ['@razroo/iso-context', 'explain'],
39
- 'context:plan': ['@razroo/iso-context', 'plan'],
40
- 'context:check': ['@razroo/iso-context', 'check'],
41
- 'context:render': ['@razroo/iso-context', 'render'],
42
- 'cache:key': ['@razroo/iso-cache', 'key'],
43
- 'cache:has': ['@razroo/iso-cache', 'has'],
44
- 'cache:get': ['@razroo/iso-cache', 'get'],
45
- 'cache:put': ['@razroo/iso-cache', 'put'],
46
- 'cache:status': ['@razroo/iso-cache', 'status'],
47
- 'cache:list': ['@razroo/iso-cache', 'list'],
48
- 'cache:verify': ['@razroo/iso-cache', 'verify'],
49
- 'cache:prune': ['@razroo/iso-cache', 'prune'],
50
- 'index:build': ['@razroo/iso-index', 'build'],
51
- 'index:status': ['@razroo/iso-index', 'status'],
52
- 'index:query': ['@razroo/iso-index', 'query'],
53
- 'index:has': ['@razroo/iso-index', 'has'],
54
- 'index:verify': ['@razroo/iso-index', 'verify'],
55
- 'facts:build': ['@razroo/iso-facts', 'build'],
56
- 'facts:status': ['@razroo/iso-facts', 'status'],
57
- 'facts:query': ['@razroo/iso-facts', 'query'],
58
- 'facts:has': ['@razroo/iso-facts', 'has'],
59
- 'facts:verify': ['@razroo/iso-facts', 'verify'],
60
- 'score:compute': ['@razroo/iso-score', 'compute'],
61
- 'score:verify': ['@razroo/iso-score', 'verify'],
62
- 'score:check': ['@razroo/iso-score', 'check'],
63
- 'score:gate': ['@razroo/iso-score', 'gate'],
64
- 'score:compare': ['@razroo/iso-score', 'compare'],
65
- 'score:explain': ['@razroo/iso-score', 'explain'],
66
- 'canon:normalize': ['@razroo/iso-canon', 'normalize'],
67
- 'canon:key': ['@razroo/iso-canon', 'key'],
68
- 'canon:compare': ['@razroo/iso-canon', 'compare'],
69
- 'canon:explain': ['@razroo/iso-canon', 'explain'],
70
- 'preflight:plan': ['@razroo/iso-preflight', 'plan'],
71
- 'preflight:check': ['@razroo/iso-preflight', 'check'],
72
- 'preflight:explain': ['@razroo/iso-preflight', 'explain'],
73
- 'postflight:status': ['@razroo/iso-postflight', 'status'],
74
- 'postflight:check': ['@razroo/iso-postflight', 'check'],
75
- 'postflight:explain': ['@razroo/iso-postflight', 'explain'],
76
- 'timeline:status': ['@razroo/iso-timeline', 'status'],
77
- 'timeline:build': ['@razroo/iso-timeline', 'build'],
78
- 'timeline:plan': ['@razroo/iso-timeline', 'plan'],
79
- 'timeline:due': ['@razroo/iso-timeline', 'due'],
80
- 'timeline:check': ['@razroo/iso-timeline', 'check'],
81
- 'timeline:verify': ['@razroo/iso-timeline', 'verify'],
82
- 'prioritize:status': ['@razroo/iso-prioritize', 'status'],
83
- 'prioritize:items': ['@razroo/iso-prioritize', 'items'],
84
- 'prioritize:build': ['@razroo/iso-prioritize', 'build'],
85
- 'prioritize:rank': ['@razroo/iso-prioritize', 'rank'],
86
- 'prioritize:select': ['@razroo/iso-prioritize', 'select'],
87
- 'prioritize:check': ['@razroo/iso-prioritize', 'check'],
88
- 'prioritize:verify': ['@razroo/iso-prioritize', 'verify'],
89
- 'lineage:status': ['@razroo/iso-lineage', 'status'],
90
- 'lineage:record': ['@razroo/iso-lineage', 'record'],
91
- 'lineage:check': ['@razroo/iso-lineage', 'check'],
92
- 'lineage:stale': ['@razroo/iso-lineage', 'stale'],
93
- 'lineage:verify': ['@razroo/iso-lineage', 'verify'],
94
- 'redact:scan': ['@razroo/iso-redact', 'scan'],
95
- 'redact:verify': ['@razroo/iso-redact', 'verify'],
96
- 'redact:apply': ['@razroo/iso-redact', 'apply'],
97
- 'migrate:plan': ['@razroo/iso-migrate', 'plan'],
98
- 'migrate:apply': ['@razroo/iso-migrate', 'apply'],
99
- 'migrate:check': ['@razroo/iso-migrate', 'check'],
26
+ 'trace:list': ['@agent-pattern-labs/iso-trace', 'list'],
27
+ 'trace:stats': ['@agent-pattern-labs/iso-trace', 'stats'],
28
+ 'trace:show': ['@agent-pattern-labs/iso-trace', 'show'],
29
+ 'guard:audit': ['@agent-pattern-labs/iso-guard', 'audit'],
30
+ 'guard:explain': ['@agent-pattern-labs/iso-guard', 'explain'],
31
+ 'ledger:status': ['@agent-pattern-labs/iso-ledger', 'status'],
32
+ 'ledger:rebuild': ['@agent-pattern-labs/iso-ledger', 'rebuild'],
33
+ 'ledger:verify': ['@agent-pattern-labs/iso-ledger', 'verify'],
34
+ 'capabilities:list': ['@agent-pattern-labs/iso-capabilities', 'list'],
35
+ 'capabilities:explain': ['@agent-pattern-labs/iso-capabilities', 'explain'],
36
+ 'capabilities:check': ['@agent-pattern-labs/iso-capabilities', 'check'],
37
+ 'context:list': ['@agent-pattern-labs/iso-context', 'list'],
38
+ 'context:explain': ['@agent-pattern-labs/iso-context', 'explain'],
39
+ 'context:plan': ['@agent-pattern-labs/iso-context', 'plan'],
40
+ 'context:check': ['@agent-pattern-labs/iso-context', 'check'],
41
+ 'context:render': ['@agent-pattern-labs/iso-context', 'render'],
42
+ 'cache:key': ['@agent-pattern-labs/iso-cache', 'key'],
43
+ 'cache:has': ['@agent-pattern-labs/iso-cache', 'has'],
44
+ 'cache:get': ['@agent-pattern-labs/iso-cache', 'get'],
45
+ 'cache:put': ['@agent-pattern-labs/iso-cache', 'put'],
46
+ 'cache:status': ['@agent-pattern-labs/iso-cache', 'status'],
47
+ 'cache:list': ['@agent-pattern-labs/iso-cache', 'list'],
48
+ 'cache:verify': ['@agent-pattern-labs/iso-cache', 'verify'],
49
+ 'cache:prune': ['@agent-pattern-labs/iso-cache', 'prune'],
50
+ 'index:build': ['@agent-pattern-labs/iso-index', 'build'],
51
+ 'index:status': ['@agent-pattern-labs/iso-index', 'status'],
52
+ 'index:query': ['@agent-pattern-labs/iso-index', 'query'],
53
+ 'index:has': ['@agent-pattern-labs/iso-index', 'has'],
54
+ 'index:verify': ['@agent-pattern-labs/iso-index', 'verify'],
55
+ 'facts:build': ['@agent-pattern-labs/iso-facts', 'build'],
56
+ 'facts:status': ['@agent-pattern-labs/iso-facts', 'status'],
57
+ 'facts:query': ['@agent-pattern-labs/iso-facts', 'query'],
58
+ 'facts:has': ['@agent-pattern-labs/iso-facts', 'has'],
59
+ 'facts:verify': ['@agent-pattern-labs/iso-facts', 'verify'],
60
+ 'score:compute': ['@agent-pattern-labs/iso-score', 'compute'],
61
+ 'score:verify': ['@agent-pattern-labs/iso-score', 'verify'],
62
+ 'score:check': ['@agent-pattern-labs/iso-score', 'check'],
63
+ 'score:gate': ['@agent-pattern-labs/iso-score', 'gate'],
64
+ 'score:compare': ['@agent-pattern-labs/iso-score', 'compare'],
65
+ 'score:explain': ['@agent-pattern-labs/iso-score', 'explain'],
66
+ 'canon:normalize': ['@agent-pattern-labs/iso-canon', 'normalize'],
67
+ 'canon:key': ['@agent-pattern-labs/iso-canon', 'key'],
68
+ 'canon:compare': ['@agent-pattern-labs/iso-canon', 'compare'],
69
+ 'canon:explain': ['@agent-pattern-labs/iso-canon', 'explain'],
70
+ 'preflight:plan': ['@agent-pattern-labs/iso-preflight', 'plan'],
71
+ 'preflight:check': ['@agent-pattern-labs/iso-preflight', 'check'],
72
+ 'preflight:explain': ['@agent-pattern-labs/iso-preflight', 'explain'],
73
+ 'postflight:status': ['@agent-pattern-labs/iso-postflight', 'status'],
74
+ 'postflight:check': ['@agent-pattern-labs/iso-postflight', 'check'],
75
+ 'postflight:explain': ['@agent-pattern-labs/iso-postflight', 'explain'],
76
+ 'timeline:status': ['@agent-pattern-labs/iso-timeline', 'status'],
77
+ 'timeline:build': ['@agent-pattern-labs/iso-timeline', 'build'],
78
+ 'timeline:plan': ['@agent-pattern-labs/iso-timeline', 'plan'],
79
+ 'timeline:due': ['@agent-pattern-labs/iso-timeline', 'due'],
80
+ 'timeline:check': ['@agent-pattern-labs/iso-timeline', 'check'],
81
+ 'timeline:verify': ['@agent-pattern-labs/iso-timeline', 'verify'],
82
+ 'prioritize:status': ['@agent-pattern-labs/iso-prioritize', 'status'],
83
+ 'prioritize:items': ['@agent-pattern-labs/iso-prioritize', 'items'],
84
+ 'prioritize:build': ['@agent-pattern-labs/iso-prioritize', 'build'],
85
+ 'prioritize:rank': ['@agent-pattern-labs/iso-prioritize', 'rank'],
86
+ 'prioritize:select': ['@agent-pattern-labs/iso-prioritize', 'select'],
87
+ 'prioritize:check': ['@agent-pattern-labs/iso-prioritize', 'check'],
88
+ 'prioritize:verify': ['@agent-pattern-labs/iso-prioritize', 'verify'],
89
+ 'lineage:status': ['@agent-pattern-labs/iso-lineage', 'status'],
90
+ 'lineage:record': ['@agent-pattern-labs/iso-lineage', 'record'],
91
+ 'lineage:check': ['@agent-pattern-labs/iso-lineage', 'check'],
92
+ 'lineage:stale': ['@agent-pattern-labs/iso-lineage', 'stale'],
93
+ 'lineage:verify': ['@agent-pattern-labs/iso-lineage', 'verify'],
94
+ 'redact:scan': ['@agent-pattern-labs/iso-redact', 'scan'],
95
+ 'redact:verify': ['@agent-pattern-labs/iso-redact', 'verify'],
96
+ 'redact:apply': ['@agent-pattern-labs/iso-redact', 'apply'],
97
+ 'migrate:plan': ['@agent-pattern-labs/iso-migrate', 'plan'],
98
+ 'migrate:apply': ['@agent-pattern-labs/iso-migrate', 'apply'],
99
+ 'migrate:check': ['@agent-pattern-labs/iso-migrate', 'check'],
100
100
  };
101
101
 
102
102
  const [, , cmd, ...rest] = process.argv;
@@ -161,7 +161,7 @@ function runIsoCli(pkgName, args) {
161
161
 
162
162
  function defaultIsoArgs(pkgName, subcommand, args) {
163
163
  const defaults = [];
164
- if (pkgName === '@razroo/iso-trace') {
164
+ if (pkgName === '@agent-pattern-labs/iso-trace') {
165
165
  if (!hasFlag(args, '--cwd')) defaults.push('--cwd', PROJECT_DIR);
166
166
  if ((subcommand === 'list' || subcommand === 'stats') && !hasFlag(args, '--since')) {
167
167
  defaults.push('--since', '7d');
@@ -68,10 +68,10 @@ domain input
68
68
  | `scripts/validate-leads.mjs` | Normalizes and validates JSON/JSONL lead artifacts |
69
69
  | `scripts/manifest.mjs` | Records validated batches in `data/lead-manifest.json` |
70
70
  | `scripts/ingest.mjs` | Posts to the configured ingest endpoint |
71
- | `scripts/batch-orchestrator.mjs` | Durable batch runner using `@razroo/iso-orchestrator` |
71
+ | `scripts/batch-orchestrator.mjs` | Durable batch runner using `@agent-pattern-labs/iso-orchestrator` |
72
72
  | `verify-pipeline.mjs` | Repo/consumer health gate |
73
73
 
74
- The package also carries the `@razroo/iso-*` helper ecosystem for trace, guard, ledger, cache, canon, context, preflight, postflight, prioritize, lineage, redact, migrate, score, and timeline commands.
74
+ The package also carries the `@agent-pattern-labs/iso-*` helper ecosystem for trace, guard, ledger, cache, canon, context, preflight, postflight, prioritize, lineage, redact, migrate, score, and timeline commands.
75
75
 
76
76
  ## Data Contract
77
77
 
@@ -82,4 +82,4 @@ The package also carries the `@razroo/iso-*` helper ecosystem for trace, guard,
82
82
  - page visits
83
83
  - ingest requests
84
84
 
85
- The validator intentionally accepts the same defaults the local runtime normalizes, but it fails missing source evidence, invalid URL fields, invalid `emailType`, invalid `verificationStatus`, invalid confidence, and person/role leads without email.
85
+ The validator intentionally accepts the same defaults the local runtime normalizes, but it fails missing source evidence, invalid URL fields, invalid `emailType`, invalid `verificationStatus`, invalid confidence, person/role leads without email, and generic catch-all inboxes such as `info@`, `hello@`, or similar organizational aliases.
@@ -14,7 +14,7 @@
14
14
  | Deterministic helpers | `scripts/crawl.mjs`, `scripts/pipeline.mjs`, `scripts/validate-leads.mjs`, `scripts/manifest.mjs`, `scripts/ingest.mjs`, `scripts/batch-orchestrator.mjs` |
15
15
  | Consumer scaffold | `create-public-leads-harness <dir>` writes local config, input, output, and ignore files |
16
16
  | Consumer sync | `public-leads sync` symlinks shared harness files from the installed package |
17
- | Batch orchestration | `batch/batch-runner.sh` delegates to `@razroo/iso-orchestrator` with bounded parallelism |
17
+ | Batch orchestration | `batch/batch-runner.sh` delegates to `@agent-pattern-labs/iso-orchestrator` with bounded parallelism |
18
18
  | Verification gates | `npm run verify`, `npm run smoke:iso`, sample validate/manifest/ingest, `npm pack` |
19
19
 
20
20
  ## Maintainer Rules
@@ -4,7 +4,7 @@ Agentic public-web lead discovery harness. It crawls company domains, extracts r
4
4
 
5
5
  ## Hard Limits
6
6
 
7
- - [H1] Only collect public-source business contact data. Do not infer, guess, brute-force, or enrich private email addresses. Every lead needs a source URL and evidence excerpt.
7
+ - [H1] Only collect public-source business contact data. Do not infer, guess, brute-force, or enrich private email addresses. Every lead needs a source URL and evidence excerpt. The primary goal is named people, not generic company inboxes.
8
8
  - [H2] Respect robots.txt, terms, rate limits, and site intent. If a page blocks crawling or is not public, record a warning and move on.
9
9
  - [H3] Never send outreach from this harness. The output is reviewable lead records and ingest-ready artifacts, not email campaigns.
10
10
  - [H4] Use file-backed artifacts before ingest. A subagent prose summary is not enough; write validated JSON/JSONL first, then ingest.
@@ -18,7 +18,7 @@ Agentic public-web lead discovery harness. It crawls company domains, extracts r
18
18
  - [D2] Use deterministic local helpers when they can validate, normalize, manifest, preflight, postflight, or ingest artifacts.
19
19
  - [D3] Read the active mode file before executing. Mode files own output shapes and gates.
20
20
  - [D4] Prefer official company websites and high-signal pages: home, contact, about, team, leadership, people, press, blog, careers, and legal pages.
21
- - [D5] Keep artifacts source-backed. Every emitted lead should include `domain`, `sourceUrl`, `evidence`, `emailType`, `extractionMethod`, `verificationStatus`, and `confidence`.
21
+ - [D5] Keep artifacts source-backed. Every emitted lead should include `domain`, `sourceUrl`, `evidence`, `emailType`, `extractionMethod`, `verificationStatus`, and `confidence`. Reject generic catch-all inboxes such as `info@`, `hello@`, `contact@`, `support@`, `team@`, and similar aliases; if no named person is available, prefer a `contact_path` record instead.
22
22
 
23
23
  ## Procedure
24
24
 
@@ -1,7 +1,7 @@
1
1
  import { createHash } from 'crypto';
2
2
  import { lookup, resolveMx } from 'dns/promises';
3
3
  import { setTimeout as sleep } from 'timers/promises';
4
- import { cleanDomains, dedupeLeadRecords, mergeLeadRecords, normalizeDomain } from './leadharness-leads.mjs';
4
+ import { cleanDomains, dedupeLeadRecords, isRejectedLeadEmail, mergeLeadRecords, normalizeDomain } from './leadharness-leads.mjs';
5
5
 
6
6
  const DEFAULT_MAX_PAGES = 10;
7
7
  const HARD_MAX_PAGES = 25;
@@ -366,7 +366,7 @@ function extractEmails(html) {
366
366
  for (const value of values) {
367
367
  for (const found of String(value || '').matchAll(EMAIL_RE)) {
368
368
  const email = found[0].toLowerCase().replace(/^mailto:/, '').replace(/[.,;:!?()[\]{}<>"']+$/g, '');
369
- if (email && !isLikelyAssetEmail(email)) emails.add(email);
369
+ if (email && !isLikelyAssetEmail(email) && !isRejectedLeadEmail(email)) emails.add(email);
370
370
  }
371
371
  }
372
372
  return [...emails].sort();
@@ -28,6 +28,37 @@ export const ALLOWED_VERIFICATION_STATUSES = new Set([
28
28
  'blocked',
29
29
  'unknown',
30
30
  ]);
31
+ export const REJECTED_EMAIL_LOCAL_PREFIXES = [
32
+ 'admin',
33
+ 'booking',
34
+ 'bookings',
35
+ 'business',
36
+ 'contact',
37
+ 'customerservice',
38
+ 'customer-service',
39
+ 'customersuccess',
40
+ 'customer-success',
41
+ 'events',
42
+ 'hello',
43
+ 'help',
44
+ 'hi',
45
+ 'info',
46
+ 'inquiries',
47
+ 'enquiries',
48
+ 'media',
49
+ 'office',
50
+ 'outreach',
51
+ 'partners',
52
+ 'partnerships',
53
+ 'press',
54
+ 'sales',
55
+ 'service',
56
+ 'services',
57
+ 'speaking',
58
+ 'success',
59
+ 'support',
60
+ 'team',
61
+ ];
31
62
 
32
63
  const EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
33
64
 
@@ -232,6 +263,9 @@ export function validatePayload(payload, { allowEmpty = false } = {}) {
232
263
 
233
264
  results.forEach((result, index) => {
234
265
  validateResult(result, `results[${index}]`, issues);
266
+ result.leads.forEach((lead, leadIndex) => {
267
+ validateLead(lead, `results[${index}].leads[${leadIndex}]`, issues);
268
+ });
235
269
  });
236
270
 
237
271
  const errors = issues.filter((item) => item.severity === 'error').length;
@@ -259,6 +293,9 @@ export function validateLead(lead, path, issues) {
259
293
  if (lead.email && !EMAIL_RE.test(lead.email)) {
260
294
  issues.push(issue('error', `${path}.email`, 'invalid_email', 'email must be a valid email address when present'));
261
295
  }
296
+ if (lead.email && isRejectedLeadEmail(lead.email)) {
297
+ issues.push(issue('error', `${path}.email`, 'generic_inbox_rejected', 'generic company inboxes such as info@, hello@, or support@ are not accepted; submit named people instead'));
298
+ }
262
299
  if (lead.emailType && !ALLOWED_EMAIL_TYPES.has(lead.emailType)) {
263
300
  issues.push(issue('error', `${path}.emailType`, 'invalid_email_type', `emailType must be one of ${[...ALLOWED_EMAIL_TYPES].join(', ')}`));
264
301
  }
@@ -685,6 +722,30 @@ export function fileHash(path) {
685
722
  return createHash('sha256').update(readFileSync(path)).digest('hex');
686
723
  }
687
724
 
725
+ export function isRejectedLeadEmail(email) {
726
+ const local = String(email || '').trim().toLowerCase().split('@')[0] || '';
727
+ return isRejectedLeadLocalPart(local);
728
+ }
729
+
730
+ export function isRejectedLeadLocalPart(local) {
731
+ const value = normalizeRejectedLeadLocalPart(local);
732
+ if (!value) return false;
733
+ return REJECTED_EMAIL_LOCAL_PREFIXES.some((prefix) => {
734
+ if (value === prefix) return true;
735
+ if (!value.startsWith(prefix) || value.length === prefix.length) return false;
736
+ const next = value[prefix.length];
737
+ return next === '.' || next === '_' || next === '-' || next === '+' || /\d/.test(next);
738
+ });
739
+ }
740
+
741
+ function normalizeRejectedLeadLocalPart(local) {
742
+ let value = String(local || '').trim().toLowerCase();
743
+ for (const noise of ['mailto', 'u003e', 'email']) {
744
+ if (value.startsWith(noise)) value = value.slice(noise.length);
745
+ }
746
+ return value.replace(/^[>._+-]+/, '');
747
+ }
748
+
688
749
  export function issue(severity, path, code, message) {
689
750
  return { severity, path, code, message };
690
751
  }
package/modes/_shared.md CHANGED
@@ -28,13 +28,14 @@ Required fields:
28
28
  - Prioritize home, contact, about, team, leadership, people, press, blog, careers, and legal pages.
29
29
  - Respect robots.txt, paywalls, login walls, and obvious anti-scraping notices.
30
30
  - Do not infer email formats. Do not brute-force guessed addresses.
31
+ - Prefer named people over organizational inboxes. Do not emit generic catch-all emails such as `info@`, `hello@`, `contact@`, `support@`, `team@`, or similar aliases. If only a general contact path exists, emit `contact_path` instead.
31
32
  - Keep contact forms as `emailType: "contact_path"` with empty `email`.
32
33
  - Mark operational no-contact inboxes such as `noreply`, `abuse`, `security`, and `legal` as `blocked` with confidence `0`.
33
34
 
34
35
  ## Quality Heuristics
35
36
 
36
37
  - `person`: named person or person-like email with source context.
37
- - `role`: public role inbox such as `sales@`, `partnerships@`, or `press@`.
38
+ - `role`: public role inbox only when it is clearly role-specific and not a generic catch-all alias.
38
39
  - `contact_path`: public form or page where no email is available.
39
40
  - `blocked`: public address that should not be used for outbound.
40
41
 
package/modes/batch.md CHANGED
@@ -10,7 +10,7 @@ Prefer:
10
10
  batch/batch-runner.sh --parallel 2
11
11
  ```
12
12
 
13
- The runner delegates to `scripts/batch-orchestrator.mjs`, which uses `@razroo/iso-orchestrator` for durable workflow records in `.public-leads-runs/`, bounded fan-out, and state updates.
13
+ The runner delegates to `scripts/batch-orchestrator.mjs`, which uses `@agent-pattern-labs/iso-orchestrator` for durable workflow records in `.public-leads-runs/`, bounded fan-out, and state updates.
14
14
 
15
15
  ## Input
16
16
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-pattern-labs/leads-rig",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "description": "Agentic public-web lead discovery harness with portable ingest artifacts",
5
5
  "type": "module",
6
6
  "author": "Razroo",
@@ -155,32 +155,32 @@
155
155
  "fast-uri": "3.1.2"
156
156
  },
157
157
  "dependencies": {
158
- "@razroo/iso-cache": "^0.1.0",
159
- "@razroo/iso-canon": "^0.1.0",
160
- "@razroo/iso-capabilities": "^0.1.0",
161
- "@razroo/iso-context": "^0.1.0",
162
- "@razroo/iso-contract": "^0.1.0",
163
- "@razroo/iso-facts": "^0.1.0",
164
- "@razroo/iso-guard": "^0.1.0",
165
- "@razroo/iso-index": "^0.1.0",
166
- "@razroo/iso-ledger": "^0.1.0",
167
- "@razroo/iso-lineage": "^0.1.0",
168
- "@razroo/iso-migrate": "^0.1.0",
169
- "@razroo/iso-orchestrator": "^0.2.0",
170
- "@razroo/iso-postflight": "^0.1.0",
171
- "@razroo/iso-preflight": "^0.1.0",
172
- "@razroo/iso-prioritize": "^0.1.0",
173
- "@razroo/iso-redact": "^0.1.0",
174
- "@razroo/iso-score": "^0.1.0",
175
- "@razroo/iso-timeline": "^0.1.0",
176
- "@razroo/iso-trace": "^0.5.0",
158
+ "@agent-pattern-labs/iso-cache": "^0.1.1",
159
+ "@agent-pattern-labs/iso-canon": "^0.1.1",
160
+ "@agent-pattern-labs/iso-capabilities": "^0.1.1",
161
+ "@agent-pattern-labs/iso-context": "^0.1.1",
162
+ "@agent-pattern-labs/iso-contract": "^0.1.1",
163
+ "@agent-pattern-labs/iso-facts": "^0.1.1",
164
+ "@agent-pattern-labs/iso-guard": "^0.1.1",
165
+ "@agent-pattern-labs/iso-index": "^0.1.1",
166
+ "@agent-pattern-labs/iso-ledger": "^0.1.1",
167
+ "@agent-pattern-labs/iso-lineage": "^0.1.1",
168
+ "@agent-pattern-labs/iso-migrate": "^0.1.1",
169
+ "@agent-pattern-labs/iso-orchestrator": "^0.2.1",
170
+ "@agent-pattern-labs/iso-postflight": "^0.1.1",
171
+ "@agent-pattern-labs/iso-preflight": "^0.1.1",
172
+ "@agent-pattern-labs/iso-prioritize": "^0.1.1",
173
+ "@agent-pattern-labs/iso-redact": "^0.1.1",
174
+ "@agent-pattern-labs/iso-score": "^0.1.1",
175
+ "@agent-pattern-labs/iso-timeline": "^0.1.1",
176
+ "@agent-pattern-labs/iso-trace": "^0.5.1",
177
177
  "playwright": "^1.58.1"
178
178
  },
179
179
  "devDependencies": {
180
- "@razroo/agentmd": "^0.3.0",
181
- "@razroo/iso": "^0.3.1",
182
- "@razroo/iso-eval": "^0.4.0",
183
- "@razroo/iso-harness": "^0.8.0",
184
- "@razroo/iso-route": "^0.6.0"
180
+ "@agent-pattern-labs/agentmd": "^0.3.1",
181
+ "@agent-pattern-labs/iso": "^0.3.2",
182
+ "@agent-pattern-labs/iso-eval": "^0.4.1",
183
+ "@agent-pattern-labs/iso-harness": "^0.8.1",
184
+ "@agent-pattern-labs/iso-route": "^0.6.1"
185
185
  }
186
186
  }
@@ -6,7 +6,7 @@ import { existsSync } from 'fs';
6
6
  import { mkdir, readFile, rm, writeFile } from 'fs/promises';
7
7
  import { dirname, join, resolve } from 'path';
8
8
  import { fileURLToPath } from 'url';
9
- import { runWorkflow } from '@razroo/iso-orchestrator';
9
+ import { runWorkflow } from '@agent-pattern-labs/iso-orchestrator';
10
10
 
11
11
  const __dirname = dirname(fileURLToPath(import.meta.url));
12
12
  const PKG_ROOT = resolve(__dirname, '..');