@tangle-network/agent-knowledge 8.0.10 → 10.6.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 (35) hide show
  1. package/AGENTS.md +14 -2
  2. package/CHANGELOG.md +91 -0
  3. package/README.md +127 -5
  4. package/dist/benchmarks/index.d.ts +1 -1
  5. package/dist/benchmarks/index.js +1 -1
  6. package/dist/{benchmarks-B_07vX0Q.js → benchmarks-B6fCb6AD.js} +2 -2
  7. package/dist/{benchmarks-B_07vX0Q.js.map → benchmarks-B6fCb6AD.js.map} +1 -1
  8. package/dist/cli.js +53 -21
  9. package/dist/cli.js.map +1 -1
  10. package/dist/{index-DypNCZtP.d.ts → index-DZeFm-BP.d.ts} +2 -2
  11. package/dist/{index-DypNCZtP.d.ts.map → index-DZeFm-BP.d.ts.map} +1 -1
  12. package/dist/{index-Ij4giqqj.d.ts → index-eDsIXWyM.d.ts} +3 -3
  13. package/dist/{index-Ij4giqqj.d.ts.map → index-eDsIXWyM.d.ts.map} +1 -1
  14. package/dist/index.d.ts +910 -290
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +1009 -382
  17. package/dist/index.js.map +1 -1
  18. package/dist/{inspect-0tmv3xV8.js → inspect-DALsvG10.js} +680 -108
  19. package/dist/inspect-DALsvG10.js.map +1 -0
  20. package/dist/memory/index.d.ts +2 -2
  21. package/dist/memory/index.js +2 -2
  22. package/dist/{memory-BPgPIEhj.js → memory-BRGsy2QN.js} +2 -2
  23. package/dist/{memory-BPgPIEhj.js.map → memory-BRGsy2QN.js.map} +1 -1
  24. package/dist/search-Cw6eYfSd.js +258 -0
  25. package/dist/search-Cw6eYfSd.js.map +1 -0
  26. package/dist/{types-CTT16XnO.d.ts → types-m2QB86fF.d.ts} +17 -3
  27. package/dist/types-m2QB86fF.d.ts.map +1 -0
  28. package/dist/viz/index.d.ts +1 -1
  29. package/docs/architecture.md +1 -0
  30. package/docs/knowledge-use-receipts.md +50 -12
  31. package/package.json +1 -1
  32. package/dist/inspect-0tmv3xV8.js.map +0 -1
  33. package/dist/search-CtVJ0PKX.js +0 -132
  34. package/dist/search-CtVJ0PKX.js.map +0 -1
  35. package/dist/types-CTT16XnO.d.ts.map +0 -1
package/AGENTS.md CHANGED
@@ -31,9 +31,13 @@ Otherwise, it stays in this package.
31
31
  ## Rules
32
32
 
33
33
  - Register sources before citing them: `agent-knowledge source-add <path>`.
34
- - Generated pages live under `knowledge/`.
34
+ - Generated pages live under `knowledge/` unless the caller names another root-relative directory with `pagesDirectory` (CLI `--pages-dir`).
35
35
  - Raw evidence lives under `raw/sources/` and should not be edited.
36
+ - Pass `intake` to `applyKnowledgeWriteBlocks` (CLI `--intake`) so a write that duplicates a visible page or cites a page id that exists nowhere is refused before any byte lands.
37
+ - Build the retrieval brief with `buildKnowledgeBrief` before a run starts, and mint a receipt from `brief.results`, so retrieval is recorded rather than instructed.
36
38
  - Run `agent-knowledge index` after page changes.
39
+ - Run `planInvalidationPropagation` + `formatKnowledgeInvalidationProposal` after grading, so every citer of a refuted page records `citesInvalidated`.
40
+ - Move knowledge into shared scope only with `promoteRunScopedPages`. A run never writes the shared root itself.
37
41
  - Run `agent-knowledge lint` before trusting or promoting knowledge.
38
42
  - Treat `missing-source` lint findings as blocking.
39
43
  - Use `--json` for automation.
@@ -71,7 +75,15 @@ Sourced knowledge with links to [[Related Page]].
71
75
  ---END FILE---
