@tangle-network/agent-knowledge 1.1.1 → 1.3.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.
package/AGENTS.md CHANGED
@@ -58,3 +58,39 @@ Use `knowledgeReleaseReportFromOptimization()` before promotion. It projects opt
58
58
  - Use `KbStore` for storage. Implement D1 in the consuming app when needed.
59
59
  - Use `KnowledgeDiscoveryDispatcher` for research workers. Production apps should wire this to their own swarm/fleet runtime.
60
60
  - Do not bypass `lint` or `validate` before using generated knowledge in an agent.
61
+
62
+ ## Pluggable Sources + Freshness + Changes
63
+
64
+ Agents that need to stay current against external authorities should compose:
65
+
66
+ - `createCornellLiiSource({ selectors })` — US Code + Wex from law.cornell.edu.
67
+ - `createIrsPublicationsSource({ publications, revenueProcedures })` — IRS index + named pubs.
68
+ - `createStateSosSource({ state, baseUrl, entities })` — generic state SOS adapter.
69
+
70
+ Every fetch returns `KnowledgeFragment[]` with `provenance.verifiable` indicating whether the authority was successfully authenticated. Refuse to cite fragments with `verifiable: false`.
71
+
72
+ Track per-tenant freshness with `createFileSystemFreshnessStore({ root })` and re-fetch only when `stale({ workspaceId, sourceId, ttlMs })` returns true.
73
+
74
+ Diff snapshots with `detectChanges(prev, next)`. Each `KnowledgeChange` carries `affectedDimensions` — pass those to your eval scheduler to re-run only the relevant campaigns.
75
+
76
+ ## Authorship
77
+
78
+ Do not add `Co-Authored-By:` trailers (or any other AI-attribution lines) to commits, PR descriptions, or other artifacts in this repo. Author = the human running the session. Applies to every contributor, including AI agents and subagents — do not include the default Claude Code template trailer.
79
+
80
+ ## Comment & doc discipline (no historical narrative)
81
+
82
+ Comments describe **what the code does and why** — never what it used to do, what it replaced, which audit found a bug, or what the prior version looked like. History belongs in commit messages and PR descriptions, not the source tree.
83
+
84
+ - Bad: `// replaces the inline retry loop`, `// fix for the silent-zero bug`, `// the 2yr rewrite added this`, `// audit fix`
85
+ - Good: `// value: null when retries exhaust — callers must inspect succeeded`
86
+
87
+ Applies to docstrings, README sections, SKILL.md, AGENTS.md, CLAUDE.md — anywhere the source tree carries prose.
88
+
89
+ ## No fallbacks. Fail loud.
90
+
91
+ Sloppy fallbacks corrupt every signal downstream. No silent zeros, no `?? default` on required fields, no `try/catch { return null }` that erases diagnostic info, no legacy back-compat mode defaulted on for new code.
92
+
93
+ External-boundary calls (LLM, network, FS, subprocess) return *typed outcomes* (`{ succeeded, value, error }`). Callers MUST inspect `succeeded` before using `value`. Named, opted-in fallback rotations (`policy.fallbackModels: [...]`) are fine; deep `?? "kimi"` helpers are not.
94
+
95
+ Full doctrine: `~/dotfiles/claude/AGENTS.md` → "No fallbacks. Fail loud."
96
+
package/README.md CHANGED
@@ -58,6 +58,13 @@ from `@tangle-network/agent-knowledge`.
58
58
  - Agent write proposals can be safely applied with `apply-write-blocks`.
59
59
  - `KbStore` keeps storage consumer-owned; use `MemoryKbStore`, `FileSystemKbStore`, or implement D1 in the app.
60
60
  - Discovery uses worker/dispatcher contracts, with a local dispatcher for dev and tests.
