harness-fleet 0.4.0__tar.gz

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 (126) hide show
  1. harness_fleet-0.4.0/LICENSE +21 -0
  2. harness_fleet-0.4.0/PKG-INFO +591 -0
  3. harness_fleet-0.4.0/README.md +553 -0
  4. harness_fleet-0.4.0/harness_fleet/__init__.py +186 -0
  5. harness_fleet-0.4.0/harness_fleet/bundler.py +257 -0
  6. harness_fleet-0.4.0/harness_fleet/calibrate.py +410 -0
  7. harness_fleet-0.4.0/harness_fleet/candidates.py +147 -0
  8. harness_fleet-0.4.0/harness_fleet/catalog.py +747 -0
  9. harness_fleet-0.4.0/harness_fleet/cli.py +2025 -0
  10. harness_fleet-0.4.0/harness_fleet/dag.py +555 -0
  11. harness_fleet-0.4.0/harness_fleet/data/routes.seed.json +320 -0
  12. harness_fleet-0.4.0/harness_fleet/discover.py +2701 -0
  13. harness_fleet-0.4.0/harness_fleet/engine.py +712 -0
  14. harness_fleet-0.4.0/harness_fleet/eval.py +409 -0
  15. harness_fleet-0.4.0/harness_fleet/export.py +355 -0
  16. harness_fleet-0.4.0/harness_fleet/grounding.py +425 -0
  17. harness_fleet-0.4.0/harness_fleet/input_data.py +539 -0
  18. harness_fleet-0.4.0/harness_fleet/mcp_server.py +445 -0
  19. harness_fleet-0.4.0/harness_fleet/migrations/001_control_plane.sql +151 -0
  20. harness_fleet-0.4.0/harness_fleet/migrations/002_intelligence_and_policy.sql +53 -0
  21. harness_fleet-0.4.0/harness_fleet/migrations/003_profiles.sql +18 -0
  22. harness_fleet-0.4.0/harness_fleet/migrations/004_studio_settings.sql +11 -0
  23. harness_fleet-0.4.0/harness_fleet/models.py +1199 -0
  24. harness_fleet-0.4.0/harness_fleet/packer.py +61 -0
  25. harness_fleet-0.4.0/harness_fleet/partner.py +97 -0
  26. harness_fleet-0.4.0/harness_fleet/profile.py +70 -0
  27. harness_fleet-0.4.0/harness_fleet/providers/antigravity.py +61 -0
  28. harness_fleet-0.4.0/harness_fleet/providers/base.py +115 -0
  29. harness_fleet-0.4.0/harness_fleet/providers/claude.py +60 -0
  30. harness_fleet-0.4.0/harness_fleet/providers/codex.py +126 -0
  31. harness_fleet-0.4.0/harness_fleet/providers/cursor.py +69 -0
  32. harness_fleet-0.4.0/harness_fleet/providers/demo.py +168 -0
  33. harness_fleet-0.4.0/harness_fleet/providers/grok.py +68 -0
  34. harness_fleet-0.4.0/harness_fleet/providers/harness.py +383 -0
  35. harness_fleet-0.4.0/harness_fleet/providers/muse.py +143 -0
  36. harness_fleet-0.4.0/harness_fleet/providers/openai_compatible.py +261 -0
  37. harness_fleet-0.4.0/harness_fleet/providers/opencode.py +175 -0
  38. harness_fleet-0.4.0/harness_fleet/providers/openrouter.py +232 -0
  39. harness_fleet-0.4.0/harness_fleet/providers/registry.py +99 -0
  40. harness_fleet-0.4.0/harness_fleet/resources/account_skill/SKILL.md +208 -0
  41. harness_fleet-0.4.0/harness_fleet/resources/account_skill/references/discovery-playbook.md +168 -0
  42. harness_fleet-0.4.0/harness_fleet/resources/account_skill/references/icp-decomposition.md +62 -0
  43. harness_fleet-0.4.0/harness_fleet/resources/account_skill/references/icp-interview.md +192 -0
  44. harness_fleet-0.4.0/harness_fleet/resources/account_skill/references/mcp-recipes.md +111 -0
  45. harness_fleet-0.4.0/harness_fleet/resources/account_skill/references/scoring-rubric-guide.md +107 -0
  46. harness_fleet-0.4.0/harness_fleet/resources/examples/account_research/sample_accounts.csv +11 -0
  47. harness_fleet-0.4.0/harness_fleet/resources/examples/account_research/task.json +35 -0
  48. harness_fleet-0.4.0/harness_fleet/resources/harness_skill/SKILL.md +57 -0
  49. harness_fleet-0.4.0/harness_fleet/resources/harness_skill/agents/openai.yaml +6 -0
  50. harness_fleet-0.4.0/harness_fleet/resources/harness_skill/references/operations.md +190 -0
  51. harness_fleet-0.4.0/harness_fleet/resources/harness_skill/references/task-contracts.md +72 -0
  52. harness_fleet-0.4.0/harness_fleet/resources/partner_skill/SKILL.md +215 -0
  53. harness_fleet-0.4.0/harness_fleet/resources/partner_skill/references/discovery-playbook.md +116 -0
  54. harness_fleet-0.4.0/harness_fleet/resources/partner_skill/references/ipp-decomposition.md +60 -0
  55. harness_fleet-0.4.0/harness_fleet/resources/partner_skill/references/ipp-interview.md +148 -0
  56. harness_fleet-0.4.0/harness_fleet/resources/partner_skill/references/mcp-recipes.md +77 -0
  57. harness_fleet-0.4.0/harness_fleet/resources/partner_skill/references/scoring-rubric-guide.md +110 -0
  58. harness_fleet-0.4.0/harness_fleet/resources/studio/index.html +320 -0
  59. harness_fleet-0.4.0/harness_fleet/scoring.py +251 -0
  60. harness_fleet-0.4.0/harness_fleet/sessions.py +106 -0
  61. harness_fleet-0.4.0/harness_fleet/setup.py +231 -0
  62. harness_fleet-0.4.0/harness_fleet/slicer.py +83 -0
  63. harness_fleet-0.4.0/harness_fleet/store.py +1863 -0
  64. harness_fleet-0.4.0/harness_fleet/studio.py +475 -0
  65. harness_fleet-0.4.0/harness_fleet/task.py +640 -0
  66. harness_fleet-0.4.0/harness_fleet/ui.py +118 -0
  67. harness_fleet-0.4.0/harness_fleet.egg-info/PKG-INFO +591 -0
  68. harness_fleet-0.4.0/harness_fleet.egg-info/SOURCES.txt +124 -0
  69. harness_fleet-0.4.0/harness_fleet.egg-info/dependency_links.txt +1 -0
  70. harness_fleet-0.4.0/harness_fleet.egg-info/entry_points.txt +2 -0
  71. harness_fleet-0.4.0/harness_fleet.egg-info/requires.txt +16 -0
  72. harness_fleet-0.4.0/harness_fleet.egg-info/top_level.txt +1 -0
  73. harness_fleet-0.4.0/pyproject.toml +108 -0
  74. harness_fleet-0.4.0/schemas/candidate-output-v1.schema.json +123 -0
  75. harness_fleet-0.4.0/schemas/input-item-v1.schema.json +77 -0
  76. harness_fleet-0.4.0/schemas/output-v2.schema.json +148 -0
  77. harness_fleet-0.4.0/schemas/packet-v2.schema.json +738 -0
  78. harness_fleet-0.4.0/schemas/task-v1.schema.json +139 -0
  79. harness_fleet-0.4.0/setup.cfg +4 -0
  80. harness_fleet-0.4.0/tests/test_antigravity.py +69 -0
  81. harness_fleet-0.4.0/tests/test_audit_fixes.py +1177 -0
  82. harness_fleet-0.4.0/tests/test_calibrate.py +270 -0
  83. harness_fleet-0.4.0/tests/test_catalog.py +290 -0
  84. harness_fleet-0.4.0/tests/test_claude.py +69 -0
  85. harness_fleet-0.4.0/tests/test_cli.py +427 -0
  86. harness_fleet-0.4.0/tests/test_codex.py +108 -0
  87. harness_fleet-0.4.0/tests/test_cooldowns.py +164 -0
  88. harness_fleet-0.4.0/tests/test_csv_io.py +258 -0
  89. harness_fleet-0.4.0/tests/test_cursor.py +71 -0
  90. harness_fleet-0.4.0/tests/test_dag.py +351 -0
  91. harness_fleet-0.4.0/tests/test_deterministic_filters.py +410 -0
  92. harness_fleet-0.4.0/tests/test_discover.py +1649 -0
  93. harness_fleet-0.4.0/tests/test_engine.py +272 -0
  94. harness_fleet-0.4.0/tests/test_eval.py +108 -0
  95. harness_fleet-0.4.0/tests/test_grok.py +73 -0
  96. harness_fleet-0.4.0/tests/test_grounding.py +144 -0
  97. harness_fleet-0.4.0/tests/test_harness.py +188 -0
  98. harness_fleet-0.4.0/tests/test_harness_live.py +56 -0
  99. harness_fleet-0.4.0/tests/test_harness_registry.py +394 -0
  100. harness_fleet-0.4.0/tests/test_input_data.py +29 -0
  101. harness_fleet-0.4.0/tests/test_mcp_server.py +252 -0
  102. harness_fleet-0.4.0/tests/test_mechanical_calibration.py +710 -0
  103. harness_fleet-0.4.0/tests/test_models.py +104 -0
  104. harness_fleet-0.4.0/tests/test_muse.py +127 -0
  105. harness_fleet-0.4.0/tests/test_offerings.py +367 -0
  106. harness_fleet-0.4.0/tests/test_openai_compatible.py +141 -0
  107. harness_fleet-0.4.0/tests/test_opencode.py +45 -0
  108. harness_fleet-0.4.0/tests/test_openrouter.py +95 -0
  109. harness_fleet-0.4.0/tests/test_openrouter_policy.py +73 -0
  110. harness_fleet-0.4.0/tests/test_packer.py +24 -0
  111. harness_fleet-0.4.0/tests/test_partner_research.py +168 -0
  112. harness_fleet-0.4.0/tests/test_portability.py +207 -0
  113. harness_fleet-0.4.0/tests/test_published_schemas.py +31 -0
  114. harness_fleet-0.4.0/tests/test_rate_limits.py +116 -0
  115. harness_fleet-0.4.0/tests/test_retry_accounting.py +41 -0
  116. harness_fleet-0.4.0/tests/test_route_policy_contract.py +151 -0
  117. harness_fleet-0.4.0/tests/test_safety_fixes.py +79 -0
  118. harness_fleet-0.4.0/tests/test_scoring.py +71 -0
  119. harness_fleet-0.4.0/tests/test_scoring_integrity.py +83 -0
  120. harness_fleet-0.4.0/tests/test_sessions.py +33 -0
  121. harness_fleet-0.4.0/tests/test_setup.py +168 -0
  122. harness_fleet-0.4.0/tests/test_slicer.py +43 -0
  123. harness_fleet-0.4.0/tests/test_status.py +84 -0
  124. harness_fleet-0.4.0/tests/test_store.py +309 -0
  125. harness_fleet-0.4.0/tests/test_streaming.py +94 -0
  126. harness_fleet-0.4.0/tests/test_studio.py +499 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 NatesVibeCode contributors
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.
@@ -0,0 +1,591 @@
1
+ Metadata-Version: 2.4
2
+ Name: harness-fleet
3
+ Version: 0.4.0
4
+ Summary: Coordinate any CLI-harness worker fleet with closed fields and exact quote verification.
5
+ Author: NatesVibeCode
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/NatesVibeCode/harness-fleet
8
+ Project-URL: Repository, https://github.com/NatesVibeCode/harness-fleet
9
+ Project-URL: Issues, https://github.com/NatesVibeCode/harness-fleet/issues
10
+ Project-URL: Security, https://github.com/NatesVibeCode/harness-fleet/security/policy
11
+ Keywords: mcp,agent-skills,sqlite,structured-output,evidence-grounding,prospecting,account-research
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Environment :: Console
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Programming Language :: Python :: 3.14
20
+ Classifier: Topic :: Scientific/Engineering :: Information Analysis
21
+ Requires-Python: >=3.10
22
+ Description-Content-Type: text/markdown
23
+ License-File: LICENSE
24
+ Requires-Dist: pydantic>=2.0.0
25
+ Requires-Dist: jsonschema>=4.20.0
26
+ Requires-Dist: httpx>=0.24.0
27
+ Requires-Dist: mcp<2,>=1.26.0
28
+ Provides-Extra: dev
29
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
30
+ Provides-Extra: discover
31
+ Requires-Dist: ddgs>=8.0; extra == "discover"
32
+ Requires-Dist: readability-lxml>=0.8; extra == "discover"
33
+ Requires-Dist: trafilatura>=1.0; extra == "discover"
34
+ Requires-Dist: pypdf>=4.0; extra == "discover"
35
+ Provides-Extra: js
36
+ Requires-Dist: playwright>=1.40; extra == "js"
37
+ Dynamic: license-file
38
+
39
+ # harness-fleet
40
+
41
+ [![CI](https://github.com/NatesVibeCode/harness-fleet/actions/workflows/ci.yml/badge.svg)](https://github.com/NatesVibeCode/harness-fleet/actions/workflows/ci.yml)
42
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
43
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue.svg)](pyproject.toml)
44
+
45
+ > **Run repeatable, evidence-grounded LLM batch jobs over free and local models. Every claim is typed, and every quote is checked against the source at exact character offsets. Scores and interpretations still need human review.**
46
+
47
+ Harness Fleet turns a pile of text into answers you can check. You describe the job — *score these accounts*, *pull the pricing out of these pages*, *flag the ones that matter* — and it returns a typed result for every record with the exact sentence it relied on. It runs on free or local AI models by default, keeps all state in a local file, and ships the assistant playbooks for every fleet product, so one install gives your AI client the account, partner, and career skills too.
48
+
49
+ *Canonical CLI is `harness-fleet`. The account-fleet and career-fleet distributions ship their own entry points from their own checkouts — install one fleet per environment.*
50
+
51
+ **New here?** [One-click install](#one-click-install) → [60-second demo](#quickstart--60-second-demo-no-api-keys) → [which fleet do I want?](#which-fleet-do-i-want)
52
+
53
+ ## Start here (no coding needed)
54
+
55
+ 1. **Install.** macOS/Linux: `./install.sh` · Windows: `powershell -ExecutionPolicy Bypass -File install.ps1`
56
+ It makes its own private Python environment, sets up a workspace, and connects Claude Desktop or Cursor for you.
57
+
58
+ Prefer a terminal one-liner to the installer? This puts the CLI on your PATH without cloning anything:
59
+ ```bash
60
+ uv tool install "git+https://github.com/NatesVibeCode/harness-fleet"
61
+ # or, without uv: python3 -m pip install "git+https://github.com/NatesVibeCode/harness-fleet"
62
+ ```
63
+ 2. **Watch it work.** The installer finishes by scoring a set of example records with a built-in fake model — no accounts, no API keys, no cost — and tells you where the results landed.
64
+ 3. **Get free model access** — about two minutes, no credit card needed: **[FREE-ACCESS.md](FREE-ACCESS.md)**. Until one of those is connected there is nothing for a real run to use.
65
+ 4. **Ask your assistant.** Restart Claude Desktop (or Cursor) and describe the job in plain words, e.g. *"score these 200 accounts and show me the strongest 25 with quotes."* The bundled skill picks the right commands.
66
+
67
+ Rather click than type? `harness-fleet studio` opens a local page for choosing which AI tools and models your runs are allowed to use.
68
+
69
+ ## Which fleet do I want?
70
+
71
+ Every distribution shares one engine — typed claims, SQLite checkpoints, and character-exact quote verification — and ships the assistant skills below. Install one per environment.
72
+
73
+ | If you want to… | Install | CLI | Skill that drives it |
74
+ | --- | --- | --- | --- |
75
+ | Score, classify, extract, or triage **your own** text at volume | **harness-fleet** ← you are here | `harness-fleet` | `harness-fleet` |
76
+ | Turn an ICP into **scored target accounts** | [account-fleet](https://github.com/NatesVibeCode/account-fleet) | `account-fleet` | `account-fleet` |
77
+ | Find and rank **employers and job postings** | [career-fleet](https://github.com/NatesVibeCode/career-fleet) | `career-fleet` | `career-fleet` |
78
+ | Find **implementation partners and SIs** | harness-fleet, preset `partner-research` | `harness-fleet` | `partner-fleet` |
79
+
80
+ Skills are installed into your workspace by `harness-fleet setup` — see [Assistant skills](#assistant-skills-what-installs-where).
81
+
82
+ ## Contents
83
+
84
+ - [Which fleet do I want?](#which-fleet-do-i-want)
85
+ - [One-click install](#one-click-install) · [Quickstart — 60-second demo](#quickstart--60-second-demo-no-api-keys)
86
+ - [30-Second Example: raw accounts in → scored, grounded CSV out](#30-second-example-raw-accounts-in--scored-grounded-csv-out)
87
+ - [Why you can trust the output](#why-you-can-trust-the-output) · [Core capabilities](#core-capabilities) · [Source quality](#source-quality)
88
+ - [SQLite control plane](#sqlite-control-plane) · [Commands](#commands) · [Assistant skills](#assistant-skills-what-installs-where)
89
+ - [MCP server](#mcp-server) · [Harness studio (local UI)](#harness-studio-local-ui)
90
+ - [Migrating from free-fleet](#migrating-from-free-fleet) · [Verification & testing](#verification--testing)
91
+
92
+ ## Migrating from free-fleet
93
+
94
+ Version 0.3.0 renames the `free-fleet` distribution to `harness-fleet` (the old `bulk-lanes` name is gone). Back up your database first, then:
95
+
96
+ ```bash
97
+ free-fleet db backup free-fleet.db.bak # back up with the OLD CLI first (SQLite backup API, WAL-safe)
98
+ mv free-fleet.db harness-fleet.db
99
+ harness-fleet setup --workspace-root . # re-installs the skill
100
+ harness-fleet mcp install # re-installs client configs
101
+ ```
102
+
103
+ Old packets (`free_fleet_v2` / `bulk_lanes_v2`) no longer read; re-export them from SQLite before upgrading. The `FREE_FLEET_DB` / `BULK_LANES_DB` / `ACCOUNT_FLEET_DB` variables are replaced by the single `HARNESS_FLEET_DB`. There is no downgrade path — restore your backup to go back.
104
+
105
+ Python 3.10+ is required. This is a command-line tool with an optional AI-assistant integration. It scores source text you supply; the CLI does not browse for companies or fetch job postings automatically. The bundled account-fleet skill guides a connected assistant through that research.
106
+
107
+ Install and try the offline demo below before running a real list. Real research requires a configured model provider and your own qualification criteria.
108
+
109
+ ---
110
+
111
+ ## 30-Second Example: Raw Accounts In → Scored, Grounded CSV Out
112
+
113
+ Suppose you have a list of target companies in `accounts.csv`:
114
+
115
+ ```csv
116
+ company,careers_text
117
+ stripe.com,"We are hiring a Staff Engineer to lead migration off legacy v1 billing pipeline to Kafka..."
118
+ hyper_ai,"Looking for Senior Backend Engineer hitting latency limits at 50k QPS on Postgres cluster..."
119
+ pinecone.io,"Hiring Infrastructure Engineer scaling vector search across multi-tenant clusters..."
120
+ ```
121
+
122
+ ### 1. Initialize the account research preset and run
123
+
124
+ ```bash
125
+ # Initialize the typed account-research preset (evidence checklist, identified_gap; score/fit_tier derived)
126
+ harness-fleet init research-demo --preset account-research
127
+
128
+ # Process the accounts through free model routes (zero API spend)
129
+ harness-fleet run research-demo --input accounts.csv --id-column company --text-column careers_text --run-id campaign-01
130
+ ```
131
+
132
+ ### 2. Export the top 25 ranked accounts
133
+
134
+ ```bash
135
+ harness-fleet export campaign-01 --format csv --sort-by score --desc --top 25 --rank --output ranked_accounts.csv
136
+ ```
137
+
138
+ ### 3. Output (`ranked_accounts.csv`)
139
+
140
+ ```csv
141
+ rank,item_id,score,identified_gap,fit_tier,primary_quote_text
142
+ 1,stripe.com,92,"Legacy billing migration",tier_1,"lead migration off legacy v1 billing pipeline to Kafka"
143
+ ```
144
+
145
+ Illustrative values only; real exports also include source URLs, digests, and quote details. Set your ICP and scoring rubric in the task's `TaskSpec` — a preset plus a task JSON file, edited by hand or by your AI client using the bundled skill. An exact source quote proves the text exists, not that a company will buy your product.
146
+
147
+ ---
148
+
149
+ ## Why You Can Trust the Output
150
+
151
+ Every output row is gated through deterministic checks *before* it is committed to SQLite. If any check fails, the batch rotates to the next route — nothing unverified is exported.
152
+
153
+ 1. **Deterministic Quote Verification**: Cited quotes are checked against the raw source text at character-level precision and resolved to canonical `[start, end]` offsets. Sections with evidence terms also expose numbered candidate spans the worker cites by id instead of free-searching; verification recomputes the same span table, so offsets are code-owned. Fabricated or altered quotes fail grounding and trigger immediate route rotation. *(This proves all cited quotes are verbatim source substrings; whether a claim is truly entailed by its quote remains model-generated.)*
154
+ 2. **Closed JSON Schemas**: Outputs adhere strictly to closed JSON Schemas defined in `TaskSpec`. Models cannot add fields, emit markdown, or drift out of schema.
155
+ 3. **Derived Scores and Tiers, Not Double Judgment**: Scoring tasks collect an evidence-bound `checklist` of true/false answers, and the pipeline computes `score` (summed points, capped at 100), `fit_tier` (85+ → `tier_1`, 70+ → `tier_2`, 50+ → `tier_3`, else `unfit`), and `passed`. A mismatched derived value fails validation and rotates routes.
156
+ 4. **Weighted, Time-Decayed Evidence**: Every true answer needs a supporting quote tagged with `supports`, and each answer scores its points scaled by source weight (configurable per-domain rules, longest match wins) and recency decay (per-item half-lives — hiring signals stale in weeks, company fundamentals in months). Untagged truth scores zero, so weak evidence can only lower a score, never inflate one.
157
+ 5. **Intelligent Route Scoring**: Bayesian-smoothed scoring by verification rate, grounding accuracy, malformed-JSON rate, and latency — not round-robin. Best routes are tried first.
158
+ 6. **Non-Destructive Rate-Limit Handling**: On `429` or `5xx`, the route is cooled down and the batch is retried immediately on the next lane with **0 attempt burn**.
159
+ 7. **Rescore Lineage, Not Overwrites**: Fresh evidence arrives as new runs linked by `parent_run_id`; every verified record lands in `score_history`, and `harness-fleet history ENTITY` shows the score trajectory across rounds. Old scores are never rewritten — a stale 40 stays visible next to the new 85 and the evidence that moved it.
160
+ 8. **Zero-Price Circuit Breaker & Spend Ceilings**: For zero-price runs, pricing is observed from provider receipts; a non-zero charge trips the breaker and disables the route. For paid runs, `--max-request-cost` enforces per-request caps. Cost ceilings fail closed on undeclared pricing.
161
+
162
+ > **Live proof:** `harness-fleet status <run_id> --watch` streams batch progress and per-route `Verified / Rate limits / Latency`. Fabricated quotes show up instantly as `grounding_failed` and the next lane is tried.
163
+
164
+ ---
165
+
166
+ ## One-click install
167
+
168
+ From a fresh checkout, one command sets up everything — no virtual environments or pip to
169
+ worry about.
170
+
171
+ macOS / Linux:
172
+
173
+ ```bash
174
+ ./install.sh
175
+ ```
176
+
177
+ Windows (PowerShell):
178
+
179
+ ```powershell
180
+ powershell -ExecutionPolicy Bypass -File install.ps1
181
+ ```
182
+
183
+ That one command:
184
+
185
+ - Creates a private Python 3.10+ environment (`.venv`) and installs `harness-fleet` into it.
186
+ - Sets up a workspace at `~/harness-fleet-workspace` and runs the offline demo there.
187
+ - Registers the `harness-fleet` MCP tools with Claude Desktop (or Cursor).
188
+ - If `OPENROUTER_API_KEY` is set in your shell, passes it into that client config too (values are never printed), so OpenRouter routes work from the desktop app.
189
+
190
+ Pass a different workspace folder if you want one, e.g. `./install.sh ~/my-harness-workspace`.
191
+ Restart Claude Desktop (or Cursor) after it finishes.
192
+
193
+ ---
194
+
195
+ ## Quickstart — 60-Second Demo (No API Keys)
196
+
197
+ ```bash
198
+ git clone https://github.com/NatesVibeCode/harness-fleet.git
199
+ cd harness-fleet
200
+ python3 -m venv .venv
201
+ source .venv/bin/activate
202
+ python -m pip install .
203
+
204
+ # Run in your own workspace; output files are written in the current directory.
205
+ mkdir my-workspace
206
+ cd my-workspace
207
+ harness-fleet setup
208
+ harness-fleet quickstart --demo --run-id demo-01
209
+
210
+ # Outputs:
211
+ # runs/demo-01/clean_packet.json (self-validating packet)
212
+ # runs/demo-01/clean_packet.csv (flat CSV)
213
+ ```
214
+
215
+ On Windows PowerShell, replace the two virtual-environment commands with `py -m venv .venv` and `.venv\Scripts\Activate.ps1`. If activation is restricted, run `..\.venv\Scripts\harness-fleet.exe` directly from `my-workspace`.
216
+
217
+ The demo uses synthetic scores for ten bundled sample accounts and makes no model API calls. It verifies installation and export, not research quality. Demo routes are excluded from real campaigns unless explicitly selected.
218
+
219
+ ### Real Workspace
220
+
221
+ ```bash
222
+ mkdir my-workspace && cd my-workspace
223
+ harness-fleet setup --workspace-root . --refresh-routes
224
+ ```
225
+
226
+ For a real run, configure one of the seven CLI harnesses (`opencode`, `claude`, `codex`, `cursor`, `grok`, `muse`, `antigravity`) with your own provider access, set `OPENROUTER_API_KEY`, or register a running local model, for example `harness-fleet routes add ollama/your-installed-model --provider ollama --free`. Refreshing routes alone does not authenticate you. `harness-fleet doctor` checks configuration; `harness-fleet test research-demo --input accounts.csv --id-column company --text-column careers_text --provider ollama` tests a real batch before a large campaign.
227
+
228
+ Each named provider uses its own settings: `OLLAMA_BASE_URL`, `LMSTUDIO_BASE_URL`, `GROQ_API_KEY`, and so on. `OPENAI_COMPATIBLE_BASE_URL` and `OPENAI_COMPATIBLE_API_KEY` configure only `--provider openai_compatible`. Environment variables must be available to the process running the CLI or MCP server; `.env` files are not loaded automatically.
229
+
230
+ `setup` installs both the account-fleet research skill and the harness-fleet execution skill in the workspace's `.agents/skills` directory. Keep the virtual environment in place when using the generated MCP configuration. Install account-fleet and harness-fleet in separate environments: they share the `harness_fleet` Python package and entry-point names, so one fleet per environment.
231
+
232
+ ### Presets
233
+
234
+ Create typed tasks instantly with built-in presets:
235
+
236
+ ```bash
237
+ harness-fleet init score-demo --preset score # Evidence checklist + pipeline-derived 0-100 score
238
+ harness-fleet init filter-demo --preset filter # Boolean qualification pass/fail gate
239
+ harness-fleet init account-demo --preset account-research # Evidence checklist + derived ICP score/tier + gap extraction
240
+ harness-fleet init triage-demo --preset triage # Priority (high/medium/low) + reason
241
+ harness-fleet init classify-demo --preset classify # Categorical labels + summary
242
+ harness-fleet init extract-demo --preset extract # Named entities + summary
243
+ harness-fleet init summarize-demo --preset summarize # Supported fact summaries
244
+ ```
245
+
246
+ Validate and test before launching large runs:
247
+
248
+ ```bash
249
+ # Validate task spec and input without making any API calls
250
+ harness-fleet validate score-demo --input input.jsonl
251
+
252
+ # Test a single real batch
253
+ harness-fleet test score-demo --input input.jsonl
254
+ ```
255
+
256
+ ---
257
+
258
+ ## Examples
259
+
260
+ Runnable starting points live in [`examples/`](examples/) — each folder has a `README.md`, a typed `task.json`, and sample input you can feed straight to `run`:
261
+
262
+ | Example | Preset | Sample input |
263
+ | --- | --- | --- |
264
+ | [`examples/account_research/`](examples/account_research/) | `account-research` | `sample_accounts.csv` |
265
+ | [`examples/partner_research/`](examples/partner_research/) | `partner-research` | `sample_partners.csv`, `sample_partners_multisource.csv` |
266
+ | [`examples/saas_intelligence/`](examples/saas_intelligence/) | `score` | `sample_data.jsonl` |
267
+ | [`examples/security_cve_triage/`](examples/security_cve_triage/) | `triage` | `sample_data.jsonl` |
268
+
269
+ ```bash
270
+ harness-fleet init my-task --preset partner-research --db ./harness-fleet.db
271
+ harness-fleet validate my-task --db ./harness-fleet.db \
272
+ --input examples/partner_research/sample_partners.csv \
273
+ --id-column domain --text-column research --json
274
+ ```
275
+
276
+ ## Core Capabilities
277
+
278
+ ### 1. CSV In / Scored, Ranked CSV Out
279
+ Directly process tabular data and export sorted, ranked deliverables with exact source quotes:
280
+
281
+ ```bash
282
+ # Run on CSV specifying ID and text columns (or let harness-fleet auto-detect them)
283
+ harness-fleet run score-demo --input accounts.csv --run-id accts-01
284
+
285
+ # Export ranked deliverable: sorted by score descending, top 25, with 1-indexed rank column
286
+ harness-fleet export accts-01 --format csv --sort-by score --desc --top 25 --rank --output ranked_target_accounts.csv
287
+ ```
288
+
289
+ ### 2. The Compounding Filter (Chaining Layers)
290
+ Run multi-stage funnel filtering without running monolithic prompts or wasting model compute:
291
+
292
+ ```bash
293
+ # Layer 1: Filter down to survivors
294
+ harness-fleet run l1-task --input 1000_candidates.csv --run-id l1
295
+ harness-fleet export l1 --format csv --filter '{"all": [{"field": "passed", "value": true}]}' --output l1_survivors.csv
296
+
297
+ # Layer 2: Only run on survivor IDs from Layer 1
298
+ harness-fleet run l2-task --input tech_docs.csv --only-ids l1_survivors.csv --run-id l2
299
+ harness-fleet export l2 --format csv --filter '{"all": [{"field": "passed", "value": true}]}' --output l2_survivors.csv
300
+
301
+ # Final Layer: Score survivors and rank top candidates
302
+ harness-fleet run l3-task --input gap_analysis.csv --only-ids l2_survivors.csv --run-id l3
303
+ harness-fleet export l3 --format csv --sort-by score --desc --top 25 --rank --output ranked_deliverable.csv
304
+ ```
305
+
306
+ Filters compose deterministically at export — a ClaimFilter document with `all`
307
+ clauses (AND), `any` branches (OR), and ops `==, !=, >=, <=, >, <, in, not_in`:
308
+
309
+ ```bash
310
+ harness-fleet export l3 --format csv \
311
+ --filter '{"all": [{"field": "score", "op": ">=", "value": 70}, {"field": "passed", "value": true}]}' \
312
+ --output qualified.csv
313
+ ```
314
+
315
+ Discovery pre-filters mechanically too:
316
+ `fetch --title-include engineer --title-exclude manager --exclude-stack mainframe --min-chars 200`.
317
+
318
+ ### 2b. DAG Workflows (multi-stage funnels without CSV round-trips)
319
+ Each workflow is a DAG of typed nodes — `run` (one Engine campaign = one SQLite run),
320
+ `filter` (deterministic ID sets from a run snapshot), `export` (packet/CSV). Edges carry
321
+ IDs and run references in-process, so funnels keep full drill-through (offsets, digests)
322
+ at every hop instead of degrading through CSV files:
323
+
324
+ ```json
325
+ {
326
+ "name": "funnel",
327
+ "nodes": [
328
+ {"kind": "run", "id": "l1", "task": "filter-task", "input": "candidates.csv",
329
+ "policy": {"allowed_routes": ["demo/fake"], "free_only": true}},
330
+ {"kind": "filter", "id": "l1f", "from_run": "l1",
331
+ "filter": {"all": [{"field": "passed", "value": true}]}, "top": 50},
332
+ {"kind": "run", "id": "l2", "task": "score-task", "input": "docs.csv", "ids_from": ["l1f"]},
333
+ {"kind": "export", "id": "out", "from_run": "l2", "format": "csv",
334
+ "sort": {"field": "score"}, "top": 25, "rank": true}
335
+ ]
336
+ }
337
+ ```
338
+
339
+ ```bash
340
+ harness-fleet dag --spec funnel.json --dry-run --json # validate + print order
341
+ harness-fleet dag --spec funnel.json --dag-id campaign-01 --json
342
+ ```
343
+
344
+ Node run IDs are deterministic (`<dag-id>-<node-id>`), so re-running resumes completed
345
+ `run` nodes from SQLite while `filter`/`export` re-execute. Lineage (spec digest, run IDs,
346
+ counts, artifacts) lands in `runs/<dag-id>/dag.json`. Cycles, unknown references, and
347
+ wrong-kind edges fail closed at parse time.
348
+
349
+ ### 3. Live Run Monitoring
350
+ Track queue progress, worker concurrency, and route-level metrics in real time:
351
+
352
+ ```bash
353
+ harness-fleet status <run_id> --watch
354
+ ```
355
+
356
+ Output:
357
+ ```
358
+ ============================================================
359
+ Run: triage-01 | Task: customer-triage | Status: RUNNING
360
+ Progress: [=========================> ] 62.5% (650/1040)
361
+ ============================================================
362
+ Batches:
363
+ Pending: 15
364
+ Leased: 4
365
+ Done: 65
366
+ Failed: 0
367
+
368
+ Route Performance:
369
+ openrouter:qwen/qwen-2.5-72b-instruct:free
370
+ Attempts: 45 | Verified: 44 | Rate limits: 1 | Latency: 1.2s
371
+ openrouter:meta-llama/llama-3.3-70b-instruct:free
372
+ Attempts: 24 | Verified: 23 | Rate limits: 0 | Latency: 1.8s
373
+ ```
374
+
375
+ ### 3. Continuous Route Evaluation
376
+ Benchmark available routes against test datasets to determine which models excel at your specific task:
377
+
378
+ ```bash
379
+ harness-fleet eval customer-triage --input test-samples.csv --id-column id --text-column comment
380
+ ```
381
+
382
+ Output:
383
+ ```
384
+ ========================================================================================
385
+ Route Evaluation Benchmark
386
+ Task: customer-triage | Samples: 20
387
+ ========================================================================================
388
+ Route Success Grounding Score Avg Latency
389
+ ----------------------------------------------------------------------------------------
390
+ openrouter:qwen/qwen-2.5-72b-instruct:free 100.0% 100.0% 0.982 1.15s
391
+ openrouter:meta-llama/llama-3.3-70b-free 95.0% 90.0% 0.871 1.82s
392
+ opencode:llama3 80.0% 85.0% 0.742 2.40s
393
+ ```
394
+ Evaluation benchmarks automatically update route selection priors for subsequent runs.
395
+
396
+ ### 4. Local Models & Generic OpenAI-Compatible Providers
397
+ Run bulk workloads completely locally with **Ollama**, **LM Studio**, **vLLM**, or fast cloud inference providers like **Groq** and **Cerebras**:
398
+
399
+ ```bash
400
+ # Register your local or custom route in the catalog
401
+ harness-fleet routes add ollama/llama3.2:latest --provider ollama --free
402
+
403
+ # Or configure environment variables
404
+ export OPENAI_COMPATIBLE_BASE_URL="http://localhost:11434/v1"
405
+ export OPENAI_COMPATIBLE_API_KEY="ollama"
406
+ export OPENAI_COMPATIBLE_MODEL="llama3.2:latest"
407
+
408
+ # Run with local provider selection
409
+ harness-fleet run my-task --input data.csv --id-column id --text-column text --provider ollama
410
+ ```
411
+
412
+ Endpoints on `localhost` or `127.0.0.1` are automatically marked free (`cost = 0.0`). For third-party cloud OpenAI-compatible endpoints, specify costs explicitly (`--input-cost` / `--output-cost`) or leave them as unknown-cost to prevent accidental misclassification.
413
+
414
+ ### 5. Explicit Data & Privacy Policy
415
+ Enforce zero data retention (ZDR), prohibit provider data collection, limit request spend, and control upstream routing on a per-run basis:
416
+
417
+ ```bash
418
+ harness-fleet run my-task \
419
+ --input sensitive-data.jsonl \
420
+ --zdr \
421
+ --no-data-collection \
422
+ --provider openrouter \
423
+ --exclude-provider opencode \
424
+ --openrouter-providers Anthropic,Together \
425
+ --max-request-cost 0.05
426
+ ```
427
+
428
+ You can pass `--openrouter-providers` as a comma-separated list or as repeatable `--openrouter-provider` flags.
429
+
430
+ ---
431
+
432
+ ## Source Quality
433
+
434
+ Mechanical `discover` and `fetch` runs enforce a default 70% source-capture
435
+ floor and report backend/query provenance for fetched records. Use `--json`
436
+ for the `source_quality` report; lower the floor with
437
+ `--min-source-coverage 0` only for an intentional sparse-source audit.
438
+
439
+ ## SQLite Control Plane
440
+
441
+ `harness-fleet` uses SQLite in WAL mode with `BEGIN IMMEDIATE` atomic leases. If a worker crashes or a laptop closes, the run can be resumed seamlessly:
442
+
443
+ ```bash
444
+ harness-fleet resume <run_id>
445
+ ```
446
+
447
+ Free routes are used by default. A paid route approved in an earlier session must be requested again with `--route <route-id>`.
448
+
449
+ - **Resumable**: Batches are committed upon verification. Completed work is never repeated.
450
+ - **Fault-Tolerant**: Stale worker leases are automatically recovered after timeout.
451
+ - **Concurrent**: Multiple worker processes can safely lease batches simultaneously without collisions.
452
+ - **Auditable**: Every attempt, model receipt, cost observation, and verification failure is recorded immutably in `inference_attempts`.
453
+
454
+ ---
455
+
456
+ ## Commands
457
+
458
+ | Command | Purpose |
459
+ |---|---|
460
+ | `quickstart` | One-command offline demo (no keys) that writes a verified packet + CSV |
461
+ | `setup` | Bootstrap a portable workspace with bundled skills and SQLite database |
462
+ | `doctor` | Check SQLite, installed CLIs, provider authentication, and available routes |
463
+ | `routes` | List or refresh discovered model routes (`--refresh`) |
464
+ | `routes add` | Register an explicit custom or local model route (`--free`, `--input-cost`) |
465
+ | `cooldowns` | Inspect active rate-limit route cooldowns or clear them (`--clear`, `--route`) |
466
+ | `tasks` | List registered task definitions |
467
+ | `init` | Create a typed task from a preset (`score`, `filter`, `account-research`, `triage`, `classify`, `extract`, `summarize`) |
468
+ | `profile` | Manage the typed Ideal Company Profile (`--init`, `--path`, `--force`) that research presets score against |
469
+ | `init --from-example` | Infer a draft `claims_schema` from a labeled CSV (`--from-example labels.csv --label-column label`) |
470
+ | `validate` | Check task schema and input formatting without inference (`--only-ids`) |
471
+ | `test` | Run one real batch through candidate models |
472
+ | `run` | Create and execute a SQLite-backed resumable run (`--only-ids` for compounding filter) |
473
+ | `resume` | Resume an unfinished run from its SQLite queue |
474
+ | `rescore` | Re-score an existing run's records against a new input round (`--input`, `--run-id`) |
475
+ | `dag` | Run a multi-stage workflow from a DAG spec (`--spec`, `--dry-run`) instead of chaining CSV rounds |
476
+ | `status` | Show real-time progress, attempts, and route stats (`--watch`, `--json`) |
477
+ | `eval` | Benchmark routes on sample inputs and update route ranking priors (`--concurrency`) |
478
+ | `calibrate` | Fit scoring points/weights/half-lives against labeled samples (`--apply` to register the revision) |
479
+ | `sessions` | Inspect recorded worker sessions and audit logs |
480
+ | `history` | Score trajectory for one entity across runs (`history ENTITY`) |
481
+ | `export` | Export a validated packet (`--format json\|csv\|jsonl`, `--sort-by`, `--desc`, `--top`, `--rank`, `--filter`) |
482
+ | `db backup` | SQLite backup to file (safe while running) |
483
+ | `schema` | Print admitted JSON Schemas or database contracts |
484
+ | `mcp install` | One-command Claude/Cursor setup (auto-wires `claude_desktop_config.json` / `mcp.json`; `--env NAME` copies a shell variable, e.g. `OPENROUTER_API_KEY`, into the client config) |
485
+ | `serve` | Run the Model Context Protocol (MCP) server over stdio |
486
+ | `settings` | Print, or `--clear`, the harness/model selection the studio saved (`run --from-studio` uses it) |
487
+ | `studio` | Serve the localhost settings companion (pick harnesses and models; saves the selection to SQLite) |
488
+ | `discover` | Broad web search (`ddgs`, self-hosted SearXNG, HN Algolia, YC, Reddit, Stack Exchange, Discourse, Lobsters, Lemmy, Dev.to) to an accounts file |
489
+ | `fetch` | Fetch URLs, sitemaps, site crawls, ATS boards (Greenhouse/Ashby/Lever), YC profiles, HN/Reddit threads, or Q&A forums to an accounts file |
490
+
491
+ Pass `--json` to any command for machine-readable JSON output. `--free-only` is the explicit zero-cost filter (replaces implicit `max-cost=0` sentinel). Long documents are warned when truncated (`partial` slices).
492
+
493
+
494
+ ---
495
+
496
+ ## Assistant skills (what installs where)
497
+
498
+ Skills are the playbooks your AI client reads to drive this CLI. `harness-fleet setup` installs every skill this distribution bundles into `<workspace>/.agents/skills/`, so a connected assistant finds them without you copying anything:
499
+
500
+ | Skill | Installed as | Drives |
501
+ | --- | --- | --- |
502
+ | `harness-fleet` | `.agents/skills/harness-fleet/` | This CLI: task contracts, runs, export, MCP, troubleshooting |
503
+ | `account-fleet` | `.agents/skills/account-fleet/` | `--preset account-research`: an ICP in, scored target accounts out |
504
+ | `partner-fleet` | `.agents/skills/partner-fleet/` | `--preset partner-research`: ecosystem requirements in, scored implementation partners out |
505
+
506
+ Every skill is plain markdown with a `SKILL.md` plus a `references/` folder (`operations.md`, `task-contracts.md`, discovery playbooks, scoring-rubric guides, MCP recipes). Read them straight from this repo under `skills/`, or preview what setup would install:
507
+
508
+ ```bash
509
+ harness-fleet setup --workspace-root "$PWD" --dry-run --json
510
+ ```
511
+
512
+ ## MCP Server
513
+
514
+ `harness-fleet` includes a Model Context Protocol (MCP) server for integration into Cursor, Claude Desktop, Antigravity, and other agent environments:
515
+
516
+ **One-command install (recommended for GTM folks):**
517
+ ```bash
518
+ harness-fleet mcp install --workspace-root "$PWD" # auto-detects Claude/Cursor, writes mcpServers entry
519
+ # Also hand the desktop app a provider key (repeatable or comma-separated)
520
+ harness-fleet mcp install --env OPENROUTER_API_KEY
521
+ # Preview first
522
+ harness-fleet mcp install --dry-run --json
523
+ harness-fleet doctor --workspace-root "$PWD" --json # verify
524
+ # Restart Claude/Cursor to load
525
+ ```
526
+
527
+ Desktop apps do not inherit your shell environment, so keys such as `OPENROUTER_API_KEY` (or `GROQ_API_KEY`, `OLLAMA_BASE_URL`, …) must be passed explicitly with `--env NAME`; the CLI writes the value into the client config and only ever prints the variable name, never the value. Unset names are skipped with a warning.
528
+
529
+ Manual entry:
530
+ ```json
531
+ {
532
+ "mcpServers": {
533
+ "harness-fleet": {
534
+ "command": "harness-fleet",
535
+ "args": ["serve", "--workspace-root", "/absolute/path/to/workspace"]
536
+ }
537
+ }
538
+ }
539
+ ```
540
+
541
+ ---
542
+
543
+ ## Harness Studio (Local UI)
544
+
545
+ `harness-fleet studio` serves a localhost-only settings companion over the same SQLite
546
+ control plane (default `http://127.0.0.1:8080`; honors `--workspace-root`, `--port`, and
547
+ `--db`). For a disposable preview workspace, run `scripts/studio_preview.sh`. The page is
548
+ read from disk per request, so UI edits only need a browser refresh; Python changes need a
549
+ restart.
550
+
551
+ It is deliberately small: pick harnesses, then pick from *their* models. Runs happen from
552
+ the CLI or MCP, which read the same catalogue.
553
+
554
+ - **Harnesses start off.** Click to include. Each card shows whether its binary is on
555
+ `PATH` and that harness's own login command (`opencode providers`, `codex login`,
556
+ `cursor-agent login`, …) or, for API providers, the environment variable it needs. The
557
+ studio never handles credentials.
558
+ - **Models are only listed for what you selected.** `Free models` uses every verified
559
+ `price_observed_zero` route of the selected harnesses; `Specific models` lists their
560
+ models so you choose. Unpriced routes are never picked automatically.
561
+
562
+ The scoring contract, tasks, and runs are edited through the CLI or an agent — their
563
+ endpoints (`/api/tasks`, `/api/tasks/<name>/scoring`, `/api/runs`, `/api/routes/refresh`)
564
+ remain available to scripts. The server refuses cross-origin requests so a page you visit
565
+ cannot drive it.
566
+
567
+ ```bash
568
+ scripts/studio_preview.sh # disposable workspace on :8099
569
+ harness-fleet studio --workspace-root "$PWD" --port 8080
570
+ ```
571
+
572
+ Agents verifying the UI with screenshots: see [AGENTS.md](AGENTS.md) — use playwright,
573
+ never raw Chrome, and give pytest runs explicit timeouts.
574
+
575
+ ---
576
+
577
+ ## Verification & Testing
578
+
579
+ Run the test suite:
580
+
581
+ ```bash
582
+ pytest -q
583
+ ```
584
+
585
+ All core components (Bayesian route scoring, SQLite control plane, rate limit cooldowns, OpenAI-compatible provider, CSV IO, real-time status monitoring, and route evals) are covered by automated unit and integration tests.
586
+
587
+ ---
588
+
589
+ ## License
590
+
591
+ MIT. See [LICENSE](LICENSE).