@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,252 @@
1
+ # Held-out investment-research eval set — material facts + provenance
2
+
3
+ This is the answer key and the provenance ledger for `tests/eval/investment-thesis-set.ts`.
4
+
5
+ **What the set measures.** Give a research loop a company + ticker + an as-of
6
+ **cutoff** date and ask it to write an investment thesis. Then grade that thesis
7
+ against the held-out **material facts** below — facts the loop never saw. A high
8
+ score means the thesis surfaced the buried, material, non-obvious drivers a
9
+ thorough analyst would flag and a single ticker search would miss; it is **not**
10
+ teaching-to-the-test, because the answer key is firewalled from every loop and
11
+ the grader is a `$0`, model-free substring check (`gradeFactAgainstText`).
12
+
13
+ **Three hard rules, enforced by how the data was gathered:**
14
+
15
+ 1. **Specific + checkable.** Every fact carries keyword groups (a number, a name,
16
+ a phrase) so the deterministic grader can score "did the thesis surface it".
17
+ 2. **Derived from real fetched evidence.** Every fact cites the primary SEC EDGAR
18
+ 10-K it was read from and the literal value in that document. Nothing is
19
+ invented; an item that could not be independently sourced was **dropped**, not
20
+ guessed (see the drop log).
21
+ 3. **Knowable at the cutoff.** Every value was disclosed in, or computable from, a
22
+ filing available on or before the cutoff. The eventual collapse is **not** a
23
+ checklist item — it is recorded as `knownOutcome`, for the reader only, and is
24
+ never graded.
25
+
26
+ All five primary documents were fetched live from `https://www.sec.gov/Archives/`
27
+ during curation (a `curl` with a descriptive `User-Agent`, per SEC fair-access
28
+ rules). Every dollar figure below was read directly out of the de-tagged filing
29
+ text. Provenance is verifiable: each `sourceUrl` contains the company's SEC CIK,
30
+ and `tests/eval/investment-thesis-set.test.ts` asserts that invariant.
31
+
32
+ ---
33
+
34
+ ## Companies + cutoffs
35
+
36
+ | Ticker | Company | CIK | Cutoff (as-of) | Sector | Primary source (10-K) |
37
+ |---|---|---|---|---|---|
38
+ | SIVB | SVB Financial Group | 719739 | 2023-02-24 | Banking | FY2022 10-K, filed 2023-02-24 |
39
+ | BBBY | Bed Bath & Beyond Inc. | 886158 | 2022-04-21 | Specialty retail | FY2021 10-K, filed 2022-04-21 |
40
+ | CVNA | Carvana Co. | 1690820 | 2023-02-23 | Auto e-commerce | FY2022 10-K, filed 2023-02-23 |
41
+ | PTON | Peloton Interactive, Inc. | 1639825 | 2022-09-07 | Consumer fitness hardware | FY2022 10-K, filed 2022-09-07 |
42
+ | SI | Silvergate Capital Corporation | 1312109 | 2022-02-28 | Banking (digital-asset) | FY2021 10-K, filed 2022-02-28 |
43
+
44
+ Each cutoff is set to the filing date of the primary 10-K, so the entire document
45
+ was public on the as-of date. All five cutoffs are **>= 18 months** before this
46
+ set was curated (June 2026); `investment-thesis-set.test.ts` asserts this.
47
+
48
+ ---
49
+
50
+ ## SIVB — SVB Financial Group (cutoff 2023-02-24)
51
+
52
+ Source: [FY2022 10-K (`sivb-20221231.htm`)](https://www.sec.gov/Archives/edgar/data/719739/000071973923000021/sivb-20221231.htm)
53
+ **Known outcome (not graded):** FDIC receivership March 10, 2023; holding-company Chapter 11 March 17, 2023.
54
+
55
+ | ID | Lens | Material fact | Value read from the filing |
56
+ |---|---|---|---|
57
+ | SIVB/f1 | off-balance-sheet | HTM securities carried at amortized cost were far above fair value | "Held-to-maturity securities, at amortized cost ... **91,321** (fair value of $ **76,169**)" → ~**$15.15B** unrealized loss, footnote-only |
58
+ | SIVB/f2 | off-balance-sheet | That HTM loss ~= the entire equity base | "Total SVBFG stockholders' equity **16,004**" → ~$15.15B is ~95% of $16.0B equity |
59
+ | SIVB/f3 | concentration | Run-prone uninsured deposit base | "estimated uninsured deposits in U.S. offices that exceed the FDIC insurance limit were **$151.5 billion**" |
60
+ | SIVB/f4 | margin-trend | Cheap deposits fleeing → funding cost set to rise | "Noninterest-bearing demand deposits to total deposits decreased by **20 percentage points to 47 percent**" |
61
+ | SIVB/f5 | concentration | Single-client-type (innovation-economy) deposit + credit base | 10-K frames the franchise around "the innovation economy" (technology, life-science, venture) |
62
+ | SIVB/f6 | off-balance-sheet | AFS loss in AOCI — the visible, smaller tip | "Available-for-sale securities, at fair value (cost of $ **28,602**) **26,069**" → ~$2.5B AFS loss in AOCI |
63
+
64
+ The decisive, non-obvious fact is SIVB/f1+f2: an interest-rate loss roughly equal
65
+ to all of equity, sitting in the footnotes because HTM accounting keeps it out of
66
+ both earnings and book equity. A ticker search shows a profitable bank; the
67
+ filing shows a mark-to-market hole the size of its capital.
68
+
69
+ ## BBBY — Bed Bath & Beyond Inc. (cutoff 2022-04-21)
70
+
71
+ Source: [FY2021 10-K (`bbby-20220226.htm`)](https://www.sec.gov/Archives/edgar/data/886158/000088615822000047/bbby-20220226.htm)
72
+ **Known outcome (not graded):** Chapter 11 on April 23, 2023; equity wiped out.
73
+
74
+ | ID | Lens | Material fact | Value read from the filing |
75
+ |---|---|---|---|
76
+ | BBBY/f1 | capital-return | Buybacks drained a loss-making balance sheet | "we have repurchased approximately **$11.685 billion**"; FY2021 alone "**$574.9 million** ... two years ahead of schedule" |
77
+ | BBBY/f2 | liquidity | Operating cash flow nearly vanished | "Net cash provided by operating activities **17,854** 268,108 590,941" ($ thousands) |
78
+ | BBBY/f3 | liquidity | Equity collapsed ~86% in one year | "Total shareholders' equity **174,145** 1,276,936" ($ thousands) |
79
+ | BBBY/f4 | liquidity | A net loss the same year it kept buying back stock | "Net loss $ (**559,623**)" ($ thousands) |
80
+ | BBBY/f5 | margin-trend | Inventory building into a demand decline | "Merchandise inventories **1,725,410** 1,671,909" ($ thousands) |
81
+
82
+ The non-obvious fact is BBBY/f1+f2+f4 together: in FY2021 the company **lost $560M,
83
+ generated only $18M of operating cash, and still spent $575M buying back stock** —
84
+ returning more cash than it had. The buyback, not the income statement alone, is
85
+ why a $1.3B equity base became $174M.
86
+
87
+ ## CVNA — Carvana Co. (cutoff 2023-02-23)
88
+
89
+ Source: [FY2022 10-K (`cvna-20221231.htm`)](https://www.sec.gov/Archives/edgar/data/1690820/000169082023000052/cvna-20221231.htm)
90
+ **Known outcome (not graded):** Stock fell ~98% from its 2021 peak; a 2023 debt exchange cut and extended obligations, narrowly avoiding bankruptcy.
91
+
92
+ | ID | Lens | Material fact | Value read from the filing |
93
+ |---|---|---|---|
94
+ | CVNA/f1 | leverage | A debt load far above the equity base | "Total debt **8,391** 5,447" ($ millions) |
95
+ | CVNA/f2 | leverage | Interest expense nearly tripled in a year | "Interest expense **486** 176" ($ millions) |
96
+ | CVNA/f3 | leverage | A ~$2.2B debt-funded acquisition as demand turned | "physical auction business of ADESA US Auction, LLC for approximately **$2.2 billion** in cash" (closed 2022-05-09) |
97
+ | CVNA/f4 | governance | Recurring related-party leases with the founder's family | Related-Party note: DriveTime, controlled by "Ernest Garcia II, Ernest Garcia III, and entities controlled by one or both of them" |
98
+ | CVNA/f5 | liquidity | A wide loss showing unit economics had not turned | "Net loss $ (**2,894**)" ($ millions) |
99
+
100
+ The non-obvious facts are CVNA/f2 (interest expense up 2.8x — the debt was now
101
+ expensive, not just large) and CVNA/f4 (the controlling Garcia family on both
102
+ sides of material leases via DriveTime), neither of which a ticker quote shows.
103
+
104
+ ## PTON — Peloton Interactive, Inc. (cutoff 2022-09-07)
105
+
106
+ Source: [FY2022 10-K (`pton-20220630.htm`)](https://www.sec.gov/Archives/edgar/data/1639825/000163982522000117/pton-20220630.htm)
107
+ **Known outcome (not graded):** Stock fell ~95% from its 2021 peak; founder-CEO departed; mass layoffs and a multi-year turnaround.
108
+
109
+ | ID | Lens | Material fact | Value read from the filing |
110
+ |---|---|---|---|
111
+ | PTON/f1 | margin-trend | Hardware gross margin turned **negative** | Connected Fitness "Gross Margin decreased to (**11**)" percent — losing money per unit sold |
112
+ | PTON/f2 | liquidity | Inventory glut as pandemic demand normalized | "Inventories, net **1,104.5** 937" ($ millions) |
113
+ | PTON/f3 | governance | Dual-class super-voting control | "Class B common stock has **20 votes per share** and our Class A common stock has one vote per share" |
114
+ | PTON/f4 | liquidity | An order-of-magnitude wider loss | "Net loss $ (**2,827**)" ($ millions) |
115
+ | PTON/f5 | regulatory | An open CPSC product-safety recall | "recall on **Tread+** ... in collaboration with the **Consumer Product Safety Commission ('CPSC')**" |
116
+ | PTON/f6 | leverage | Locked-in purchase commitments into falling demand | "purchase commitments related to the manufacture of Peloton products were estimated to be approximately **$334**" million |
117
+
118
+ The non-obvious fact is PTON/f1: revenue was still large, but the **hardware was
119
+ sold below cost** (−11% gross margin) — the unit economics, not just the growth
120
+ rate, had broken. PTON/f6 compounds it: the company was contractually obliged to
121
+ buy more inventory it could not sell.
122
+
123
+ ## SI — Silvergate Capital Corporation (cutoff 2022-02-28)
124
+
125
+ Source: [FY2021 10-K (`si-20211231.htm`)](https://www.sec.gov/Archives/edgar/data/1312109/000131210922000051/si-20211231.htm)
126
+ **Known outcome (not graded):** After the FTX collapse triggered a deposit run, Silvergate announced a voluntary wind-down and liquidation of Silvergate Bank in March 2023.
127
+
128
+ | ID | Lens | Material fact | Value read from the filing |
129
+ |---|---|---|---|
130
+ | SI/f1 | concentration | Essentially all funding was on-demand money | "noninterest bearing deposits as a percentage of total deposits was **99.5%** as of December 31, 2021" |
131
+ | SI/f2 | concentration | Deposits dominated by crypto exchanges | "Deposits from digital currency exchanges represent approximately **58%**" |
132
+ | SI/f3 | concentration | The whole deposit base tied to one volatile industry | Strategy + risk factors center on "digital currency customers" and "the concentration of our deposits" |
133
+ | SI/f4 | liquidity | Hot-money deposit growth that could reverse fast | "Total deposits $ **14,290,628**" vs prior year "$ 10,411,278" ($ thousands) |
134
+ | SI/f5 | concentration | The moat AND the funding are the same crypto-only bet | "Silvergate Exchange Network ('SEN'), our proprietary ... payment network for participants in the digital currency industry" |
135
+
136
+ The non-obvious fact is SI/f1+f2 together: **99.5% noninterest-bearing deposits,
137
+ ~58% from crypto exchanges** — a funding base with no contractual term and a
138
+ single correlated counterparty type. A ticker quote shows a fast-growing,
139
+ low-cost-funding bank; the filing shows a bank that could be emptied in days if
140
+ crypto sentiment turned.
141
+
142
+ ---
143
+
144
+ ## Curation-bias disclosure (read this before trusting a score on this set)
145
+
146
+ This set is **not** a representative sample of public companies, and a score on it
147
+ should not be read as a general "investment-research quality" number. The biases:
148
+
149
+ 1. **Survivorship / outcome selection.** All five companies are ones whose buried
150
+ risks later **materialized** (four failed or near-failed; one was forced into a
151
+ multi-year turnaround). They were chosen partly because that is where the
152
+ material-vs-surface distinction is sharpest, and partly because the figures are
153
+ easy to verify after the fact. A set built only on known blow-ups will reward a
154
+ loop that pattern-matches "find the downside" and will not test whether a loop
155
+ can surface a buried **positive** driver or correctly conclude a company is
156
+ sound. A production set must add survivors and upside cases.
157
+
158
+ 2. **Lens skew toward downside risk.** The 27 facts are not evenly spread across
159
+ the eight analyst lenses. Measured by `lensDistribution()`:
160
+
161
+ | Lens | Facts |
162
+ |---|---|
163
+ | liquidity | 7 |
164
+ | concentration | 6 |
165
+ | leverage | 4 |
166
+ | off-balance-sheet | 3 |
167
+ | margin-trend | 3 |
168
+ | governance | 2 |
169
+ | capital-return | 1 |
170
+ | regulatory | 1 |
171
+
172
+ Liquidity / concentration / leverage dominate (17 of 27). Governance,
173
+ capital-return, and regulatory are thin. The set therefore tests "can you find
174
+ the cash/funding/debt hole" much more than "can you find the governance or
175
+ regulatory landmine."
176
+
177
+ 3. **Sector skew toward financials + distressed consumer.** Two of five are banks
178
+ (SIVB, SI). The two banks are deliberately given **different** buried-risk
179
+ lenses — SIVB is an interest-rate / duration / off-balance-sheet story, SI is a
180
+ single-industry deposit-concentration story — so they are not redundant, but
181
+ the set still over-indexes on balance-sheet fragility and under-tests, e.g.,
182
+ technology platform risk, supply-chain concentration, or accounting-policy
183
+ aggressiveness in a healthy grower.
184
+
185
+ 4. **Grader leniency vs strictness is a knob, not a truth.** The grader counts a
186
+ fact "surfaced" on a case-insensitive substring of any synonym in a group. This
187
+ can **over-credit** a thesis that name-drops a number without understanding it
188
+ (e.g. mentions "$151.5 billion" in passing), and can **under-credit** a thesis
189
+ that explains the risk in numbers the grader did not anticipate. The synonym
190
+ groups were written to be faithful, but they are a human artifact; treat the
191
+ absolute score as ordinal (arm A vs arm B), not cardinal.
192
+
193
+ 5. **Single-source provenance.** Every fact is sourced to the company's own 10-K.
194
+ That makes provenance clean and checkable, but it means the set tests "did you
195
+ read the filing", not "did you triangulate the filing against an independent
196
+ source" (analyst reports, court filings, short-seller research). A fact that
197
+ required a second independent source to establish was dropped (below) rather
198
+ than sourced to the filing alone.
199
+
200
+ ## Drop log — items considered and NOT included (honesty over coverage)
201
+
202
+ These were candidate facts I could not independently ground to a primary source
203
+ available at the cutoff, so I **dropped them rather than guess**:
204
+
205
+ - **First Republic Bank (FRC)** — dropped as a company entirely. First Republic
206
+ was a state-chartered bank that filed its annual reports with the **FDIC**, not
207
+ on SEC EDGAR, so its 10-K is not at a `sec.gov/Archives` URL and I could not give
208
+ it the same clean, CIK-verifiable provenance as the other five. Its widely cited
209
+ figures (~$15B HTM-style loss, ~$119.5B uninsured deposits) are real but are best
210
+ sourced from the FDIC OIG Material Loss Review, a **post**-cutoff document — using
211
+ it would violate rule 3. Replaced with Silvergate, whose 10-K is on EDGAR.
212
+
213
+ - **SIVB exact total unrealized-loss footnote line** — I report the HTM gap as the
214
+ arithmetic difference of two figures printed on the balance sheet
215
+ ($91,321M − $76,169M), which is exact and on-cutoff. I did **not** include a
216
+ separately-quoted "$15.1B net unrealized loss" sentence because I did not locate
217
+ that exact phrasing in the de-tagged text; quoting a number I could not point to
218
+ verbatim would break rule 2. The computed value is conservative and checkable.
219
+
220
+ - **CVNA negative gross-profit-per-unit** — a frequently-cited Carvana red flag,
221
+ but the per-unit figure I could find cleanly was a derived/analyst number, not a
222
+ single line item I could quote verbatim from the 10-K at the cutoff. Dropped in
223
+ favor of the directly-quoted total debt, interest expense, ADESA price, related
224
+ party, and net loss.
225
+
226
+ - **PTON / SI specific debt-covenant or going-concern language** — I searched for
227
+ explicit "substantial doubt / going concern" wording in both filings and did
228
+ **not** find it at these cutoffs (it came later). I did not invent it. The facts
229
+ included are the ones actually present in the cutoff-date document.
230
+
231
+ ## How a loop is graded against this set
232
+
233
+ ```ts
234
+ import {
235
+ investmentThesisSet,
236
+ gradeCompanyAgainstText,
237
+ totalMaterialFacts,
238
+ } from '../../tests/eval/investment-thesis-set'
239
+
240
+ // For each company, the loop writes a thesis BLIND (it sees only company +
241
+ // ticker + cutoff, never the facts above). Then:
242
+ for (const company of investmentThesisSet) {
243
+ const thesisText = /* the loop's full thesis for this company */ ''
244
+ const { surfaced, total } = gradeCompanyAgainstText(company, thesisText)
245
+ // surfaced / total = held-out material facts this thesis caught.
246
+ }
247
+ // totalMaterialFacts() = 27 is the denominator across the whole set.
248
+ ```
249
+
250
+ The grader is deterministic and model-free, so the same thesis always scores the
251
+ same and the answer key never reaches a model the loop could observe — the same
252
+ firewall the deep-question exam (`tests/loops/held-out-exam.ts`) uses.
@@ -0,0 +1,119 @@
1
+ # RAG Eval Completion Roadmap
2
+
3
+ Verdict: `runRetrievalImprovementLoop()` is the right first loop, but it is only the retrieval layer.
4
+ SOTA RAG evaluation requires retrieval quality, context quality, generated-answer quality, abstention behavior, robustness, and operating budgets.
5
+
6
+ ## Research Basis
7
+
8
+ | Source | What matters for us |
9
+ | --- | --- |
10
+ | [Ragas](https://docs.ragas.io/en/stable/concepts/metrics/available_metrics/) / [paper](https://arxiv.org/abs/2309.15217) | Standard RAG eval splits retrieval and generation into context precision, context recall, faithfulness, and answer relevance. |
11
+ | [ARES](https://arxiv.org/abs/2311.09476) | Strong RAG eval scores context relevance, answer faithfulness, and answer relevance, and uses small human-labeled sets to calibrate automated judges. |
12
+ | [TruLens RAG Triad](https://www.trulens.org/getting_started/core_concepts/rag_triad/) | The minimal end-to-end triad is context relevance, groundedness, and answer relevance. |
13
+ | [RAGChecker](https://papers.nips.cc/paper_files/paper/2024/hash/27245589131d17368cccdfa990cbf16e-Abstract-Datasets_and_Benchmarks_Track.html) | Fine-grained diagnosis should separate retrieval misses, noisy context, and unsupported generated claims. |
14
+ | [BEIR](https://arxiv.org/abs/2104.08663) / TREC-style retrieval | Retrieval still needs classical rank metrics: Recall@k, Precision@k, MRR, MAP, and nDCG. |
15
+ | [CRAG](https://arxiv.org/abs/2406.04744) | Real RAG evals must include long-tail, dynamic, multi-hop, and unanswerable questions, not only easy static facts. |
16
+ | [DeepEval RAG metrics](https://deepeval.com/docs/metrics-faithfulness) | Production tools converge on faithfulness, answer relevance, and context relevance as generator/retriever checks. |
17
+
18
+ ## Current Repo Status
19
+
20
+ Done:
21
+
22
+ - `runRetrievalImprovementLoop()` auto-searches retrieval configs through `agent-eval`.
23
+ - `runRagKnowledgeImprovementLoop()` exposes the whole RAG lifecycle as typed phases:
24
+ retrieval tuning, gap diagnosis, knowledge acquisition, knowledge update, answer-quality eval, and promotion.
25
+ - Retrieval scenarios can label pages, page paths, sources, source anchors, and source spans.
26
+ - The retrieval judge reports recall, MRR, nDCG, precision@k, cost, and held-out promotion.
27
+ - The loop is tested with a real `agent-eval` run where `{ k: 2 }` beats `{ k: 1 }`.
28
+ - The lifecycle loop is tested both with pluggable phase hooks and with a real local KB update through `runKnowledgeResearchLoop()`.
29
+ - `ragAnswerQualityJudge()` and `createRagAnswerQualityHook()` score context precision/recall/relevance/sufficiency, faithfulness, answer relevance/correctness, citation support, abstention, and unsupported-answer rate.
30
+ - `normalizeExternalRagScores()` and the row exporters make Ragas, DeepEval, TruLens, RAGChecker, and custom evaluator outputs pluggable instead of hard dependencies.
31
+ - `scoreKnowledgeBaseIndex()` validates generic wiki/KB health: citation coverage, source-backed pages, stale sources, duplicate source hashes, and lint/validation errors.
32
+ - `calibrateRagAnswerJudge()` enforces the strong-vs-weak metric check before trusting a RAG answer metric.
33
+
34
+ Not done:
35
+
36
+ - Slice-level reporting for freshness, distractors, multi-hop, and long-tail cases.
37
+ - Packaged runtime adapters for browser/coding/research agents.
38
+ The lifecycle API accepts those agents as hooks today; it does not hardcode provider-specific workers.
39
+
40
+ ## Completion Criteria
41
+
42
+ ### Phase 1: Retrieval Quality
43
+
44
+ Build a retrieval eval pack with at least 100 labeled scenarios.
45
+ Use source-span labels wherever possible.
46
+
47
+ Required slices:
48
+
49
+ - 25 known-answer questions.
50
+ - 25 paraphrase questions.
51
+ - 20 distractor questions.
52
+ - 10 freshness/version questions.
53
+ - 10 multi-source questions.
54
+ - 10 unanswerable or forbidden-source questions.
55
+
56
+ Ship criteria:
57
+
58
+ - Holdout source-span Recall@5 is at least 0.90.
59
+ - Holdout nDCG@5 is at least 0.80.
60
+ - Train-to-holdout recall gap is at most 0.08.
61
+ - Stale or forbidden source hit rate is at most 0.02.
62
+ - p95 retrieval latency and cost do not regress by more than 10 percent versus baseline.
63
+
64
+ ### Phase 2: Answer Quality
65
+
66
+ Add a generated-answer eval artifact that includes query, retrieved context, answer text, citations, cost, latency, and trace ids.
67
+ Score it with deterministic checks first and LLM judges only for semantic quality.
68
+
69
+ Ship criteria:
70
+
71
+ - Faithfulness or groundedness is at least 0.95 on holdout.
72
+ - Answer relevance is at least 0.90 on holdout.
73
+ - Answer correctness is at least 0.85 on human-labeled holdout.
74
+ - Citation support is at least 0.95 for claims that cite sources.
75
+ - Unsupported-answer rate on unanswerable questions is at most 0.05.
76
+
77
+ ### Phase 3: Diagnosis
78
+
79
+ Add RAGChecker-style failure attribution.
80
+ Every failed case must classify as one primary cause.
81
+
82
+ Required failure classes:
83
+
84
+ - Retrieval miss.
85
+ - Retrieval noisy context.
86
+ - Stale retrieval.
87
+ - Missing multi-hop evidence.
88
+ - Generator ignored evidence.
89
+ - Generator hallucinated unsupported claim.
90
+ - Citation mismatch.
91
+ - Correct abstention.
92
+ - Incorrect abstention.
93
+
94
+ Ship criteria:
95
+
96
+ - Every failed eval has one primary failure class.
97
+ - At least 95 percent of generated claims can be mapped to supporting context, contradicted context, or no context.
98
+ - Reports show metrics by slice and by failure class, not only the aggregate score.
99
+
100
+ ### Phase 4: Production Loop
101
+
102
+ Run the same eval pack on every retrieval or prompt change.
103
+ Keep train/dev/holdout isolated.
104
+ Never tune on holdout.
105
+
106
+ Ship criteria:
107
+
108
+ - `runRetrievalImprovementLoop()` gates retrieval config changes.
109
+ - `runRagKnowledgeImprovementLoop()` is the default front door when retrieval changes, source acquisition, KB updates, answer checks, and promotion must run together.
110
+ - Answer-quality eval gates prompt and synthesis changes.
111
+ - Reports persist run id, commit, config hash, dataset hash, metric versions, cost, latency, and traces.
112
+ - A promoted candidate must improve the target metric without violating faithfulness, abstention, cost, or latency limits.
113
+
114
+ ## Next Implementation Steps
115
+
116
+ 1. Add slice-level aggregation helpers for freshness, distractors, multi-hop, long-tail, and unanswerable cases.
117
+ 2. Add forbidden/stale source targets to retrieval scenarios.
118
+ 3. Add packaged adapters that turn `agent-runtime` browser, research, and coding agents into `runRagKnowledgeImprovementLoop()` hooks.
119
+ 4. Add a CLI command that runs the lifecycle loop and writes a reproducible report under `.agent-knowledge/eval/`.
@@ -0,0 +1,120 @@
1
+ # Adaptive topology: spend the LLM verifier only when it pays
2
+
3
+ The cost/quality A/B (`docs/results/cost-quality.md`) found the LLM relevance
4
+ verifier's cleanliness win is dominated by **de-duplication** — which a
5
+ deterministic content-hash / canonical-URL check captures at ~none of the LLM
6
+ premium — and that an LLM check only earns its dollar on the off-scope tail. The
7
+ production move it named was: do the cheap deterministic work first, reserve the
8
+ LLM for the ambiguous tail. `createAdaptiveResearchDriver`
9
+ (`src/adaptive-driver.ts`) is that driver, and this is its measurement.
10
+
11
+ Per candidate source the adaptive driver runs three stages, cheapest first,
12
+ stopping at the first that decides:
13
+
14
+ 1. **Dedup ($0).** Reject a source whose canonical URL (scheme/`www`/trailing
15
+ slash/tracking params stripped) or normalized-text content hash matches one
16
+ already accepted this round or in the KB.
17
+ 2. **Heuristic triage ($0).** Classify a unique survivor with host/title/length
18
+ signals only: an authoritative host (arxiv, `*.edu`, `*.gov`, official docs,
19
+ github, …) with a substantial body is **kept**; an obvious spam/listicle
20
+ title or a too-thin body is **dropped**; everything else is **ambiguous**.
21
+ 3. **LLM escalation ($).** Only ambiguous survivors reach the shipped LLM
22
+ relevance verifier (`createVerifyingResearchDriver`) — one call each.
23
+
24
+ ## Live frontier, n=5 topics (glm-5.2)
25
+
26
+ Real web-research worker fetches each topic once; the same fetched proposals
27
+ (plus one planted tracking-decorated mirror of the first source, so the dedup
28
+ stage has a real duplicate to catch) are gated through all three drivers. Cost
29
+ is the per-arm `RouterClient.usage()` diff (#36). Total spend for the run:
30
+ **$0.033**.
31
+
32
+ | topic | fetched | single admit | full-LLM admit / calls / $ | adaptive admit / LLM calls / $ |
33
+ |---|---|---|---|---|
34
+ | self-speculative decoding | 3 | 3 | 1 / 3 / $0.0027 | 2 / **0** / **$0.0000** |
35
+ | rotary position embeddings | 3 | 3 | 1 / 3 / $0.0031 | 2 / **0** / **$0.0000** |
36
+ | grouped-query attention | 7 | 7 | 3 / 7 / $0.0072 | 6 / 3 / $0.0030 |
37
+ | KV-cache quantization | 5 | 5 | 3 / 5 / $0.0052 | 4 / **0** / **$0.0000** |
38
+ | LoRA fine-tuning | 7 | 7 | 4 / 7 / $0.0079 | 6 / 3 / $0.0037 |
39
+ | **total** | **25** | **25** | **12 / 25 / $0.0261** | **20 / 6 / $0.0068** |
40
+
41
+ **Cost.** Adaptive cuts LLM verifier calls **76%** (25 → 6) and dollars **74%**
42
+ ($0.0261 → $0.0068). On 3 of the 5 topics it spent **zero** LLM calls — every
43
+ unique survivor was on an authoritative host, so the $0 stages decided
44
+ everything.
45
+
46
+ ## The honest reading: adaptive is a frontier POINT, not a free lunch
47
+
48
+ Admitted-source counts (lower = cleaner KB): **single 25, adaptive 20,
49
+ full-LLM 12**. Adaptive sits **between** the two:
50
+
51
+ - It removes **5 of the 13 sources** the full-LLM judge rejects that the
52
+ single-agent loop keeps (every one of them a real duplicate caught by the $0
53
+ dedup stage — exactly the de-dup-dominated win the cost/quality result
54
+ predicted).
55
+ - It does **NOT** match full-LLM cleanliness. The remaining 8 sources full-LLM
56
+ rejects, adaptive keeps. The cause is structural and visible in the trace: on
57
+ this topic set every non-duplicate survivor landed on an authoritative host
58
+ (arxiv / github / official docs), so the heuristic **kept** it without ever
59
+ asking the LLM — and the LLM, when full-LLM did ask it, judged several of
60
+ those same authoritative pages not-quite-on-topic and dropped them. The host
61
+ prior is coarser than the relevance judge.
62
+
63
+ So the frontier tradeoff is concrete: **adaptive recovers the deterministic
64
+ de-dup half of full-LLM's cleanliness for ~26% of full-LLM's dollars, and gives
65
+ up the relevance-judgment half.** Whether that is the right point depends on the
66
+ cost of a kept-but-marginal source. If a slightly-off-topic authoritative page
67
+ is cheap to carry, adaptive dominates. If every admitted source must clear a
68
+ relevance bar, the host heuristic is too permissive and you want the full LLM —
69
+ or a tightened heuristic.
70
+
71
+ ## Where the heuristic is weak — stated plainly
72
+
73
+ The escalation count is the diagnostic. On 3 of 5 topics it was **zero**: the
74
+ heuristic never deferred to the LLM, so on those topics adaptive is a
75
+ **pure host/title/length rule**, and its cleanliness is exactly that rule's
76
+ cleanliness — no smarter than "trust arxiv/github, drop spam." That is fine when
77
+ the worker's sources are dominated by authoritative hosts (as here), but it
78
+ means the LLM's relevance judgment is contributing nothing on those topics, by
79
+ construction. The two topics where adaptive *did* escalate (grouped-query
80
+ attention, LoRA) are where some survivors were on unknown hosts — and there the
81
+ 3 LLM calls per topic are the off-scope tail the verifier is actually for.
82
+
83
+ The heuristic would mis-route in two directions a richer worker would expose,
84
+ neither seen on this authoritative-host-heavy set:
85
+
86
+ - **False keep:** an authoritative-host page that is off-topic or low-value
87
+ (an arxiv paper on an unrelated subject) is kept without the LLM ever seeing
88
+ it. The host prior cannot catch this; only the relevance judge can.
89
+ - **False drop:** a genuinely good source on an unknown blog/host with a
90
+ spam-shaped title, or under the 400-char body floor, is dropped before the LLM
91
+ could rescue it.
92
+
93
+ ## What this changes
94
+
95
+ The deployable recommendation from the cost/quality result was "deterministic
96
+ dedup first, reserve the LLM for the tail." This driver ships that and the
97
+ measurement confirms the **cost** half cleanly (76% fewer calls, 74% cheaper)
98
+ and qualifies the **quality** half honestly: adaptive captures the de-dup
99
+ cleanliness (the dominant, free win) but not the LLM's relevance cleanliness,
100
+ because the host heuristic resolves authoritative survivors without asking. For
101
+ a worker whose sources are mostly authoritative, adaptive is the right frontier
102
+ point. For one whose junk is on-topic-looking pages on unknown hosts, the
103
+ ambiguous tail grows and adaptive converges toward full-LLM cost — which is the
104
+ correct behavior: it pays for the LLM exactly when the cheap signals can't
105
+ decide.
106
+
107
+ ## Run it
108
+
109
+ ```
110
+ # offline (controlled wiring + escalates-only-ambiguous proof, no creds)
111
+ pnpm exec vitest run tests/loops/adaptive-ab.test.ts
112
+
113
+ # live three-topology frontier (needs TANGLE_API_KEY with glm-5.2 credits)
114
+ AGENT_KNOWLEDGE_LIVE=1 \
115
+ ADAPTIVE_LIVE_GOALS="self-speculative decoding|rotary position embeddings|grouped-query attention|KV-cache quantization|LoRA fine-tuning" \
116
+ pnpm exec vitest run tests/loops/adaptive-ab.test.ts -t "three-topology"
117
+ ```
118
+
119
+ A cheap one-call glm-5.2 smoke gates the multi-topic burn (fails fast if the key
120
+ or the reasoning-token floor is broken) before any dollars are spent.
@@ -0,0 +1,97 @@
1
+ # Claim-grounding: the band where the verifier earns its dollar
2
+
3
+ `docs/results/cost-quality.md` found the relevance verifier's cleanliness win is
4
+ **dominated by de-duplication** — a deterministic content-hash captures most of it
5
+ at ~none of the LLM premium. So the open question was: is there an error band where
6
+ a verifier earns its cost — something a hash AND a relevance judge both miss?
7
+
8
+ **Yes: misattributed citations.** A source that is on-topic, unique, and real, but
9
+ whose cited CLAIM does not appear in the page (the LLM wrote a plausible sentence
10
+ and hung a real URL off it). De-dup passes it (it's unique). A relevance judge
11
+ passes it (the page is on-topic). Only checking the claim against the fetched text
12
+ catches it — and that check is **deterministic text presence, $0 inference**.
13
+
14
+ ## The mode
15
+
16
+ Each proposed source now carries the specific claim it is cited for
17
+ (`withCitedClaim` → `metadata.citedClaim`). The verifier
18
+ (`createClaimGroundingVerifier`) runs `groundClaimInText(claim, pageText)` over the
19
+ `htmlToText` output of the page the worker actually fetched — verbatim, normalized
20
+ (punctuation/whitespace-insensitive), or a ≥70% content-word overlap close
21
+ paraphrase. A claim that isn't present is rejected as **misattributed**. The oracle
22
+ is text presence, not a model call, so it composes with the LLM relevance verifier
23
+ (reject off-topic AND misattributed) or runs alone at zero inference cost.
24
+
25
+ ## Live A/B (glm-5.2, real web fetch, planted misattribution band)
26
+
27
+ Real worker (glm-5.2 query-gen → live `/v1/search` → `politeFetch` → `htmlToText`)
28
+ fetches the sources once per topic; we then plant ONE misattribution per topic (real
29
+ fetched page + a deliberately-wrong claim) and run three verifier arms over the SAME
30
+ proposals. Cost diffed per arm with the #36 `RouterClient.usage()` instrumentation.
31
+
32
+ | n=5 topics | misattributions caught | marginal $ | $/topic | per-$ caught |
33
+ |---|---|---|---|---|
34
+ | no-verifier | 0 / 5 | $0.0000 | — | — |
35
+ | relevance (LLM judge) | **4 / 5** | $0.0157 | ~$0.0031 | 254 |
36
+ | claim-grounding (text) | **5 / 5** | **$0.0000** | $0 | ∞ |
37
+
38
+ Per-topic (caught relevance / grounding): self-speculative decoding 1/1, rotary
39
+ position embeddings 1/1, grouped-query attention 1/1, **KV-cache quantization 0/1**,
40
+ LoRA 1/1. (An earlier 3-topic run missed self-speculative decoding instead — the
41
+ miss moves around; it is not a fixed topic.)
42
+
43
+ **Reading.** Claim-grounding catches every misattribution at **$0**; the relevance
44
+ judge catches most but **misses one in five at ~$0.003/topic**. The miss is the
45
+ point: the relevance verifier only ever sees the page text, never the cited claim,
46
+ so it is *structurally blind* to misattribution. It catches one only by accident —
47
+ when the fabricated claim happens to also make the page read off-topic
48
+ (e.g. a "12-billion-parameter draft transformer" claim on a rotary-embeddings page).
49
+ When the fabrication stays on-topic (the KV-cache case), the judge waves it through.
50
+
51
+ So on THIS band the verifier-per-dollar comparison inverts the cost/quality result:
52
+ there, the LLM verifier bought a dedup-shaped gain a free hash already captures —
53
+ expensive for what a cheap rule does. Here the cheap, deterministic check
54
+ **dominates** the expensive judge: it catches strictly more (5/5 vs 4/5) at strictly
55
+ less ($0 vs $0.0157). The verifier earns its dollar on misattribution; it does not on
56
+ de-duplication.
57
+
58
+ ## Why this is a real correctable band (not dedup, not relevance)
59
+
60
+ - **Not de-duplication.** Every planted source has a unique URL and unique text; a
61
+ content-hash / canonical-URL dedup keeps all of them.
62
+ - **Not generic relevance.** Every planted source is on-topic; the relevance judge
63
+ (and the offline relevance stand-in) accept them. The error is in the *claim*, not
64
+ the *topic*.
65
+ - **Executable ground truth.** The check is presence/close-paraphrase of the claim
66
+ in the fetched text — deployable in production with no oracle and no model call.
67
+
68
+ The offline arm proves the floor with a controlled 4-source pool (2 grounded, 2
69
+ misattributed): claim-grounding admits **0/2** misattributions and keeps **2/2**
70
+ grounded sources, while relevance and no-verifier both admit **2/2**.
71
+
72
+ ## Threats to validity
73
+
74
+ - **n=5 topics, 1 misattribution each.** The direction (grounding ≥ relevance caught,
75
+ at ≤ cost) is asserted in the test on every run; the magnitude is small-n. The
76
+ relevance miss-rate (1/5 here, 1/3 earlier) is an existence proof of the blind
77
+ spot, not a calibrated rate.
78
+ - **Planted misattributions, not naturally-occurring ones.** Like the cost/quality
79
+ offline floor, the misattribution is injected so the band is measurable. It models
80
+ the real LLM citation-fabrication failure but does not measure its base rate in the
81
+ wild — that needs a corpus of model-written citations checked by hand.
82
+ - **The grounding oracle is conservative.** A real paraphrase whose inflected words
83
+ differ from the page ("drafts" vs "draft") can score below 0.7 and be rejected —
84
+ a false-positive misattribution flag. `minOverlap` tunes this; the worker should
85
+ cite the page's own key terms (the `createClaimDecorator` extractor is told to).
86
+
87
+ ## Run it
88
+
89
+ ```bash
90
+ # offline floor (no creds)
91
+ pnpm exec vitest run tests/loops/claim-grounding-ab.test.ts -t "offline"
92
+
93
+ # live A/B (creds-gated). A cheap glm-5.2 smoke runs BEFORE the multi-topic burn.
94
+ AGENT_KNOWLEDGE_LIVE=1 TANGLE_API_KEY=… \
95
+ CLAIM_GROUNDING_LIVE_GOALS='self-speculative decoding|rotary position embeddings|grouped-query attention|KV-cache quantization|LoRA' \
96
+ pnpm exec vitest run tests/loops/claim-grounding-ab.test.ts -t "three verifier arms"
97
+ ```
@@ -0,0 +1,27 @@
1
+ # Cost/quality: the two-agent loop's inference premium
2
+
3
+ Live 9-topic A/B (glm-5.2, budget B ≤ 4 passes/arm), measured per arm with the
4
+ router-client instrumentation. The original A/B reported only admitted-sources at
5
+ "equal passes" — which charged the two-agent verify step as one pass while it is
6
+ actually N `verifySource` LLM calls. Pricing the calls shows what that hid.
7
+
8
+ | per topic (mean) | two-agent | single-agent | ratio |
9
+ |---|---|---|---|
10
+ | LLM chat calls | 5.4 | 1.0 | ~5.4× |
11
+ | tokens (in+out) | ~4,900 | ~530 | ~9× |
12
+ | cost (USD) | ~$0.0072 | ~$0.0013 | ~5.5× |
13
+ | latency (wall) | ~37 s | ~11 s | ~3.4× |
14
+ | cleanliness Δ (single − two admitted) | — | — | +1.56, 95% CI [0.33, 2.67] |
15
+
16
+ Per-topic Δ (single − two admitted) this run: self-speculative decoding +4,
17
+ grouped-query attention 0, rotary position embeddings +1, KV-cache quantization
18
+ **−1**, LoRA +4, ring attention +2, constitutional AI +3, transformer +2, gradient
19
+ descent **−1**. Coverage 1.00 every topic, both arms.
20
+
21
+ **Reading.** The verifier buys ~1.5–2.7 fewer junk sources for roughly **5× the
22
+ dollars, 9× the tokens, and 3× the latency** — and on two topics it admitted *more*
23
+ than the single agent (the cleanliness signal is real but noisier than the +2.3 /
24
+ +2.7 of earlier runs). The cleanliness gain is dominated by de-duplication, so the
25
+ honest production move is a deterministic content-hash / canonical-URL dedup, which
26
+ captures most of the cleanliness at ~none of this premium; reserve an LLM check for
27
+ the off-scope tail. This is the cost half the "equal passes" framing left out.