@tangle-network/agent-knowledge 1.9.0 → 1.11.0

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 (42) hide show
  1. package/README.md +256 -74
  2. package/dist/benchmarks/index.d.ts +5 -0
  3. package/dist/benchmarks/index.js +52 -0
  4. package/dist/chunk-DQ3PDMDP.js +115 -0
  5. package/dist/chunk-DQ3PDMDP.js.map +1 -0
  6. package/dist/chunk-ULXZI235.js +1855 -0
  7. package/dist/chunk-ULXZI235.js.map +1 -0
  8. package/dist/{chunk-U6KQ4FS3.js → chunk-VN2OGUUP.js} +306 -40
  9. package/dist/chunk-VN2OGUUP.js.map +1 -0
  10. package/dist/{chunk-WWY5FTKQ.js → chunk-W6VWYTNH.js} +10 -115
  11. package/dist/chunk-W6VWYTNH.js.map +1 -0
  12. package/dist/chunk-XVU5FFQA.js +49 -0
  13. package/dist/chunk-XVU5FFQA.js.map +1 -0
  14. package/dist/cli.js +4 -2
  15. package/dist/cli.js.map +1 -1
  16. package/dist/index-Cj5jRXOz.d.ts +426 -0
  17. package/dist/index.d.ts +2225 -1058
  18. package/dist/index.js +4463 -1275
  19. package/dist/index.js.map +1 -1
  20. package/dist/memory/index.d.ts +5 -70
  21. package/dist/memory/index.js +20 -4
  22. package/dist/{types-BEDGlXB-.d.ts → types-C17sAROL.d.ts} +1 -1
  23. package/dist/types-CjqPcTTK.d.ts +319 -0
  24. package/dist/viz/index.d.ts +1 -1
  25. package/docs/architecture.md +7 -5
  26. package/docs/eval/investment-material-facts.md +252 -0
  27. package/docs/eval/rag-eval-roadmap.md +119 -0
  28. package/docs/results/adaptive.md +120 -0
  29. package/docs/results/claim-grounding.md +97 -0
  30. package/docs/results/cost-quality.md +27 -0
  31. package/docs/results/investment-thesis.md +306 -0
  32. package/docs/results/research-driving.md +265 -0
  33. package/docs/two-agent-research-ab.md +539 -0
  34. package/package.json +8 -9
  35. package/dist/chunk-MU5CEOGE.js +0 -387
  36. package/dist/chunk-MU5CEOGE.js.map +0 -1
  37. package/dist/chunk-U6KQ4FS3.js.map +0 -1
  38. package/dist/chunk-WWY5FTKQ.js.map +0 -1
  39. package/dist/profiles/index.d.ts +0 -194
  40. package/dist/profiles/index.js +0 -11
  41. package/docs/recursive-research-leaf.md +0 -86
  42. /package/dist/{profiles → benchmarks}/index.js.map +0 -0
