Files
fusion/docs/knowledge-graph.md
gsxdsm eef68fe0b9 FN-8933: capture semantic memory from completed work
Add inferred graph relationships and detached recall capture across completed-work memory surfaces.

- Validate and persist deterministic inferred semantic edges with audit outcomes.
- Capture completed tasks, research findings, and insights as bounded recall entries.
- Wire memory semantics through engine, research APIs, and coverage tests.

Files changed:
 .changeset/fn-8933-memory-semantics-capture.md     |   7 +
 AGENTS.md                                          |   1 +
 docs/knowledge-graph.md                            |  10 +-
 .../src/__tests__/memory/recall-capture.test.ts    | 111 +++++++++++++
 .../__tests__/postgres/insight-store.pg.test.ts    |  25 +++
 .../postgres/research-execution.pg.test.ts         |  38 +++++
 .../__tests__/research-feature-promotion.test.ts   |  39 +++++
 .../core/src/async-stores/async-insight-store.ts   |  23 ++-
 packages/core/src/index.ts                         |   1 +
 .../__tests__/graph-builder-incremental.test.ts    |  28 ++++
 .../__tests__/inferred-edge-writer.test.ts         |  74 +++++++++
 packages/core/src/knowledge-graph/graph-builder.ts |  27 ++-
 .../src/knowledge-graph/graph-serialization.ts     |   2 +-
 packages/core/src/knowledge-graph/graph-store.ts   |  12 ++
 packages/core/src/knowledge-graph/graph-types.ts   |   2 +-
 packages/core/src/knowledge-graph/index.ts         |   1 +
 .../src/knowledge-graph/inferred-edge-writer.ts    |  96 +++++++++++
 packages/core/src/memory/index.ts                  |   1 +
 packages/core/src/memory/recall-capture.ts         | 184 +++++++++++++++++++++
 .../src/research/research-feature-promotion.ts     |  23 ++-
 packages/core/src/task-store/task-store-helpers.ts |  13 +-
 .../src/__tests__/research-routes.test.ts          |  80 ++++++++-
 packages/dashboard/src/research-routes.ts          |  27 ++-
 .../src/__tests__/agent-mission-tools.test.ts      |  60 ++++++-
 .../src/__tests__/in-process-runtime.pg.test.ts    |  28 +++-
 .../memory-consolidation-heartbeat-hook.test.ts    |   8 +-
 .../__tests__/memory-consolidation-ports.test.ts   |  17 +-
 .../src/__tests__/memory-semantics-pass.test.ts    | 115 +++++++++++++
 .../engine/src/__tests__/project-engine.test.ts    |  65 +++++++-
 packages/engine/src/agent-heartbeat.ts             |  14 +-
 packages/engine/src/agent-tools.ts                 |  12 +-
 packages/engine/src/agents/agent-reflection.ts     |   9 +-
 packages/engine/src/memory/index.ts                |   1 +
 .../src/memory/memory-consolidation-adapters.ts    |  18 +-
 packages/engine/src/memory/memory-consolidation.ts |  13 +-
 packages/engine/src/memory/memory-semantics.ts     |  67 ++++++++
 packages/engine/src/project-engine.ts              |   3 +
 .../engine/src/research/research-orchestrator.ts   |  20 ++-
 packages/engine/src/runtimes/in-process-runtime.ts |  12 ++
 packages/engine/src/util/run-audit.ts              |  11 ++
 40 files changed, 1250 insertions(+), 48 deletions(-)

Fusion-Task-Id: FN-8933

Fusion-Task-Lineage: b75a6b23-906f-4255-92f1-7684beb742b8

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-11 05:45:36 -07:00

6.2 KiB

← Docs index

Knowledge graph

fn knowledge-graph build creates the deterministic structure graph for the FN-8920 memory epic. Memory Keeper may subsequently add clearly provenance-tagged inferred semantic relationships; deterministic extraction itself remains LLM-free.

Artifact and configuration

The default knowledgeGraphDir is .fusion-knowledge/graph, deliberately outside ignored .fusion/. It contains nodes.json, edges.json, and manifest.json; all use sorted, LF JSON. Nodes and edges are written before the manifest so a torn write safely triggers a full rebuild. The manifest records SHA-256 fingerprints and import references, enabling changed files only to be re-extracted and deleted file ownership to be pruned.