72
76
  ```
73
77
 
74
- The parser rejects absolute paths, `..`, control characters, and writes outside `knowledge/`.
78
+ The parser rejects absolute paths, `..`, control characters, and writes outside the pages directory (`knowledge/` by default).
79
+ Pass the same `pagesDirectory` to `applyKnowledgeWriteBlocks` that the reader uses; the file transaction enforces the same bound.
80
+
81
+ ## Tool Boundary
82
+
83
+ Expose knowledge to an agent with `createKnowledgeTools({ stores, runId, retrieverVersion })`.
84
+ It returns `ToolDefinition[]` from `@tangle-network/agent-interface`.
85
+ This package owns every handler; a runtime transports the definitions and the calls and runs no knowledge loop.
86
+ The application supplies the roots, the lineage authority, and the effect authorization.
75
87
 
76
88
  ## Eval Boundary
77
89
 
package/CHANGELOG.md CHANGED
@@ -1,5 +1,96 @@
1
1
  # Changelog
2
2
 
3
+ ## 10.6.0 — 2026-08-21
4
+
5
+ ### Added
6
+
7
+ - Add `createKnowledgeTools({ stores, runId, retrieverVersion, ... })`, returning provider-neutral `ToolDefinition[]` for `knowledge_search`, `knowledge_read`, `knowledge_record`, and `knowledge_resolve`. This package owns every handler; a runtime transports the definitions and the calls and runs no knowledge loop. `knowledge_search` mints a retrieval receipt on every call and hands it to the optional `recordRetrieval` sink, so retrieval is recorded rather than claimed. `knowledge_record` applies the write intake gate. `knowledge_read` reports an id visible at two origins as `ambiguous` with both candidates and never chooses one.
8
+ - Add `createKnowledgeRetrievalDisposition` and `verifyKnowledgeRetrievalDisposition`, the record for a retrieval that influenced nothing. A use receipt requires a selected rank, so a retrieval with no use previously left no record at all and "no evidence of use" was indistinguishable from "evidence of no use". The disposition binds to one `retrievalReceiptDigest`, carries `relation: 'irrelevant' | 'no-use'`, and has no rank.
9
+
10
+ ## 10.5.0 — 2026-08-21
11
+
12
+ ### Added
13
+
14
+ - Add `promoteRunScopedPages(stores, runId, { pageIds, sharedRoot, actor, reason })`, the only path from run scope into the curated shared store. It carries the closure of the run-local pages a promoted page cites, each keeping its own evidence fields exactly as written, and refuses the promotion when any citation would not resolve in the target — including one qualified with `here::` or `inherited:`, whose scope does not exist in shared. Pages travel as the bytes their store holds, so a promoted page has one digest in both scopes.
15
+ - Every promotion writes a record at `<shared>/.agent-knowledge/promotions/<digest>.json` naming the source run, each page digest, which pages were requested and which were carried support, the actor, the reason, and the time. The record is content-addressed, so re-running one promotion writes the same bytes at the same path. Read it back with `loadKnowledgePromotionRecord(sharedRoot, digest)`.
16
+ - Add `RunScopedStores.storePath(runId)`. Promotion carries a page unchanged, which needs the store root a chain read hides.
17
+
18
+ ## 10.4.0 — 2026-08-21
19
+
20
+ ### Added
21
+
22
+ - Add `buildKnowledgeBrief(visiblePages, question, options)`. It ranks the knowledge one question can see, renders a deterministic `- [id] title — snippet` line per page, and returns `results` in exactly the shape `createKnowledgeRetrievalReceipt` takes, so a retrieval is recorded rather than claimed. It is pure: no clock, no filesystem, no network. `excludeInvalidated` defaults to `true`, the opposite of `searchKnowledge`, because a brief offers every page it names with an id ready to cite.
23
+ - The brief also returns `retrieverId` and `retrieverConfigDigest`, the retriever identity a receipt needs, so a caller declares only the running package version.
24
+ - Add `searchKnowledgePages(pages, query, options)`, the ranking over a page set that is not a built index, such as the chain a run can see. `searchKnowledge(index, ...)` is now this function over `index.pages`, so the two entry points cannot drift.
25
+
26
+ ## 10.3.0 — 2026-08-21
27
+
28
+ ### Added
29
+
30
+ - Add `planInvalidationPropagation(visiblePages)` and `formatKnowledgeInvalidationProposal(plan)`. Every page authored in the target store that cites a page carrying an `invalidation` is stamped with `citesInvalidated: [ids]`; a citation whose target was revalidated has the stamp removed. The plan is a diff, so a second pass over an already stamped store produces no mutation. Only `here` pages are stamped, because a run does not write the stores it inherits or shares.
31
+ - Add the `cites-invalidated` lint finding, a warning naming every live citation from a page into a page its own evidence refuted.
32
+ - Add `SearchKnowledgeOptions.excludeInvalidated`, which drops refuted pages from a result set. It defaults to `false`, so what search returns does not change for an existing caller.
33
+ - Add `originatedPages(pages, origin?)`, which presents plain pages as a visibility chain of one origin, so citation resolution, the write intake gate, and invalidation propagation take one page shape whether or not the caller runs run-scoped stores.
34
+
35
+ ## 10.2.0 — 2026-08-21
36
+
37
+ ### Added
38
+
39
+ - Add `assertKnowledgeWriteIntake(candidates, { visiblePages, nearDuplicates?, citations? })`, a write-time gate that refuses a page which restates visible knowledge without relating itself to it, and a page whose citation resolves to no visible page. A duplicate is cleared by citing the matched page, naming it in `contradicts`, or reusing its id so the write updates it. The candidates are part of the corpus both checks see, so a batch may cite a page it writes in the same call.
40
+ - Add the `intake` option to `applyKnowledgeWriteBlocks` and `applyKnowledgeWriteBlocksFile`, and `--intake` / `--intake-threshold` to `agent-knowledge apply-write-blocks`. The gate runs inside the write lock and refuses the whole proposal, so a refused write leaves nothing on disk.
41
+ - Add `knowledgePageFromMarkdown(path, content, pagesDirectory?)` and `isKnowledgePagePath(path)`. The reader and the intake gate build pages through this one constructor, so a gate judges exactly what the store loads back.
42
+
43
+ ## 10.1.0 — 2026-08-21
44
+
45
+ ### Changed
46
+
47
+ - `searchKnowledge` ranks its lexical list with Okapi BM25 instead of the hand-weighted substring scorer. A term that occurs in most pages is discounted by inverse document frequency, term frequency saturates, and a long page no longer outranks a short one by repetition. An exact title or path match, a title that contains the query, and a body that contains the query stay ahead of a bag-of-words match, so exact lookups keep their order. The hit shape, `normalizedScore`, `snippet`, `reasons`, the reciprocal-rank fusion with the link graph, and the path tie-break are unchanged. There is no option to select the previous scorer.
48
+ - The retrieval-eval retriever, the CLI `search` command, and `FileSystemSearchProvider` inherit the new ranking. The provider builds one lexical index per page index and drops both together on `refresh` or `invalidate()`.
49
+
50
+ ### Added
51
+
52
+ - Add `buildKnowledgeLexicalIndex(pages, { tokenize, fieldBoosts })` and `scoreBm25(index, tokens, { k1, b })` in `src/lexical-index.ts`: a pure inverted index with field-boosted term frequencies, document lengths, average document length, and document count. No dependency and no native module, so the package stays importable at the edge.
53
+ - Add `tokenizeText`, the token stream that indexing and querying share; `tokenizeQuery` is its distinct-token form and moves to the same module, so one tokenizer serves both sides and the vocabularies cannot drift.
54
+ - Add `KNOWLEDGE_SEARCH_RETRIEVER_ID` (`bm25-rrf-v1`), the retriever identity to declare in a retrieval receipt minted from `searchKnowledge` results.
55
+ - `SearchKnowledgeOptions.lexicalIndex` accepts an index built from exactly the searched pages, for a caller that queries one page index repeatedly. A mismatched index is refused.
56
+
57
+ ## 10.0.0 — 2026-08-20
58
+
59
+ ### Breaking Changes
60
+
61
+ - **A retrieval receipt now references the visibility snapshot instead of embedding it.** `KnowledgeRetrievalReceipt.visibility` becomes `KnowledgeVisibilityRef { snapshotDigest, pageCount, artifact?: { uri, digest, byteLength } }`, and `KNOWLEDGE_USE_RECEIPT_SCHEMA_VERSION` becomes `2.0.0`. Every verifier refuses a `1.0.0` record, which has no reader. A receipt is now bounded by its results rather than by the visible page count.
62
+ - **`createKnowledgeRetrievalReceipt` takes `visibility: KnowledgeVisibilitySnapshot` instead of `visiblePages`.** Create the snapshot once with `createKnowledgeVisibilitySnapshot` and reuse it for every retrieval over that view. Results still join against the snapshot entries, so a result absent from the view is refused as before. Repeated retrievals over one snapshot no longer re-serialize or re-hash the page inventory.
63
+ - **The verification claim is split, so a check cannot overstate what it proved.** `verifyKnowledgeRetrievalReceipt(receipt)` proves receipt shape, canonical digest, rank continuity, finite scores, and a well-formed reference, and makes no result-to-snapshot claim. `assertKnowledgeRetrievalMatchesVisibility(receipt, snapshot | visiblePages)` recomputes the snapshot digest and page count and joins every returned result.
64
+
65
+ ### Added
66
+
67
+ - Add `assertKnowledgeRetrievalMatchesVisibilityArtifact(receipt, loadArtifact)`, which loads the referenced snapshot artifact, checks its stored-byte digest and byte length, decodes and verifies the snapshot, and then proves the same join. A snapshot that cannot be obtained raises `KnowledgeVisibilityUnavailableError` with an explicit reason; it is never treated as an empty snapshot.
68
+ - Add `verifyKnowledgeVisibilitySnapshot`, `encodeKnowledgeVisibilitySnapshot`, `decodeKnowledgeVisibilitySnapshot`, and `knowledgeVisibilityArtifactRef({ uri, bytes })` so an adapter persists and reloads a snapshot without inventing its serialization.
69
+
70
+ ## 9.0.0 — 2026-08-20
71
+
72
+ ### Breaking Changes
73
+
74
+ - Rename `LoadKnowledgePagesOptions` to `KnowledgePagesOptions`. The same `{ pagesDirectory }` option now drives the write path as well as the reader, so the `Load` name no longer described it. Replace the type name; the option field is unchanged.
75
+
76
+ **What to do:** import `KnowledgePagesOptions` where `LoadKnowledgePagesOptions` was imported. No runtime behavior changes for a caller that names no directory.
77
+
78
+ ### Added
79
+
80
+ - `applyKnowledgeWriteBlocks(root, text, { pagesDirectory })` and `applyKnowledgeWriteBlocksFile` accept the pages directory the reader accepts. The parser allows only `FILE` blocks under `<pagesDirectory>/`, and the file transaction enforces the same bound, so a store laid out as `kb/pages/<line>/` can use the safe-write protocol.
81
+ - `buildKnowledgeIndex`, `writeKnowledgeIndex`, `FileSystemSearchProviderOptions`, and `RunScopedStoresOptions` take `pagesDirectory`, so the custom directory is indexed, searched, and read through the lineage chain. The CLI takes `--pages-dir <dir>` on `apply-write-blocks`, `index`, `search`, and every other index-reading command.
82
+ - `normalizePagesDirectory` and `DEFAULT_PAGES_DIRECTORY` are exported. The normalizer refuses `..`, `.` and empty segments, absolute paths, drive letters, control characters, and the package-owned `.agent-knowledge` and `raw` trees, because the value is a write allowlist prefix as well as a read location.
83
+ - A knowledge file transaction journals the pages directory it was prepared under (`pagesDirectory`, absent for the default), so recovery and replay enforce the same allowlist as the prepare step. The default journal is byte-identical to before.
84
+
85
+ ## 8.1.0 — 2026-08-20
86
+
87
+ ### Added
88
+
89
+ - Add `buildKnowledgeRelationGraph({ nodes, relations })`, which builds a labeled multi-edge graph from `KnowledgeRelation[]` and caller-declared nodes with a `kind`, `label`, and `metadata`. The graph keeps one edge per `(sourceId, targetId, predicate)`; a repeated triple is accepted only when it is byte-identical, and an endpoint outside the declared nodes is refused.
90
+ - Add `neighbors`, `walk`, and `isReachable` over that graph, filtered by predicate and direction (`out`, `in`, `both`), with a cycle-safe breadth-first walk.
91
+ - Add `KnowledgeRelationSchema`, `KnowledgeRelationNodeSchema`, and `KnowledgeRelationGraphSchema`, with an explicit `metadata` field so a persisted graph round-trips. `KnowledgeBaseCandidateSchema` uses the same relation schema.
92
+ - Add `knowledgePageRelations(pages)`, the labeled page relations (`wikilink`, `citation`, `shared-source`, `contradicts`) that `buildKnowledgeGraph` now collapses into its weighted edges; the collapsed graph bytes are unchanged.
93
+
3
94
  ## 8.0.10 — 2026-08-19
4
95
 
5
96
  ### Changed
package/README.md CHANGED
@@ -78,10 +78,19 @@ const search = createFileSystemSearchProvider({ root, index })
78
78
  console.log(await search.search('How long is the refund window?', { limit: 3 }))
79
79
  ```