61
+ - `runKnowledgeResearchLoop()` provides thin loop mechanics for researcher
62
+ agents: ingest sources, apply safe write blocks, rebuild the index,
63
+ lint/validate, score readiness, and return a transcript. The agent still
64
+ decides what to research, what to write, and when the wiki is good enough.
65
+ - `createKnowledgeControlLoopAdapter()` maps those mechanics into
66
+ `agent-eval`'s `runAgentControlLoop()` so products can plug in their own
67
+ proposer, reviewer, and driver policies.
61
68
  - Zod schemas define the stable wire shape.
62
69
  - Graph/search/lint are deterministic and fast.
63
70
  - `searchKnowledge` returns hits with three score fields. `score` and
@@ -111,3 +118,178 @@ console.log(readiness.report.recommendedAction)
111
118
  Pass `readiness.report` to `blockingKnowledgeEval()` from
112
119
  `@tangle-network/agent-eval`; use `readiness.questions` and
113
120
  `readiness.acquisitionPlans` to drive UI or connector workflows.
121
+
122
+ ## Research Loop
123
+
124
+ Use `runKnowledgeResearchLoop()` when an agent is acting as a researcher or
125
+ librarian. Keep the loop small: the package handles deterministic mechanics;
126
+ your agent handles judgment.
127
+
128
+ ```ts
129
+ import {
130
+ defineReadinessSpec,
131
+ runKnowledgeResearchLoop,
132
+ } from '@tangle-network/agent-knowledge'
133
+
134
+ await runKnowledgeResearchLoop({
135
+ root: './kb',
136
+ goal: 'Build a grounded onboarding wiki for billing support',
137
+ readinessSpecs: [defineReadinessSpec({
138
+ id: 'refund-policy',
139
+ description: 'Refund policy grounding',
140
+ query: 'refund policy customer request',
141
+ requiredFor: ['support-agent'],
142
+ })],
143
+ async step({ iteration, index, readiness }) {
144
+ // Call your researcher/LLM/browser/connector workflow here.
145
+ if (iteration > 1 && readiness?.report.blockingMissingRequirements.length === 0) {
146
+ return { done: true, notes: 'ready for eval' }
147
+ }
148
+ return {
149
+ sourceTexts: [{
150
+ uri: 'research://refund-policy',
151
+ title: 'Refund Policy Source',
152
+ text: 'Source text gathered by the researcher.',
153
+ }],
154
+ proposalText: [
155
+ '---FILE: knowledge/support/refund-policy.md---',
156
+ '---',
157
+ 'id: refund-policy',
158
+ 'title: Refund Policy',
159
+ '---',
160
+ '# Refund Policy',
161
+ 'Grounded summary written by the researcher.',
162
+ '---END FILE---',
163
+ ].join('\n'),
164
+ }
165
+ },
166
+ })
167
+ ```
168
+
169
+ This is intentionally not a crawler, prompt framework, or agent. It is the
170
+ repeatable shell around one.
171
+
172
+ For full `agent-eval` control-loop integration, use
173
+ `createKnowledgeControlLoopAdapter()` and provide `decide` yourself:
174
+
175
+ ```ts
176
+ import { runAgentControlLoop } from '@tangle-network/agent-eval'
177
+ import { createKnowledgeControlLoopAdapter } from '@tangle-network/agent-knowledge'
178
+
179
+ const adapter = createKnowledgeControlLoopAdapter({
180
+ root: './kb',
181
+ goal: 'Maintain the billing support wiki',
182
+ readinessSpecs,
183
+ })
184
+
185
+ await runAgentControlLoop({
186
+ ...adapter,
187
+ async decide({ state, evals }) {
188
+ if (state.previousSteps.length > 0 && evals.every((e) => e.passed)) {
189
+ return { type: 'stop', pass: true, reason: 'knowledge ready' }
190
+ }
191
+ const proposal = await proposerAgent(state)
192
+ const review = await reviewerAgent({ ...state, proposal })
193
+ return {
194
+ type: 'continue',
195
+ reason: review.summary,
196
+ action: driverPolicy({ proposal, review }),
197
+ }
198
+ },
199
+ })
200
+ ```
201
+
202
+ ## Pluggable Knowledge Sources
203
+
204
+ Static knowledge rots. Authorities like Cornell LII, the IRS, and state
205
+ Secretaries of State change without warning — a ruling vacates an FTC
206
+ non-compete rule, a CFR section renumbers, a state replaces Beverly-Killea
207
+ with RULLCA. The `@tangle-network/agent-knowledge/sources` subpath ships
208
+ three primitives that bridge "live authority" → "eval re-runs":
209
+
210
+ - `KnowledgeSource` — pluggable contract (`fetch(opts) → KnowledgeFragment[]`).
211
+ Every fragment carries `provenance` (URL, source-attested timestamp,
212
+ jurisdiction, `verifiable` flag) and `dimensionHints` (which eval
213
+ dimensions a change in this fragment should re-score).
214
+ - `KnowledgeFreshnessStore` — per-`(workspaceId, sourceId)` last-refresh
215
+ tracker. Filesystem adapter ships in-package; D1 / Postgres adapter
216
+ scaffold is shipped as `createD1FreshnessStoreStub(adapter)`.
217
+ - `detectChanges(prev, next)` — diffs two fragment snapshots, emits
218
+ `KnowledgeChange[]` tagged with the affected eval dimensions so a cron
219
+ scheduler knows exactly which campaigns to re-run.
220
+
221
+ Three concrete sources ship in-package:
222
+
223
+ ```ts
224
+ import {
225
+ createCornellLiiSource,
226
+ createIrsPublicationsSource,
227
+ createStateSosSource,
228
+ createFileSystemFreshnessStore,
229
+ detectChanges,
230
+ type KnowledgeChange,
231
+ type KnowledgeFragment,
232
+ } from '@tangle-network/agent-knowledge'
233
+
234
+ const sources = [
235
+ // Federal statutes + Wex encyclopedia from law.cornell.edu.
236
+ createCornellLiiSource({
237
+ selectors: [
238
+ { kind: 'uscode', path: '18/1836' }, // DTSA
239
+ { kind: 'wex', path: 'restraint_of_trade', dimensionHints: ['jurisdictional_accuracy'] },
240
+ ],
241
+ }),
242
+ // IRS publications index + named publications + revenue procedures.
243
+ createIrsPublicationsSource({
244
+ publications: ['p15', 'p17', 'p463'],
245
+ revenueProcedures: [],
246
+ }),
247
+ // Generic state SOS adapter — one config per state you need tracked.
248
+ createStateSosSource({
249
+ state: 'CA',
250
+ baseUrl: 'https://www.sos.ca.gov',
251
+ entities: [{
252
+ id: 'business-entities-forms',
253
+ path: '/business-programs/business-entities/forms',
254
+ title: 'CA Business Entities Forms',
255
+ selector: { kind: 'whole' },
256
+ }],
257
+ }),
258
+ ]
259
+
260
+ const freshness = createFileSystemFreshnessStore({ root: './kb' })
261
+
262
+ // Worked example: Cornell LII updates the Wex `restraint_of_trade` entry
263
+ // to reflect Ryan-LLC v. FTC. The cron tick below detects the change,
264
+ // extracts the `jurisdictional_accuracy` dimension hint, and hands it to
265
+ // the eval scheduler which re-runs only the campaigns tagged with that
266
+ // dimension.
267
+ async function tick({ workspaceId, prevSnapshots }: {
268
+ workspaceId: string
269
+ prevSnapshots: Record<string, KnowledgeFragment[]>
270
+ }): Promise<KnowledgeChange[]> {
271
+ const allChanges: KnowledgeChange[] = []
272
+ for (const source of sources) {
273
+ const stale = await freshness.stale({
274
+ workspaceId,
275
+ sourceId: source.id,
276
+ ttlMs: 24 * 60 * 60 * 1000,
277
+ })
278
+ if (!stale) continue
279
+
280
+ const next = await source.fetch({ cacheDir: './.agent-knowledge/http-cache' })
281
+ const prev = prevSnapshots[source.id] ?? []
282
+ const { changes } = detectChanges(prev, next)
283
+ allChanges.push(...changes)
284
+
285
+ await freshness.mark({ workspaceId, sourceId: source.id, when: new Date() })
286
+ prevSnapshots[source.id] = next
287
+ }
288
+ return allChanges
289
+ }
290
+ ```
291
+
292
+ Polite-by-default: every HTTP fetch carries the package User-Agent, is
293
+ throttled to 1 req/sec/origin, caches successful responses to disk, and
294
+ marks `verifiable: false` on block pages / 4xx rather than promoting
295
+ un-grounded content. See `src/sources/http.ts` for the invariants.
@@ -144,4 +144,4 @@ export {
144
144
  detectKnowledgeGaps,
145
145
  findSurprisingConnections
146
146
  };