The artifact is not committed. As of 2026-08-10 .fusion-knowledge/ is gitignored: the graph is deterministic and fully regenerable from source (the manifest's SHA-256 fingerprints drive incremental rebuilds), so tracking it preserves nothing a rebuild cannot reproduce, while costing ~85MB of irreversible, compounding history bloat on every clone and CI checkout — edges.json alone is 43MB, past GitHub's 50MB warning threshold. Regenerate it with fn knowledge-graph build rather than pulling it.

An operator who explicitly wants a snapshot in history can still force one with git add -f .fusion-knowledge/graph; prefer a rebuild.

Model

Nodes are file, module, symbol, doc-concept, or rationale. Structural edges are contains, imports, and re-exports; semantic edges are relates-to and rationale-supports. Every edge includes source, owner (file or derived), and provenance (extracted or inferred). IDs are path-derived (file:path, module:dir, symbol:path#name, doc:path#slug~index, and rationale:path#area@stamp~index) with reserved separators percent-escaped.

TypeScript/TSX parsing is parser-only. Exported declarations become symbols; duplicate exports collapse to one earliest-position node with declarationCount, including invalid source. Syntax errors remain best-effort. export * records a re-export relationship but cannot expand names without a checker. Relative imports are resolved lexically using .ts, .tsx, and index candidates; package and tsconfig aliases are out of scope.

Discovery includes package src, package scripts, scripts, plugins, docs, root policy documents, and packages/dashboard/app, whose UI is outside src. Modules are derived from direct TypeScript files every build. queryNodes, neighbors, and shortestPath expose the in-process API and retain complete edge provenance.

FNXC rationale comes from TypeScript parser comment ranges and markdown HTML comments. Markdown fenced/indented code cannot open a rationale comment; once opened, a comment continues through indentation. Multiple stamped headers in one comment produce separate rationale nodes.

Extraction and recovery contract

The dispatcher creates exactly one file node per discovered file. TypeScript and TSX are parsed with the TypeScript parser only; malformed source remains best-effort and never blocks a build. Symbol identity uses the exported name. Legal declaration merges and invalid redeclarations use the same deterministic collapse: the first source location and attributes win, while declarationCount and (when needed) symbolKinds preserve the fact of the collision. The only graph errors are invalid caller paths, an impossible internal cross-kind/owner collision, and artifact I/O failures.

File-owned facts are replaced only when that file hash changes. Module nodes and module containment are derived from the final file set every build. Import references are persisted in the manifest and import/re-export edges are synthesized every build, so adding or deleting a target never requires parsing an unchanged importer. Relative resolution tries .ts, .tsx, then index candidates; it intentionally does not resolve aliases, packages, or expand export * names.

Every real source position is recorded as a repository-relative path, line, and column. File and module-derived items use a syntheticSource: "true" attribute and a 1:1 anchor. Artifact payloads contain only content-derived values (including source FNXC stamps and hashes), never build time, host, or process metadata. Missing, malformed, mismatched, or inconsistent artifact files trigger a safe full rebuild; artifacts are written nodes, edges, then manifest so a torn write cannot validate incomplete output.

FNXC and query behavior

FNXC rationale is first-class data. TypeScript-family comment ranges come from the parsed tree, not a raw scanner, which prevents strings, regexes, template text, and JSX text from becoming rationale. Markdown recognizes HTML comments outside fenced or narrowly defined indented code; code state gates the comment opener only, so an already-open multi-header comment is not truncated by indentation. Each stamped header starts a separate rationale node and runs to the next header in its comment.

queryNodes(filter), neighbors(id, options), and shortestPath(from, to) are deterministic in-process APIs. Neighbor and path results retain complete edge objects, including source, ownership, and provenance. The sole inferred-edge writer stamps inferred unconditionally and accepts an input type with no provenance field, so model output can never masquerade as deterministic extraction.

Automatic recall capture

Memory capture is optional and detached. RecallCaptureWriter.capture() returns void, so task completion, research finalization/promotion, and insight upsert cannot await recall persistence. Completed tasks and research findings capture solution records with task-completion/deep-research provenance; insights capture decision records with the available other provenance. Live writers are composed at the in-process reflection runtime, research orchestrator construction, research-promotion callers, and the lazy async insight-store factory; absent memory falls back to a shared no-op writer.

Non-goals

This layer has no LLM calls, embeddings, vector recall, MCP tools, source-validity diagnostics, language support beyond TypeScript/TSX symbols, CommonMark parser, cross-rename identity, or capability-fabric bundle. The FR-29/FR-34 bundle format is deferred.