80
80
 
81
- The provider uses the package's local text search.
81
+ The provider ranks with BM25 over title, path, and body, keeps exact-title and phrase matches ahead of bag-of-words matches, and fuses that list with link and shared-source structure by reciprocal rank fusion.
82
+ It builds the lexical index once per page index and drops both together on `refresh` or `invalidate()`.
83
+ Declare `KNOWLEDGE_SEARCH_RETRIEVER_ID` (`bm25-rrf-v1`) as the retriever id when minting a retrieval receipt from these results.
82
84
  Pass `refresh: 'always'` to rebuild its index before every query, or call `invalidate()` after changing files.
83
85
  Use `asRetrievalEvalRetriever()` to send the same search path into retrieval tests.
84
86
 
87
+ `knowledgePageRelations(pages)` lists the labeled relations between pages (`wikilink`, `citation`, `shared-source`, `contradicts`), and `buildKnowledgeGraph` collapses them into the weighted page graph stored in the index.
88
+ For caller-defined provenance (runs, claims, models, any predicate), `buildKnowledgeRelationGraph({ nodes, relations })` keeps one edge per `(sourceId, targetId, predicate)`, refuses a conflicting repeat or an undeclared endpoint, and `neighbors`, `walk`, and `isReachable` query it by predicate and direction; `KnowledgeRelationGraphSchema` round-trips a persisted graph with its metadata.
89
+
90
+ Pages live under `knowledge/` unless you name another root-relative directory.
91
+ `loadKnowledgePages`, `buildKnowledgeIndex`, `writeKnowledgeIndex`, `applyKnowledgeWriteBlocks`, `createFileSystemSearchProvider`, and `createRunScopedStores` all take one `pagesDirectory` option (`KnowledgePagesOptions`), so a store laid out as `kb/pages/<line>/` is read, indexed, searched, chained, and written through the same value.
92
+ The write protocol and the file transaction refuse a `FILE` block outside `<pagesDirectory>/`, and `normalizePagesDirectory` refuses `..`, absolute paths, drive letters, and the package-owned `.agent-knowledge` and `raw` trees.
93
+
85
94
  ## Prove what the agent saw and used