@@ -0,0 +1,306 @@
1
+ # From paper-retrieval to investigation — a research eval where one search is not enough, a metric that discriminates depth, and a 3-arm topology A/B
2
+
3
+ *Tangle Network · `agent-knowledge`*
4
+
5
+ ## Verdict (BLUF)
6
+
7
+ We moved the research eval off ML-paper retrieval — where a **single** web search
8
+ already returns the answer, so the only thing the metric could measure was
9
+ *collection* — onto **investment research**, where the material facts are buried in
10
+ the footnotes of an SEC filing and genuinely require *investigation* to surface. On
11
+ this harder domain we (1) **calibrated** a `$0`, model-free metric and proved it
12
+ discriminates research depth — a shallow ticker summary scores **1/27 (4%)**, a
13
+ deep filings-grounded thesis scores **27/27 (100%)**, a **+96-point** gap — and then
14
+ (2) ran **three research topologies head-to-head** on the same five held-out
15
+ companies at matched compute, grading each one's knowledge base against a firewalled
16
+ checklist of **27 buried material facts** a ticker search misses.
17
+
18
+ **The honest A/B verdict: the research-DRIVING loop surfaced the most buried facts
19
+ (16/27, 59%), +5 over blind collection (11/27, 41%) — but at n=5 companies that lift
20
+ is NOT statistically clean: the 95% confidence interval crosses zero (P(Δ≤0)=0.08).**
21
+ The verify/dedup loop did **not** beat collection at all (10/27, 37% — a wash,
22
+ slightly worse). So no topology *significantly* beats collection here either —
23
+ **driving is the only arm that even points the right way, and it points there
24
+ suggestively, not significantly.** What the reframe *did* buy is a domain and a meter
25
+ where the question is finally well-posed: the metric is no longer measuring whether a
26
+ single search ran, but whether investigation reached the buried fact.
27
+
28
+ | arm | what the coordinator does | material facts | cost (5 cos.) | chats | searches | tokens |
29
+ |---|---|---|---|---|---|---|
30
+ | **A · collection** | nothing — accepts every source (1 agent collects) | 11/27 (41%) | $0.082 | 10 | 20 | 64,248 |
31
+ | **B · verify/dedup** | LLM gates each source for relevance, rejects off-topic | 10/27 (37%) | $0.125 | 56 | 52 | 84,678 |
32
+ | **C · driving (deepen)** | extracts claims, demands corroboration, asks deep follow-ups | **16/27 (59%)** | $0.157 | 33 | 28 | 124,387 |
33
+
34
+ Cost is real provenance, not an estimate: every `$`/call/token is diffed from
35
+ `RouterClient.usage()` per company (the router's own `usage` field, priced at
36
+ glm-5.2 rates), so "driving cost 1.9× collection" is measured, not modelled.
37
+
38
+ ## 1. The domain reframe — why we left ML-paper retrieval
39
+
40
+ The companion paper's depth eval (`docs/two-agent-research-ab.md` §9) measures a
41
+ research loop on **20 deep questions across 5 ML topics**. That apparatus is sound —
42
+ its grader scores 0/20 on a one-line topic definition and 20/20 on a mechanism-rich
43
+ paragraph, so it *can* tell depth from surface. But the topology A/B on top of it
44
+ came back a clean null (driving 16/20 @ budget 4, 13/20 @ budget 6 — the winner
45
+ *flips with the compute budget*, and the within-arm swing is as large as the
46
+ between-arm gap). The autopsy named the cause: **on an ML topic a single good search
47
+ already collects the answer.** Every arm finished in one effective round because the
48
+ generic "one source closes the gap" readiness was met by the *first* fetch — so the
49
+ driving driver, whose entire mechanism is steering a *second* round, never got to
50
+ act. When one search suffices, there is no investigation for a smarter coordinator to
51
+ do, and the metric can only reward collection. That is the failure-mode-in-spirit the
52
+ ML exam couldn't escape: not that the grader was loose, but that the *domain* was too
53
+ easy for topology to matter.
54
+
55
+ So we changed the domain to one where a single search **provably cannot** suffice.
56
+ **Investment research**: give a loop a company + ticker + an as-of cutoff date and ask
57
+ for a thesis; grade it on the buried, material, non-obvious drivers a thorough analyst
58
+ flags and a ticker search misses. The decisive facts here live in 10-K footnotes — an
59
+ HTM securities mark roughly equal to a bank's entire equity (SIVB), a deposit base
60
+ that is 97% uninsured, a negative per-unit gross margin, a related-party lease. A web
61
+ search for the company name returns "profitable regional bank" or "high-growth auto
62
+ e-commerce"; the filing shows the mark-to-market hole the size of capital. **The
63
+ answer is not collectable in one fetch — it has to be investigated for.** That is the
64
+ property the ML domain lacked, and it is what makes a topology A/B finally meaningful:
65
+ if a smarter coordinator can ever beat blind collection, a domain where the answer is
66
+ buried is where it has the room to.
67
+
68
+ The held-out set is **5 companies, 27 material facts**, every fact read live out of
69
+ the primary SEC EDGAR 10-K during curation, every dollar figure quoted from the
70
+ de-tagged filing text, every value knowable *at the cutoff* (the eventual collapse is
71
+ recorded for the reader only and is **never graded**). The companies skew distressed /
72
+ downside-risk — a documented curation bias, not a hidden one (full provenance, the
73
+ drop log, and the per-fact keyword groups: `docs/eval/investment-material-facts.md`):
74
+
75
+ | ticker | company | as-of cutoff | CIK | facts |
76
+ |---|---|---|---|---|
77
+ | SIVB | SVB Financial Group | 2023-02-24 | 719739 | 6 |
78
+ | BBBY | Bed Bath & Beyond | 2022-04-21 | 886158 | 5 |
79
+ | CVNA | Carvana | 2023-02-23 | 1690820 | 5 |
80
+ | PTON | Peloton | 2022-09-07 | 1639825 | 6 |
81
+ | SI | Silvergate | 2022-02-28 | 1312109 | 5 |
82
+
83
+ ## 2. Calibration — does the metric discriminate depth? (the gate the ML exam passed only weakly)
84
+
85
+ A topology A/B is meaningless unless the metric grading it can tell a *deep* thesis
86
+ from a *shallow* one. If it can't, it is measuring word-collection — the exact failure
87
+ the reframe set out to escape — and any A/B on top of it is noise. So **before** the
88
+ A/B, we ran a calibration gate (`$0`, offline, the binding result):
89
+
90
+ For each of the 5 companies we hand-wrote two theses and scored each with the metric's
91
+ pure core (`materialFactsSurfacedInText`):
92
+
93
+ - **shallow** — a one-paragraph ticker summary: what the company does, a vibe on the
94
+ stock, generic macro/competition risk. The kind a single name-search returns. Names
95
+ none of the buried, filing-level facts.
96
+ - **deep** — a filings-grounded analyst memo naming the buried drivers (the duration
97
+ loss, the buyback drain, the negative unit margin, the deposit concentration, the
98
+ related party) in independent prose, with the real numbers.
99
+
100
+ The grader is the same `$0`, model-free, case-insensitive substring check the held-out
101
+ checklist ships (`gradeFactAgainstText`); the checklist is firewalled — read only by
102
+ the metric, never shown to a loop.
103
+
104
+ | ticker | shallow | deep | gap |
105
+ |---|---|---|---|
106
+ | SIVB | 1/6 (17%) | 6/6 (100%) | +83pp |
107
+ | BBBY | 0/5 (0%) | 5/5 (100%) | +100pp |
108
+ | CVNA | 0/5 (0%) | 5/5 (100%) | +100pp |
109
+ | PTON | 0/6 (0%) | 6/6 (100%) | +100pp |
110
+ | SI | 0/5 (0%) | 5/5 (100%) | +100pp |
111
+ | **total** | **1/27 (4%)** | **27/27 (100%)** | **+96pp** |
112
+
113
+ **The metric is VALID:** it cleanly separates a shallow ticker-summary from a deep,
114
+ filings-grounded thesis — a +96-point aggregate gap, every company clearing the bars
115
+ (shallow `< 30%`, deep `> 70%`) with wide margin. Two guards make the gap real and not
116
+ a teaching-to-the-test artifact:
117
+
118
+ - **Anti-circularity.** The gate asserts **no deep thesis verbatim-embeds any
119
+ checklist `evidence` string** — the deep theses state the same publicly-documented
120
+ facts in independent analyst prose. A high deep score is the meter catching real,
121
+ independently-phrased depth, not an answer-key echo.
122
+ - **The one honest shallow hit.** The single shallow surface (SIVB 1/6) is SIVB/f5 —
123
+ the innovation-economy / venture-client concentration — which fires on "technology"
124
+ / "venture" in the SVB summary. That genuinely *is* the least-buried of SVB's six
125
+ facts (a ticker search does return "SVB banks tech and venture startups"). We kept it
126
+ as a 4% leak rather than tighten the group, because it honestly reflects one
127
+ near-surface fact while the five truly buried ones (the ~$15B HTM loss, the
128
+ equity-sized mark, the $151.5B uninsured base, the 20-point deposit-mix shift, the
129
+ AFS/AOCI loss) stay unsurfaced. The firewall holds (17% << 30%).
130
+
131
+ Calibration also did its job as more than a rubber stamp: the first pass had the
132
+ **Silvergate shallow thesis scoring 3/5 (60%)**, blowing the bar, because three fact
133
+ groups accepted bare crypto-bank vocabulary (`crypto`, `grew rapidly`, `proprietary` /
134
+ `payment network`) that any one-line summary trips. We tightened those three to require
135
+ the *buried* signal — the deposit-**concentration** framing, the specific **$14.3B**
136
+ figure, the **SEN** (Silvergate Exchange Network) name — and dropped the generic vocab.
137
+ The deep thesis still hits all three; the shallow one no longer does. The metric found
138
+ a way it could be fooled and we closed it before any A/B depended on it.
139
+
140
+ **This is the gate the ML exam passed only in spirit.** The ML grader discriminated
141
+ 0/20 vs 20/20 too — but on a domain where the deep answer was *collectable* in one
142
+ search, so the discrimination measured grammar, not investigation. Here the +96-point
143
+ gap is over facts that are *buried by construction*, so a high score is reachable only
144
+ by reaching into the filing. Same shape of result, materially harder domain.
145
+
146
+ ## 3. The 3-arm A/B — what each topology surfaced, head-to-head
147
+
148
+ For each company the loop is told **only** `{company, ticker, cik, cutoff}` plus a
149
+ generic set of analyst-lens readiness specs (balance-sheet risk, concentration,
150
+ leverage, margins, liquidity, governance, regulatory — the *lenses* and where they
151
+ live, the latest SEC 10-K — **not the answers**). It researches the company *as of* the
152
+ cutoff over web + SEC EDGAR (both public), writes a thesis, and we grade the resulting
153
+ KB with `materialFactsSurfaced` — the firewalled checklist the loop never sees.
154
+
155
+ **Compute is matched by construction.** All three arms run the *same* web worker, the
156
+ *same* 3-round budget, the *same* worker config (`resultsPerQuery: 3, queriesPerGap: 1,
157
+ maxSourcesPerRound: 6`). The **only** thing that varies is the driver — the coordinator
158
+ between the worker and the knowledge base:
159
+
160
+ - **A · collection** (`createCollectionResearchDriver`) — an inert rubber stamp:
161
+ accepts every source, gates nothing, steers only with the loop's built-in open-gap
162
+ list. The driver adds **zero** router calls. This is the blind-collection floor.
163
+ - **B · verify/dedup** (`createVerifyingResearchDriver`) — an LLM relevance gate: one
164
+ chat call per candidate source to accept-or-reject for on-topic relevance and
165
+ near-duplication. The worker ADDS; the driver GATES.
166
+ - **C · driving** (`createResearchDrivingDriver`) — extracts each source's claims,
167
+ tracks how many *independent* sources corroborate each, and synthesizes deep
168
+ follow-up sub-questions (comparative / mechanism / gap / contradiction) it folds into
169
+ the worker's next prompt to push depth and demand corroboration.
170
+
171
+ So any quality difference is attributable to topology, and any cost difference is the
172
+ price each topology pays in extra inference.
173
+
174
+ ### Per-company matrix
175
+
176
+ | ticker | A · collection | B · verify | C · driving |
177
+ |---|---|---|---|
178
+ | SIVB | 2/6 · $0.017 | 0/6 · $0.019 | **5/6 · $0.017** |
179
+ | BBBY | 4/5 · $0.014 | 0/5 · $0.026 | **5/5 · $0.027** |
180
+ | CVNA | **3/5 · $0.016** | 2/5 · $0.028 | 2/5 · $0.025 |
181
+ | PTON | 2/6 · $0.019 | **4/6 · $0.026** | 2/6 · $0.054 |
182
+ | SI | 0/5 · $0.016 | **4/5 · $0.027** | 2/5 · $0.033 |
183
+ | **total** | **11/27 (41%)** | **10/27 (37%)** | **16/27 (59%)** |
184
+ | **cost** | **$0.082** | **$0.125** | **$0.157** |
185
+
186
+ No arm dominates company-by-company. Driving owns the two banks; verify owns PTON and
187
+ SI; collection owns CVNA. That spread is the whole story at n=5: the topology that wins
188
+ depends heavily on which pages the web returned for that company that minute.
189
+
190
+ ### Significance (paired bootstrap, unit = company, 10k resamples)
191
+
192
+ | comparison | total facts | per-company Δ | mean Δ/co. | 95% CI | P(Δ≤0) |
193
+ |---|---|---|---|---|---|
194
+ | driving − collection | 16 vs 11 (+19pp) | `[+3,+1,−1,0,+2]` | +1.0 | **[−0.20, +2.20]** | 0.08 |
195
+ | verify − collection | 10 vs 11 (−4pp) | `[−2,−4,−1,+2,+4]` | −0.2 | [−2.60, +2.40] | 0.60 |
196
+ | driving − verify | 16 vs 10 (+22pp) | `[+5,+5,0,−2,−2]` | +1.2 | [−1.60, +4.00] | 0.23 |
197
+
198
+ Every interval crosses zero. **Driving vs collection is the closest to clean
199
+ (P=0.08)** but does not pass the project's significance bar. Verify vs collection is a
200
+ coin flip. This is the project's well-documented small-n mirage: exciting deltas born
201
+ at n=5 do not survive a paired bootstrap.
202
+
203
+ ## 4. Autopsy — the two things worth understanding
204
+
205
+ ### 4.1 Why driving wins where it wins
206
+
207
+ Driving's mechanism is multi-round: extract claims from round 1, then steer the worker
208
+ in rounds 2–3 to corroborate the weak ones and chase the deep questions. It helps most
209
+ where the **first** fetch lands real filing data the driver can build on — the two
210
+ banks, where SEC bank-call-report / 10-K data is dense and reachable. SIVB jumps from 2
211
+ buried facts (collection) to 5 (driving): the duration loss, the deposit concentration,
212
+ the AFS/AOCI mark all surface once the driver demands the balance-sheet detail a second
213
+ time. Where the first fetch is thin (PTON, SI), the driver has little to deepen and the
214
+ extra rounds mostly burn searches (PTON driving: 12 searches, 2 facts, the most
215
+ expensive cell at $0.054). This is the reframe paying off mechanically: it is exactly
216
+ the *second-round investigation* the ML domain never reached, and it is the only thing
217
+ that moved the number.
218
+
219
+ ### 4.2 Why verify scored ZERO on SIVB and BBBY (a real effect, not a bug)
220
+
221
+ This was the surprising result, so we probed it directly (a 2-round live replay of the
222
+ BBBY verify arm with round-level accept/reject logging). The verifier rejected **every**
223
+ source both rounds, accepting nothing, writing no KB pages:
224
+
225
+ ```
226
+ ROUND 1: accepted=0 rejected=3 writtenPages=0
227
+ REJECT stockanalysis.com/stocks/bbby/financials :: Third-party aggregator, not the SEC EDGAR 10-K primary source…
228
+ REJECT stocktitan.net/financials/BBBY :: Third-party financial data aggregator, not the authoritative SEC 10-K…
229
+ REJECT last10k.com/sec-filings/bbby :: Third-party aggregator showing a 2025/2026 10-K, well after the 2022-04-21 research date…
230
+ ROUND 2: accepted=0 rejected=2 writtenPages=0
231
+ ```
232
+
233
+ The verifier was **correct on the merits** — those are aggregators, not the primary
234
+ filing, and last10k showed a post-cutoff filing. But the worker never surfaced the
235
+ EDGAR primary for BBBY, so a strict primary-only gate left the KB **empty**. Collection
236
+ accepts the same aggregator pages and scores 4/5 on BBBY; driving accepts them and
237
+ scores 5/5. **The gate's strictness is a liability when the worker's sourcing is
238
+ imperfect:** it throws away the only evidence the loop had. This is a genuine topology
239
+ trade-off worth naming, not a harness break — the verify arm surfaced facts fine on
240
+ CVNA (2), PTON (4), SI (4), so the harness works.
241
+
242
+ ### 4.3 The empty-thesis caveat (honest)
243
+
244
+ Some runs show `thesis=0ch` (empty synthesis) yet still score facts. That is expected:
245
+ `materialFactsSurfaced` grades the **whole KB** (the worker's fetched `knowledge/*.md`
246
+ pages), not only the final thesis page. glm-5.2 occasionally spends its entire output
247
+ budget on hidden reasoning and returns empty visible content on the synthesis call — a
248
+ known reasoning-model behavior we floor at 1200 tokens but can't fully eliminate. The
249
+ score still reflects what the loop fetched, so an empty thesis does not invalidate a
250
+ run; it just means the synthesis prose was lost while the curated evidence was not.
251
+
252
+ ## 5. What this does and does not establish
253
+
254
+ - **Does**: the metric *discriminates depth on a domain where one search is not
255
+ enough* (calibration: 1/27 shallow vs 27/27 deep, +96pp) — so the topology A/B on top
256
+ of it is finally well-posed, unlike the ML retrieval exam where one search already
257
+ collected the answer. At matched compute on the 5-company held-out set, the
258
+ research-driving topology surfaced the most buried material facts (16/27 vs 11/27 for
259
+ blind collection), a +5-fact / +18pp lift, for ~1.9× the cost. Every dollar is real,
260
+ per-call provenance from `RouterClient.usage()`.
261
+ - **Does NOT**: prove driving *significantly* beats collection. At n=5 the
262
+ paired-bootstrap CI for the driving lift crosses zero (P(Δ≤0)=0.08). The verdict is
263
+ "promising, under-powered," consistent with the project's prior topology nulls (the
264
+ ML exam, depth-vs-breadth, native-skills), not "driving wins." No topology cleared the
265
+ bar. Nor does the 27-fact checklist generalize beyond its documented curation bias
266
+ (downside-risk, distressed-name skew).
267
+ - **The next rung** (to turn the P=0.08 lean into a verdict): expand the held-out set
268
+ well past 5 companies (the checklist is the constraint, not the harness) and re-run at
269
+ n≥24 so a +1-fact/company effect can clear a paired bootstrap. The driving arm is the
270
+ one worth funding that test on; verify is not.
271
+
272
+ ## 6. Reproduce
273
+
274
+ ```bash
275
+ # The calibration gate that must pass FIRST ($0, offline) — the metric is valid.
276
+ pnpm test investment-calibration
277
+
278
+ # The offline task wiring ($0) — proves page → index → grade end-to-end.
279
+ pnpm test investment-thesis-task
280
+
281
+ # The full live 3-arm A/B (costs ~$0.36 total at 5 companies × 3 arms × 3 rounds).
282
+ # Needs a router key that can reach glm-5.2.
283
+ export TANGLE_API_KEY=<router key>
284
+ AGENT_KNOWLEDGE_LIVE=1 IT_LIVE_ROUNDS=3 \
285
+ npx vitest run tests/eval/investment-thesis-ab.test.ts --reporter=basic
286
+
287
+ # A single arm / single company (cheap smoke before the full burn):
288
+ AGENT_KNOWLEDGE_LIVE=1 IT_LIVE_TICKERS=CVNA IT_LIVE_ARMS=collection \
289
+ npx vitest run tests/eval/investment-thesis-ab.test.ts --reporter=basic
290
+ ```
291
+
292
+ `IT_LIVE_ARMS` (`|`-separated subset of `collection|verify|driving`) and
293
+ `IT_LIVE_TICKERS` scope the run; `IT_LIVE_ROUNDS` sets the per-arm round budget
294
+ (default 3 — driving needs > 1). The smoke (one cheap glm-5.2 call) runs once before any
295
+ arm, so a bad key fails fast, before the burn.
296
+
297
+ ---
298
+
299
+ *Run provenance. Calibration: `$0`, offline, reproducible — numbers from
300
+ `tests/eval/investment-calibration.test.ts` (shallow `< 30%`, deep `> 70%`,
301
+ gap `> 40pp` per company and aggregate; all pass). A/B: 5 companies × 3 arms × 3 rounds
302
+ = 15 live company-runs, glm-5.2 over the Tangle router, ~37.5 min wall, $0.36 total;
303
+ grader `materialFactsSurfaced` (firewalled, `$0`, model-free substring check); numbers
304
+ transcribed verbatim from the test's `[IT 3-ARM TOTALS]` console output and recorded in
305
+ commit `338bc54`; statistics from a paired bootstrap over the per-company fact deltas.
306
+ Held-out set + per-fact provenance: `docs/eval/investment-material-facts.md`.*
@@ -0,0 +1,265 @@
1
+ # Does driving research DEEPER beat just collecting it? A held-out deep-question A/B — and an honest null
2
+
3
+ *Tangle Network · `agent-knowledge`*
4
+
5
+ ## Verdict (BLUF)
6
+
7
+ We built a research driver whose job is to push a web-research loop **deeper** —
8
+ extract each source's claims, demand a second independent source for every claim,
9
+ generate comparative / mechanism / contradiction sub-questions, and steer the
10
+ worker to chase them. The hypothesis: a KB built this way answers **more held-out
11
+ deep questions** than one built by plain collection or by a relevance/dedup
12
+ verifier.
13
+
14
+ On a **firewalled exam of 20 deep questions across 5 ML topics**, graded with a
15
+ $0 deterministic check the loop never sees, at equal compute, **the driving loop
16
+ did NOT reliably beat plain collection — and cost ~12–16× more.** The verdict
17
+ flips with the compute budget, which is the tell that it is **noise, not signal**:
18
+
19
+ | arm | answered @ B=4 | answered @ B=6 | cost (5 topics) | tokens |
20
+ |---|---|---|---|---|
21
+ | single-agent (collect) | 13/20 | **15/20** | $0.005–0.007 | ~2.4–3.0k |
22
+ | verify/dedup | **15/20** | **15/20** | $0.031–0.027 | ~21k |
23
+ | **DRIVING (deepen)** | **16/20** | 13/20 | **$0.089–0.084** | ~69–71k |
24
+
25
+ Driving "wins" at B=4 (16 > 15 > 13) and "loses" at B=6 (13 < 15), while the
26
+ single-agent arm itself swings 15→13 and driving swings 16→13 on the *same* exam.
27
+ At n=5 topics a ±1–3 question difference is within the run-to-run web variance —
28
+ the arms are not separated by topology, they are separated by **which pages the
29
+ web returned that minute**. The one thing that is stable and large is the **cost**:
30
+ driving spends an order of magnitude more for no reliable quality gain.
31
+
32
+ **Why** (the autopsy that explains it, §4): every arm finished in **one effective
33
+ round** (`passes=2` on every topic, every budget). The generic readiness gate —
34
+ "one source closes the gap" — is satisfied by the first round's fetch, so the
35
+ loop *stops before the driving driver ever steers a second round*. Driving's
36
+ entire mechanism is multi-round (extract → demand corroboration → re-search). So
37
+ the headline A/B under-tests it. **We then gave it its fairest test** — a
38
+ controlled probe (§5) that *forces* 3 rounds so the driver actually steers — and
39
+ it **still does not win: 8 vs 8 against a blind worker, at ~9× the cost.** The
40
+ negative result is robust, not a gate artifact.
41
+
42
+ This is a real negative result, and we report it as one.
43
+
44
+ ## 1. Why a new metric
45
+
46
+ The prior A/B in this repo
47
+ ([two-agent-research-ab.md](../two-agent-research-ab.md)) measured **cleanliness**
48
+ — how *few* sources a verifier admits at equal coverage. That is the right metric
49
+ for a verifier whose job is to filter. It is the **wrong** metric for the driving
50
+ driver, whose thesis is the opposite: it is not trying to admit fewer sources, it
51
+ is trying to build a KB that *answers more*. Measuring it on admitted-count would
52
+ score its whole point as a regression (it admits *more*, because it accepts every
53
+ source with an extractable claim and then chases more).
54
+
55
+ So we need a metric for research **quality**, not hygiene. We use:
56
+
57
+ > **QUALITY = how many held-out deep questions the resulting KB can answer.**
58
+
59
+ ## 2. The held-out exam (the firewall)
60
+
61
+ [`tests/loops/held-out-exam.ts`](../../tests/loops/held-out-exam.ts). 5 ML topics,
62
+ 4 questions each = **20 deep questions**. Each is a *depth* question by
63
+ construction — comparative, mechanism-level, or contradiction-aware — chosen so a
64
+ single web search for the topic name does **not** surface the answer:
65
+
66
+ - *speculative decoding* — the rejection-sampling acceptance rule and why output
67
+ is lossless; how self-speculative/Medusa (no draft model) trades off vs the
68
+ two-model scheme; what bounds the speedup; why one verify pass is ~free.
69
+ - *LoRA* — the `W = W₀ + BA` update and which matrices train; QLoRA's 4-bit
70
+ tradeoff; why LoRA adds zero inference latency (merge); the very-low-rank claim.
71
+ - *grouped-query attention* — the MQA↔GQA↔MHA spectrum of KV heads; the real
72
+ bottleneck (KV cache / memory bandwidth, not FLOPs); uptraining from a
73
+ checkpoint; the MQA quality cost GQA recovers.
74
+ - *RLHF/PPO* — the KL-to-reference penalty and what it prevents; the pairwise
75
+ preference reward model + Bradley-Terry loss; DPO's reward-model-free insight;
76
+ PPO's clipped surrogate.
77
+ - *mixture-of-experts* — top-k routing and sparse activation; load imbalance + the
78
+ auxiliary balancing loss; params-decoupled-from-FLOPs; the memory cost at
79
+ inference.
80
+
81
+ **The firewall.** The questions and their expected answers are **never shown to
82
+ any loop.** A loop is told only the topic name and the *same generic readiness
83
+ specs* every arm gets ("what X is and how it works" / "results, mechanisms,
84
+ trade-offs"). It researches blind. **After** it finishes, we grade the KB it built
85
+ against the held-out questions with a **$0 deterministic substring grader** (no
86
+ LLM — so the exam cannot leak into a model the loop observes), where each question
87
+ carries the specific load-bearing answer tokens as keyword groups (a number, a
88
+ name, a mechanism phrase), with synonym groups so a faithful page in its own words
89
+ still grades as answered.
90
+
91
+ **The exam discriminates depth, not surface facts** (calibration, run offline):
92
+
93
+ | graded against | held-out answered |
94
+ |---|---|
95
+ | a one-line topic-definition snippet (what a single search returns) | **0 / 20** |
96
+ | a deep, mechanism-rich paragraph | **20 / 20** |
97
+
98
+ So a high score is only reachable by depth — the firewall is real, and the gap
99
+ between arms (if any) would be real depth, not grader slack.
100
+
101
+ ## 3. The three arms, at equal compute
102
+
103
+ [`tests/loops/research-driving-ab.test.ts`](../../tests/loops/research-driving-ab.test.ts).
104
+ All three arms run the **same** real web worker
105
+ ([`createWebResearchWorker`](../../src/web-research-worker.ts) — glm-5.2 query-gen
106
+ → live `/v1/search` → `politeFetch` → `htmlToText`). They differ **only** in the
107
+ driver:
108
+
109
+ - **(A) single-agent collection** — the worker alone, no driver. It collects.
110
+ - **(B) verify/dedup** — [`createVerifyingResearchDriver`](../../src/web-research-worker.ts):
111
+ a second glm-5.2 pass filters each source for relevance / near-duplicates.
112
+ - **(C) DRIVING** — [`createResearchDrivingDriver`](../../src/research-driving-driver.ts):
113
+ the driver extracts each source's claims (glm-5.2), tracks independent-source
114
+ support + contradictions, and folds comparative / mechanism / gap /
115
+ contradiction sub-questions into the worker's next prompt.
116
+
117
+ **Equal compute** is counted in agent passes (same unit as the prior A/B): a
118
+ single-agent iteration is 1 worker pass; a two-agent round is 1 worker + 1 driver
119
+ pass = 2. Each arm gets the same pass ceiling B; the single-agent arm gets more
120
+ iterations to spend the budget the two-agent arms burn on their driver. Cost is
121
+ read per-arm from `RouterClient.usage()` — measured dollars/tokens/calls, not
122
+ estimates.
123
+
124
+ ## 4. Result — driving does not reliably win, and the verdict flips with budget
125
+
126
+ Per-topic held-out questions answered (out of 4 each), at both budgets:
127
+
128
+ | topic | single B4 / B6 | verify B4 / B6 | driving B4 / B6 |
129
+ |---|---|---|---|
130
+ | speculative decoding | 1 / 2 | 2 / 2 | 2 / 1 |
131
+ | LoRA | 2 / 3 | 2 / 3 | 3 / 3 |
132
+ | grouped-query attention | 4 / 4 | 4 / 4 | 4 / 4 |
133
+ | RLHF / PPO | 2 / 2 | 3 / 3 | 3 / 2 |
134
+ | mixture-of-experts | 4 / 4 | 4 / 3 | 4 / 3 |
135
+ | **total /20** | **13 / 15** | **15 / 15** | **16 / 13** |
136
+
137
+ The driving arm answers **16** at B=4 and **13** at B=6 — a 3-question swing on
138
+ the *same* exam, the same arm, just a different compute ceiling and a different
139
+ minute of web results. Single swings 13→15; verify is flat 15→15. **The within-arm
140
+ swing is as large as the between-arm gap**, which is the signature of a null:
141
+ whatever separates a "win" from a "loss" here is web variance, not the driver.
142
+
143
+ The **cost**, by contrast, is stable and large. Driving spends **~$0.084–0.089**
144
+ across 5 topics vs **~$0.005–0.007** for single-agent — **12–16× the dollars** and
145
+ **~24× the tokens** (~70k vs ~2.5k) — because it runs a claim-extraction LLM call
146
+ on every fetched source. For that 12–16× it buys no reliable held-out-question
147
+ gain over plain collection.
148
+
149
+ ### Why every arm stopped after one round
150
+
151
+ The decisive diagnostic is `passes=2` on **every** topic at **every** budget: the
152
+ two-agent loop ran exactly **one** worker round before the readiness gate reported
153
+ done, even with B=6 budget for three rounds. The generic specs require one source
154
+ to close a gap, and the worker's first-round fetch closes them — so the loop stops
155
+ before round 2. The driving driver's mechanism is *multi-round*: round 1 extracts
156
+ claims and flags the weakly-supported ones; round 2+ is where it steers the worker
157
+ to corroborate and go deeper. **It never got a round 2.** So in this setting
158
+ driving's only active effect was a one-round claim-extraction tax with no chance to
159
+ use what it extracted — which is exactly what the numbers show: same answers as
160
+ collection, much higher cost.
161
+
162
+ That makes the equal-compute/generic-gate A/B a test of the wrong thing for the
163
+ driving thesis. The fair test has to *force* multiple rounds.
164
+
165
+ ## 5. Controlled multi-round probe — the driving thesis's fairest test
166
+
167
+ To isolate "does depth-steering help **when it actually runs**?", we raise the
168
+ readiness bar so the gate stays unmet and the loop runs the full round budget,
169
+ forcing the driving driver to steer each round. Same real worker, same number of
170
+ rounds; the only difference is whether the driver **steers** (driving) or the
171
+ worker **re-searches the same gaps blind** (a no-op driver that accepts every
172
+ source and never steers). If driving's steering has any value, this is where it
173
+ shows.
174
+
175
+ **Result — 3 rounds, 3 topics, driving steers vs blind re-search:**
176
+
177
+ | topic | driving (steered) answered / cost | blind (no steer) answered / cost |
178
+ |---|---|---|
179
+ | speculative decoding | 2/4 — $0.032 | **4/4 — $0.004** |
180
+ | LoRA | 3/4 — $0.028 | 3/4 — $0.003 |
181
+ | RLHF / PPO | **3/4** — $0.033 | 1/4 — $0.003 |
182
+ | **total /12** | **8/12 — $0.093** | **8/12 — $0.010** |
183
+
184
+ **Steering does not help: 8 vs 8, at ~9× the cost.** Given its fairest test — the
185
+ full multi-round regime its mechanism was designed for — the driving driver ties a
186
+ blind worker that just re-searches the same gaps three times. It is **better on
187
+ RLHF** (3 vs 1, the one topic where chasing corroboration found a page blind
188
+ re-search missed) and **worse on speculative decoding** (2 vs 4 — steering pulled
189
+ the worker *off* the pages that answered the exam and toward corroborating a
190
+ narrower claim set). Those cancel. So the depth-steering does change *what* gets
191
+ fetched, but not *how many* held-out questions get answered — and it pays ~9× the
192
+ dollars for the privilege. The headline null (§4) is therefore **not** merely a
193
+ gate artifact: even forced to run, driving does not beat blind collection on
194
+ research quality at this n.
195
+
196
+ ## 6. Threats to validity
197
+
198
+ - **Small n, high web variance.** n = 5 topics; one live run per arm per budget.
199
+ The §4 budget-flip is itself the evidence that the per-run magnitudes are
200
+ variance-bound. We did not run a paired bootstrap because the within-arm swing
201
+ already exceeds the between-arm gap — the honest read is "no separation," and a
202
+ significance test on a known-null at n=5 would dress it up, not clarify it.
203
+ - **The gate, not the driver, ended the headline loop (§4) — but the probe
204
+ controls for it.** The headline A/B's generic one-source readiness gate closed
205
+ every loop after one round, so on its own it would only show "driving adds a
206
+ one-round extraction tax." The §5 probe removes that confound by forcing 3
207
+ rounds, and driving still ties blind (8 vs 8) — so the null survives the fix,
208
+ it is not an artifact of the permissive gate.
209
+ - **The worker is shared and shallow.** All arms use the same ~500-line direct
210
+ pipeline (query-gen → search → fetch), not an `AgentProfile` on a harness. A
211
+ richer worker that follows citations or reads PDFs might give depth-steering more
212
+ to work with.
213
+ - **glm-5.2-specific.** A stronger extractor/judge would change both the cost and
214
+ the per-round depth. The grader is conservative (substring/synonym presence); a
215
+ faithful paraphrase using none of the listed synonyms would read as unanswered.
216
+ - **Depth-components is a proxy.** "Distinct expected-answer groups present" tracks
217
+ the binary answered-count closely here; it is a finer-grained view, not an
218
+ independent oracle.
219
+
220
+ ## 7. What this says, plainly
221
+
222
+ Adding a "drive it deeper" agent did **not** make the research measurably better at
223
+ answering hard, held-out questions — at equal compute (§4) *and* forced to run its
224
+ full multi-round mechanism (§5), on this worker, at n=5 — and it cost 9–16× more.
225
+ The steering changes *what* gets fetched (it helped on RLHF, hurt on speculative
226
+ decoding) but not *how many* held-out questions get answered. The most durable
227
+ thing the experiment produced is the **measurement apparatus**: a firewalled
228
+ deep-question exam with a $0 deterministic grader that *can* tell depth from
229
+ surface (0/20 vs 20/20), reusable for any future research-quality claim in this
230
+ repo. The driving thesis — that pursuing depth + corroboration beats plain
231
+ collection — is, on the evidence here, **not supported**; the cheaper paths
232
+ (collect, or dedup) match it. Where it might still earn its cost: a worker rich
233
+ enough that "go corroborate this claim" reaches a page blind re-search can't
234
+ (the RLHF case), measured at an n large enough to separate that from variance.
235
+
236
+ ## 8. Reproduce
237
+
238
+ ```bash
239
+ git clone https://github.com/tangle-network/agent-knowledge
240
+ cd agent-knowledge && pnpm install
241
+
242
+ # offline: the exam wiring + the $0 grader (no credentials)
243
+ pnpm exec vitest run tests/loops/research-driving-ab.test.ts
244
+
245
+ # the live 3-arm A/B — real web search + glm-5.2, per-arm cost reported
246
+ export TANGLE_API_KEY=<router key with glm-5.2 credits>
247
+ AGENT_KNOWLEDGE_LIVE=1 RQ_LIVE_BUDGET=4 \
248
+ pnpm exec vitest run tests/loops/research-driving-ab.test.ts -t "3-arm A/B"
249
+ # re-run at RQ_LIVE_BUDGET=6 to see the verdict flip (the §4 variance point)
250
+
251
+ # the controlled multi-round probe — forces N rounds so driving actually steers
252
+ AGENT_KNOWLEDGE_LIVE=1 RQ_PROBE=1 RQ_PROBE_ROUNDS=3 TANGLE_API_KEY=<…> \
253
+ pnpm exec vitest run tests/loops/research-driving-ab.test.ts -t "multi-round probe"
254
+ # (~$0.10 for the 5-topic A/B at one budget; ~$0.10 for the 3-topic probe)
255
+ ```
256
+
257
+ `RQ_LIVE_TOPICS` takes a `|`-separated subset of the exam topic names to run a
258
+ cheaper slice. The exam is held out by construction — no flag shows it to a loop.
259
+
260
+ **Source:** the exam + grader —
261
+ [`tests/loops/held-out-exam.ts`](../../tests/loops/held-out-exam.ts);
262
+ the 3-arm A/B + multi-round probe —
263
+ [`tests/loops/research-driving-ab.test.ts`](../../tests/loops/research-driving-ab.test.ts);
264
+ the driving driver under test —
265
+ [`src/research-driving-driver.ts`](../../src/research-driving-driver.ts).