147
- //# sourceMappingURL=chunk-TXNYP4WI.js.map
147
+ //# sourceMappingURL=chunk-4PNXQ2NT.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/viz/index.ts"],"sourcesContent":["import type { KnowledgeGraph, KnowledgeGraphEdge, KnowledgeGraphNode } from '../types'\n\nexport interface KnowledgeVizNode extends KnowledgeGraphNode {\n degree: number\n community: number\n}\n\nexport interface KnowledgeVizEdge extends KnowledgeGraphEdge {\n id: string\n}\n\nexport interface KnowledgeCommunity {\n id: number\n nodeIds: string[]\n topTitles: string[]\n cohesion: number\n}\n\nexport interface KnowledgeVizGraph {\n nodes: KnowledgeVizNode[]\n edges: KnowledgeVizEdge[]\n communities: KnowledgeCommunity[]\n}\n\nexport interface KnowledgeGap {\n type: 'isolated-node' | 'sparse-community' | 'bridge-node'\n title: string\n nodeIds: string[]\n suggestion: string\n}\n\nexport interface SurprisingConnection {\n source: KnowledgeVizNode\n target: KnowledgeVizNode\n score: number\n reasons: string[]\n}\n\nexport function toKnowledgeVizGraph(graph: KnowledgeGraph): KnowledgeVizGraph {\n const adjacency = buildAdjacency(graph)\n const communities = assignCommunities(graph.nodes, adjacency)\n const communityByNode = new Map<number, number>()\n communities.forEach((community) => {\n for (const nodeId of community.nodeIds) communityByNode.set(hashNode(nodeId), community.id)\n })\n const nodes = graph.nodes.map((node) => ({\n ...node,\n degree: node.inDegree + node.outDegree,\n community: communityByNode.get(hashNode(node.id)) ?? 0,\n }))\n return {\n nodes,\n edges: graph.edges.map((edge) => ({ ...edge, id: `${edge.source}->${edge.target}` })),\n communities,\n }\n}\n\nexport function detectKnowledgeGaps(graph: KnowledgeVizGraph, limit = 10): KnowledgeGap[] {\n const gaps: KnowledgeGap[] = []\n const isolated = graph.nodes.filter((node) => node.degree <= 1 && !isStructural(node.path))\n if (isolated.length > 0) {\n gaps.push({\n type: 'isolated-node',\n title: `${isolated.length} isolated page${isolated.length === 1 ? '' : 's'}`,\n nodeIds: isolated.map((node) => node.id),\n suggestion:\n 'Add cross-links, sources, or follow-up research to connect these pages to the knowledge graph.',\n })\n }\n for (const community of graph.communities) {\n if (community.nodeIds.length >= 3 && community.cohesion < 0.15) {\n gaps.push({\n type: 'sparse-community',\n title: `Sparse cluster: ${community.topTitles[0] ?? `community ${community.id}`}`,\n nodeIds: community.nodeIds,\n suggestion:\n 'This cluster has weak internal evidence. Add synthesis pages or relation links between its strongest concepts.',\n })\n }\n }\n const byCommunityNeighbors = new Map<string, Set<number>>()\n const nodeById = new Map(graph.nodes.map((node) => [node.id, node]))\n for (const edge of graph.edges) {\n const source = nodeById.get(edge.source)\n const target = nodeById.get(edge.target)\n if (!source || !target) continue\n if (!byCommunityNeighbors.has(source.id)) byCommunityNeighbors.set(source.id, new Set())\n if (!byCommunityNeighbors.has(target.id)) byCommunityNeighbors.set(target.id, new Set())\n byCommunityNeighbors.get(source.id)!.add(target.community)\n byCommunityNeighbors.get(target.id)!.add(source.community)\n }\n for (const node of graph.nodes) {\n if ((byCommunityNeighbors.get(node.id)?.size ?? 0) >= 3) {\n gaps.push({\n type: 'bridge-node',\n title: `Bridge page: ${node.title}`,\n nodeIds: [node.id],\n suggestion: 'This page connects multiple knowledge areas. Keep it well cited and current.',\n })\n }\n }\n return gaps.slice(0, limit)\n}\n\nexport function findSurprisingConnections(\n graph: KnowledgeVizGraph,\n limit = 10,\n): SurprisingConnection[] {\n const nodeById = new Map(graph.nodes.map((node) => [node.id, node]))\n const scored: SurprisingConnection[] = []\n for (const edge of graph.edges) {\n const source = nodeById.get(edge.source)\n const target = nodeById.get(edge.target)\n if (!source || !target) continue\n let score = edge.weight\n const reasons = [...edge.reasons]\n if (source.community !== target.community) {\n score += 3\n reasons.push('cross-community')\n }\n if (source.tags.some((tag) => !target.tags.includes(tag))) {\n score += 1\n reasons.push('cross-tag')\n }\n if (score >= 3) scored.push({ source, target, score, reasons })\n }\n return scored.sort((a, b) => b.score - a.score).slice(0, limit)\n}\n\nfunction buildAdjacency(graph: KnowledgeGraph): Map<string, Set<string>> {\n const out = new Map<string, Set<string>>()\n for (const node of graph.nodes) out.set(node.id, new Set())\n for (const edge of graph.edges) {\n out.get(edge.source)?.add(edge.target)\n out.get(edge.target)?.add(edge.source)\n }\n return out\n}\n\nfunction assignCommunities(\n nodes: KnowledgeGraphNode[],\n adjacency: Map<string, Set<string>>,\n): KnowledgeCommunity[] {\n const seen = new Set<string>()\n const communities: KnowledgeCommunity[] = []\n for (const node of nodes) {\n if (seen.has(node.id)) continue\n const queue = [node.id]\n const ids: string[] = []\n seen.add(node.id)\n while (queue.length > 0) {\n const id = queue.shift()!\n ids.push(id)\n for (const next of adjacency.get(id) ?? []) {\n if (!seen.has(next)) {\n seen.add(next)\n queue.push(next)\n }\n }\n }\n const memberNodes = ids\n .map((id) => nodes.find((candidate) => candidate.id === id))\n .filter((item): item is KnowledgeGraphNode => Boolean(item))\n communities.push({\n id: communities.length,\n nodeIds: ids,\n topTitles: memberNodes\n .sort((a, b) => b.inDegree + b.outDegree - (a.inDegree + a.outDegree))\n .slice(0, 5)\n .map((item) => item.title),\n cohesion: cohesion(ids, adjacency),\n })\n }\n return communities.sort((a, b) => b.nodeIds.length - a.nodeIds.length)\n}\n\nfunction cohesion(ids: string[], adjacency: Map<string, Set<string>>): number {\n if (ids.length < 2) return 0\n let edges = 0\n const idSet = new Set(ids)\n for (const id of ids) {\n for (const next of adjacency.get(id) ?? []) {\n if (idSet.has(next)) edges++\n }\n }\n return edges / (ids.length * (ids.length - 1))\n}\n\nfunction hashNode(id: string): number {\n let hash = 0\n for (const char of id) hash = (hash * 31 + char.charCodeAt(0)) | 0\n return hash\n}\n\nfunction isStructural(path: string): boolean {\n return path.endsWith('/index.md') || path.endsWith('/log.md')\n}\n"],"mappings":"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","names":[]}