@agent-pattern-labs/leads-rig 0.1.3
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.
- package/.claude/agents/general-free.md +39 -0
- package/.claude/agents/general-paid.md +20 -0
- package/.claude/agents/glm-minimal.md +9 -0
- package/.claude/iso-route.resolved.json +21 -0
- package/.claude/settings.json +3 -0
- package/.codex/config.toml +24 -0
- package/.cursor/iso-route.md +17 -0
- package/.cursor/mcp.json +19 -0
- package/.cursor/rules/agent-general-free.mdc +38 -0
- package/.cursor/rules/agent-general-paid.mdc +19 -0
- package/.cursor/rules/agent-glm-minimal.mdc +8 -0
- package/.cursor/rules/main.mdc +61 -0
- package/.mcp.json +19 -0
- package/.opencode/agents/general-free.md +48 -0
- package/.opencode/agents/general-paid.md +29 -0
- package/.opencode/agents/glm-minimal.md +19 -0
- package/.opencode/instructions.md +3 -0
- package/.opencode/skills/lead-harness.md +56 -0
- package/.opencode/skills/public-leads.md +56 -0
- package/.pi/prompts/lead-harness.md +54 -0
- package/.pi/prompts/public-leads.md +54 -0
- package/.pi/skills/general-free/SKILL.md +38 -0
- package/.pi/skills/general-paid/SKILL.md +19 -0
- package/.pi/skills/glm-minimal/SKILL.md +8 -0
- package/AGENTS.md +56 -0
- package/CLAUDE.md +56 -0
- package/LICENSE +21 -0
- package/README.md +61 -0
- package/batch/README.md +37 -0
- package/batch/batch-prompt.md +19 -0
- package/batch/batch-runner.sh +18 -0
- package/bin/create-leads-harness.mjs +178 -0
- package/bin/lead-harness.mjs +201 -0
- package/bin/sync.mjs +150 -0
- package/config/profile.example.yml +34 -0
- package/docs/ARCHITECTURE.md +85 -0
- package/docs/CONSTRUCTION.md +40 -0
- package/docs/README.md +5 -0
- package/docs/SETUP.md +89 -0
- package/examples/README.md +9 -0
- package/examples/sample-leads.json +57 -0
- package/iso/agents/general-free.md +50 -0
- package/iso/agents/general-paid.md +31 -0
- package/iso/agents/glm-minimal.md +21 -0
- package/iso/commands/lead-harness.md +59 -0
- package/iso/commands/public-leads.md +59 -0
- package/iso/config.json +11 -0
- package/iso/instructions.md +56 -0
- package/iso/instructions.opencode.md +3 -0
- package/iso/mcp.json +16 -0
- package/lib/leadharness-crawler.mjs +911 -0
- package/lib/leadharness-ingest.mjs +157 -0
- package/lib/leadharness-leads.mjs +574 -0
- package/models.yaml +32 -0
- package/modes/_shared.md +50 -0
- package/modes/batch.md +34 -0
- package/modes/crawl.md +25 -0
- package/modes/ingest.md +33 -0
- package/modes/pipeline.md +27 -0
- package/modes/reference-local-helpers.md +13 -0
- package/modes/review.md +15 -0
- package/modes/setup.md +25 -0
- package/opencode.json +43 -0
- package/package.json +186 -0
- package/scripts/batch-orchestrator.mjs +558 -0
- package/scripts/crawl.mjs +129 -0
- package/scripts/ingest.mjs +48 -0
- package/scripts/manifest.mjs +71 -0
- package/scripts/pipeline.mjs +118 -0
- package/scripts/validate-leads.mjs +69 -0
- package/templates/canon.json +26 -0
- package/templates/capabilities.json +23 -0
- package/templates/context.json +20 -0
- package/templates/contracts.json +72 -0
- package/templates/facts.json +13 -0
- package/templates/index.json +13 -0
- package/templates/lead-schema.json +143 -0
- package/templates/lineage.json +10 -0
- package/templates/migrations.json +4 -0
- package/templates/postflight.json +11 -0
- package/templates/preflight.json +19 -0
- package/templates/prioritize.json +10 -0
- package/templates/redact.json +15 -0
- package/templates/score.json +18 -0
- package/templates/states.yml +25 -0
- package/templates/timeline.json +10 -0
- package/verify-pipeline.mjs +123 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: general-free
|
|
3
|
+
description: Procedural lead-crawl worker for public-web extraction, JSON artifact creation, validation, manifest updates, and ingest retries.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
You are the @general-free subagent. The orchestrator delegated procedural lead-discovery work to you: bounded public-page crawling, structured extraction, validation, and local artifact updates.
|
|
7
|
+
|
|
8
|
+
## Browser Preflight
|
|
9
|
+
|
|
10
|
+
If your task uses Geometra, start with:
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
geometra_list_sessions()
|
|
14
|
+
geometra_disconnect({ closeBrowser: true })
|
|
15
|
+
geometra_connect({
|
|
16
|
+
pageUrl: "<the assigned URL>",
|
|
17
|
+
isolated: true,
|
|
18
|
+
headless: true,
|
|
19
|
+
slowMo: 250,
|
|
20
|
+
stealth: true
|
|
21
|
+
})
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Skip this only if the task explicitly says to attach to an existing session.
|
|
25
|
+
|
|
26
|
+
## Do
|
|
27
|
+
|
|
28
|
+
- Crawl only public, high-signal company pages.
|
|
29
|
+
- Extract emails, role inboxes, contact forms, public names/titles, source URL, evidence, and warnings.
|
|
30
|
+
- Emit JSON/JSONL matching `templates/lead-schema.json`.
|
|
31
|
+
- Run `npx public-leads validate --input <file>` before returning a result.
|
|
32
|
+
- Return file paths and terminal status, not a prose-only summary.
|
|
33
|
+
|
|
34
|
+
## Do Not
|
|
35
|
+
|
|
36
|
+
- Guess email patterns, scrape private/authenticated pages, send outreach, or invent source evidence.
|
|
37
|
+
- Spawn or check other tasks.
|
|
38
|
+
- Paste secrets from config or environment.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: general-paid
|
|
3
|
+
description: Quality-sensitive lead research worker for ICP fit, company context, and nuanced review notes.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
You are the @general-paid subagent. Use judgment for ICP fit, lead quality review, company context, and evidence quality. Keep final outputs tied to source URLs and local artifacts.
|
|
7
|
+
|
|
8
|
+
## Do
|
|
9
|
+
|
|
10
|
+
- Research target-company context when the orchestrator requests quality review.
|
|
11
|
+
- Explain why a lead is high/medium/low value using evidence already captured in artifacts.
|
|
12
|
+
- Improve source-backed evidence snippets without fabricating facts.
|
|
13
|
+
- Validate any edited artifact with `npx public-leads validate --input <file>`.
|
|
14
|
+
|
|
15
|
+
## Do Not
|
|
16
|
+
|
|
17
|
+
- Replace deterministic validation with prose.
|
|
18
|
+
- Send outreach or generate cold emails unless the user explicitly asks for copy outside the crawl workflow.
|
|
19
|
+
- Spawn or check other tasks.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: glm-minimal
|
|
3
|
+
description: Narrow JSON extractor for small lead snippets and schema transforms. Not for multi-step crawling.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
You are the @glm-minimal subagent. Return the requested small structured output only.
|
|
7
|
+
|
|
8
|
+
If the orchestrator asks for JSON, return JSON without markdown fences. If you cannot complete the transform, return `{"error":"<one-sentence reason>"}`.
|
package/AGENTS.md
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Agent: public-leads-harness
|
|
2
|
+
|
|
3
|
+
Agentic public-web lead discovery harness. It crawls company domains, extracts reviewable public-source contacts, validates artifacts against the local ingest contract, and can submit completed batches to a configured ingest API.
|
|
4
|
+
|
|
5
|
+
## Hard Limits
|
|
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.
|
|
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
|
+
- [H3] Never send outreach from this harness. The output is reviewable lead records and ingest-ready artifacts, not email campaigns.
|
|
10
|
+
- [H4] Use file-backed artifacts before ingest. A subagent prose summary is not enough; write validated JSON/JSONL first, then ingest.
|
|
11
|
+
- [H5] Do not paste API tokens, proxy credentials, or cookies into task prompts or summaries. Reference `config/profile.yml` or environment variables by name only.
|
|
12
|
+
- [H6] For batch domain crawling, dispatch at most 2 subagents per round and wait for final artifact paths before launching the next round.
|
|
13
|
+
- [H7] Before using browser/MCP crawling in a batch round, run Geometra cleanup: `geometra_list_sessions()` then `geometra_disconnect({ closeBrowser: true })`.
|
|
14
|
+
|
|
15
|
+
## Defaults
|
|
16
|
+
|
|
17
|
+
- [D1] Use `@general-free` for procedural crawl/extract/validate work, `@general-paid` for quality-sensitive ICP research and lead-fit reasoning, and `@glm-minimal` for narrow JSON transforms.
|
|
18
|
+
- [D2] Use deterministic local helpers when they can validate, normalize, manifest, preflight, postflight, or ingest artifacts.
|
|
19
|
+
- [D3] Read the active mode file before executing. Mode files own output shapes and gates.
|
|
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`.
|
|
22
|
+
|
|
23
|
+
## Procedure
|
|
24
|
+
|
|
25
|
+
1. Check for `config/profile.yml` and `data/domains.tsv` or `data/pipeline.md`; onboard if missing.
|
|
26
|
+
2. Pick and name the mode from Routing. If no mode fits, ask.
|
|
27
|
+
3. Read `modes/_shared.md` plus `modes/{mode}.md` unless the mode says otherwise.
|
|
28
|
+
4. Normalize domains and dedupe against prior artifacts.
|
|
29
|
+
5. Crawl bounded, public pages only. Preserve warnings and page visits.
|
|
30
|
+
6. Validate lead artifacts with `npx public-leads validate`.
|
|
31
|
+
7. Create or update the manifest with `npx public-leads manifest`.
|
|
32
|
+
8. Ingest only validated payloads with `npx public-leads ingest`.
|
|
33
|
+
9. Run `npx public-leads verify` before ending a batch workflow.
|
|
34
|
+
|
|
35
|
+
## Routing
|
|
36
|
+
|
|
37
|
+
| If the user... | Mode |
|
|
38
|
+
|---|---|
|
|
39
|
+
| wants to crawl domains | `crawl` |
|
|
40
|
+
| gives a domain list or asks for leads | `pipeline` |
|
|
41
|
+
| asks to submit/store leads | `ingest` |
|
|
42
|
+
| asks to inspect lead state | `review` |
|
|
43
|
+
| asks for batch processing | `batch` |
|
|
44
|
+
| asks for setup | `setup` |
|
|
45
|
+
| otherwise | Ask which mode fits |
|
|
46
|
+
|
|
47
|
+
## Output
|
|
48
|
+
|
|
49
|
+
Output shape is mode-specific. Keep user-facing status terse and ground claims in files, command output, or ingest responses.
|
|
50
|
+
|
|
51
|
+
## Reference
|
|
52
|
+
|
|
53
|
+
- `modes/{mode}.md` for active workflow instructions.
|
|
54
|
+
- `templates/lead-schema.json` for the lead artifact contract.
|
|
55
|
+
- `templates/states.yml` for canonical run and ingest states.
|
|
56
|
+
- `docs/ARCHITECTURE.md` for harness architecture.
|
package/CLAUDE.md
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Agent: public-leads-harness
|
|
2
|
+
|
|
3
|
+
Agentic public-web lead discovery harness. It crawls company domains, extracts reviewable public-source contacts, validates artifacts against the local ingest contract, and can submit completed batches to a configured ingest API.
|
|
4
|
+
|
|
5
|
+
## Hard Limits
|
|
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.
|
|
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
|
+
- [H3] Never send outreach from this harness. The output is reviewable lead records and ingest-ready artifacts, not email campaigns.
|
|
10
|
+
- [H4] Use file-backed artifacts before ingest. A subagent prose summary is not enough; write validated JSON/JSONL first, then ingest.
|
|
11
|
+
- [H5] Do not paste API tokens, proxy credentials, or cookies into task prompts or summaries. Reference `config/profile.yml` or environment variables by name only.
|
|
12
|
+
- [H6] For batch domain crawling, dispatch at most 2 subagents per round and wait for final artifact paths before launching the next round.
|
|
13
|
+
- [H7] Before using browser/MCP crawling in a batch round, run Geometra cleanup: `geometra_list_sessions()` then `geometra_disconnect({ closeBrowser: true })`.
|
|
14
|
+
|
|
15
|
+
## Defaults
|
|
16
|
+
|
|
17
|
+
- [D1] Use `@general-free` for procedural crawl/extract/validate work, `@general-paid` for quality-sensitive ICP research and lead-fit reasoning, and `@glm-minimal` for narrow JSON transforms.
|
|
18
|
+
- [D2] Use deterministic local helpers when they can validate, normalize, manifest, preflight, postflight, or ingest artifacts.
|
|
19
|
+
- [D3] Read the active mode file before executing. Mode files own output shapes and gates.
|
|
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`.
|
|
22
|
+
|
|
23
|
+
## Procedure
|
|
24
|
+
|
|
25
|
+
1. Check for `config/profile.yml` and `data/domains.tsv` or `data/pipeline.md`; onboard if missing.
|
|
26
|
+
2. Pick and name the mode from Routing. If no mode fits, ask.
|
|
27
|
+
3. Read `modes/_shared.md` plus `modes/{mode}.md` unless the mode says otherwise.
|
|
28
|
+
4. Normalize domains and dedupe against prior artifacts.
|
|
29
|
+
5. Crawl bounded, public pages only. Preserve warnings and page visits.
|
|
30
|
+
6. Validate lead artifacts with `npx public-leads validate`.
|
|
31
|
+
7. Create or update the manifest with `npx public-leads manifest`.
|
|
32
|
+
8. Ingest only validated payloads with `npx public-leads ingest`.
|
|
33
|
+
9. Run `npx public-leads verify` before ending a batch workflow.
|
|
34
|
+
|
|
35
|
+
## Routing
|
|
36
|
+
|
|
37
|
+
| If the user... | Mode |
|
|
38
|
+
|---|---|
|
|
39
|
+
| wants to crawl domains | `crawl` |
|
|
40
|
+
| gives a domain list or asks for leads | `pipeline` |
|
|
41
|
+
| asks to submit/store leads | `ingest` |
|
|
42
|
+
| asks to inspect lead state | `review` |
|
|
43
|
+
| asks for batch processing | `batch` |
|
|
44
|
+
| asks for setup | `setup` |
|
|
45
|
+
| otherwise | Ask which mode fits |
|
|
46
|
+
|
|
47
|
+
## Output
|
|
48
|
+
|
|
49
|
+
Output shape is mode-specific. Keep user-facing status terse and ground claims in files, command output, or ingest responses.
|
|
50
|
+
|
|
51
|
+
## Reference
|
|
52
|
+
|
|
53
|
+
- `modes/{mode}.md` for active workflow instructions.
|
|
54
|
+
- `templates/lead-schema.json` for the lead artifact contract.
|
|
55
|
+
- `templates/states.yml` for canonical run and ingest states.
|
|
56
|
+
- `docs/ARCHITECTURE.md` for harness architecture.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Razroo
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# @agent-pattern-labs/leads-rig
|
|
2
|
+
|
|
3
|
+
Agentic public-web lead discovery harness for portable, source-backed lead artifacts. It uses a package-oriented harness shape with an installable npm package, `iso/` source for multi-agent config, mode files, deterministic local helpers, batch orchestration, and a verifier gate.
|
|
4
|
+
|
|
5
|
+
## What It Does
|
|
6
|
+
|
|
7
|
+
- Crawls public company websites through agent workflows.
|
|
8
|
+
- Produces source-backed lead artifacts matching the local lead-ingest contract.
|
|
9
|
+
- Validates lead JSON/JSONL before database handoff.
|
|
10
|
+
- Builds a local manifest for batch auditability.
|
|
11
|
+
- Submits validated payloads to a configured ingest API.
|
|
12
|
+
- Ships OpenCode, Claude Code, Cursor, Codex, and Pi harness config from one `iso/` source.
|
|
13
|
+
|
|
14
|
+
## Core Commands
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install
|
|
18
|
+
npm run verify
|
|
19
|
+
npm run smoke:iso
|
|
20
|
+
|
|
21
|
+
npx -p @agent-pattern-labs/leads-rig create-public-leads-harness my-lead-project
|
|
22
|
+
npx public-leads crawl --domains example.com --out data/lead-results.json
|
|
23
|
+
npx public-leads pipeline --input data/domains.tsv --ingest --target-project /path/to/cold-agent-leads
|
|
24
|
+
npx public-leads validate --input examples/sample-leads.json
|
|
25
|
+
npx public-leads ingest --input examples/sample-leads.json --dry-run --out output/sample-ingest.json
|
|
26
|
+
batch/batch-runner.sh --help
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Reference Ingest Handoff
|
|
30
|
+
|
|
31
|
+
The default reference client posts to the Cold Agent Leads ingest API:
|
|
32
|
+
|
|
33
|
+
```http
|
|
34
|
+
POST /api/lead-ingests
|
|
35
|
+
Authorization: Bearer $ADMIN_API_TOKEN
|
|
36
|
+
X-Admin-Email: admin@example.com
|
|
37
|
+
Content-Type: application/json
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
All endpoint details are configurable through `config/profile.yml`, CLI flags, environment variables, or `--target-project /path/to/cold-agent-leads` for reading that app's `.env` at runtime. Payloads contain `jobId`, `domains`, `leads`, `results`, and `errors`, with the schema defined in `templates/lead-schema.json`.
|
|
41
|
+
|
|
42
|
+
Legacy aliases `lead-harness` and `create-leads-harness` remain available for compatibility.
|
|
43
|
+
|
|
44
|
+
## Publishing
|
|
45
|
+
|
|
46
|
+
The npm package publishes as `@agent-pattern-labs/leads-rig` with public scoped access. The GitHub Actions publish workflow expects `NPM_TOKEN` to be available as a repo or organization secret.
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
gh workflow run publish.yml --ref main
|
|
50
|
+
gh run watch
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
You can also publish by creating a GitHub release for the package version:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
gh release create v0.1.3 --title v0.1.3 --generate-notes
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
The package version must not already exist on npm.
|
|
60
|
+
|
|
61
|
+
See [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md), [docs/CONSTRUCTION.md](docs/CONSTRUCTION.md), [docs/SETUP.md](docs/SETUP.md), and [batch/README.md](batch/README.md).
|
package/batch/README.md
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Batch Lead Discovery
|
|
2
|
+
|
|
3
|
+
`batch/` contains the durable runner for processing many company domains with headless agent workers.
|
|
4
|
+
|
|
5
|
+
## Input
|
|
6
|
+
|
|
7
|
+
Create `batch/batch-input.tsv`:
|
|
8
|
+
|
|
9
|
+
```text
|
|
10
|
+
id domain company notes
|
|
11
|
+
1 example.com Example Seed target
|
|
12
|
+
2 example.org Example Org Official site
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Commands
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
batch/batch-runner.sh --dry-run
|
|
19
|
+
batch/batch-runner.sh --parallel 2
|
|
20
|
+
batch/batch-runner.sh --runner codex --parallel 2
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
`--parallel` is capped at `2` to keep browser-heavy work bounded. Worker CLI permission-bypass flags are disabled by default; pass `--allow-unsafe-workers` only in a trusted local workspace when you explicitly want the old unsafe behavior.
|
|
24
|
+
|
|
25
|
+
The runner writes:
|
|
26
|
+
|
|
27
|
+
- `batch/batch-state.tsv`
|
|
28
|
+
- `batch/logs/*.log`
|
|
29
|
+
- `batch/lead-results-*.json`
|
|
30
|
+
- `.public-leads-runs/` durable workflow records
|
|
31
|
+
|
|
32
|
+
After a run:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npm run verify
|
|
36
|
+
npx public-leads ingest --input batch/lead-results-1.json --dry-run
|
|
37
|
+
```
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Lead Harness Batch Worker
|
|
2
|
+
|
|
3
|
+
You are processing assigned public company domains for a source-backed lead discovery workflow.
|
|
4
|
+
|
|
5
|
+
Follow `modes/_shared.md` and `modes/crawl.md`.
|
|
6
|
+
|
|
7
|
+
For each assigned domain:
|
|
8
|
+
|
|
9
|
+
1. Crawl only bounded public official-company pages.
|
|
10
|
+
2. Extract source-backed public leads.
|
|
11
|
+
3. Write `batch/lead-results-{id}.json` matching `templates/lead-schema.json`.
|
|
12
|
+
4. Run `npx public-leads validate --input batch/lead-results-{id}.json`.
|
|
13
|
+
5. End with one JSON status line:
|
|
14
|
+
|
|
15
|
+
```json
|
|
16
|
+
{"id":"<id>","status":"completed|failed","domain":"example.com","leadCount":0,"artifact":"batch/lead-results-<id>.json","error":null}
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Do not send outreach. Do not infer or brute-force emails. Do not paste secrets.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
5
|
+
PROJECT_DIR="${PUBLIC_LEADS_PROJECT:-${LEAD_HARNESS_PROJECT:-$(cd "$SCRIPT_DIR/.." && pwd)}}"
|
|
6
|
+
|
|
7
|
+
SOURCE="${BASH_SOURCE[0]}"
|
|
8
|
+
while [[ -L "$SOURCE" ]]; do
|
|
9
|
+
SOURCE_DIR="$(cd -P "$(dirname "$SOURCE")" && pwd)"
|
|
10
|
+
SOURCE="$(readlink "$SOURCE")"
|
|
11
|
+
[[ "$SOURCE" != /* ]] && SOURCE="$SOURCE_DIR/$SOURCE"
|
|
12
|
+
done
|
|
13
|
+
HARNESS_BATCH_DIR="$(cd -P "$(dirname "$SOURCE")" && pwd)"
|
|
14
|
+
HARNESS_DIR="$(cd "$HARNESS_BATCH_DIR/.." && pwd)"
|
|
15
|
+
|
|
16
|
+
export PUBLIC_LEADS_PROJECT="$PROJECT_DIR"
|
|
17
|
+
export LEAD_HARNESS_PROJECT="$PROJECT_DIR"
|
|
18
|
+
exec node "$HARNESS_DIR/scripts/batch-orchestrator.mjs" "$@"
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { copyFileSync, existsSync, mkdirSync, writeFileSync } from 'fs';
|
|
4
|
+
import { basename, dirname, join, resolve } from 'path';
|
|
5
|
+
import { fileURLToPath } from 'url';
|
|
6
|
+
|
|
7
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
8
|
+
const PKG_ROOT = resolve(__dirname, '..');
|
|
9
|
+
|
|
10
|
+
const args = process.argv.slice(2);
|
|
11
|
+
const FORCE = args.includes('--force');
|
|
12
|
+
const HELP = args.includes('--help') || args.includes('-h');
|
|
13
|
+
const positional = args.filter((arg) => !arg.startsWith('--'));
|
|
14
|
+
|
|
15
|
+
if (HELP || positional.length === 0) {
|
|
16
|
+
console.log(`create-public-leads-harness — scaffold a new lead discovery project
|
|
17
|
+
|
|
18
|
+
Usage:
|
|
19
|
+
npx -p @agent-pattern-labs/leads-rig create-public-leads-harness <dir> [--force]
|
|
20
|
+
|
|
21
|
+
After scaffolding:
|
|
22
|
+
cd <dir>
|
|
23
|
+
npm install
|
|
24
|
+
edit config/profile.yml and data/domains.tsv
|
|
25
|
+
opencode
|
|
26
|
+
`);
|
|
27
|
+
process.exit(HELP ? 0 : 1);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const targetDir = resolve(positional[0]);
|
|
31
|
+
const name = basename(targetDir);
|
|
32
|
+
|
|
33
|
+
console.log(`\nScaffolding lead harness project in ${targetDir}\n`);
|
|
34
|
+
if (!existsSync(targetDir)) mkdirSync(targetDir, { recursive: true });
|
|
35
|
+
|
|
36
|
+
write('package.json', JSON.stringify({
|
|
37
|
+
name,
|
|
38
|
+
version: '0.1.0',
|
|
39
|
+
private: true,
|
|
40
|
+
scripts: {
|
|
41
|
+
sync: 'public-leads sync',
|
|
42
|
+
verify: 'public-leads verify',
|
|
43
|
+
crawl: 'public-leads crawl',
|
|
44
|
+
pipeline: 'public-leads pipeline',
|
|
45
|
+
validate: 'public-leads validate',
|
|
46
|
+
manifest: 'public-leads manifest',
|
|
47
|
+
ingest: 'public-leads ingest',
|
|
48
|
+
'trace:list': 'public-leads trace:list',
|
|
49
|
+
'trace:stats': 'public-leads trace:stats',
|
|
50
|
+
'trace:show': 'public-leads trace:show',
|
|
51
|
+
'update-harness': 'npm install @agent-pattern-labs/leads-rig@latest && public-leads sync',
|
|
52
|
+
},
|
|
53
|
+
dependencies: {
|
|
54
|
+
'@agent-pattern-labs/leads-rig': '^0.1.3',
|
|
55
|
+
},
|
|
56
|
+
engines: {
|
|
57
|
+
node: '>=20.6.0',
|
|
58
|
+
},
|
|
59
|
+
}, null, 2) + '\n');
|
|
60
|
+
|
|
61
|
+
write('opencode.json', JSON.stringify({
|
|
62
|
+
$schema: 'https://opencode.ai/config.json',
|
|
63
|
+
model: 'opencode-go/deepseek-v4-flash',
|
|
64
|
+
small_model: 'opencode-go/deepseek-v4-flash',
|
|
65
|
+
instructions: [
|
|
66
|
+
'AGENTS.harness.md',
|
|
67
|
+
'.opencode/instructions.md',
|
|
68
|
+
'templates/lead-schema.json',
|
|
69
|
+
'templates/states.yml',
|
|
70
|
+
'modes/_shared.md',
|
|
71
|
+
],
|
|
72
|
+
mcp: {
|
|
73
|
+
geometra: {
|
|
74
|
+
type: 'local',
|
|
75
|
+
command: ['npx', '-y', '@geometra/mcp@1.61.3'],
|
|
76
|
+
enabled: true,
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
permission: {
|
|
80
|
+
task: {
|
|
81
|
+
'general-free': 'allow',
|
|
82
|
+
'general-paid': 'allow',
|
|
83
|
+
'glm-minimal': 'allow',
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
tools: {
|
|
87
|
+
'geometra_*': false,
|
|
88
|
+
},
|
|
89
|
+
}, null, 2) + '\n');
|
|
90
|
+
|
|
91
|
+
write('AGENTS.md', `# AGENTS — ${name}
|
|
92
|
+
|
|
93
|
+
This is a consumer project for the @agent-pattern-labs/leads-rig package. Keep private configuration, target domains, and local artifacts here; the shared harness files are symlinked from \`node_modules/@agent-pattern-labs/leads-rig\` after \`npm install\`.
|
|
94
|
+
|
|
95
|
+
## Local Files
|
|
96
|
+
|
|
97
|
+
| What | Where |
|
|
98
|
+
|---|---|
|
|
99
|
+
| Harness rules | \`AGENTS.harness.md\` |
|
|
100
|
+
| Domain input | \`data/domains.tsv\` or \`data/pipeline.md\` |
|
|
101
|
+
| Lead artifacts | \`data/lead-results.json\`, \`batch/lead-results*.json\` |
|
|
102
|
+
| Manifest | \`data/lead-manifest.json\` |
|
|
103
|
+
| Ingest response | \`data/ingest-response.json\` |
|
|
104
|
+
| Config | \`config/profile.yml\` |
|
|
105
|
+
`);
|
|
106
|
+
|
|
107
|
+
copy('config/profile.example.yml', 'config/profile.yml');
|
|
108
|
+
write('data/domains.tsv', `domain\tcompany\tnotes
|
|
109
|
+
example.com\tExample\tSeed target
|
|
110
|
+
`);
|
|
111
|
+
write('data/pipeline.md', `# Lead Pipeline
|
|
112
|
+
|
|
113
|
+
- [ ] example.com | Example | Seed target
|
|
114
|
+
`);
|
|
115
|
+
write('reports/.gitkeep', '');
|
|
116
|
+
write('output/.gitkeep', '');
|
|
117
|
+
write('batch/logs/.gitkeep', '');
|
|
118
|
+
write('.gitignore', `node_modules/
|
|
119
|
+
.env
|
|
120
|
+
.env.*
|
|
121
|
+
config/profile.yml
|
|
122
|
+
data/*.json
|
|
123
|
+
data/*.jsonl
|
|
124
|
+
data/runs/
|
|
125
|
+
batch/*.json
|
|
126
|
+
batch/*.jsonl
|
|
127
|
+
batch/logs/*
|
|
128
|
+
!batch/logs/.gitkeep
|
|
129
|
+
reports/*
|
|
130
|
+
!reports/.gitkeep
|
|
131
|
+
output/*
|
|
132
|
+
!output/.gitkeep
|
|
133
|
+
`);
|
|
134
|
+
write('README.md', `# ${name}
|
|
135
|
+
|
|
136
|
+
Lead discovery project powered by \`@agent-pattern-labs/leads-rig\`.
|
|
137
|
+
|
|
138
|
+
## Start
|
|
139
|
+
|
|
140
|
+
\`\`\`bash
|
|
141
|
+
npm install
|
|
142
|
+
npm run verify
|
|
143
|
+
opencode
|
|
144
|
+
\`\`\`
|
|
145
|
+
|
|
146
|
+
Update \`config/profile.yml\` with your ingest API settings and add domains to \`data/domains.tsv\` or \`data/pipeline.md\`.
|
|
147
|
+
`);
|
|
148
|
+
|
|
149
|
+
console.log('\nNext: npm install, then edit config/profile.yml and data/domains.tsv.\n');
|
|
150
|
+
|
|
151
|
+
function write(rel, content, { overwrite = FORCE } = {}) {
|
|
152
|
+
const abs = join(targetDir, rel);
|
|
153
|
+
if (existsSync(abs) && !overwrite) {
|
|
154
|
+
console.log(` skip: ${rel} (exists)`);
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
const parent = dirname(abs);
|
|
158
|
+
if (!existsSync(parent)) mkdirSync(parent, { recursive: true });
|
|
159
|
+
writeFileSync(abs, content, 'utf8');
|
|
160
|
+
console.log(` create: ${rel}`);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function copy(srcRel, dstRel, { overwrite = FORCE } = {}) {
|
|
164
|
+
const src = join(PKG_ROOT, srcRel);
|
|
165
|
+
const abs = join(targetDir, dstRel);
|
|
166
|
+
if (!existsSync(src)) {
|
|
167
|
+
console.log(` skip: ${dstRel} (template ${srcRel} missing)`);
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
if (existsSync(abs) && !overwrite) {
|
|
171
|
+
console.log(` skip: ${dstRel} (exists)`);
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
const parent = dirname(abs);
|
|
175
|
+
if (!existsSync(parent)) mkdirSync(parent, { recursive: true });
|
|
176
|
+
copyFileSync(src, abs);
|
|
177
|
+
console.log(` create: ${dstRel}`);
|
|
178
|
+
}
|