86
95
 
87
96
  A page existing in a knowledge base, a page appearing in retrieval results, and a page influencing a decision are three different facts. The receipt APIs preserve those joins without pretending they prove the page is true or that it improved the outcome.
@@ -91,16 +100,24 @@ import {
91
100
  createKnowledgeRetrievalReceipt,
92
101
  createKnowledgeUseReceipt,
93
102
  createKnowledgeVisibilitySnapshot,
103
+ encodeKnowledgeVisibilitySnapshot,
104
+ KNOWLEDGE_SEARCH_RETRIEVER_ID,
105
+ knowledgeVisibilityArtifactRef,
94
106
  } from '@tangle-network/agent-knowledge'
95
107
 
96
- const visiblePages = await runStores.loadChain(runId)
97
- const visibility = createKnowledgeVisibilitySnapshot(visiblePages)
108
+ const visibility = createKnowledgeVisibilitySnapshot(await runStores.loadChain(runId))
109
+ const bytes = encodeKnowledgeVisibilitySnapshot(visibility)
110
+ await artifacts.put('artifact://run/visibility.json', bytes)
98
111
 
99
112
  const retrieval = createKnowledgeRetrievalReceipt({
100
113
  runId,
101
114
  query: 'prior verifier obstruction',
102
- retriever: { id: 'hybrid-search', version: '1.0.0', configDigest },
103
- visiblePages,
115
+ retriever: { id: KNOWLEDGE_SEARCH_RETRIEVER_ID, version: '1.0.0', configDigest },
116
+ visibility,
117
+ visibilityArtifact: knowledgeVisibilityArtifactRef({
118
+ uri: 'artifact://run/visibility.json',
119
+ bytes,
120
+ }),
104
121
  results,
105
122
  })
106
123
 
@@ -116,6 +133,9 @@ console.log(visibility.snapshotDigest, retrieval.receiptDigest, use.receiptDiges
116
133
 
117
134
  ELI5: the visibility snapshot is the bookshelf the agent was allowed to see, the retrieval receipt is the exact books search handed back, and the use receipt records which returned book the agent attached to a downstream decision or artifact.
118
135
 
136
+ Create the snapshot once per knowledge view and reuse it: the retrieval receipt stores the snapshot's digest, page count, and storage locator, not its pages, so repeated queries over one view do not re-serialize the inventory.
137
+ `verifyKnowledgeRetrievalReceipt` proves the receipt itself; `assertKnowledgeRetrievalMatchesVisibility` and `assertKnowledgeRetrievalMatchesVisibilityArtifact` prove that every returned result occurs in that exact snapshot.
138
+
119
139
  The receipts are content-addressed and mutation-sensitive. They do **not** establish correctness, novelty, compliance, or causal lift; Eval owns those later judgments. Read [knowledge retrieval and use receipts](docs/knowledge-use-receipts.md) for the complete proof boundary, trace attributes, and experiment design.
120
140
 
121
141
  ## Use the CLI
@@ -132,6 +152,20 @@ pnpm exec agent-knowledge validate --strict --root ./support-kb
132
152
  ```
133
153
 
134
154
  Run `pnpm exec agent-knowledge help` for every command.
155
+ Pass `--pages-dir <dir>` to `apply-write-blocks`, `index`, `search`, and the other index-reading commands when the pages live outside `knowledge/`.
156
+
157
+ ## Gate a write before it lands
158
+
159
+ A store degrades in two ways no later report reverses: a page restates knowledge already in the store without relating itself to it, and a page cites an id that exists nowhere.
160
+ `assertKnowledgeWriteIntake(candidates, { visiblePages })` refuses both, and `applyKnowledgeWriteBlocks(root, text, { intake })` runs it inside the write lock, so a refused proposal writes nothing.
161
+
162
+ ```bash
163
+ pnpm exec agent-knowledge apply-write-blocks ./proposal.txt --root ./support-kb --intake
164
+ ```
165
+
166
+ A duplicate is cleared by one authoring action, each of which turns the duplication into structure: cite the matched page, name it in `contradicts`, or give the candidate that page's id so the write updates it.
167
+ The candidates are part of the corpus both checks see, so a proposal may cite a page it writes in the same call.
168
+ `--intake-threshold` sets the duplicate similarity; the near-duplicate detector's own default applies when it is absent.
135
169
 
136
170
  The default layout is:
137
171
 
@@ -144,6 +178,94 @@ support-kb/
144
178
  index.json # generated search index
145
179
  ```
146
180
 
181
+ ## Give an agent the tools
182
+
183
+ `createKnowledgeTools` returns provider-neutral `ToolDefinition[]` for search, read, record, and resolve. Knowledge owns what each tool does; a runtime only transports the definitions and the calls.
184
+
185
+ ```ts
186
+ const tools = createKnowledgeTools({
187
+ stores,
188
+ runId,
189
+ retrieverVersion,
190
+ actorId,
191
+ intake: {},
192
+ recordRetrieval: (receipt) => ledger.append(receipt),
193
+ })
194
+ ```
195
+
196
+ `knowledge_search` builds a brief and mints a retrieval receipt on every call, so retrieval is recorded by the infrastructure rather than claimed by the run.
197
+ `knowledge_read` reports an id visible at two origins as `ambiguous` with both candidates, and never chooses one.
198
+ `knowledge_record` writes into this run's store through the intake gate.
199
+ `knowledge_resolve` returns the resolution status of each reference.
200
+
201
+ Supply `retrieverVersion` yourself: a bundled build cannot read its own manifest, and a receipt that guessed the version would be a receipt that lies about what ranked the results.
202
+
203
+ When a retrieval influences nothing, record that too:
204
+
205
+ ```ts
206
+ createKnowledgeRetrievalDisposition({
207
+ retrieval: receipt,
208
+ relation: 'no-use',
209
+ consumer: { kind: 'decision', uri },
210
+ })
211
+ ```
212
+
213
+ A use receipt requires a selected rank, so without this record a retrieval that influenced nothing is indistinguishable from a retrieval nobody bothered to record. `irrelevant` means the results did not bear on the question; `no-use` means they did and the consumer still used none of them.
214
+
215
+ ## Promote a run's knowledge into the shared store
216
+
217
+ A run writes only its own store. Knowledge reaches the curated shared store through one call, and every promotion leaves a record:
218
+
219
+ ```ts
220
+ const record = await promoteRunScopedPages(stores, runId, {
221
+ pageIds: ['latency-budget'],
222
+ sharedRoot,
223
+ actor: 'drew',
224
+ reason: 'The measurement replicated twice.',
225
+ })
226
+ ```
227
+
228
+ A claim's cited support travels with it. Promoting a claim and leaving the run-local pages it cites behind is what turns a resolved citation into a dangling one, so the closure of cited pages is carried, each keeping its own evidence fields exactly as written — a promoted claim cannot inherit a confidence its support does not carry.
229
+ The promotion is refused when any citation would not resolve in the shared store, including a citation qualified with `here::` or `inherited:`, whose scope does not exist there.
230
+ Pages travel as the bytes their store holds, so a promoted page has one digest in both scopes.
231
+ The record lands at `<shared>/.agent-knowledge/promotions/<digest>.json` with the source run, every page digest, which pages were requested and which were carried support, the actor, the reason, and the time. Re-running the same promotion writes the same record at the same path.
232
+
233
+ ## Brief a run before its first token
234
+
235
+ "Search the store first" is an instruction an agent may or may not follow. A brief is infrastructure: it retrieves the settled knowledge a question can reach and hands it over with the ids a later write must cite.
236
+
237
+ ```ts
238
+ const brief = buildKnowledgeBrief(originatedPages(await loadKnowledgePages(root)), question)
239
+ const receipt = createKnowledgeRetrievalReceipt({
240
+ runId,
241
+ query: brief.question,
242
+ retriever: { id: brief.retrieverId, version, configDigest: brief.retrieverConfigDigest },
243
+ visibility: createKnowledgeVisibilitySnapshot(visiblePages),
244
+ results: brief.results,
245
+ })
246
+ ```
247
+
248
+ `brief.text` is deterministic Markdown, one `- [id] title — snippet` line per page in rank order.
249
+ `brief.results` is the exact shape `createKnowledgeRetrievalReceipt` takes, so what an actor was given is recorded rather than asserted.
250
+ `excludeInvalidated` defaults to **true** here, the opposite of `searchKnowledge`: a brief offers every page it names with an id ready to cite, so a refuted page in it invites a run to build on a dead claim.
251
+ `maxChars` bounds the brief, and a page whose line does not fit is left out of `text`, `hits`, `citationIds`, and `results` alike, so all four always describe one identical set.
252
+
253
+ ## Propagate an invalidation
254
+
255
+ A page whose own evidence refuted it carries an `invalidation`. A reader who arrives through a citation never meets that verdict, so run the propagation pass after grading:
256
+
257
+ ```ts
258
+ const plan = planInvalidationPropagation(originatedPages(await loadKnowledgePages(root)))
259
+ if (plan.stamps.length > 0) {
260
+ await applyKnowledgeWriteBlocks(root, formatKnowledgeInvalidationProposal(plan))
261
+ }
262
+ ```
263
+
264
+ Each stamped page records `citesInvalidated: [ids]` in its frontmatter, and nothing else changes.
265
+ The plan is a diff, so a second pass over an already stamped store produces no mutation, and a citation whose target was revalidated has its stamp removed.
266
+ `agent-knowledge lint` reports a `cites-invalidated` warning for every live citation into a refuted page, and `searchKnowledge(index, query, { excludeInvalidated: true })` drops the refuted pages from a result set.
267
+ The default stays `false`: a caller reading history needs them.
268
+
147
269
  ## Improve a live knowledge base
148
270
 
149
271
  `improveKnowledgeBase` creates an isolated candidate, runs your update callback, measures the candidate, and returns an exact candidate reference.
@@ -1,2 +1,2 @@
1
- import { A as KnowledgeBenchmarkResponder, B as KnowledgeMemoryEvent, C as KnowledgeBenchmarkArtifact, Ct as createInMemoryBenchmarkAdapter, D as KnowledgeBenchmarkEvaluation, E as KnowledgeBenchmarkDistribution, F as KnowledgeBenchmarkSplit, G as MemoryAdapterBenchmarkCandidate, H as KnowledgeRetrievalBenchmarkCase, I as KnowledgeBenchmarkTaskKind, J as RunKnowledgeBenchmarkSuiteResult, K as MemoryAdapterBenchmarkRankingRow, L as KnowledgeClaimMatcher, M as KnowledgeBenchmarkSliceSummary, N as KnowledgeBenchmarkSource, O as KnowledgeBenchmarkFamily, P as KnowledgeBenchmarkSpec, R as KnowledgeMemoryBenchmarkCase, S as KnowledgeAnswerBenchmarkTaskKind, T as KnowledgeBenchmarkCaseBase, U as KnowledgeRetrievalBenchmarkQrel, V as KnowledgeMemoryFactMatcher, W as KnowledgeRetrievalBenchmarkQuery, X as RunMemoryAdapterBenchmarkResult, Y as RunMemoryAdapterBenchmarkOptions, _ as buildIndustryRagBenchmarkSmokeCases, a as runKnowledgeBenchmarkSuite, b as BuildRetrievalBenchmarkCasesFromQrelsOptions, c as buildRetrievalBenchmarkCasesFromQrels, d as summarizeKnowledgeBenchmarkCampaign, f as runMemoryAdapterBenchmark, g as buildIndustryMemoryBenchmarkSmokeCases, h as buildFirstPartyMemoryLifecycleBenchmarkCases, i as renderKnowledgeBenchmarkReportMarkdown, j as KnowledgeBenchmarkScenario, k as KnowledgeBenchmarkReport, l as parseKnowledgeBenchmarkJsonl, m as INDUSTRY_RAG_BENCHMARKS, n as buildKnowledgeBenchmarkScenarios, o as scoreKnowledgeBenchmarkArtifact, p as INDUSTRY_MEMORY_BENCHMARKS, q as RunKnowledgeBenchmarkSuiteOptions, r as knowledgeBenchmarkJudge, s as scoreMemoryBenchmarkArtifact, t as isKnowledgeMemoryBenchmarkCase, u as parseKnowledgeBenchmarkQrels, v as respondToIndustryMemoryBenchmarkSmokeCase, w as KnowledgeBenchmarkCase, wt as createNoopMemoryBenchmarkAdapter, x as KnowledgeAnswerBenchmarkCase, y as respondToIndustryRagBenchmarkSmokeCase, z as KnowledgeMemoryBenchmarkTaskKind } from "../index-DypNCZtP.js";
1
+ import { A as KnowledgeBenchmarkResponder, B as KnowledgeMemoryEvent, C as KnowledgeBenchmarkArtifact, Ct as createInMemoryBenchmarkAdapter, D as KnowledgeBenchmarkEvaluation, E as KnowledgeBenchmarkDistribution, F as KnowledgeBenchmarkSplit, G as MemoryAdapterBenchmarkCandidate, H as KnowledgeRetrievalBenchmarkCase, I as KnowledgeBenchmarkTaskKind, J as RunKnowledgeBenchmarkSuiteResult, K as MemoryAdapterBenchmarkRankingRow, L as KnowledgeClaimMatcher, M as KnowledgeBenchmarkSliceSummary, N as KnowledgeBenchmarkSource, O as KnowledgeBenchmarkFamily, P as KnowledgeBenchmarkSpec, R as KnowledgeMemoryBenchmarkCase, S as KnowledgeAnswerBenchmarkTaskKind, T as KnowledgeBenchmarkCaseBase, U as KnowledgeRetrievalBenchmarkQrel, V as KnowledgeMemoryFactMatcher, W as KnowledgeRetrievalBenchmarkQuery, X as RunMemoryAdapterBenchmarkResult, Y as RunMemoryAdapterBenchmarkOptions, _ as buildIndustryRagBenchmarkSmokeCases, a as runKnowledgeBenchmarkSuite, b as BuildRetrievalBenchmarkCasesFromQrelsOptions, c as buildRetrievalBenchmarkCasesFromQrels, d as summarizeKnowledgeBenchmarkCampaign, f as runMemoryAdapterBenchmark, g as buildIndustryMemoryBenchmarkSmokeCases, h as buildFirstPartyMemoryLifecycleBenchmarkCases, i as renderKnowledgeBenchmarkReportMarkdown, j as KnowledgeBenchmarkScenario, k as KnowledgeBenchmarkReport, l as parseKnowledgeBenchmarkJsonl, m as INDUSTRY_RAG_BENCHMARKS, n as buildKnowledgeBenchmarkScenarios, o as scoreKnowledgeBenchmarkArtifact, p as INDUSTRY_MEMORY_BENCHMARKS, q as RunKnowledgeBenchmarkSuiteOptions, r as knowledgeBenchmarkJudge, s as scoreMemoryBenchmarkArtifact, t as isKnowledgeMemoryBenchmarkCase, u as parseKnowledgeBenchmarkQrels, v as respondToIndustryMemoryBenchmarkSmokeCase, w as KnowledgeBenchmarkCase, wt as createNoopMemoryBenchmarkAdapter, x as KnowledgeAnswerBenchmarkCase, y as respondToIndustryRagBenchmarkSmokeCase, z as KnowledgeMemoryBenchmarkTaskKind } from "../index-DZeFm-BP.js";
2
2
  export { type BuildRetrievalBenchmarkCasesFromQrelsOptions, INDUSTRY_MEMORY_BENCHMARKS, INDUSTRY_RAG_BENCHMARKS, type KnowledgeAnswerBenchmarkCase, type KnowledgeAnswerBenchmarkTaskKind, type KnowledgeBenchmarkArtifact, type KnowledgeBenchmarkCase, type KnowledgeBenchmarkCaseBase, type KnowledgeBenchmarkDistribution, type KnowledgeBenchmarkEvaluation, type KnowledgeBenchmarkFamily, type KnowledgeBenchmarkReport, type KnowledgeBenchmarkResponder, type KnowledgeBenchmarkScenario, type KnowledgeBenchmarkSliceSummary, type KnowledgeBenchmarkSource, type KnowledgeBenchmarkSpec, type KnowledgeBenchmarkSplit, type KnowledgeBenchmarkTaskKind, type KnowledgeClaimMatcher, type KnowledgeMemoryBenchmarkCase, type KnowledgeMemoryBenchmarkTaskKind, type KnowledgeMemoryEvent, type KnowledgeMemoryFactMatcher, type KnowledgeRetrievalBenchmarkCase, type KnowledgeRetrievalBenchmarkQrel, type KnowledgeRetrievalBenchmarkQuery, type MemoryAdapterBenchmarkCandidate, type MemoryAdapterBenchmarkRankingRow, type RunKnowledgeBenchmarkSuiteOptions, type RunKnowledgeBenchmarkSuiteResult, type RunMemoryAdapterBenchmarkOptions, type RunMemoryAdapterBenchmarkResult, buildFirstPartyMemoryLifecycleBenchmarkCases, buildIndustryMemoryBenchmarkSmokeCases, buildIndustryRagBenchmarkSmokeCases, buildKnowledgeBenchmarkScenarios, buildRetrievalBenchmarkCasesFromQrels, createInMemoryBenchmarkAdapter, createNoopMemoryBenchmarkAdapter, isKnowledgeMemoryBenchmarkCase, knowledgeBenchmarkJudge, parseKnowledgeBenchmarkJsonl, parseKnowledgeBenchmarkQrels, renderKnowledgeBenchmarkReportMarkdown, respondToIndustryMemoryBenchmarkSmokeCase, respondToIndustryRagBenchmarkSmokeCase, runKnowledgeBenchmarkSuite, runMemoryAdapterBenchmark, scoreKnowledgeBenchmarkArtifact, scoreMemoryBenchmarkArtifact, summarizeKnowledgeBenchmarkCampaign };
@@ -1,2 +1,2 @@
1
- import { B as createNoopMemoryBenchmarkAdapter, F as buildIndustryRagBenchmarkSmokeCases, I as respondToIndustryMemoryBenchmarkSmokeCase, L as respondToIndustryRagBenchmarkSmokeCase, M as INDUSTRY_RAG_BENCHMARKS, N as buildFirstPartyMemoryLifecycleBenchmarkCases, P as buildIndustryMemoryBenchmarkSmokeCases, R as isKnowledgeMemoryBenchmarkCase, a as buildKnowledgeBenchmarkScenarios, c as runKnowledgeBenchmarkSuite, d as summarizeKnowledgeBenchmarkCampaign, i as runMemoryAdapterBenchmark, j as INDUSTRY_MEMORY_BENCHMARKS, l as scoreKnowledgeBenchmarkArtifact, n as parseKnowledgeBenchmarkJsonl, o as knowledgeBenchmarkJudge, r as parseKnowledgeBenchmarkQrels, s as renderKnowledgeBenchmarkReportMarkdown, t as buildRetrievalBenchmarkCasesFromQrels, u as scoreMemoryBenchmarkArtifact, z as createInMemoryBenchmarkAdapter } from "../benchmarks-B_07vX0Q.js";
1
+ import { B as createNoopMemoryBenchmarkAdapter, F as buildIndustryRagBenchmarkSmokeCases, I as respondToIndustryMemoryBenchmarkSmokeCase, L as respondToIndustryRagBenchmarkSmokeCase, M as INDUSTRY_RAG_BENCHMARKS, N as buildFirstPartyMemoryLifecycleBenchmarkCases, P as buildIndustryMemoryBenchmarkSmokeCases, R as isKnowledgeMemoryBenchmarkCase, a as buildKnowledgeBenchmarkScenarios, c as runKnowledgeBenchmarkSuite, d as summarizeKnowledgeBenchmarkCampaign, i as runMemoryAdapterBenchmark, j as INDUSTRY_MEMORY_BENCHMARKS, l as scoreKnowledgeBenchmarkArtifact, n as parseKnowledgeBenchmarkJsonl, o as knowledgeBenchmarkJudge, r as parseKnowledgeBenchmarkQrels, s as renderKnowledgeBenchmarkReportMarkdown, t as buildRetrievalBenchmarkCasesFromQrels, u as scoreMemoryBenchmarkArtifact, z as createInMemoryBenchmarkAdapter } from "../benchmarks-B6fCb6AD.js";
2
2
  export { INDUSTRY_MEMORY_BENCHMARKS, INDUSTRY_RAG_BENCHMARKS, buildFirstPartyMemoryLifecycleBenchmarkCases, buildIndustryMemoryBenchmarkSmokeCases, buildIndustryRagBenchmarkSmokeCases, buildKnowledgeBenchmarkScenarios, buildRetrievalBenchmarkCasesFromQrels, createInMemoryBenchmarkAdapter, createNoopMemoryBenchmarkAdapter, isKnowledgeMemoryBenchmarkCase, knowledgeBenchmarkJudge, parseKnowledgeBenchmarkJsonl, parseKnowledgeBenchmarkQrels, renderKnowledgeBenchmarkReportMarkdown, respondToIndustryMemoryBenchmarkSmokeCase, respondToIndustryRagBenchmarkSmokeCase, runKnowledgeBenchmarkSuite, runMemoryAdapterBenchmark, scoreKnowledgeBenchmarkArtifact, scoreMemoryBenchmarkArtifact, summarizeKnowledgeBenchmarkCampaign };
@@ -1,5 +1,5 @@
1
1
  import { r as stableId, t as sha256 } from "./ids-Bevz_pXV.js";
2
- import { n as searchKnowledge } from "./search-CtVJ0PKX.js";
2
+ import { r as searchKnowledge } from "./search-Cw6eYfSd.js";
3
3
  import { randomUUID } from "node:crypto";
4
4
  import { join } from "node:path";
5
5
  import { canonicalJson } from "@tangle-network/agent-eval";
@@ -2783,4 +2783,4 @@ function defaultDocumentTarget(documentId, targetKind) {
2783
2783
  //#endregion
2784
2784
  export { reserveRecoveryAttempts as A, createNoopMemoryBenchmarkAdapter as B, sleepForMemoryRecovery as C, hasSettledPaidCall as D, assertNoInterruptedPaidCalls as E, buildIndustryRagBenchmarkSmokeCases as F, retrievalConfigFromSurface as G, memoryWriteResultToSourceRecord as H, respondToIndustryMemoryBenchmarkSmokeCase as I, scoreRetrievalArtifact as J, retrievalConfigSurface as K, respondToIndustryRagBenchmarkSmokeCase as L, INDUSTRY_RAG_BENCHMARKS as M, buildFirstPartyMemoryLifecycleBenchmarkCases as N, readActiveAttemptJournal as O, buildIndustryMemoryBenchmarkSmokeCases as P, isKnowledgeMemoryBenchmarkCase as R, runBoundedMemoryLifecycle as S, appendDurableJournalEvent as T, buildRetrievalEvalDispatch as U, memoryHitToSourceRecord as V, partitionRetrievalScenarios as W, MEMORY_OPERATION_CANCELLATION_TIMEOUT_MS as _, buildKnowledgeBenchmarkScenarios as a, memoryRecoveryDelayMs as b, runKnowledgeBenchmarkSuite as c, summarizeKnowledgeBenchmarkCampaign as d, acquireAgentMemoryRunLease as f, MEMORY_CAMPAIGN_DISPATCH_SHUTDOWN_TIMEOUT_MS as g, DEFAULT_MEMORY_CLEANUP_TIMEOUT_MS as h, runMemoryAdapterBenchmark as i, INDUSTRY_MEMORY_BENCHMARKS as j, reconcileInterruptedMemoryPaidCalls as k, scoreKnowledgeBenchmarkArtifact as l, AgentMemoryLifecycleUnsafeError as m, parseKnowledgeBenchmarkJsonl as n, knowledgeBenchmarkJudge as o, AgentMemoryLifecycleTimeoutError as p, retrievalRecallJudge as q, parseKnowledgeBenchmarkQrels as r, renderKnowledgeBenchmarkReportMarkdown as s, buildRetrievalBenchmarkCasesFromQrels as t, scoreMemoryBenchmarkArtifact as u, createBoundedMemoryAdapter as v, appendAttemptJournalEvent as w, resolveMemoryCleanupTimeoutMs as x, createMemoryExecutionPool as y, createInMemoryBenchmarkAdapter as z };
2785
2785
 
2786
- //# sourceMappingURL=benchmarks-B_07vX0Q.js.map
2786
+ //# sourceMappingURL=benchmarks-B6fCb6AD.js.map