diff --git a/AGENTS.md b/AGENTS.md index 3e80763..40dc65b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -126,9 +126,10 @@ strut/ │ │ ├── claims-writer.ts # ClaimsWriter: the claim graph's invariants — ≥1 check per claim, edits SUPERSEDE (successor claim carries ABOUT + checks; successor check takes over TESTS), retire = timestamp, detach = deleted edge, last check / last subject refused │ │ ├── claim-schema-upgrade.ts # one-shot standalone mirror of jarvis migration 124 (Claim re-keyed on id, Epistemic/Thing); runs before the ontology seed, only with STRUT_GRAPH_SEED_ONTOLOGY │ │ ├── exact-key-migration.ts # one-shot boot re-key of existing StrutWorkflow/-Version/StrutStep/-Version nodes from the sanitized name to the exact (hex) key — ledger-stamped, idempotent, every namespace, soft-deleted nodes included; ref_ids, edges and the Schema nodes untouched -│ │ ├── embeddings.ts # local all-MiniLM-L6-v2 via transformers.js, tokenized like sentence-transformers (256 incl. specials); NULL-scan backfill -│ │ ├── search.ts # the read surface: hybrid search (RRF + title boost + usage tiebreak), get/neighbors/counts, ontology, namespaces -│ │ ├── backend.ts # openGraphBackend(): cached per config; runs seed + backfill on first open +│ │ ├── index-reconcile.ts # boot step (plans/semantic-search.md §2): a live Schema's `index` that is a non-empty STRICT SUBSET of the bundled library's (`fixtures/jarvis-ontology.ts`) is widened to the library's list — jarvis's own values, written directly (its Schema API re-embeds a whole type in one request and rebuilds the shared keyword index per type). Once per fixture `version` (a `Migration` ledger row), so a list jarvis narrows on purpose is never fought over; the pass then sees every node of the type as stale +│ │ ├── embeddings.ts # local all-MiniLM-L6-v2 via transformers.js, tokenized like sentence-transformers (256 incl. specials), 2 intra-op threads; + the EMBEDDING PASS (plans/semantic-search.md §1): a timer in the serving process that keeps `Data_Bank` + `text_embeddings` + the domain label current on EVERY node of a Schema-marked type, whoever wrote it (stakgraph's ingest, jarvis, an import) — stale = the stored text ≠ the writer's composition from the Schema's `index` fields, or no vector — strips the no-embed types (`embed: false`: `Turn` via its Schema, `StrutToolCall` / `StrutTurn` in code), pages by `node_key` (an index seek per page, never a scan), works 15 s a minute, sweeps hourly (code types first), embeds NEWCOMERS by `date_added_to_graph` between sweeps. `GET /graph/embeddings` is its status; `STRUT_GRAPH_EMBEDDINGS=off` turns it off with the embedder +│ │ ├── search.ts # the read surface: hybrid search (RRF + title boost + usage tiebreak), get/neighbors/counts, ontology, namespaces. Routing (`routeIndexes`): a typed search reads the requested types' DOMAIN vector/fulltext indexes with an over-fetch (`overfetch`: k from cap×10 by ×4 to 2,000 — the database cannot filter a vector query, so `type` is a WHERE after the nearest-k cut), an untyped one the global `text_embeddings_vector_index` +│ │ ├── backend.ts # openGraphBackend(): cached per config; runs the migrations, the seeds and the Schema `index` reconcile on first open, then STARTS the embedding pass (nothing waits on it; `close()` stops it) │ │ ├── query.ts # readQuery(): read-only raw Cypher for the chat builder's graph_query — keyword pre-check + READ tx, streamed row cap, tx timeout, strings/vectors compacted; a chat tool, deliberately not a step │ │ ├── test-util.ts # live-test helpers (wipe, canonical graph snapshot) — only ever point at a throwaway Neo4j │ │ └── fixtures/ # Python-produced MiniLM golden vectors + jarvis sanitize_node_key parity cases @@ -296,7 +297,7 @@ GATEWAY_IMAGE=stakgraph-gateway:v1.6.2 docker compose -f docker-compose.yml \ | `STRUT_AUTO_RESUME` | `1` (persistent run store) | Boot-time auto-resume of runs cut off by a crash/restart (RUN_CONTROL_SPEC §5.3): on whenever the run store outlives the process — anything but `MemoryRunStore`, whatever the workspace's kind, so the lab's graph workspace + `FileRunStore` counts — the newest root run per workflow with a log but no summary, unless paused/cancelling, older than 7 days, or already resumed 5 times. `0` disables. | | `NEO4J_URI` / `NEO4J_HOST` | (unset) / `localhost:7687` | Graph backend connection — same names and defaults as mcp's own Neo4j client: `NEO4J_URI` wins, else `bolt://`; `NEO4J_USER`/`NEO4J_PASSWORD` default `neo4j`/`testtest`; optional `NEO4J_DATABASE`. The `graph/*` lib steps read these via the secrets capability (secret store → env) and need nothing configured for a local Neo4j; `openGraphBackendFromEnv` stays opt-in (null when neither is set). | | `STRUT_GRAPH_NAMESPACE` | `default` | jarvis namespace every Strut node is written into | -| `STRUT_GRAPH_EMBEDDINGS` | (on) | `off` disables the local MiniLM embedder (vectors stay NULL; search is fulltext-only) | +| `STRUT_GRAPH_EMBEDDINGS` | (on) | `off` disables the local MiniLM embedder and the embedding pass (vectors stay NULL; search is fulltext-only) | | `STRUT_GRAPH_SEED_ONTOLOGY` | (off) | `1` seeds the bundled jarvis ontology (153 schemas + edge schemas + indexes, add-only) on first open, so a standalone Neo4j can host jarvis-typed data (Document, EvalSet, Concept, …) with no jarvis process. No-op on a jarvis-seeded DB. Also turns on the one-shot `Claim` schema upgrade (the standalone mirror of jarvis migration 124) — never run against a jarvis-hosted graph. | | `STRUT_VERIFY_BUDGET_USD` | `10` | Verify-pass spend cap PER VERIFIED RUN: once the pass's checks have reported this much, remaining checks presumed paid (an `agent`/`llm` step anywhere in the check closure, or an unresolvable one) are skipped (`lastVerify: { skipped: "budget" }`) and the claim stays `unknown` — never `supported`. Checks that report no cost never count. | | `STRUT_VERIFY_BUDGET_USD_PER_DAY` | `100` | The same cap PER SUBJECT PER (UTC) DAY, computed from the run store alone: the cost of today's runs under `check:` tagged with that subject. A harness that verifies many candidates raises it, or sets its paid checks to `manual`. | diff --git a/plans/jarvis-graph-compat.md b/plans/jarvis-graph-compat.md index 8e13787..19d8100 100644 --- a/plans/jarvis-graph-compat.md +++ b/plans/jarvis-graph-compat.md @@ -300,20 +300,16 @@ vector) to prove parity with jarvis's encoder. compatible: a jarvis backfill would simply find nothing NULL. Never invent a pending-marker property. -**Crash-safe backfill sweep** (replaces the durability the queue gave -jarvis): a crash between the node MERGE and the vector write leaves -`text_embeddings` NULL permanently. At every boot of the graph -backend, sweep and heal: - -```cypher -MATCH (n:Domain_strut) -WHERE n.Data_Bank IS NOT NULL AND n.text_embeddings IS NULL -RETURN n.ref_id, n.Data_Bank -``` - -→ embed in batches → `SET n.text_embeddings` (matching jarvis's own -NULL-scan backfill idiom, `migration.py:857-861`). Idempotent, cheap -when clean. +**The pass** (replaces the durability the queue gave jarvis, and the +boot-time `Domain_strut` NULL-scan backfill this plan first specified): +a crash between the node MERGE and the vector write leaves +`text_embeddings` NULL — and so does every node another writer puts in +the graph. `EmbeddingPass` (`embeddings.ts`; `plans/semantic-search.md` +§1) runs on a timer inside the serving process, started when the graph +backend opens: every node of a Schema-marked type, whoever wrote it, is +stale when its stored `Data_Bank` is not the writer's composition from +the Schema's `index` fields or its vector is missing, and is rewritten +the way the writer would have written it. Idempotent, cheap when clean. **Do not implement**: `edge_text_embeddings`; metaphone3. Per-property `vector_index` embeddings (`{stem}_embeddings`) ARE diff --git a/plans/semantic-search.md b/plans/semantic-search.md index 90ebabe..56dd078 100644 --- a/plans/semantic-search.md +++ b/plans/semantic-search.md @@ -1,6 +1,23 @@ # Semantic search without jarvis — strut keeps the graph's vectors -> **Status (2026-10-11): PROPOSED, nothing built.** Written after a seeded +> **Status (2026-10-11): the strut side is BUILT** — §1 (`src/graph/embeddings.ts`, +> `EmbeddingPass`), §2 (`src/graph/index-reconcile.ts`), §3 (`routeIndexes` / +> `overfetch` in `search.ts`), strut's half of §4 (`embed` in the core-key +> mirror, the resolver, the writer, the two registry entries), `GET +> /graph/embeddings`. Not yet: the jarvis PR (§4), the stakgraph PR (§5), the +> fixture re-dump after the jarvis PR lands (until then a test sets `Turn`'s +> mark by hand), the swarm38 validation (after the mcp pin). Where the build +> differs from the text below: the reconcile only WIDENS (a string `index` +> equal to the library's one-item list is left as it is — fewer writes to +> jarvis's nodes, same meaning); the pass addresses a node by `elementId`, +> never by `ref_id` or `(node_key, namespace)` (stakgraph writes both, but +> nothing here should depend on it); the newcomer tick is one range seek over +> `Data_Bank` reading every marked type's index fields at once, not one query +> per type; a tick logs only when it did something, and a page that fails +> moves the sweep to the next type (the next sweep retries); the per-field +> `vector_index` vectors are filled by the sweep, not by the newcomer tick; +> `GET /graph/embeddings` has no web client. Before this it was PROPOSED, +> written after a seeded > `explore` run on swarm38 never used the graph (job run `1791735838490` → > explore run `1791735843683`, a question about hive's GitHub integration: > 0 graph calls, 16 file reads), and revised twice the same day. First diff --git a/specs/API.md b/specs/API.md index 143b283..949ecea 100644 --- a/specs/API.md +++ b/specs/API.md @@ -495,6 +495,7 @@ injected its own `sessions` capability. | Method | Path | Response | | ------ | ---- | -------- | | GET | `/graph/nodes/:ref_id` | `{ ref_id, node_type, name, properties }` — the node as the graph holds it NOW (vectors and internal stamps stripped); 404 when it is gone; 501 on a deployment with no graph | +| GET | `/graph/embeddings` | the embedding pass's status (`plans/semantic-search.md` §1; a debugging read): `{ enabled: true, sweep: { n, startedAt, finishedAt, phase, type, cursor }, current, last, skipped, newcomers: { since, embedded }, lastError, ticks }` — `current` / `last` are per type `{ seen, stale, embedded, removed, errors }` for the sweep in flight / the last complete one; `skipped` is `[{ type, reason: "no_schema" \| "no_index" \| "no_embed" \| "invalid_label" }]`. `{ enabled: false }` with `STRUT_GRAPH_EMBEDDINGS=off`; 501 on a deployment with no graph | What the run view opens when a node in a step's **Nodes** list is clicked: a run's events say which nodes a step touched (`nodes`, above), never their diff --git a/src/createStrut.test.ts b/src/createStrut.test.ts index 4a54e47..3898af8 100644 --- a/src/createStrut.test.ts +++ b/src/createStrut.test.ts @@ -473,6 +473,7 @@ describe("createStrut", () => { const res = await strut.app.request("/graph/nodes/n-1"); assert.equal(res.status, 501); assert.match(((await res.json()) as { error: string }).error, /no graph/); + assert.equal((await strut.app.request("/graph/embeddings")).status, 501); }); it("exposes /steps with registered types", async () => { diff --git a/src/createStrut.ts b/src/createStrut.ts index 11543a0..515cfbd 100644 --- a/src/createStrut.ts +++ b/src/createStrut.ts @@ -2000,6 +2000,16 @@ export async function createStrut( return c.json({ ref_id: node.ref_id, node_type: node.node_type ?? null, name: node.name ?? null, properties: node.properties }); }); + // The embedding pass (plans/semantic-search.md §1) as the graph backend + // reports it: the sweep's position, per-type counts, the types it skips + // and why, the newcomer mark, the last error. `{ enabled: false }` with + // embeddings off. Read-only — a debugging read. 501 without a graph. + app.get("/graph/embeddings", async (c) => { + const graph = opts.graph ?? workspace.graph; + if (!graph) return c.json({ error: "this deployment has no graph" }, 501); + return c.json(graph.embeddings ? graph.embeddings.status() : { enabled: false }); + }); + // ── Secrets ────────────────────────────────────────────────────────────── // Deployment-scoped credential store behind `ctx.services.secrets`. Values // are write-only over the API: GET returns NAMES + metadata only, never the diff --git a/src/graph/backend.ts b/src/graph/backend.ts index 97190bf..34d502b 100644 --- a/src/graph/backend.ts +++ b/src/graph/backend.ts @@ -10,7 +10,11 @@ * 2c. `migrateExactKeys` — one-shot re-key of the workspace nodes from the * sanitized name to the exact one (hex); * 3. `seedStrutDomain` — schema meta-graph, constraints, indexes (§4); - * 4. `backfillEmbeddings` — heal any NULL vectors left by a crash (§2). + * 3b. `reconcileIndexLists` — stale Schema `index` lists widened to the + * bundled library's, once per fixture version (semantic-search.md §2); + * 4. the `EmbeddingPass` is STARTED (semantic-search.md §1): a timer in + * this process that embeds every marked node whoever wrote it, strips + * the no-embed types, and keeps up with newcomers. Nothing waits on it. * * Consumers (the `graph/*` lab steps, a future `Neo4jWorkspaceStore` and * run projector) call `openGraphBackend(cfg)` and share the instance. @@ -18,7 +22,8 @@ import { Bolt, graphConfigFromEnv, type GraphConfig } from "./bolt.js"; import { upgradeClaimSchema, type ClaimSchemaUpgradeReport } from "./claim-schema-upgrade.js"; import { EdgeWriter } from "./edge-writer.js"; -import { MiniLMEmbedder, backfillEmbeddings, type BackfillReport } from "./embeddings.js"; +import { EmbeddingPass, MiniLMEmbedder, type EmbeddingPassOptions } from "./embeddings.js"; +import { reconcileIndexLists, type IndexReconcileReport } from "./index-reconcile.js"; import { NodeWriter, type Embedder } from "./node-writer.js"; import { seedJarvisOntology, type OntologySeedReport } from "./ontology-seed.js"; import { SchemaResolver } from "./schema-resolver.js"; @@ -40,6 +45,9 @@ export interface GraphBackendOptions { * host jarvis-typed data (Document, EvalSet, Concept, …) with no jarvis * process. Env: `STRUT_GRAPH_SEED_ONTOLOGY=1`. */ seedOntology?: boolean; + /** Tuning for the embedding pass (page sizes, the tick, `autoStart`) — + * tests. Not part of the cache key. */ + pass?: EmbeddingPassOptions; } export interface GraphBackend { @@ -58,7 +66,10 @@ export interface GraphBackend { readonly exactKeyMigration: ExactKeyMigrationReport | undefined; readonly claimSchemaUpgrade: ClaimSchemaUpgradeReport | undefined; readonly ontologySeed: OntologySeedReport | undefined; - readonly backfill: BackfillReport | undefined; + readonly indexReconcile: IndexReconcileReport | undefined; + /** The pass, running on its timer; undefined with embeddings off or the + * boot skipped. `status()` is `GET /graph/embeddings`. */ + readonly embeddings: EmbeddingPass | undefined; close(): Promise; } @@ -108,7 +119,7 @@ export function openGraphBackendFromEnv( export async function closeGraphBackends(): Promise { const all = [...cache.values()]; cache.clear(); - await Promise.all(all.map((p) => p.then((b) => b.bolt.close()).catch(() => undefined))); + await Promise.all(all.map((p) => p.then((b) => b.close()).catch(() => undefined))); } async function open(cfg: GraphConfig, opts: GraphBackendOptions): Promise { @@ -123,7 +134,7 @@ async function open(cfg: GraphConfig, opts: GraphBackendOptions): Promise null)) === backend) cache.delete(k); + await embeddings?.stop(); await bolt.close(); }, }; diff --git a/src/graph/embeddings.test.ts b/src/graph/embeddings.test.ts index b57ac02..50c02b5 100644 --- a/src/graph/embeddings.test.ts +++ b/src/graph/embeddings.test.ts @@ -1,11 +1,22 @@ import { describe, it, before, after, beforeEach } from "node:test"; import assert from "node:assert/strict"; import { readFileSync } from "node:fs"; -import { Bolt } from "./bolt.js"; +import { mkdtemp, rm } from "node:fs/promises"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; +import { Bolt, int } from "./bolt.js"; import { seedStrutDomain } from "./schema-seed.js"; -import { NodeWriter, type Embedder } from "./node-writer.js"; -import { EMBEDDING_DIM, MiniLMEmbedder, backfillEmbeddings, cosine, meanPoolNormalize } from "./embeddings.js"; -import { testGraphConfig, wipeGraph } from "./test-util.js"; +import { seedJarvisOntology } from "./ontology-seed.js"; +import { NodeWriter, buildSearchText, type Embedder } from "./node-writer.js"; +import { EMBEDDING_DIM, EmbeddingPass, MiniLMEmbedder, cosine, decideRow, meanPoolNormalize } from "./embeddings.js"; +import { SchemaResolver, fromStrut } from "./schema-resolver.js"; +import { getStrutSchema } from "./strut-schemas.js"; +import { openGraphBackend } from "./backend.js"; +import { Neo4jWorkspaceStore } from "./workspace-store.js"; +import { MemoryRunStore } from "../store.js"; +import { coreRegistry } from "../steps/registry.js"; +import { createStrut } from "../createStrut.js"; +import { graphSnapshot, testGraphConfig, wipeGraph } from "./test-util.js"; const cfg = testGraphConfig(); const runModel = process.env["STRUT_TEST_EMBEDDINGS"] === "1"; @@ -63,48 +74,288 @@ describe("MiniLMEmbedder parity vs sentence-transformers", { skip: runModel ? fa }); }); -describe("backfillEmbeddings (live Neo4j)", { skip: cfg ? false : "STRUT_TEST_NEO4J_URI not set" }, () => { +describe("decideRow (pure)", () => { + const index = ["name", "summary", "description"]; + it("stale when the stored text is not the composed one, or the vector is missing", () => { + assert.deepEqual(decideRow(index, { text: "POST", values: ["POST", null, "Creates a thing"], unembedded: false }), { text: "POST\nCreates a thing", fields: ["name", "description"] }); + assert.equal(decideRow(index, { text: "POST\nCreates a thing", values: ["POST", null, "Creates a thing"], unembedded: false }), "clean"); + assert.deepEqual(decideRow(index, { text: "POST\nCreates a thing", values: ["POST", null, "Creates a thing"], unembedded: true }), { text: "POST\nCreates a thing", fields: ["name", "description"] }); + }); + it("blank when every index field is blank — never jarvis's catch-all text", () => { + assert.equal(decideRow(index, { text: "x", values: [" ", null, ""], unembedded: true }), "blank"); + assert.equal(decideRow(index, { text: null, values: [null, null, null], unembedded: true }), "blank"); + }); + it("renders a list-valued field as the writer does", () => { + assert.deepEqual(decideRow(["tags"], { text: null, values: [["a", "b"]], unembedded: true }), { text: "a,b", fields: ["tags"] }); + }); + it("is the writer's composition", () => { + const schema = fromStrut(getStrutSchema("StrutRun")!); + const values: Record = { run_id: "1", workflow_name: "wf", run_status: "ok", summary: "s" }; + const d = decideRow(schema.index, { text: null, values: schema.index.map((f) => values[f]), unembedded: true }); + assert.equal((d as { text: string }).text, buildSearchText(schema, values).text); + }); +}); + +/** First dim = the text's length, second = a hash of it, so two texts + * never share a vector and a vector names its text. */ +function hashText(t: string): number { + let h = 0; + for (const ch of t) h = (h * 31 + ch.charCodeAt(0)) % 1_000_003; + return h; +} +const fake: Embedder = { + async embed(texts) { + return texts.map((t) => { + const v = new Array(EMBEDDING_DIM).fill(0); + v[0] = t.length; + v[1] = hashText(t); + return v; + }); + }, +}; + +describe("EmbeddingPass (live Neo4j)", { skip: cfg ? false : "STRUT_TEST_NEO4J_URI not set" }, () => { let bolt: Bolt; + let resolver: SchemaResolver; + let pass: EmbeddingPass; + const lines: string[] = []; + const BEFORE = Date.now() - 60_000; + const skipMe = (reason: string) => (s: { type: string; reason: string }) => s.reason === reason; + + /** A node as another writer leaves it: labels, properties, no vector. */ + const raw = (type: string, key: string, props: Record, stamp = BEFORE) => + bolt.run( + `CREATE (n:\`${type}\`:Node:Data_Bank) SET n = $p, n.node_key = $k, n.ref_id = $k, n.namespace = 'default', n.date_added_to_graph = $now`, + { p: props, k: key, now: int(stamp) }, + ); + /** stakgraph's shape: `Data_Bank` = the name, no domain label, no vector. */ + const fn = (key: string, name: string, description?: string, stamp?: number) => + raw("Function", key, { name, file: "src/access.ts", Data_Bank: name, ...(description === undefined ? {} : { description }) }, stamp); + const node = async (key: string) => { + const r = await bolt.run(`MATCH (n:Data_Bank {node_key: $k}) RETURN labels(n) AS labels, properties(n) AS p`, { k: key }); + assert.equal(r.length, 1, key); + return { labels: [...(r[0]!["labels"] as string[])].sort(), p: r[0]!["p"] as Record }; + }; + const vectorOf = (p: Record) => p["text_embeddings"] as number[] | undefined; + before(async () => { bolt = new Bolt(cfg!); await bolt.verify(); + await wipeGraph(bolt); + await seedJarvisOntology(bolt); + await seedStrutDomain(bolt); + // The mark on `Turn` by hand, until the fixture is re-dumped after the + // jarvis PR lands (plans/semantic-search.md §4). + await bolt.run(`MATCH (s:Schema {type: "Turn"}) SET s.embed = false`); }); after(async () => { + await pass?.stop(); await bolt?.close(); }); beforeEach(async () => { - await wipeGraph(bolt); - await seedStrutDomain(bolt); + await pass?.stop(); + // The Schemas stay; everything written by a test goes. + await bolt.run(`MATCH (n) WHERE NOT n:Schema AND NOT n:Migration DETACH DELETE n`); + resolver = new SchemaResolver(bolt); + lines.length = 0; + pass = new EmbeddingPass(bolt, fake, resolver, { autoStart: false, sweepEveryMs: 1e12, log: (l) => lines.push(l) }); }); - const fake: Embedder = { - async embed(texts) { - return texts.map((t) => Array.from({ length: EMBEDDING_DIM }, (_, i) => (i === 0 ? t.length : 0))); - }, - }; + it("embeds a node another writer put in the graph; a later description, an edit and a stakgraph reset re-embed it; a clean sweep writes nothing", async () => { + await fn("function-a", "resolveWorkspaceAccess", "Checks a user may read the workspace"); + await fn("function-b", "validateWorkspaceAccess"); + await pass.sweep(); + let a = await node("function-a"); + assert.equal(a.p["Data_Bank"], "resolveWorkspaceAccess\nChecks a user may read the workspace"); + assert.deepEqual(a.p["_search_fields_used"], ["name", "description"]); + assert.ok(a.labels.includes("Domain_codeartifact"), `labels ${a.labels}`); + const v1 = vectorOf(a.p)!; + assert.equal(v1[0], (a.p["Data_Bank"] as string).length); + let b = await node("function-b"); + assert.equal(b.p["Data_Bank"], "validateWorkspaceAccess"); + assert.deepEqual(b.p["_search_fields_used"], ["name"]); + assert.ok(vectorOf(b.p)); + let s = pass.status(); + assert.deepEqual([s.sweep.n, s.sweep.phase, s.sweep.type, s.sweep.cursor], [1, "idle", null, null]); + assert.deepEqual(s.last["Function"], { seen: 2, stale: 2, embedded: 2, removed: 0, errors: 0 }); + assert.ok(lines.some((l) => /sweep 1 done/.test(l)), lines.join("\n")); + + // A description filled in after the node was written (mcp's describe job). + await bolt.run(`MATCH (n:Function {node_key: "function-b"}) SET n.description = "Validates access before a write"`); + // A field edited since. + await bolt.run(`MATCH (n:Function {node_key: "function-a"}) SET n.description = "Checks a user may read or write the workspace"`); + await pass.sweep(); + a = await node("function-a"); + b = await node("function-b"); + assert.equal(a.p["Data_Bank"], "resolveWorkspaceAccess\nChecks a user may read or write the workspace"); + assert.notDeepEqual(vectorOf(a.p), v1); + assert.equal(b.p["Data_Bank"], "validateWorkspaceAccess\nValidates access before a write"); + assert.deepEqual(pass.status().last["Function"], { seen: 2, stale: 2, embedded: 2, removed: 0, errors: 0 }); + + // stakgraph's re-sync: `ON MATCH SET node += {Data_Bank: name}` — the + // vector and the record survive, the text is the name again. + await bolt.run(`MATCH (n:Function {node_key: "function-a"}) SET n += {Data_Bank: n.name}`); + await pass.sweep(); + a = await node("function-a"); + assert.equal(a.p["Data_Bank"], "resolveWorkspaceAccess\nChecks a user may read or write the workspace"); + assert.deepEqual(pass.status().last["Function"], { seen: 2, stale: 1, embedded: 1, removed: 0, errors: 0 }); + + // Clean: a sweep reads and writes nothing. + const snap = await graphSnapshot(bolt); + await pass.sweep(); + assert.deepEqual(await graphSnapshot(bolt), snap); + assert.deepEqual(pass.status().last["Function"], { seen: 2, stale: 0, embedded: 0, removed: 0, errors: 0 }); + }); - it("heals NULL text_embeddings and per-stem vectors, then is a no-op", async () => { - // Written WITHOUT an embedder → vectors NULL (the crash case). - const w = new NodeWriter(bolt); - await w.writeMany([ - { type: "StrutRun", data: { run_id: "1", workflow_name: "wf", run_status: "ok", started_at: 1 } }, - { type: "StrutRun", data: { run_id: "2", workflow_name: "wf", run_status: "ok", started_at: 1 } }, - { type: "StrutStep", data: { step_type: "s", input_schema: "{in}", output_schema: " " } }, - { type: "StrutTurn", data: { chat_id: "c", turn: 0 } }, // no index text → kitchen-sink Data_Bank "c\n0" + it("leaves unmarked types alone and names them: no index, no Schema node, no-embed; a blank node is left alone", async () => { + await bolt.run(`CREATE (:Schema {type: "Advisor", domain: "Cloud", node_key: "advisor-name", name: "string", ref_id: "schema-advisor"})`); + await raw("Advisor", "advisor-1", { name: "Adv", Data_Bank: "Adv" }); + await raw("Context", "context-1", { name: "ctx", Data_Bank: "ctx" }); // a label with no Schema (stakgraph's) + await fn("function-blank", " "); + await pass.sweep(); + for (const k of ["advisor-1", "context-1", "function-blank"]) { + const n = await node(k); + assert.equal(vectorOf(n.p), undefined, k); + assert.ok(!n.labels.some((l) => l.startsWith("Domain_")), `${k}: ${n.labels}`); + } + assert.equal((await node("advisor-1")).p["Data_Bank"], "Adv"); + const s = pass.status(); + const named = s.skipped.filter((x) => ["Advisor", "Context", "Turn", "StrutToolCall", "StrutTurn"].includes(x.type)).sort((x, y) => x.type.localeCompare(y.type)); + assert.deepEqual(named, [ + { type: "Advisor", reason: "no_index" }, + { type: "Context", reason: "no_schema" }, + { type: "StrutToolCall", reason: "no_embed" }, + { type: "StrutTurn", reason: "no_embed" }, + { type: "Turn", reason: "no_embed" }, ]); - const r1 = await backfillEmbeddings(bolt, fake, 1); - assert.equal(r1.text_embeddings, 4); - assert.deepEqual(r1.vector_fields, { input_embeddings: 1 }); - const rows = await bolt.run( - `MATCH (n:Domain_strut) RETURN n.node_key AS k, n.text_embeddings[0] AS t0, n.input_embeddings[0] AS i0, n.output_embeddings AS o ORDER BY k`, + assert.ok(!s.skipped.some(skipMe("invalid_label"))); + assert.deepEqual(s.last["Function"], { seen: 1, stale: 0, embedded: 0, removed: 0, errors: 0 }); + assert.ok(!("Advisor" in s.last) && !("Context" in s.last)); + await bolt.run(`MATCH (s:Schema {type: "Advisor"}) DETACH DELETE s`); + }); + + it("pages by node_key: every node once, a tick resumes at the cursor, the code types first", async () => { + await pass.stop(); + pass = new EmbeddingPass(bolt, fake, resolver, { autoStart: false, sweepEveryMs: 1e12, pageSize: 1000, tickBudgetMs: 0, log: (l) => lines.push(l) }); + await bolt.run( + `UNWIND range(1, 2500) AS i + CREATE (n:Function:Node:Data_Bank) + SET n.name = 'fn' + i, n.file = 'f.ts', n.Data_Bank = 'fn' + i, n.node_key = 'function-' + right('0000' + toString(i), 4), + n.ref_id = 'function-' + i, n.namespace = 'default', n.date_added_to_graph = $now`, + { now: int(BEFORE) }, ); - assert.deepEqual(rows, [ - { k: "strutrun-1", t0: "wf\nok".length, i0: null, o: null }, - { k: "strutrun-2", t0: "wf\nok".length, i0: null, o: null }, - { k: "strutstep-73", t0: "s".length, i0: "Input:\n{in}".length, o: null }, // an exact_key type: hex("s") - { k: "strutturn-c-0", t0: "c\n0".length, i0: null, o: null }, - ]); - const r2 = await backfillEmbeddings(bolt, fake); - assert.deepEqual(r2, { text_embeddings: 0, vector_fields: {} }); + await raw("Concept", "concept-1", { name: "Billing", description: "How we bill", Data_Bank: "Billing" }); + // Budget 0 = one page per tick. Tick until Function's first page is in. + let ticks = 0; + while (pass.status().current["Function"]?.seen !== 1000) { + await pass.tick(); + assert.ok(++ticks < 100, `no Function page after ${ticks} ticks: ${JSON.stringify(pass.status())}`); + } + let s = pass.status(); + assert.deepEqual([s.sweep.phase, s.sweep.type, s.sweep.cursor], ["embed", "Function", "function-1000"]); + assert.ok(!("Concept" in s.current), "the code types come first"); + await pass.tick(); + s = pass.status(); + assert.deepEqual([s.current["Function"]!.seen, s.sweep.cursor], [2000, "function-2000"]); + await pass.sweep(); + s = pass.status(); + assert.deepEqual(s.last["Function"], { seen: 2500, stale: 2500, embedded: 2500, removed: 0, errors: 0 }); + assert.deepEqual(s.last["Concept"], { seen: 1, stale: 1, embedded: 1, removed: 0, errors: 0 }); + const missing = await bolt.run(`MATCH (n:Function) WHERE n.text_embeddings IS NULL OR NOT n:Domain_codeartifact RETURN count(n) AS c`); + assert.equal(missing[0]!["c"], 0); + }); + + it("embeds newcomers between sweeps, within a tick, without a sweep", async () => { + await fn("function-old", "oldFn", "there before"); + await pass.sweep(); + assert.equal(pass.status().sweep.n, 1); + await fn("function-new", "newFn", "added after the sweep", Date.now()); + await pass.tick(); + const n = await node("function-new"); + assert.equal(n.p["Data_Bank"], "newFn\nadded after the sweep"); + assert.ok(vectorOf(n.p)); + assert.ok(n.labels.includes("Domain_codeartifact")); + const s = pass.status(); + assert.deepEqual([s.sweep.n, s.newcomers.embedded], [1, 1]); + assert.ok(typeof s.newcomers.since === "number"); + await pass.tick(); + assert.equal(pass.status().newcomers.embedded, 1, "nothing new: nothing done"); + }); + + it("no-embed: strut's execution records get text and no vector (write and update); a marked jarvis type too; a vector found on one is removed, the text kept", async () => { + const w = new NodeWriter(bolt, { embedder: fake, resolver }); + const [tc] = await w.writeMany([{ type: "StrutToolCall", data: { run_id: "r", path: "wf/agent", seq: 1, tool_name: "bash", input_preview: "ls" } }], "upsert"); + const byRef = async (ref_id: string) => (await bolt.run(`MATCH (n:Data_Bank {ref_id: $r}) RETURN properties(n) AS p`, { r: ref_id }))[0]!["p"] as Record; + let p = await byRef(tc!.ref_id); + assert.equal(p["Data_Bank"], "bash\nls"); + assert.deepEqual(p["_search_fields_used"], ["tool_name", "input_preview"]); + assert.equal(vectorOf(p), undefined); + await w.update(tc!.ref_id, { set: { input_preview: "ls -la" } }); + p = await byRef(tc!.ref_id); + assert.equal(p["Data_Bank"], "bash\nls -la"); + assert.equal(vectorOf(p), undefined); + // A vector an earlier writer left goes with the next update. + await bolt.run(`MATCH (n:Data_Bank {ref_id: $r}) SET n.text_embeddings = [1.0, 2.0]`, { r: tc!.ref_id }); + await w.update(tc!.ref_id, { set: { input_preview: "pwd" } }); + assert.equal(vectorOf(await byRef(tc!.ref_id)), undefined); + + const [turn] = await w.writeMany([{ type: "Turn", data: { turn_id: "t1", content: "ran ls", tool: "shell" } }], "create"); + p = await byRef(turn!.ref_id); + assert.equal(p["Data_Bank"], "ran ls\nshell"); + assert.equal(vectorOf(p), undefined); + // jarvis's worker, before the PR: a Turn with a vector. + await bolt.run(`MATCH (n:Data_Bank {ref_id: $r}) SET n.text_embeddings = [0.5, 0.5]`, { r: turn!.ref_id }); + await bolt.run(`MATCH (n:Data_Bank {ref_id: $r}) SET n.text_embeddings = [0.5, 0.5]`, { r: tc!.ref_id }); + await pass.sweep(); + p = await byRef(turn!.ref_id); + assert.equal(vectorOf(p), undefined); + assert.equal(p["Data_Bank"], "ran ls\nshell"); + assert.equal(vectorOf(await byRef(tc!.ref_id)), undefined); + const s = pass.status(); + assert.deepEqual(s.last["Turn"], { seen: 1, stale: 0, embedded: 0, removed: 1, errors: 0 }); + assert.deepEqual(s.last["StrutToolCall"], { seen: 1, stale: 0, embedded: 0, removed: 1, errors: 0 }); + }); + + it("labels: the resolver's — none for a hidden type", async () => { + await bolt.run(`CREATE (:About {hidden_types: ["Var"]})`); + await raw("Var", "var-1", { name: "X", file: "a.ts", body: "const x = 1", Data_Bank: "X" }); + await fn("function-l", "f", "d"); + await pass.sweep(); + const v = await node("var-1"); + assert.equal(v.p["Data_Bank"], "X\nconst x = 1"); + assert.ok(vectorOf(v.p), "hidden is a search-time filter: embedded all the same"); + assert.ok(!v.labels.some((l) => l.startsWith("Domain_")), `${v.labels}`); + assert.ok((await node("function-l")).labels.includes("Domain_codeartifact")); + }); + + it("GET /graph/embeddings reports the sweep and the skipped types; { enabled: false } with embeddings off", async () => { + const dataDir = await mkdtemp(join(tmpdir(), "strut-emb-")); + const backend = await openGraphBackend(cfg!, { embeddings: fake, seedOntology: true, pass: { autoStart: false, sweepEveryMs: 1e12, log: () => undefined } }); + const off = await openGraphBackend(cfg!, { embeddings: false }); + const mk = (b: typeof backend) => createStrut({ workspace: new Neo4jWorkspaceStore(b), store: new MemoryRunStore(), registry: coreRegistry(), dataDir, serveUi: false, enableChat: false, stt: false, scheduler: false }); + const strut = await mk(backend); + const strutOff = await mk(off); + try { + assert.equal(backend.indexReconcile!.status, "nothing_to_do", "the fixture's lists are the library's"); + assert.ok(backend.embeddings); + let res = await strut.app.request("/graph/embeddings"); + assert.equal(res.status, 200); + let body = (await res.json()) as { enabled: boolean; sweep: { n: number; phase: string }; skipped: Array<{ type: string; reason: string }>; ticks: number }; + assert.deepEqual([body.enabled, body.sweep.n, body.ticks], [true, 0, 0]); + await backend.embeddings!.sweep(); + res = await strut.app.request("/graph/embeddings"); + body = await res.json(); + assert.deepEqual([body.sweep.n, body.sweep.phase], [1, "idle"]); + assert.ok(body.skipped.some((s) => s.type === "Turn" && s.reason === "no_embed"), JSON.stringify(body.skipped)); + assert.ok(body.skipped.some((s) => s.type === "StrutToolCall" && s.reason === "no_embed")); + const offRes = await strutOff.app.request("/graph/embeddings"); + assert.deepEqual(await offRes.json(), { enabled: false }); + } finally { + await strut.close(); + await strutOff.close(); + await backend.close(); + await off.close(); + await rm(dataDir, { recursive: true, force: true }); + } }); }); diff --git a/src/graph/embeddings.ts b/src/graph/embeddings.ts index 08195c5..500d258 100644 --- a/src/graph/embeddings.ts +++ b/src/graph/embeddings.ts @@ -11,16 +11,17 @@ * `embeddings.test.ts` against a Python-produced golden vector. * * No Redis queue: vectors are computed in-process before the node write. - * jarvis's "pending" state is purely `text_embeddings IS NULL`, so a crash - * between MERGE and vector write is healed by `backfillEmbeddings` at boot — - * the same NULL-scan idiom jarvis's own migration uses (`migration.py:857`). + * jarvis's "pending" state is purely `text_embeddings IS NULL`. What that + * leaves behind — a crash between MERGE and vector write, and every node + * some OTHER writer put in the graph with no vector at all — is the + * `EmbeddingPass`'s job (below; plans/semantic-search.md). */ import { modelDirFromEnv } from "../model-dir.js"; -import { join } from "node:path"; import { int, type Bolt } from "./bolt.js"; -import type { Embedder } from "./node-writer.js"; -import { renderVectorField } from "./node-writer.js"; -import { STRUT_DOMAIN_LABEL, embeddingColumn, vectorIndexedPairs } from "./strut-schemas.js"; +import { buildSearchText, renderVectorField, type Embedder } from "./node-writer.js"; +import type { SchemaResolver } from "./schema-resolver.js"; +import { schemaStatement } from "./schema-seed.js"; +import { STRUT_SCHEMAS, THING_TYPE, embeddingColumn } from "./strut-schemas.js"; export const EMBEDDING_MODEL = "Xenova/all-MiniLM-L6-v2"; export const EMBEDDING_DIM = 384; @@ -72,7 +73,11 @@ export class MiniLMEmbedder implements Embedder { const [tokenizer, net] = await Promise.all([ tf.AutoTokenizer.from_pretrained(model), // fp32 explicitly: quantized weights would drift from jarvis's encoder. - tf.AutoModel.from_pretrained(model, { dtype: "fp32" }), + // Two intra-op threads, not onnxruntime's default of every core: the + // pass runs hours of inference inside the serving process, beside + // chat turns and runs; the search path embeds one query at a time + // and does not notice. + tf.AutoModel.from_pretrained(model, { dtype: "fp32", session_options: { intraOpNumThreads: 2 } }), ]); // Special-token ids via the public API: an empty input encodes to // exactly [CLS, SEP]. @@ -175,59 +180,537 @@ export function cosine(a: number[], b: number[]): number { return dot / (Math.sqrt(na) * Math.sqrt(nb)); } -export interface BackfillReport { - /** Nodes whose `text_embeddings` was filled. */ - text_embeddings: number; - /** Per `{stem}_embeddings` column, nodes filled. */ - vector_fields: Record; + +// ── The pass ──────────────────────────────────────────────────────────────── +// +// plans/semantic-search.md §1 — the one repair job for everything semantic +// search needs, for every node type the live `:Schema` meta-graph marks for +// search, whoever wrote the node (strut, stakgraph's ingest over bolt, +// jarvis, an import). A node is STALE when its stored `Data_Bank` is not +// the text the writer would compose today from the schema's `index` +// fields, or its vector is missing — one comparison that catches a node +// never embedded, one embedded before its Schema's `index` widened, a +// field filled in or edited since, and a text another writer reset. The +// pass writes what the writer writes and nothing else: `Data_Bank`, +// `text_embeddings`, `_search_fields_used` (jarvis's record, kept for +// parity) and the resolver's domain label. A type marked `embed: false` is +// never embedded, and a vector found on one is removed. +// +// It pages by `node_key` (an index seek per page, never a scan), decides +// in strut, runs inside the serving process on a timer with a per-tick +// budget, and nothing waits on it: a sweep walks every marked type (the +// code types first, then the rest, then the no-embed removals); between +// sweeps each tick embeds the NEWCOMERS — nodes stamped +// `date_added_to_graph` past the last tick's high-water mark, so a freshly +// ingested function is searchable by meaning within a minute. The cursor +// is memory-only: a restart begins the sweep again, cheap on a clean graph. + +export interface EmbeddingPassOptions { + /** Nodes per page read (one index seek each). */ + pageSize?: number; + /** Texts per embedder call and rows per write. */ + batchSize?: number; + /** How often a tick runs. */ + tickMs?: number; + /** How long one tick may work before it yields; at least one page runs. */ + tickBudgetMs?: number; + /** Pause between the end of one sweep and the start of the next. */ + sweepEveryMs?: number; + /** Start the timer at construction (the default). Tests pass `false` and + * drive `tick()` / `sweep()` by hand. */ + autoStart?: boolean; + log?: (line: string) => void; + now?: () => number; +} + +export type SkipReason = "no_schema" | "no_index" | "no_embed" | "invalid_label"; + +export interface TypeCounts { + /** Nodes the sweep read. */ + seen: number; + /** Of those, stale: text or vector rewritten. */ + stale: number; + embedded: number; + /** Vectors removed (no-embed types). */ + removed: number; + /** Pages that failed (the type is left for the next sweep). */ + errors: number; +} + +/** `GET /graph/embeddings`. */ +export interface EmbeddingPassStatus { + enabled: true; + sweep: { + /** Sweeps begun since the process started (the one in flight included). */ + n: number; + startedAt: number | null; + finishedAt: number | null; + phase: "embed" | "remove" | "idle"; + type: string | null; + cursor: string | null; + }; + /** The sweep in flight, per type. */ + current: Record; + /** The last complete sweep, per type. */ + last: Record; + /** Types the sweep does not embed, and why: no Schema node (a label with + * `Data_Bank` nodes and no schema), no `index` on its Schema (the + * catch-all text is never embedded by the pass), the no-embed mark, or + * a type name that is not a label. */ + skipped: Array<{ type: string; reason: SkipReason }>; + newcomers: { since: number | null; embedded: number }; + lastError: string | null; + ticks: number; +} + +export const PASS_DEFAULTS = { + pageSize: 1000, + batchSize: 100, + tickMs: 60_000, + tickBudgetMs: 15_000, + sweepEveryMs: 3_600_000, +} as const; + +const LABEL = /^[A-Za-z_][A-Za-z0-9_]*$/; +/** Labels every node carries beside its type, and the meta-graph's own. */ +const NON_TYPE_LABELS = new Set(["Node", "Data_Bank", "Schema", "Migration", "About", "Namespace", THING_TYPE]); +const CODE_DOMAIN_LABEL = "Domain_codeartifact"; + +interface Marked { + type: string; + index: string[]; + /** The resolver's domain label, none for a hidden type or domain. */ + label: string | undefined; + /** `vector_index` properties with their own `{stem}_embeddings`. */ + vectorIndex: string[]; +} + +interface PageRow { + eid: string; + node_key: string; + text: unknown; + values: unknown[]; + unembedded: boolean; + labeled: boolean; + vvalues: unknown[]; + vnull: boolean[]; } /** - * Crash-safe sweep: embed every Strut node whose search text exists but - * whose vector is NULL, in batches, until none remain. Idempotent and cheap - * when clean. Run at every boot of the graph backend. Also covers the - * per-property `{stem}_embeddings` of the `vector_index` types. + * The stale decision for one page row — pure. `values` holds the index + * fields ALONE, never the node's other properties: the writer's + * composition falls through to jarvis's catch-all text when none of the + * index fields is usable, and with nothing else to find it composes + * nothing, which is what "a node whose index fields are all blank is left + * alone" rests on. A list-valued field renders as the writer renders it. */ -export async function backfillEmbeddings(bolt: Bolt, embedder: Embedder, batchSize = 100): Promise { - const report: BackfillReport = { text_embeddings: 0, vector_fields: {} }; - - for (;;) { - const rows = await bolt.run( - `MATCH (n:\`${STRUT_DOMAIN_LABEL}\`) - WHERE n.Data_Bank IS NOT NULL AND n.text_embeddings IS NULL - RETURN n.ref_id AS ref_id, n.Data_Bank AS text LIMIT $limit`, - { limit: int(batchSize) }, +export function decideRow(index: string[], row: { text: unknown; values: unknown[]; unembedded: boolean }): { text: string; fields: string[] } | "clean" | "blank" { + const values: Record = {}; + index.forEach((f, i) => { + const v = row.values[i]; + if (v !== null && v !== undefined) values[f] = v; + }); + const { text, fields } = buildSearchText({ index }, values); + if (text === null) return "blank"; + if (!row.unembedded && row.text === text) return "clean"; + return { text, fields }; +} + +const PAGE_COLUMNS = `elementId(n) AS eid, n.node_key AS node_key, n.Data_Bank AS text, + [f IN $F | n[f]] AS values, n.text_embeddings IS NULL AS unembedded, + CASE WHEN $L IS NULL THEN true ELSE $L IN labels(n) END AS labeled, + [p IN $V | n[p]] AS vvalues, [c IN $C | n[c] IS NULL] AS vnull`; + +export class EmbeddingPass { + private readonly pageSize: number; + private readonly batchSize: number; + private readonly tickMs: number; + private readonly tickBudgetMs: number; + private readonly sweepEveryMs: number; + private readonly log: (line: string) => void; + private readonly now: () => number; + + private timer: ReturnType | null = null; + private first: ReturnType | null = null; + private inflight: Promise | null = null; + private stopped = false; + private ddlDone = false; + + private sweepN = 0; + private startedAt: number | null = null; + private finishedAt: number | null = null; + private plan: { embed: Marked[]; remove: Marked[] } | null = null; + /** The last plan's embed list — what the newcomer tick covers. */ + private embedList: Marked[] = []; + private pos: { phase: "embed" | "remove" | "idle"; i: number; cursor: string } = { phase: "idle", i: 0, cursor: "" }; + private current: Record = {}; + private last: Record = {}; + private skipped: Array<{ type: string; reason: SkipReason }> = []; + private since: number | null = null; + private newcomersEmbedded = 0; + private lastError: string | null = null; + private ticks = 0; + + constructor( + private readonly bolt: Bolt, + private readonly embedder: Embedder, + private readonly resolver: SchemaResolver, + opts: EmbeddingPassOptions = {}, + ) { + this.pageSize = opts.pageSize ?? PASS_DEFAULTS.pageSize; + this.batchSize = opts.batchSize ?? PASS_DEFAULTS.batchSize; + this.tickMs = opts.tickMs ?? PASS_DEFAULTS.tickMs; + this.tickBudgetMs = opts.tickBudgetMs ?? PASS_DEFAULTS.tickBudgetMs; + this.sweepEveryMs = opts.sweepEveryMs ?? PASS_DEFAULTS.sweepEveryMs; + this.log = opts.log ?? ((line) => console.log(`[graph embeddings] ${line}`)); + this.now = opts.now ?? Date.now; + if (opts.autoStart !== false) this.start(); + } + + /** Start the timer: a first tick right away, then every `tickMs`. The + * timers never hold the process open. */ + start(): void { + if (this.timer) return; + this.stopped = false; + this.first = setTimeout(() => void this.tick(), 0); + this.first.unref?.(); + this.timer = setInterval(() => void this.tick(), this.tickMs); + this.timer.unref?.(); + } + + /** Stop the timer and wait for the tick in flight to end (it yields at + * the next page boundary). */ + async stop(): Promise { + this.stopped = true; + if (this.first) clearTimeout(this.first); + if (this.timer) clearInterval(this.timer); + this.first = null; + this.timer = null; + await this.inflight?.catch(() => undefined); + } + + status(): EmbeddingPassStatus { + const copy = (c: Record) => Object.fromEntries(Object.entries(c).map(([k, v]) => [k, { ...v }])); + const list = this.plan ? (this.pos.phase === "embed" ? this.plan.embed : this.plan.remove) : []; + return { + enabled: true, + sweep: { + n: this.sweepN, + startedAt: this.startedAt, + finishedAt: this.finishedAt, + phase: this.pos.phase, + type: list[this.pos.i]?.type ?? null, + cursor: this.plan ? this.pos.cursor : null, + }, + current: copy(this.current), + last: copy(this.last), + skipped: this.skipped.map((s) => ({ ...s })), + newcomers: { since: this.since, embedded: this.newcomersEmbedded }, + lastError: this.lastError, + ticks: this.ticks, + }; + } + + /** One tick: resume the sweep in flight (or begin one when the pause has + * passed, else embed the newcomers) for up to the budget. Ticks never + * overlap — a call during one joins it. */ + tick(): Promise { + if (this.inflight) return this.inflight; + this.inflight = this.run() + .catch((e) => { + this.lastError = errorMessage(e); + this.log(`tick failed: ${this.lastError}`); + }) + .finally(() => { + this.inflight = null; + }); + return this.inflight; + } + + /** Run the sweep in flight — or a new one — to its end. What a caller + * that wants the graph repaired NOW uses; the timer never needs it. */ + async sweep(): Promise { + if (!this.plan) await this.beginSweep(); + while (this.plan && !this.stopped) await this.tick(); + } + + private async run(): Promise { + this.ticks++; + const start = this.now(); + const did = { embedded: 0, removed: 0, newcomers: 0, ended: false }; + if (!this.plan && (this.finishedAt === null || this.now() - this.finishedAt >= this.sweepEveryMs)) await this.beginSweep(); + const was = this.plan ? `sweep ${this.sweepN}` : "between sweeps"; + if (this.plan) await this.work(start, did); + else await this.newcomers(start, did); + if (did.embedded || did.removed || did.newcomers || did.ended) { + const at = this.plan ? ` at ${this.pos.phase} ${this.status().sweep.type ?? "-"} ${JSON.stringify(this.pos.cursor)}` : ""; + this.log(`tick ${this.ticks} (${was}${at}): embedded ${did.embedded}, removed ${did.removed}, newcomers ${did.newcomers}${did.ended ? "; sweep done" : ""}`); + } + } + + // ── the sweep ───────────────────────────────────────────────────────── + + private async beginSweep(): Promise { + this.resolver.invalidate(); + const { embed, remove, skipped } = await this.planSweep(); + if (!this.ddlDone) { + // The cursor seeks on `node_key`; every seeded type has the index + // (jarvis's `add_node_key_indexes`, strut's two seeds), and this + // makes it so on any graph. The newcomer tick seeks on the stamp. + for (const m of [...embed, ...remove]) await schemaStatement(this.bolt, `CREATE INDEX IF NOT EXISTS FOR (n:\`${m.type}\`) ON (n.node_key)`); + await schemaStatement(this.bolt, `CREATE INDEX IF NOT EXISTS FOR (n:Data_Bank) ON (n.date_added_to_graph)`); + this.ddlDone = true; + } + this.sweepN++; + this.startedAt = this.now(); + this.finishedAt = null; + // Everything stamped after this is a newcomer; the sweep covers what + // exists now (a node written behind the cursor is caught after it). + if (this.since === null) this.since = this.startedAt; + this.plan = { embed, remove }; + this.embedList = embed; + this.skipped = skipped; + this.current = {}; + this.pos = { phase: embed.length ? "embed" : remove.length ? "remove" : "idle", i: 0, cursor: "" }; + this.log( + `sweep ${this.sweepN} begins: ${embed.length} type(s) to embed (${embed.map((m) => m.type).join(", ")}), ` + + `${remove.length} no-embed (${remove.map((m) => m.type).join(", ")}), ${skipped.length} skipped`, ); - if (rows.length === 0) break; - const vectors = await embedder.embed(rows.map((r) => String(r["text"]))); - await bolt.run( - `UNWIND $rows AS row - MATCH (n:Data_Bank {ref_id: row.ref_id}) - SET n.text_embeddings = row.vector`, - { rows: rows.map((r, i) => ({ ref_id: r["ref_id"], vector: vectors[i] })) }, + if (!embed.length && !remove.length) this.endSweep(); + } + + /** Every type with a live Schema, through the resolver: what to embed + * (its `index`, its domain label), what to strip, what to leave alone. */ + private async planSweep(): Promise<{ embed: Marked[]; remove: Marked[]; skipped: Array<{ type: string; reason: SkipReason }> }> { + const types = new Set(STRUT_SCHEMAS.map((s) => s.type)); + const live = await this.bolt.run( + `MATCH (s:Schema) WHERE s.type IS NOT NULL AND s.type <> '*' AND (s.is_deleted IS NULL OR s.is_deleted = false) + RETURN DISTINCT s.type AS t`, + ); + for (const r of live) types.add(String(r["t"])); + const embed: Marked[] = []; + const remove: Marked[] = []; + const skipped: Array<{ type: string; reason: SkipReason }> = []; + for (const t of [...types].sort()) { + if (NON_TYPE_LABELS.has(t)) continue; + if (!LABEL.test(t)) { + skipped.push({ type: t, reason: "invalid_label" }); + continue; + } + const s = await this.resolver.schema(t); + if (!s) { + skipped.push({ type: t, reason: "no_schema" }); + continue; + } + const m: Marked = { type: s.type, index: s.index, label: s.domainLabels[0], vectorIndex: s.vector_index }; + if (!s.embed) { + remove.push(m); + skipped.push({ type: s.type, reason: "no_embed" }); + } else if (s.index.length === 1 && s.index[0] === "node_key") { + skipped.push({ type: s.type, reason: "no_index" }); + } else embed.push(m); + } + // A label with `Data_Bank` nodes and no Schema node (stakgraph's + // `Context`, `Chunk`): named, never embedded — the status read says so. + const labels = (await this.bolt.run(`CALL db.labels() YIELD label RETURN label`)).map((r) => String(r["label"])); + for (const l of labels.sort()) { + if (types.has(l) || NON_TYPE_LABELS.has(l) || l.startsWith("Domain_") || !LABEL.test(l)) continue; + const any = await this.bolt.run(`MATCH (n:\`${l}\`:Data_Bank) RETURN true AS x LIMIT 1`); + if (any.length) skipped.push({ type: l, reason: "no_schema" }); + } + const code = (m: Marked) => (m.label === CODE_DOMAIN_LABEL ? 0 : 1); + embed.sort((a, b) => code(a) - code(b) || a.type.localeCompare(b.type)); + return { embed, remove, skipped }; + } + + private endSweep(): void { + this.last = this.current; + this.current = {}; + this.finishedAt = this.now(); + this.plan = null; + this.pos = { phase: "idle", i: 0, cursor: "" }; + const total = (k: keyof TypeCounts) => Object.values(this.last).reduce((s, c) => s + c[k], 0); + this.log( + `sweep ${this.sweepN} done in ${this.finishedAt - (this.startedAt ?? this.finishedAt)} ms: ` + + `seen ${total("seen")}, stale ${total("stale")}, embedded ${total("embedded")}, removed ${total("removed")}, errors ${total("errors")}`, + ); + } + + /** Pages until the budget is spent or the sweep ends. */ + private async work(start: number, did: { embedded: number; removed: number; ended: boolean }): Promise { + let pages = 0; + while (this.plan && !this.stopped) { + if (pages > 0 && this.now() - start >= this.tickBudgetMs) return; + const list = this.pos.phase === "embed" ? this.plan.embed : this.plan.remove; + const m = list[this.pos.i]; + if (!m) { + if (this.pos.phase === "embed" && this.plan.remove.length) this.pos = { phase: "remove", i: 0, cursor: "" }; + else { + this.endSweep(); + did.ended = true; + } + continue; + } + try { + const exhausted = this.pos.phase === "embed" ? await this.embedPage(m, did) : await this.removePage(m, did); + if (exhausted) this.pos = { ...this.pos, i: this.pos.i + 1, cursor: "" }; + } catch (e) { + // On to the next type; the next sweep retries this one. + this.counts(m.type).errors++; + this.lastError = `${m.type}: ${errorMessage(e)}`; + this.log(`page failed, ${this.lastError}`); + this.pos = { ...this.pos, i: this.pos.i + 1, cursor: "" }; + } + pages++; + } + } + + private counts(type: string): TypeCounts { + return (this.current[type] ??= { seen: 0, stale: 0, embedded: 0, removed: 0, errors: 0 }); + } + + /** One page of a marked type from the cursor. True when the type is done. */ + private async embedPage(m: Marked, did: { embedded: number }): Promise { + const rows = (await this.bolt.run( + `MATCH (n:\`${m.type}\`) WHERE n.node_key > $cursor + WITH n ORDER BY n.node_key LIMIT $page + RETURN ${PAGE_COLUMNS}`, + this.pageParams(m, { cursor: this.pos.cursor }), + )) as unknown as PageRow[]; + if (rows.length === 0) return true; + this.counts(m.type).seen += rows.length; + did.embedded += await this.repair(m, rows, this.counts(m.type)); + this.pos = { ...this.pos, cursor: rows[rows.length - 1]!.node_key }; + return rows.length < this.pageSize; + } + + private pageParams(m: Marked, extra: Record): Record { + return { ...extra, page: int(this.pageSize), F: m.index, V: m.vectorIndex, C: m.vectorIndex.map(embeddingColumn), L: m.label ?? null }; + } + + /** Rewrite the stale rows of a page (text, record, vector, per-field + * vectors), label the unlabeled ones. Returns how many were embedded. */ + private async repair(m: Marked, rows: PageRow[], counts: TypeCounts): Promise { + const stale: Array<{ eid: string; text: string; fields: string[] }> = []; + const unlabeled: string[] = []; + const fieldJobs = new Map>(); + for (const r of rows) { + const d = decideRow(m.index, r); + if (d === "blank") continue; + if (d !== "clean") stale.push({ eid: r.eid, ...d }); + if (!r.labeled) unlabeled.push(r.eid); + m.vectorIndex.forEach((p, i) => { + const v = r.vvalues[i]; + if (!r.vnull[i] || v === null || v === undefined) return; + const rendered = renderVectorField(p, String(v)); + if (rendered) (fieldJobs.get(embeddingColumn(p)) ?? fieldJobs.set(embeddingColumn(p), []).get(embeddingColumn(p))!).push({ eid: r.eid, text: rendered }); + }); + } + counts.stale += stale.length; + let embedded = 0; + for (let i = 0; i < stale.length; i += this.batchSize) { + const batch = stale.slice(i, i + this.batchSize); + const vectors = await this.embedder.embed(batch.map((b) => b.text)); + await this.bolt.run( + `UNWIND $rows AS row + MATCH (n) WHERE elementId(n) = row.eid + SET n.Data_Bank = row.text, n._search_fields_used = row.fields, n.text_embeddings = row.vector`, + { rows: batch.map((b, j) => ({ eid: b.eid, text: b.text, fields: b.fields, vector: vectors[j] })) }, + ); + counts.embedded += batch.length; + embedded += batch.length; + } + for (const [column, jobs] of fieldJobs) { + for (let i = 0; i < jobs.length; i += this.batchSize) { + const batch = jobs.slice(i, i + this.batchSize); + const vectors = await this.embedder.embed(batch.map((b) => b.text)); + await this.bolt.run( + `UNWIND $rows AS row MATCH (n) WHERE elementId(n) = row.eid SET n.\`${column}\` = row.vector`, + { rows: batch.map((b, j) => ({ eid: b.eid, vector: vectors[j] })) }, + ); + } + } + if (m.label && unlabeled.length) { + await this.bolt.run(`UNWIND $eids AS eid MATCH (n) WHERE elementId(n) = eid SET n:\`${m.label}\``, { eids: unlabeled }); + } + return embedded; + } + + /** One page of a no-embed type: strip the vectors it holds. */ + private async removePage(m: Marked, did: { removed: number }): Promise { + const rows = await this.bolt.run( + `MATCH (n:\`${m.type}\`) WHERE n.node_key > $cursor + WITH n ORDER BY n.node_key LIMIT $page + RETURN elementId(n) AS eid, n.node_key AS node_key, n.text_embeddings IS NOT NULL AS embedded`, + { cursor: this.pos.cursor, page: int(this.pageSize) }, ); - report.text_embeddings += rows.length; + if (rows.length === 0) return true; + const counts = this.counts(m.type); + counts.seen += rows.length; + const eids = rows.filter((r) => r["embedded"] === true).map((r) => String(r["eid"])); + for (let i = 0; i < eids.length; i += this.batchSize) { + const batch = eids.slice(i, i + this.batchSize); + await this.bolt.run(`UNWIND $eids AS eid MATCH (n) WHERE elementId(n) = eid REMOVE n.text_embeddings`, { eids: batch }); + counts.removed += batch.length; + did.removed += batch.length; + } + this.pos = { ...this.pos, cursor: String(rows[rows.length - 1]!["node_key"]) }; + return rows.length < this.pageSize; } - for (const { type, prop } of vectorIndexedPairs()) { - const column = embeddingColumn(prop); + // ── between sweeps ──────────────────────────────────────────────────── + + /** Embed what was stamped since the last tick and carries a marked label + * and no vector — one range seek on `date_added_to_graph` per page, the + * index fields of every marked type read at once. A node that gets no + * vector here (blank) waits for the next sweep. */ + private async newcomers(start: number, did: { newcomers: number }): Promise { + if (this.since === null || this.embedList.length === 0) return; + const until = this.now(); + const byLabel = new Map(this.embedList.map((m) => [m.type, m])); + const fields = [...new Set(this.embedList.flatMap((m) => m.index))]; + let pages = 0; for (;;) { - const rows = await bolt.run( - `MATCH (n:\`${type}\`) - WHERE n.\`${prop}\` IS NOT NULL AND trim(n.\`${prop}\`) <> '' AND n.\`${column}\` IS NULL - RETURN n.ref_id AS ref_id, n.\`${prop}\` AS text LIMIT $limit`, - { limit: int(batchSize) }, + if (pages > 0 && this.now() - start >= this.tickBudgetMs) return; // keep `since`; the next tick resumes + const rows = await this.bolt.run( + `MATCH (n:Data_Bank) WHERE n.date_added_to_graph > $since AND n.text_embeddings IS NULL + WITH n ORDER BY n.date_added_to_graph LIMIT $page + RETURN elementId(n) AS eid, labels(n) AS labels, n.Data_Bank AS text, [f IN $F | n[f]] AS values`, + { since: int(this.since), page: int(this.pageSize), F: fields }, ); + pages++; if (rows.length === 0) break; - const vectors = await embedder.embed(rows.map((r) => renderVectorField(prop, String(r["text"]))!)); - await bolt.run( - `UNWIND $rows AS row - MATCH (n:Data_Bank {ref_id: row.ref_id}) - SET n.\`${column}\` = row.vector`, - { rows: rows.map((r, i) => ({ ref_id: r["ref_id"], vector: vectors[i] })) }, - ); - report.vector_fields[column] = (report.vector_fields[column] ?? 0) + rows.length; + const byType = new Map(); + for (const r of rows) { + const labels = r["labels"] as string[]; + const m = labels.map((l) => byLabel.get(l)).find((x): x is Marked => !!x); + if (!m) continue; + const all = r["values"] as unknown[]; + const row: PageRow = { + eid: String(r["eid"]), + node_key: "", + text: r["text"], + values: m.index.map((f) => all[fields.indexOf(f)]), + unembedded: true, + labeled: !m.label || labels.includes(m.label), + vvalues: [], + vnull: [], + }; + byType.set(m, [...(byType.get(m) ?? []), row]); + } + let embedded = 0; + const scratch: TypeCounts = { seen: 0, stale: 0, embedded: 0, removed: 0, errors: 0 }; // `current` is the sweep's + for (const [m, typed] of byType) embedded += await this.repair({ ...m, vectorIndex: [] }, typed, scratch); + this.newcomersEmbedded += embedded; + did.newcomers += embedded; + // A full page that embedded nothing is all blank or unmarked: stop, + // or this loop would read it again. + if (rows.length < this.pageSize || embedded === 0) break; } + this.since = until; } - return report; +} + +function errorMessage(e: unknown): string { + return ((e as Error)?.message ?? String(e)).split("\n")[0]!; } diff --git a/src/graph/fixtures/jarvis-ontology.ts b/src/graph/fixtures/jarvis-ontology.ts index 1973e14..7d4fbde 100644 --- a/src/graph/fixtures/jarvis-ontology.ts +++ b/src/graph/fixtures/jarvis-ontology.ts @@ -9,9 +9,11 @@ */ export interface OntologyFixture { source: string; + /** Bumped at every re-dump: the `index` reconcile (index-reconcile.ts) runs once per version. */ + version: string; schemas: Array>; edge_schemas: Array<{ source: string; edge: string; target: string; props: Record }>; hidden_domains: string[] | null; } -export const JARVIS_ONTOLOGY: OntologyFixture = {"source":"jarvis-backend local default seed (sphinxlightning/sphinx-neo4j) at migration 125 (Check node + ABOUT/TESTS/PRODUCED_BY pairs), read-only dump","schemas":[{"ref_id":"83bb6c45-40c5-45de-b76f-8aeb5ee75f33","type":"*","is_system":true},{"next_review":"?datetime","node_key":"aisystem-name","secondary_color":"#D7CCC8","type":"AISystem","obligations_assessed":"?boolean","workflow_position":"?string","review_trigger":"?string","risk_tier":"?string","description":"?string","name":"string","governance_tier":"?string","type_description":"An AI or automated decision-making system subject to governance and regulatory obligations.","domain":"Legal","role":"?string","icon":"ChipIcon","primary_color":"#6D4C41","index":["ref_id","name","risk_tier","regulatory_regime"],"regulatory_regime":"?string","status":"?string","parent":"Thing","shape":"sphere","eu_nexus":"?boolean","human_in_loop":"?boolean","description_key":"description","title_key":"name","classification":"?string","ref_id":"1c93f74c-b212-4493-98b9-833decb96315","obligations_note":"?string","affected_population":"?string","output_type":"?string","tier_basis":"?string"},{"icon":"BookIcon","primary_color":"#222B48","index":["text","level"],"text":"string","abstraction_id":"string","parent":"Workflow","node_key":"abstraction-abstraction_id","secondary_color":"#5E84F8","shape":"sphere","type":"Abstraction","level":"string","description_key":"text","title_key":"level","domain":"Workflow","type_description":"A named level of abstraction for an agent session — title, narrative, or decision — with optional embedding for retrieval.","ref_id":"31ba479a-5928-4ad1-b074-1dedb265036e","embedding":"?string"},{"action_id":"string","icon":"GeneratedStepIcon","primary_color":"#38243C","index":["name","description"],"status":"?string","parent":"Workflow","node_key":"action-action_id","secondary_color":"#F468D4","shape":"sphere","type":"Action","description_key":"description","title_key":"name","description":"?string","name":"?string","domain":"Workflow","type_description":"Represents a single action or procedural step within a broader strategy.","ref_id":"28159b06-14d2-4df3-b0e1-bace578f0320"},{"icon":"GeneratedStepIcon","primary_color":"#38243C","index":["agent_id","role"],"parent":"Workflow","node_key":"agent-agent_id","secondary_color":"#F468D4","shape":"sphere","agent_id":"int","type":"Agent","description_key":"role","title_key":"agent_id","domain":"Workflow","type_description":"An autonomous entity that can perform actions and make decisions.","ref_id":"e54fef17-be5f-4893-8bee-9f1da0bab9b2","role":"?string"},{"icon":"PersonIcon","primary_color":"#222B48","index":["source"],"parent":"Workflow","node_key":"agentrole-source","secondary_color":"#5E84F8","shape":"sphere","type":"AgentRole","description_key":"source","title_key":"source","source":"string","domain":"CodeArtifact","type_description":"A named agent type (e.g. plan-agent, coding-agent) that groups its execution sessions.","ref_id":"cd4025c7-575c-4fd2-8f18-e162bafd0eea"},{"model":"?string","session_id":"string","output_tokens":"?int","total_tokens":"?int","task_id":"?string","duration_ms":"?int","node_key":"agentsession-session_id","log_url":"?string","secondary_color":"#C25AF3","type":"AgentSession","repo":"?string","feature_id":"?string","error_message":"?string","type_description":"A single agent execution run, keyed by per-run UUID.","domain":"CodeArtifact","created_at":"?datetime","icon":"GeneratedStepIcon","primary_color":"#302342","index":["source","status","repo"],"status":"?string","cache_read_tokens":"?int","parent":"Workflow","provider":"?string","input_tokens":"?int","shape":"sphere","description_key":"status","title_key":"source","source":"string","end_time":"?int","ref_id":"e0eace93-0e5c-4f27-bd28-ec94a0f1b17a","start_time":"?int","cache_write_tokens":"?int"},{"agreement_type":"?string","icon":"DocumentIcon","primary_color":"#6D4C41","index":["name","agreement_type","effective_date","governing_law"],"status":"?string","governing_law":"?string","parent":"Legal","node_key":"agreement-id","secondary_color":"#D7CCC8","shape":"sphere","type":"Agreement","id":"string","description_key":"agreement_type","title_key":"name","execution_date":"?string","expiration_date":"?string","name":"?string","domain":"Legal","type_description":"A legally binding contract between two or more parties. Matches the Agreement label produced by the graphrag-contract-review ingestion pipeline.","ref_id":"718a2c7e-fe85-44ae-90ea-847974f6fa78","effective_date":"?string"},{"icon":"PaperClipIcon","primary_color":"#1A3A52","size_bytes":"?int","index":["filename","content_type"],"parent":"Content","node_key":"attachment-filename","secondary_color":"#5BA4CF","shape":"sphere","type":"Attachment","description_key":"content_type","title_key":"filename","domain":"Content","type_description":"A file attached to an email message.","ref_id":"4bbd7399-656d-48b3-9718-8e47ed63c49c","filename":"string","source_link":"?string","content_type":"?string"},{"icon":"NodesIcon","primary_color":"#2A3229","index":"user_reference","update_type":"string","parent":"KnowledgeArtifact","node_key":"belief-user_reference-referenced_id","refutes_supports":"float","date_created":"datetime","secondary_color":"#96BD3F","shape":"sphere","type":"Belief","decay_curve":"?string","confidence_score":"float","user_reference":"string","description_key":"user_reference","title_key":"user_reference","update_trigger":"?string","graph_url":"?string","domain":"KnowledgeArtifact","type_description":"A user epistemic position on a referenced graph node, with confidence scoring, support/refutation polarity, and configurable decay or trigger-based update logic","ref_id":"980dd66a-e226-4bab-9768-0c64be03d14c","referenced_id":"string"},{"cause_detail":"string","icon":"ExclamationCircleIcon","primary_color":"#6D4C41","index":["cause_type","task_slug_prefix","dedup_hash"],"first_seen_run_id":"?string","cause_summary":"string","parent":"Legal","suggested_fix":"?string","node_key":"benchmarkfailurecause-dedup_hash","secondary_color":"#D7CCC8","issue_group":"?string","shape":"sphere","type":"BenchmarkFailureCause","cause_type":"string","dedup_hash":"string","log_evidence":"?string","description_key":"cause_detail","title_key":"cause_summary","last_seen_run_id":"?string","domain":"Legal","type_description":"A classified root cause of failure for one or more Harvey LAB benchmark criteria. One node per unique cause_type + task_slug_prefix + issue_group combination, deduped via SHA-256 hash. Linked to EvalTriggerOutput nodes of all runs that exhibited this cause via ATTRIBUTED_TO, and to the EvalRequirement it affects via AFFECTS. occurrence_count is incremented on each association. Cause types: CALCULATION_ERROR, THRESHOLD_NOT_APPLIED, MISSING_DOWNSTREAM_CONCLUSION, JURISDICTION_RULE_MISSING, MULTI_JURISDICTION_INCOMPLETE, SCOPE_GAP_NOT_IDENTIFIED, CROSS_DOCUMENT_CONFLICT_MISSED, HEADCOUNT_ATTRIBUTION_ERROR, MISSING_STATUTORY_CITATION, PRIVILEGE_MISCLASSIFICATION, AGENT_REASONING_GAP, RETRIEVAL_FAILURE.","ref_id":"4edc2855-3f17-4d1a-bb36-207c07a9b0e5","occurrence_count":"?int","task_slug_prefix":"?string"},{"one_sentence_summary":"?string","phase_priority":"?int","org_uuid":"?string","bounty_type":"?string","node_key":"bounty-bounty_id","show":"?boolean","secondary_color":"#54AC52","estimated_completion_date":"?string","type":"Bounty","bounty_id":"int","estimated_session_length":"?string","title":"?string","deliverables":"?string","paid":"?boolean","created":"?int","updated":"?string","description":"?string","type_description":"A reward offered for completing a task or challenge","domain":"Entity","phase_uuid":"?string","github_description":"?boolean","bounty_expires":"?string","completed":"?boolean","primary_color":"#22362A","workspace_uuid":"?string","index":["description","title"],"ticket_url":"?string","tribe":"?string","assigned_hours":"?int","commitment_fee":"?int","parent":"Thing","assignee":"?string","shape":"sphere","wanted_type":"?string","price":"?int","description_key":"description","title_key":"title","owner_id":"?string","ref_id":"704f1683-7a0d-4792-b772-7c317f4514cb","coding_languages":"?string"},{"icon":"EpisodeIcon","primary_color":"#222B48","index":["episode_title","description"],"status":"?string","episode_title":"?string","media_url":"?string","parent":"Show","node_key":"call-source_link","show_title":"?string","secondary_color":"#5E84F8","shape":"sphere","date":"?datetime","type":"Call","pubkey":"?string","description_key":"description","title_key":"episode_title","image_url":"?string","description":"?string","project_id":"?string","domain":"Content","type_description":"A single installment in a series of related productions e.g Show","ref_id":"1d02e951-e415-4e3f-beb4-b777778501c1","source_link":"string"},{"icon":"ExclamationCircleIcon","primary_color":"#362429","index":["cause_type","severity"],"parent":"Thing","node_key":"cause-id","severity":"?string","secondary_color":"#D25353","shape":"sphere","type":"Cause","cause_type":"?string","id":"string","title":"string","description_key":"description","title_key":"title","resolved":"?boolean","description":"?string","domain":"CodeArtifact","type_description":"A structured root cause attributed to one or more CriterionResult failures. Supports hierarchical grouping via CAUSE_CHILD_OF. cause_type values: prompt_gap | reasoning_error | missing_context | format_violation. severity values: critical | high | medium | low.","ref_id":"a5d69c3a-5208-4cae-8063-5a80493503d0","created_at":"?datetime"},{"transcript":"?string","index":["name","description"],"parent":"Content","node_key":"chapter-name-timestamp-source_link","type":"Chapter","is_favorite":"?boolean","timestamp":"string","description_key":"description","title_key":"name","paid_properties":["transcript"],"is_ad":"?boolean","description":"?string","name":"string","domain":"Content","ref_id":"babd19b8-9d80-46ed-b4b6-0d8472b5fa5a","source_link":"string"},{"retired_at":"?datetime","node_key":"check-id","secondary_color":"#4FA7D9","type":"Check","step_type":"?string","publisher":"?string","id":"string","step_config":"?string","description":"?string","name":"string","type_description":"One instrument that can test one Claim (migration 125) — the node the epistemic layer first held off on. A Claim is the statement, a Check is a way of testing it, Evidence is what one test observed: Check -[TESTS]-> Claim, and the Evidence a check yields points back via Evidence -[PRODUCED_BY]-> Check. A node rather than attributes on the Claim because one claim can have SEVERAL checks (a free script on every run, a model judge on change, a person once per version), each with its own policy, cost and evidence stream, and a check can be replaced without touching the statement. step_type names the executable instrument in the producer's registry and step_config is its JSON config; step_type ABSENT means an EXTERNAL check — answered by a person or an outside system, usually by filling a planned Evidence slot (Evidence.evidence_status) — and description then says what to look at and why code cannot. run_when: run | publish — whether the check fires on an execution of the subject or when a new version of it is published. policy: always | on_change | sample | manual — how often a run check fires; freshness_days bounds on_change (re-run when the latest evidence is older, catching environment drift) and sample_rate is the fraction of runs for sample. publisher records who wrote the check (ai, a person, a seeder). A check is IMMUTABLE once it has evidence: editing it creates a new Check that SUPERSEDES the old one and sets the old node's retired_at — a changed instrument has measured nothing yet, so a retired check's evidence stays in the graph but no longer counts. Active = retired_at unset (there is no status attribute: `status` is a reserved name). run_when and policy are documented contracts, not DB-enforced enums (the Claim.verdict / Evidence.evidence_status convention); readers must treat any other value as unknown/unspecified.","domain":"Epistemic","created_at":"datetime","run_when":"?string","icon":"TaskIcon","primary_color":"#1D3140","index":["name","description"],"sample_rate":"?float","parent":"Thing","shape":"sphere","description_key":"description","title_key":"name","ref_id":"c4902dcf-4a44-4d38-9389-361d43d24bef","policy":"?string","freshness_days":"?int"},{"answer_volatility":"?string","claim_text":"string","valid_from":"?datetime","node_key":"claim-id","type":"Claim","id":"string","polarity":"?string","name":"string","type_description":"An assertion whose truth can be evaluated — the unit of knowing in the epistemic layer (Claim / Evidence, migration 119). Extracted claims record a speaker's statement; the epistemic attributes score ANY claim by its evidence. answer_volatility uses the temporal-layer classes (STATIC | STABLE | EVOLVING | VOLATILE | INSTANTANEOUS): STATIC is the static-vs-dynamic dimension's static pole, everything else is dynamic (named answer_volatility because bare `volatility` is a schema-level core property the read path swallows out of attributes). derivation: atomic | calculated — calculated claims point at their inputs via DERIVED_FROM. polarity: affirms | negates — whether the claim asserts or denies its proposition. Bitemporal fields split ontic from epistemic time: valid_from/valid_to is when the claim is true IN THE WORLD; belief_valid_from/belief_valid_to is when the graph believed it (closed by supersession or retraction). verdict: known | likely | contested | unknown | stale, with confidence_score in [0.0, 1.0] as of assessed_at. Evidence hangs off EVIDENCED_BY {strength: -1.0 disproves .. +1.0 proves}; compound claims decompose via PARENT_OF; claim-to-claim relations use the existing SUPPORTS / CONTRADICTS / SUPERSEDES edges.","triplicate_object":"?string","verdict":"?string","domain":"Epistemic","belief_valid_from":"?datetime","belief_valid_to":"?datetime","valid_to":"?datetime","speaker_name":"?string","assessed_at":"?datetime","index":["name","claim_text","speaker_name"],"triplicate_subject":"?string","parent":"Thing","triplicate":"?string","confidence_score":"?float","source_role":"?string","derivation":"?string","triplicate_predicate":"?string","description_key":"claim_text","title_key":"name","paid_properties":[],"ref_id":"67fcc508-e296-4411-896b-6f431e8c0c9d"},{"icon":"NodesIcon","body":"?string","index":["name","body"],"parent":"CodeArtifact","node_key":"class-name-file","shape":"sphere","type":"Class","description_key":"body","title_key":"name","start":"?int","file":"string","name":"string","domain":"CodeArtifact","type_description":"A class definition in source code, representing an object-oriented structure with attributes and methods.","ref_id":"1738aaf1-b30a-4f7d-9a76-4cc88c4c367f","end":"?int"},{"icon":"TagIcon","primary_color":"#6D4C41","index":["name"],"parent":"Thing","node_key":"clausetype-name","secondary_color":"#D7CCC8","shape":"sphere","type":"ClauseType","description_key":"description","title_key":"name","description":"?string","name":"string","domain":"Legal","type_description":"A classification label for a ContractClause (e.g. indemnification, termination, confidentiality).","ref_id":"924bb19a-b6f4-4aa2-92a6-832f9dc96a46"},{"transcript":"?string","link":"?string","node_key":"clip-episode_title-timestamp","secondary_color":"#4FA7D9","sentiment_score":"?float","date":"?datetime","type":"Clip","timestamp":"string","image_url":"?string","description":"?string","type_description":"A short audio or video segment extracted from a longer episode","domain":"Content","source_link":"?string","pub_key":"?string","icon":"AudioIcon","primary_color":"#1D3140","text":"?string","index":["episode_title","text","description"],"episode_title":"string","media_url":"string","parent":"Episode","show_title":"?string","shape":"sphere","num_boost":"?int","description_key":"description","title_key":"episode_title","english_translation":"?string","ref_id":"788d5a44-1a5e-4533-8de4-ceaf887ede41","boost":"?int","language":"?string"},{"icon":"ConstructionIcon","index":"name","domain":"CodeArtifact","type_description":"An abstract parent for all source code constructs within a repository.","ref_id":"b9d1bbef-bf58-4877-9181-9e058af71078","parent":"Thing","type":"CodeArtifact"},{"summary":"?string","icon":"ChatAltIcon","primary_color":"#6D4C41","index":["regulation_name","comment_deadline","decision"],"link":"?string","parent":"Legal","node_key":"commentperiod-regulation_name-comment_deadline","regulation_name":"string","secondary_color":"#D7CCC8","shape":"sphere","type":"CommentPeriod","decision":"string","description_key":"decision","title_key":"regulation_name","owner":"?string","domain":"Legal","type_description":"A public comment period for a proposed regulation or rule, with tracking of the organization's response.","ref_id":"9e9c1a31-cf54-4162-8a63-4bff2bdeb952","filed_at":"?datetime","comment_deadline":"datetime","rationale":"?string","notes":"?string"},{"summary":"?string","icon":"NodesIcon","index":["name","message","summary"],"committed_at":"?string","sha":"?string","parent":"Repository","node_key":"commit-sha","shape":"sphere","type":"Commit","url":"?string","namespace":"?string","message":"?string","author":"?string","description_key":"summary","title_key":"name","name":"string","domain":"CodeArtifact","type_description":"An individual git commit, including its message, author, and a summary of the change.","ref_id":"6b564e70-e0c7-4111-8fc1-47a56b689153","source_link":"?string"},{"icon":"NodesIcon","index":"name","count":"?int","parent":"Repository","node_key":"commits-name","shape":"sphere","type":"Commits","namespace":"?string","description_key":"name","title_key":"name","name":"string","domain":"CodeArtifact","type_description":"A collection of individual commit nodes belonging to a repository.","ref_id":"dfe13962-8ead-400c-9145-444acd917242"},{"icon":"CalculatorIcon","primary_color":"#6D4C41","result":"?float","index":["label","matter_slug","discrepancy_flag"],"computed_by":"?string","parent":"Legal","node_key":"computedfigure-label","label":"string","secondary_color":"#D7CCC8","shape":"sphere","type":"ComputedFigure","discrepancy_note":"?string","discrepancy_flag":"boolean","description_key":"formula","title_key":"label","inputs":"?string","verified":"boolean","domain":"Legal","type_description":"An independently-derived numerical calculation with its formula, inputs (Excerpt refs), and result — used by the computation verifier agent to cross-check figures extracted by research agents and flag discrepancies.","ref_id":"434f593f-c719-4010-a5e5-4537e1abce6f","result_string":"?string","statutory_basis":"?string","formula":"string"},{"icon":"NodesIcon","index":["name","description","docs"],"docs":"?string","pr_numbers":"?string","parent":"Thing","node_key":"concept-name","commit_shas":"?string","shape":"sphere","type":"Concept","id":"?string","description_key":"description","title_key":"name","repo":"?string","description":"?string","file":"?string","name":"string","documentation":"?string","domain":"General","type_description":"A reusable unit of knowledge or capability — a codebase capability, a legal methodology, a domain practice. Cross-domain by design, which is why it is homed in General rather than CodeArtifact. BODY FIELD — `docs` is the canonical long-form body (migration 106). stakgraph's lab/concepts pipeline writes `docs` directly over a bolt session (bypassing this API and its schema validation) and its nodeToConcept() reads only `docs`, so `docs` is the field that actually carries nearly every live Concept's content. DEPRECATED — `documentation` is the pre-106 body field. It is still declared so existing API writers do not hard-fail, but it is NO LONGER INDEXED: content written there is invisible to both the composite Data_Bank fulltext index and text_embeddings, and invisible to stakgraph. Write `docs`, not `documentation`. Migration 106 backfilled existing `documentation` bodies into `docs`; removing the attribute outright requires a coordinated writer migration first (a removal would 400 any payload still sending it).","ref_id":"a530f22b-b0aa-46d6-bf6c-3e7e1afa1111","created_at":"?string","last_updated":"?string"},{"conflicts":"?string","icon":"ShieldCheckIcon","primary_color":"#6D4C41","result":"string","index":["matter_slug","checked_date","result"],"parent":"Legal","node_key":"conflictcheck-matter_slug-checked_date","checked_by":"string","secondary_color":"#D7CCC8","shape":"sphere","type":"ConflictCheck","description_key":"result","title_key":"matter_slug","domain":"Legal","type_description":"A conflict-of-interest check performed before or during a legal matter.","ref_id":"6e875c60-3757-4011-8b05-a4f749f97dfe","checked_date":"datetime","notes":"?string","matter_slug":"string"},{"icon":"InterestsIcon","index":"name","domain":"Content","type_description":"Any form of media, including text, images, or videos","ref_id":"60883d1a-6b68-44d5-b0c5-d06bbf9c84f5","parent":"Thing","type":"Content"},{"summary":"?string","icon":"ClipboardIcon","primary_color":"#6D4C41","index":["clause_type","risk_level"],"parent":"Thing","recommendation":"?string","node_key":"contractclause-id","secondary_color":"#D7CCC8","shape":"sphere","confidence":"?float","type":"ContractClause","clause_type":"?string","id":"string","description_key":"risk_level","title_key":"clause_type","risk_level":"?string","priority":"?string","domain":"Legal","type_description":"A discrete clause or provision within a legal agreement, categorised by type and risk level.","ref_id":"8e304fe3-8cd5-43ba-bccf-3aa47af2652e"},{"location":"?string","node_key":"contributor-username","type":"Contributor","namespace":"?string","followers":"?int","following":"?int","username":"string","image_url":"?string","description":"?string","public_repos":"?int","name":"string","type_description":"A person who contributes to a project or repository, including authors and maintainers.","domain":"Entity","icon":"PersonIcon","index":["username","description","bio"],"parent":"Person","shape":"sphere","account_created_at":"?datetime","description_key":"description","title_key":"username","bio":"?string","email":"?string","company":"?string","ref_id":"858f9367-a600-486e-99e4-120a55cc90cf","role_name":"?string"},{"icon":"CorporationIcon","primary_color":"#222B48","index":["name","description"],"parent":"Organization","node_key":"corporation-name","secondary_color":"#5E84F8","shape":"sphere","type":"Corporation","description_key":"description","title_key":"name","image_url":"?string","description":"?string","name":"string","domain":"Entity","type_description":"A legally recognized business entity or company","ref_id":"ccc1a080-92f0-473b-82c1-331cd670346e"},{"icon":"PlaceIcon","primary_color":"#2A2545","index":["name","iso_code"],"iso_code":"?string","parent":"Thing","node_key":"country-name","secondary_color":"#9368FB","shape":"sphere","type":"Country","description_key":"name","title_key":"name","image_url":"?string","name":"string","domain":"Entity","type_description":"A sovereign nation or country, used e.g. as a place of incorporation or governing-law jurisdiction","ref_id":"3a892221-8210-4031-ad89-182677d3c035"},{"icon":"CheckCircleIcon","primary_color":"#36292D","index":["criterion_id","verdict"],"flagged":"?boolean","parent":"Thing","node_key":"criterionresult-id","secondary_color":"#A96755","shape":"sphere","type":"CriterionResult","contested":"?boolean","document_excerpt":"?string","id":"string","llm_flag_reason":"?string","title":"?string","reasoning":"?string","description_key":"reasoning","title_key":"title","verdict":"?string","domain":"CodeArtifact","type_description":"A generic per-criterion, per-run verdict node — the domain-neutral form of RubricCriterion. Records a judge's verdict, reasoning, and flag metadata for a single criterion within one EvalTriggerOutput scored attempt. Used by both Hive prompt/agent evals and the Harvey benchmark unified model.","ref_id":"13959bfa-6d96-4106-b490-34316bb311e5","criterion_id":"string","agent_thinking_excerpt":"?string"},{"icon":"ClipboardListIcon","primary_color":"#6D4C41","index":["request_id","status","category"],"status":"?string","request_text":"?string","parent":"Legal","node_key":"ddrequestitem-request_id","secondary_color":"#D7CCC8","shape":"sphere","type":"DDRequestItem","category":"?string","description_key":"category","request_id":"string","title_key":"request_text","fulfilled_date":"?datetime","responding_party":"?string","domain":"Legal","type_description":"A discrete line item within a due diligence request list, tracking the request, its status, and the responding party.","ref_id":"ca6bd1b2-4177-4a09-bc1f-a3841383c5f6","due_date":"?datetime","notes":"?string"},{"exemptions":"?string","deadline_statutory":"?datetime","node_key":"dsarrequest-id","secondary_color":"#D7CCC8","type":"DSARRequest","date_responded":"?datetime","what_produced":"?string","id":"string","deadline_internal":"?datetime","type_description":"A Data Subject Access Request (DSAR) submitted under a privacy regulation.","domain":"Legal","regime":"?string","icon":"IdentificationIcon","primary_color":"#6D4C41","index":["id","right_invoked","regime","status"],"status":"?string","date_received":"?datetime","parent":"Thing","date_identity_verified":"?datetime","shape":"sphere","identity_verified":"?boolean","description_key":"right_invoked","title_key":"id","handled_by":"?string","ref_id":"adffcca1-968d-46c3-b7aa-066899b9c5dd","right_invoked":"?string"},{"field_name":"string","observed_value":"?string","icon":"ExclamationIcon","primary_color":"#6D4C41","index":["anomaly_type","source_doc_ref","resolved"],"parent":"Legal","node_key":"dataanomalyrecord-source_doc_ref-field_name","severity":"?string","secondary_color":"#D7CCC8","shape":"sphere","type":"DataAnomalyRecord","source_doc_ref":"string","description_key":"anomaly_type","title_key":"field_name","detected_at":"datetime","resolved":"boolean","expected_value_or_rule":"?string","domain":"Legal","type_description":"A data quality anomaly detected at document ingest time — impossible dates, missing required fields, stale denominators, or cross-document value mismatches. Also covers one-sided findings (observed_value and expected_value_or_rule are both optional): unexpected-location facts (anomaly_type='unexpected_location' — a substantive fact appearing in a document where it is not expected, or a controlling primary record differing from the citing document; observed_value=actual location, expected_value_or_rule=expected location), absent clause types (anomaly_type='missing_clause_type'), figures asserted without derivation (anomaly_type='asserted_without_derivation'), and intra-section self-contradictions (anomaly_type='self_contradiction'). Anchor to the relevant node via FLAGS (TimelineEntry, ContractClause, Figure, Document, Excerpt, or a clause-type Concept for absence findings). Seeded before research rounds begin so all agents are aware of adversarial data traps.","ref_id":"921bc872-85f1-45aa-98b9-4ded0b027362","anomaly_type":"string"},{"icon":"NodesIcon","body":"?string","index":["name","body"],"parent":"CodeArtifact","node_key":"datamodel-name-file","shape":"sphere","type":"Datamodel","description_key":"body","title_key":"name","start":"?int","file":"string","name":"string","domain":"CodeArtifact","type_description":"A structured representation of data within a system, typically defining entities, relationships, attribute types, and corresponding SQL table definitions.","ref_id":"a76bdcfb-652e-4568-ab51-949e97f4543d","end":"?int"},{"icon":"CalendarIcon","primary_color":"#6D4C41","index":["deadline_type","matter_slug","due_date","status"],"status":"?string","parent":"Thing","node_key":"deadline-deadline_type-matter_slug-due_date","secondary_color":"#D7CCC8","shape":"sphere","type":"Deadline","description_key":"due_date","title_key":"deadline_type","deadline_type":"string","description":"?string","warning_days":"?int","owner":"?string","domain":"Legal","type_description":"A legal or regulatory deadline associated with a matter, agreement, IP asset, or AI system.","ref_id":"45edc8b5-a569-40f2-9470-152940e688e3","due_date":"string","matter_slug":"string"},{"icon":"BookOpenIcon","primary_color":"#6D4C41","index":["term","matter_slug","source_ref","scope"],"scope":"?string","definition_text":"string","parent":"Legal","node_key":"definedterm-matter_slug-source_ref-term","source_ref":"string","secondary_color":"#D7CCC8","shape":"sphere","first_used_section":"?string","type":"DefinedTerm","description_key":"definition_text","title_key":"term","term":"string","domain":"Legal","type_description":"A term as defined by one specific document — the per-document definition record, distinct from Lingo (the global vocabulary entry). One node per (matter_slug, source_ref, term), so two documents defining the same term differently yield two nodes; definitional divergence is asserted via DefinedTerm-[CONFLICTS_WITH]->DefinedTerm, and cross-document borrowing (a document using a term it does not itself define) via DefinedTerm-[USED_IN]->the borrowing document.","ref_id":"b7017069-4ffa-4851-847b-115aead96392","matter_slug":"string"},{"icon":"ClipboardCheckIcon","primary_color":"#6D4C41","index":["deliverable_type"],"parent":"Legal","node_key":"deliverableschema-deliverable_type","required_sections":"?string","deliverable_type":"string","secondary_color":"#D7CCC8","shape":"sphere","type":"DeliverableSchema","required_tabs":"?string","description_key":"deliverable_type","title_key":"deliverable_type","placeholder_patterns":"?string","domain":"Legal","type_description":"Specifies the required structure of a task output deliverable — tabs, columns, required sections, and placeholder patterns. Used by the deliverable schema enforcer to validate synthesized outputs before scoring.","required_columns":"?string","ref_id":"f66c86cd-a615-42d7-afad-da26efa1a355","formatting_rules":"?string"},{"icon":"ExclamationCircleIcon","primary_color":"#6D4C41","index":["category","severity","status"],"status":"string","parent":"Legal","node_key":"diligenceissue-category-description","severity":"string","secondary_color":"#D7CCC8","shape":"sphere","resolution":"?string","type":"DiligenceIssue","category":"string","description_key":"category","title_key":"description","description":"string","domain":"Legal","type_description":"A due-diligence issue identified during a deal or transaction review.","ref_id":"bcce77bc-1cc4-409f-bb93-64bd977da832","source_doc":"?string","materiality":"?string"},{"body":"?string","index":["name","description"],"parent":"Repository","node_key":"directory-name-file","shape":"sphere","type":"Directory","description_key":"description","title_key":"name","start":"?int","description":"?string","file":"string","name":"string","domain":"CodeArtifact","type_description":"A folder within a repository that organizes files and subdirectories.","ref_id":"350dee1e-e4be-4366-b878-2dcda901d3f1","source_link":"?string","end":"?int"},{"icon":"BookOpenIcon","primary_color":"#6D4C41","practice_area":"?string","index":["name","jurisdiction_ref","authority_level","practice_area"],"superseded_by":"?string","parent":"Legal","node_key":"doctrine-jurisdiction_ref-name","secondary_color":"#D7CCC8","shape":"sphere","type":"Doctrine","authority_level":"?string","jurisdiction_ref":"string","description_key":"rule_text","title_key":"name","source_citation":"?string","rule_text":"string","name":"string","domain":"Legal","type_description":"A standing legal rule or doctrine scoped to a jurisdiction — e.g. Third Circuit dominant-purpose test, post-TCJA 80% NOL cap. Distinct from LegalArgument (per-matter finding) and LegalDocument (case citation). Allows agents to retrieve jurisdiction-specific legal rules directly from the graph.","ref_id":"56f872ad-b980-4aea-8cac-79cd0ed583cc","effective_date":"?string"},{"summary":"?string","icon":"DocumentIcon","primary_color":"#302342","index":["source_link","title"],"status":"?string","parent":"Content","node_key":"document-source_link","secondary_color":"#C25AF3","shape":"sphere","type":"Document","pubkey":"?string","author":"?string","title":"?string","description_key":"summary","title_key":"title","domain":"Content","type_description":"A written, printed, or digital record of information","ref_id":"cde66016-4d46-4d55-b5b6-285ddcc5cfff","source_link":"string","content_type":"?string"},{"icon":"DocumentSearchIcon","primary_color":"#6D4C41","index":["document_subtype"],"parent":"Legal","example_values":"?string","node_key":"documenttypetemplate-document_subtype","secondary_color":"#D7CCC8","shape":"sphere","type":"DocumentTypeTemplate","description_key":"document_subtype","title_key":"document_subtype","mandatory_fields":"string","domain":"Legal","type_description":"Maps a legal document subtype to its mandatory quantitative fields — used by specificsSweep to generate targeted extraction queries per document type at task start, ensuring policy parameters (e.g. RWI limit + retention) are always seeded as findings even if no research agent explicitly queries for them.","ref_id":"631316a5-10e8-4ed8-83e3-75f7b91647df","document_subtype":"string"},{"body":"?string","index":["name","body"],"parent":"Test","node_key":"e2etest-name-file","type":"E2etest","description_key":"body","title_key":"name","start":"?int","file":"string","name":"string","domain":"CodeArtifact","type_description":"An end-to-end test that validates the entire system functionality by simulating real-world interactions.","ref_id":"15fed8c3-c844-407d-bd3a-e0e9049d2c5f","end":"?int"},{"icon":"MailIcon","primary_color":"#1A3A52","index":["message_id","subject","thread_id"],"subject":"string","parent":"Message","message_id":"string","node_key":"email-message_id","secondary_color":"#5BA4CF","shape":"sphere","type":"Email","in_reply_to":"?string","references":"?string","description_key":"message_id","title_key":"subject","domain":"Content","type_description":"An email message in the knowledge graph.","ref_id":"56eacec5-cd7c-4cd7-a581-4a5c4a6c75f3","thread_id":"?string"},{"body":"?string","subject":"string","node_key":"emailinvite-message_id","secondary_color":"#5BA4CF","conference_platform":"?string","type":"EmailInvite","timezone":"?string","type_description":"A calendar invitation delivered via email (iCalendar / .ics attachment).","domain":"Content","conference_url":"?string","icon":"CalendarIcon","primary_color":"#1A3A52","index":["message_id","subject","start_datetime"],"location_type":"?string","end_datetime":"?datetime","status":"?string","organizer":"?string","parent":"Message","message_id":"string","shape":"sphere","start_datetime":"?datetime","description_key":"start_datetime","recurrence":"?string","title_key":"subject","ref_id":"4d3f887d-6268-4683-8811-b9b2ca5cbb9f"},{"summary":"?string","body":"?string","node_key":"endpoint-name-file-verb","type":"Endpoint","namespace":"?string","verb":"string","description":"?string","file":"string","name":"string","type_description":"A defined entry point for accessing functionality within an application or service, typically through an API.","domain":"CodeArtifact","source_link":"?string","end":"?int","icon":"ConstructionIcon","text":"?string","index":["name","summary","description"],"hash":"?string","parent":"CodeArtifact","shape":"sphere","description_key":"summary","title_key":"name","start":"?int","ref_id":"87dcc921-01cb-4552-a710-ab06dc994260","method":"?string","handler":"?string"},{"icon":"NodesIcon","primary_color":"#1B3134","index":"entity","trusted":"?boolean","entity":"string","parent":"Thing","node_key":"entity-entity","secondary_color":"#21B38A","shape":"sphere","type":"Entity","entity_lower":"?string","description_key":"entity","title_key":"entity","domain":"Entity","type_description":"A general entity that can represent any identified concept or object","ref_id":"5b8aea7c-1ffd-433d-989f-6be32a0d6788","metaphone3":"?string"},{"summary":"?string","transcript":"?string","node_key":"episode-source_link","secondary_color":"#5E84F8","date":"?datetime","type":"Episode","image_url":"?string","description":"?string","type_description":"A single installment in a series of related productions e.g Show","domain":"Content","source_link":"string","icon":"EpisodeIcon","primary_color":"#222B48","index":["episode_title","description","summary"],"status":"?string","episode_title":"?string","media_url":"?string","parent":"Show","show_title":"?string","shape":"sphere","pubkey":"?string","duration":"?string","description_key":"description","title_key":"episode_title","paid_properties":["media_url","transcript"],"project_id":"?string","ref_id":"79c0a059-e819-42ec-bc69-d274076e1e62"},{"repo_key":"?string","icon":"ConstructionIcon","primary_color":"#2A2545","exceptionType":"?string","index":["title","exceptionType","fingerprint","status"],"first_seen_at":"?string","status":"?string","workspace_id":"?string","parent":"CodeArtifact","node_key":"errorissue-fingerprint","secondary_color":"#C25AF3","shape":"sphere","type":"ErrorIssue","repository_id":"?string","occurrenceCount":"?int","fingerprint":"string","title":"?string","description_key":"exceptionType","title_key":"title","last_seen_at":"?string","domain":"CodeArtifact","type_description":"A tracked error or exception in a codebase, identified by a unique fingerprint and associated with files and functions in the call stack.","ref_id":"afd6193e-e613-4ea0-a7cc-3cfa3d681145"},{"icon":"ExclamationCircleIcon","primary_color":"#6D4C41","index":["matter_slug","escalation_type","status"],"status":"string","trigger_finding_ref":"string","parent":"Legal","node_key":"escalationrecord-matter_slug-trigger_finding_ref","secondary_color":"#D7CCC8","shape":"sphere","type":"EscalationRecord","rpc_rule_ref":"?string","escalation_type":"string","description_key":"matter_slug","title_key":"escalation_type","resolved_by":"?string","domain":"Legal","type_description":"A structured record of a legal ethics or crime-fraud escalation triggered by a finding — capturing the escalation type, recommended actions (senior counsel / in camera / ethics consult), and the RPC rule that mandates it.","ref_id":"02e1b372-1816-4381-b54e-c5c1f927d640","recommended_actions":"?string","notes":"?string","matter_slug":"string"},{"icon":"StepIcon","primary_color":"#1B3134","index":["name","description"],"positive_cases":"?list","negative_cases":"?list","parent":"Thing","node_key":"evalrequirement-id","secondary_color":"#21B38A","shape":"sphere","type":"EvalRequirement","contested":"?boolean","id":"string","deliverables":"?list","updated_at":"?datetime","description_key":"description","title_key":"name","prompt_snippet":"?string","description":"?string","name":"?string","domain":"CodeArtifact","type_description":"A success criterion (test case) with positive and negative examples, captured from a real agent interaction.","ref_id":"3c1385ec-7602-4a68-9605-780ab678a97a","created_at":"?datetime"},{"icon":"TaskIcon","primary_color":"#1D3140","index":["name","description"],"parent":"Thing","node_key":"evalset-id","secondary_color":"#4FA7D9","shape":"sphere","type":"EvalSet","id":"string","updated_at":"?datetime","description_key":"description","title_key":"name","description":"?string","project_id":"?int","name":"?string","domain":"CodeArtifact","type_description":"A dataset (suite) grouping related test cases (EvalRequirements) for validating agent behaviour.","ref_id":"3e5e8c3d-0819-4659-8cff-ff7ad6f9a7ee","created_at":"?datetime","recursion":"?boolean"},{"body":"?string","start_point":"?string","workflow_input":"?string","prompts":"?list","node_key":"evaltrigger-id","secondary_color":"#BA9D39","type":"EvalTrigger","id":"string","prompt_id":"?string","workflow_id":"?string","type_description":"A captured, replayable input configuration — the source event that gave rise to an EvalRequirement.","domain":"CodeArtifact","icon":"GeneratedStepIcon","primary_color":"#353124","positive_cases":"?list","index":["agent","environment","change_type"],"end_point":"?string","negative_cases":"?list","workflow_version_id":"?string","parent":"Thing","shape":"sphere","change_type":"?string","agent":"?string","endpoint_url":"?string","prompt_version_id":"?string","run_count":"?int","description_key":"change_type","environment":"?string","title_key":"agent","source":"?string","paid_properties":["workflow_input"],"project_id":"?string","ref_id":"0b3c193c-6b9a-4020-96eb-c798b645cccd"},{"result":"string","judge_notes":"?string","judge_model":"?string","score":"?float","node_key":"evaltriggeroutput-id","secondary_color":"#E09242","type":"EvalTriggerOutput","id":"string","n_passed":"?int","n_total":"?int","type_description":"The result of a single evaluation run attempt: score, verdict, and judge notes. report_url, when present, is the URL of the run report bundle for this scored attempt — an https:// Stakwork-hosted bundle URL; optional and null on historical nodes. Consumers must treat it as untrusted input and must validate scheme and host before fetching (SSRF caution). The concept-analysis consumer must read report_url via an authenticated/proxied route, as it is a paid property and is silently stripped to null for unauthenticated readers.","verdict":"?string","domain":"CodeArtifact","max_score":"?float","icon":"StepIcon","primary_color":"#392828","index":"evaltriggeroutput-id","attempt_number":"?int","parent":"Thing","shape":"sphere","endpoint_url":"?string","description_key":"judge_notes","title_key":"result","report_url":"?string","paid_properties":["report_url"],"ref_id":"1826ff32-dfe6-409e-857d-187142aff915"},{"icon":"EventIcon","primary_color":"#38243C","index":["name","description"],"parent":"Thing","node_key":"event-name","secondary_color":"#F468D4","shape":"sphere","type":"Event","description_key":"description","title_key":"name","image_url":"?string","description":"?string","name":"string","domain":"Entity","type_description":"A thing that happens or takes place, especially one of importance","ref_id":"431687d4-a420-46fb-93b2-0acc412559e1"},{"icon":"DocumentIcon","primary_color":"#222B48","index":["name","description","content"],"parent":"Thing","node_key":"evidence-id","secondary_color":"#5E84F8","shape":"sphere","type":"Evidence","evidence_mode":"?string","content":"?string","observed_at":"?datetime","id":"string","confidence_score":"?float","description_key":"description","title_key":"name","description":"?string","name":"string","domain":"Epistemic","type_description":"One captured datum backing a Claim — a quote, reading, attestation, or record, captured AS OBSERVED (the Figure discipline from the Legal domain: capture first, derive later). content holds the observed value, statement, or excerpt — ON THE NODE, where it is indexed and searchable; where-in-the-source locators (timestamps, message id, page, url) ride the HAS_SOURCE edge instead. observed_at is when the datum was true in the world — the anchor for freshness against the claim's answer_volatility. evidence_mode is the asserted-vs-observed dimension: observed | asserted — observed means we or an instrument measured it, asserted means someone said it. Provenance: this Evidence -[HAS_SOURCE {authority_level, locators}]-> the canonical entity it came from (Person, Organization, Document, ...); a Claim points here via EVIDENCED_BY {strength}. Independent corroboration is counted over DISTINCT source entities, not Evidence rows. confidence_score is this datum's own trustworthiness in [0.0, 1.0], consistent with Belief and temporal-edge confidence. evidence_status is the collection lifecycle: planned means the slot has been named via name/description but content is still empty; collected means content has been populated. The allowed set is exactly {'planned', 'collected'} — a documented contract, not a DB-enforced enum (same convention as Claim.verdict and ProposedFix.eval_status); readers must treat any other value as unknown/unspecified.","ref_id":"d6ad0728-1710-4e49-a237-c684bc8ca70a","evidence_status":"?string"},{"icon":"QuoteIcon","primary_color":"#6D4C41","index":["text"],"text":"string","is_verbatim":"?boolean","page_number":"?int","parent":"Thing","node_key":"excerpt-text","secondary_color":"#D7CCC8","shape":"sphere","confidence":"?float","type":"Excerpt","bbox_y1":"?float","section":"?string","bbox_y0":"?float","bbox_x1":"?float","bbox_x0":"?float","description_key":"text","title_key":"text","domain":"Legal","type_description":"A verbatim text excerpt from a legal document. May carry a dual embedding: jarvis 384-dim text_embeddings and a graphrag-contract-review 1536-dim embedding property.","ref_id":"4a8dda06-3855-4be4-83c6-1b0de2c222ef"},{"icon":"NodesIcon","index":["name","description","documentation"],"pr_numbers":"?string","parent":"CodeArtifact","node_key":"feature-name","commit_shas":"?string","shape":"sphere","type":"Feature","description_key":"description","title_key":"name","repo":"?string","description":"?string","file":"?string","name":"string","documentation":"?string","domain":"CodeArtifact","type_description":"A specific capability or functionality within the application or codebase.","ref_id":"0fb370dc-4a4b-4caf-b3d7-a56149cdc366","created_at":"?string","last_updated":"?string"},{"page_number":"?int","node_key":"figure-matter_slug-source_ref-locator","secondary_color":"#D7CCC8","source_ref":"string","type":"Figure","currency":"?string","value_as_stated":"string","value_normalized":"?float","cell_ref":"?string","sheet_name":"?string","type_description":"The primary, as-stated datum captured verbatim from one specific source location — PRE-COMPUTATION and PRE-DERIVATION. NOT a ComputedFigure (a derived calculation) and NOT a FormulaComponent (a named formula input). ComputedFigure and FormulaComponent should link here via DERIVED_FROM edges to trace every calculated result back to its primary source.\n\nSOURCE_REF / LOCATOR GRAMMAR (agents MUST emit this exact form — punctuation and case are stripped before keying, so an inconsistent rendering creates a duplicate node for the same cell):\n source_ref = workbook or document filename exactly as ingested (e.g. 'RateCard_2024.xlsx').\n locator = ! for spreadsheets (e.g. 'RateCard!C2') OR p\\u00a7
for prose (e.g. 'p12\\u00a74.2').\n\nRE-INGEST SEMANTICS: re-ingest updates the node only when the caller passes reprocess=True (per create_or_merge_node in api/helper/schema_node_helper.py); non-key fields are last-write-wins (ON MATCH SET).","domain":"Legal","icon":"DocumentIcon","primary_color":"#6D4C41","locator":"string","index":["label","matter_slug","source_ref","locator","sheet_name","cell_ref","page_number","section","value_as_stated"],"parent":"Legal","label":"string","shape":"sphere","section":"?string","unit":"?string","extracted_by":"?string","description_key":"value_as_stated","title_key":"label","ref_id":"35aa277c-080f-41ba-8964-8d1d882ea91c","matter_slug":"string"},{"summary":"?string","icon":"ConstructionIcon","body":"?string","index":["name","summary"],"text":"?string","hash":"?string","parent":"Directory","node_key":"file-name-file","code":"?string","shape":"sphere","type":"File","description_key":"summary","title_key":"name","start":"?int","file":"string","name":"string","domain":"CodeArtifact","type_description":"A file within a repository, containing source code, configuration, or other project-related content.","ref_id":"1edd4f6d-b07c-4309-b40b-c4997cf35830","source_link":"?string","end":"?int"},{"current_value":"?string","index":["fluent_of","fluent_property"],"fluent_of":"string","domain":"entity","ref_id":"4c3db758-aec4-411e-bd5f-5b4fd78f6ccd","parent":"Thing","node_key":"fluent-fluent_of-fluent_property","type":"Fluent","fluent_property":"string"},{"value_ref_id":"string","asserted_by":"?string","index":["fluent_ref_id","valid_from"],"valid_from":"datetime","domain":"entity","ref_id":"3da3f8ca-7826-4137-ab3e-fe1a1f40fdf1","parent":"Thing","node_key":"fluentevent-fluent_ref_id-valid_from","confidence":"?float","fluent_ref_id":"string","type":"FluentEvent","valid_to":"?datetime"},{"icon":"CalculatorIcon","primary_color":"#6D4C41","index":["label"],"parent":"Legal","node_key":"formulacomponent-label","label":"string","secondary_color":"#D7CCC8","shape":"sphere","type":"FormulaComponent","unit":"?string","description_key":"description","title_key":"label","source":"?string","description":"?string","domain":"Legal","value":"?float","type_description":"A named, typed numeric input to a formula — carries its raw value, unit, source attribution, and plain-language description.","ref_id":"66362f5a-19d8-46cc-8f5b-faf53d10cc03"},{"summary":"?string","icon":"ConstructionIcon","body":"?string","index":["name","summary","description"],"text":"?string","docs":"?string","parent":"CodeArtifact","node_key":"function-name-file","code":"?string","shape":"sphere","type":"Function","operand":"?string","description_key":"summary","title_key":"name","output_data_type":"?string","start":"?int","description":"?string","file":"string","name":"string","domain":"CodeArtifact","type_description":"A function or method definition in source code, representing executable logic within a program, including backend logic and frontend components.","ref_id":"2c2b38fb-3bc9-415e-ac9d-af2d7326b153","source_link":"?string","end":"?int"},{"gap_type":"?string","remediation_plan":"?string","node_key":"gapitem-id","secondary_color":"#D7CCC8","resolution":"?string","type":"GapItem","id":"string","significance":"?string","description":"?string","priority":"?string","type_description":"A compliance gap — a requirement not yet met by the organization, with remediation tracking.","domain":"Legal","notified":"?boolean","opened":"?datetime","comment_tracker_id":"?string","icon":"ExclamationIcon","primary_color":"#6D4C41","policy_affected":"?string","index":["id","gap_type","owner","status"],"requirement":"?string","status":"?string","parent":"Thing","status_verified":"?boolean","shape":"sphere","change_needed":"?string","description_key":"gap_type","title_key":"requirement","owner":"?string","regulation":"?string","ref_id":"54743019-f3eb-4c15-b9ca-0ab5cece8753","due":"?string"},{"output_json":"?string","node_key":"generated_step-step_unique_id","secondary_color":"#F468D4","type":"Generated_step","workflow_position":"?int","id":"string","description":"?string","name":"string","type_description":"A dynamically generated step in a workflow with specific configuration and parameters","domain":"Workflow","skill_name":"?string","skill_id":"?int","icon":"GeneratedStepIcon","primary_color":"#38243C","index":["name","description"],"parent":"Workflow","input_json":"?string","shape":"sphere","params":"?string","step_unique_id":"string","description_key":"description","title_key":"name","step_json":"?string","ref_id":"72935346-72fa-41e8-b1d2-b05392010461","attributes":"?string"},{"icon":"NodesIcon","index":["name","description"],"parent":"Repository","node_key":"githubrepo-name","shape":"sphere","type":"GitHubRepo","namespace":"?string","forks":"?int","description_key":"description","title_key":"name","description":"?string","stars":"?int","age_years":"?float","name":"string","domain":"CodeArtifact","type_description":"A GitHub repository containing metadata such as stars, forks, description, and language information.","ref_id":"ca6c9c0b-3bad-4421-993e-aedb7dbcd783","language":"?string"},{"index":["name","description"],"twitter_handle":"?string","parent":"Person","node_key":"guest-name","type":"Guest","is_favorite":"?boolean","description_key":"description","title_key":"name","image_url":"?string","description":"?string","name":"string","domain":"Entity","ref_id":"dde71be2-df05-4fa4-a47e-8ba8a4575a0b"},{"icon":"NodesIcon","index":["ref_id","question","answer"],"answer":"?string","parent":"KnowledgeArtifact","node_key":"hint-ref_id","shape":"sphere","type":"Hint","description_key":"answer","title_key":"ref_id","domain":"KnowledgeArtifact","type_description":"A question and answer pair generated from exploring the codebase to capture contextual understanding.","ref_id":"db4b0f4c-d1df-4188-813c-ba2b928085e3","question":"?string"},{"icon":"NodesIcon","primary_color":"#1B3134","index":["name","display_name","description"],"default_model":"?string","parent":"Thing","node_key":"hiveagent-name","secondary_color":"#21B38A","shape":"sphere","type":"HiveAgent","display_name":"?string","updated_at":"?string","description_key":"description","title_key":"display_name","description":"?string","name":"string","domain":"Hive","type_description":"An AI agent in the Hive agent catalog, mirrored from the gateway registry.","ref_id":"6704bd70-20b1-4891-8fb7-2689751f9e97"},{"icon":"MessageIcon","primary_color":"#1D3140","index":["name","message"],"status":"?string","task_id":"?string","parent":"Thing","message_id":"string","node_key":"hivechatmessage-message_id","secondary_color":"#4FA7D9","shape":"sphere","type":"HiveChatMessage","message":"string","updated_at":"?string","description_key":"message","title_key":"name","feature_id":"?string","name":"string","domain":"Hive","type_description":"A chat message in a Hive task/feature conversation, mirrored from Postgres.","ref_id":"4ca85386-86da-49fc-b85d-53452dac07e9","role":"?string","created_at":"?string","user_id":"?string"},{"decision_id":"string","icon":"MessageIcon","primary_color":"#302342","index":["name","text"],"text":"?string","canvas_ref":"?string","parent":"Thing","node_key":"hivedecision-decision_id","secondary_color":"#C25AF3","shape":"sphere","type":"HiveDecision","description_key":"text","title_key":"name","name":"string","domain":"Hive","type_description":"A decision extracted from a Hive canvas, mirrored from Postgres.","ref_id":"8694bce9-a70b-4922-8bed-4e86733cbfa5","y":"?float","x":"?float"},{"icon":"NodesIcon","primary_color":"#2A2545","index":["name","brief","requirements","architecture"],"status":"?string","workspace_id":"?string","parent":"Thing","node_key":"hivefeature-feature_id","secondary_color":"#9368FB","shape":"sphere","architecture":"?string","type":"HiveFeature","requirements":"?string","updated_at":"?string","description_key":"brief","title_key":"name","assignee_id":"?string","priority":"?string","feature_id":"string","name":"string","domain":"Hive","type_description":"A roadmap feature in the Hive PM app, mirrored from Postgres.","ref_id":"b9c9f00c-40dd-48a8-8c38-656fdfa325d7","created_at":"?string","brief":"?string"},{"icon":"NodesIcon","primary_color":"#22362A","index":["name","description"],"completed_at":"?string","status":"?string","parent":"Thing","node_key":"hiveinitiative-initiative_id","secondary_color":"#54AC52","shape":"sphere","type":"HiveInitiative","org_id":"?string","updated_at":"?string","description_key":"description","title_key":"name","assignee_id":"?string","description":"?string","name":"string","initiative_id":"string","domain":"Hive","type_description":"An org-level initiative in the Hive PM app, mirrored from Postgres.","ref_id":"abebfe52-8b71-487c-84ce-6c7048e49f04","target_date":"?string","created_at":"?string","start_date":"?string"},{"milestone_id":"string","icon":"NodesIcon","primary_color":"#2A3229","index":["name","description"],"completed_at":"?string","status":"?string","parent":"Thing","node_key":"hivemilestone-milestone_id","secondary_color":"#96BD3F","shape":"sphere","type":"HiveMilestone","updated_at":"?string","description_key":"description","title_key":"name","assignee_id":"?string","description":"?string","sequence":"?int","name":"string","initiative_id":"?string","domain":"Hive","type_description":"A milestone within a Hive initiative, mirrored from Postgres.","ref_id":"8b0a7cf1-4d62-4470-a360-768874a9686b","due_date":"?string","created_at":"?string"},{"icon":"MessageIcon","primary_color":"#38243C","index":["name","text"],"text":"?string","canvas_ref":"?string","parent":"Thing","node_key":"hivenote-note_id","secondary_color":"#F468D4","shape":"sphere","type":"HiveNote","description_key":"text","title_key":"name","note_id":"string","name":"string","domain":"Hive","type_description":"A note extracted from a Hive canvas, mirrored from Postgres.","ref_id":"28f166cc-6b8e-411b-b6fe-fd2f8e432a18","y":"?float","x":"?float"},{"summary":"?string","topic":"?string","icon":"NodesIcon","primary_color":"#36292D","index":["name","topic","summary","content"],"parent":"Thing","node_key":"hiveresearch-research_id","secondary_color":"#A96755","shape":"sphere","type":"HiveResearch","content":"?string","org_id":"?string","updated_at":"?string","description_key":"summary","title_key":"name","name":"string","research_id":"string","initiative_id":"?string","domain":"Hive","type_description":"A research document in the Hive PM app, mirrored from Postgres.","ref_id":"486de1e8-9fe2-4509-bbf7-cfdc15c3cecd","created_at":"?string","slug":"?string"},{"summary":"?string","task_id":"string","node_key":"hivetask-task_id","source_type":"?string","secondary_color":"#5E84F8","type":"HiveTask","repository_id":"?string","assignee_id":"?string","description":"?string","priority":"?string","feature_id":"?string","name":"string","type_description":"A task / work item in the Hive PM app, mirrored from Postgres.","domain":"Hive","created_at":"?string","phase_id":"?string","icon":"TaskIcon","primary_color":"#222B48","index":["name","description","summary"],"status":"?string","workspace_id":"?string","parent":"Thing","shape":"sphere","updated_at":"?string","description_key":"description","title_key":"name","ref_id":"4c420f55-a788-443a-af4c-75fbe926513e","branch":"?string"},{"icon":"BriefcaseIcon","primary_color":"#362429","index":["name","description","mission"],"workspace_id":"string","parent":"Thing","node_key":"hiveworkspace-workspace_id","secondary_color":"#D25353","shape":"sphere","type":"HiveWorkspace","updated_at":"?string","description_key":"description","title_key":"name","mission":"?string","description":"?string","name":"string","domain":"Hive","type_description":"A Hive workspace, mirrored from Postgres. The single anchor node for workspace-level knowledge: general Concepts (preferences, best practices, gotchas, processes) link here rather than to any repository.","ref_id":"d7f784a6-faa5-4721-99ef-76f1d628c13a","created_at":"?string","slug":"?string"},{"icon":"PersonIcon","primary_color":"#38243C","index":["name","description"],"parent":"Thing","node_key":"hiveworkspacemember-member_id","secondary_color":"#F468D4","shape":"sphere","type":"HiveWorkspaceMember","member_id":"string","description_key":"description","title_key":"name","description":"?string","name":"string","joined_at":"?string","domain":"Hive","type_description":"A member of a Hive workspace, mirrored from Postgres. Anchor node for per-person knowledge: a member's preference Concepts link here via PREFERENCE edges.","ref_id":"88e5a7c7-2b22-471e-a7d4-11cea2a57130","role":"?string","github_username":"?string","user_id":"?string"},{"index":["name","description"],"description_key":"description","title_key":"name","image_url":"?string","description":"?string","name":"string","domain":"Entity","ref_id":"b1c5f9b6-0f92-4613-9145-9a2798624fed","parent":"Person","node_key":"host-name","type":"Host","is_favorite":"?boolean"},{"registration_id":"string","use_in_commerce":"?boolean","owner_name":"?string","node_key":"ipasset-registration_id","secondary_color":"#D7CCC8","type":"IPAsset","docket_id":"?string","asset_type":"?string","name":"?string","type_description":"An intellectual property asset such as a patent, trademark, or copyright.","domain":"Legal","agent_managed":"?boolean","business_owner":"?string","classes":"?string","icon":"LightBulbIcon","primary_color":"#6D4C41","index":["registration_id","asset_type","name","status"],"priority_date":"?string","status":"?string","deployment_risk":"?string","local_agent":"?string","parent":"Thing","shape":"sphere","filing_date":"?string","description_key":"asset_type","title_key":"name","renewal_deadline":"?string","license_bucket":"?string","expiration_date":"?string","grant_date":"?string","ref_id":"911e578d-4dcf-4117-bf8d-e31162a451ac"},{"body":"?string","index":["name","body"],"parent":"CodeArtifact","node_key":"import-name-file","type":"Import","description_key":"body","title_key":"name","start":"?int","file":"string","name":"string","domain":"CodeArtifact","type_description":"A section at the top of a file that contains all imported modules, libraries, or dependencies used within the file.","ref_id":"370d619f-e4fb-42ca-8ed4-25034c178aab","end":"?int"},{"icon":"NodesIcon","body":"?string","index":["name","body"],"parent":"CodeArtifact","node_key":"instance-name-file","shape":"sphere","type":"Instance","description_key":"body","title_key":"name","start":"?int","file":"string","name":"string","domain":"CodeArtifact","type_description":"An instantiation of a class in source code, representing a specific object created from a class definition.","ref_id":"7aa1521f-4804-476f-9aca-066976165a5d","end":"?int"},{"icon":"NodesIcon","body":"?string","index":["name","body"],"parent":"Test","node_key":"integrationtest-name-file","shape":"sphere","type":"IntegrationTest","description_key":"body","title_key":"name","start":"?int","file":"string","name":"string","domain":"CodeArtifact","type_description":"An integration test verifying multiple components or an API boundary working together.","ref_id":"d29c7643-41e0-4d28-b334-d234e96be5d2","end":"?int"},{"icon":"SearchIcon","primary_color":"#6D4C41","index":["matter_slug","status","investigation_type"],"status":"string","parent":"Legal","node_key":"investigationlog-allegation","secondary_color":"#D7CCC8","shape":"sphere","type":"InvestigationLog","conduct_timeframe":"?string","attorney_directed":"boolean","investigation_type":"?string","allegation":"string","description_key":"investigation_type","title_key":"allegation","domain":"Legal","type_description":"An attorney-directed or HR investigation log for a workplace or regulatory matter.","ref_id":"40876b28-17da-4fbd-aef0-305af9809be9","last_updated":"?datetime"},{"icon":"NodesIcon","index":"name","count":"?int","parent":"Repository","node_key":"issues-name","shape":"sphere","type":"Issues","namespace":"?string","description_key":"name","title_key":"name","name":"string","domain":"CodeArtifact","type_description":"A collection of individual issue nodes belonging to a repository.","ref_id":"57061e5d-760d-4765-87da-e91cf6420b66"},{"icon":"NodesIcon","index":["name","description"],"parent":"KnowledgeArtifact","node_key":"jargon-name","shape":"sphere","type":"Jargon","description_key":"description","title_key":"name","description":"?string","name":"string","domain":"KnowledgeArtifact","type_description":"An internally-used term and its meaning, optionally linked to the graph node it names.","ref_id":"9bde9004-f412-48c2-ad52-3809ce2fbdf6"},{"forum":"?string","state":"?string","node_key":"jurisdiction-name","secondary_color":"#D7CCC8","type":"Jurisdiction","court_system":"?string","level":"?string","name":"string","type_description":"A legal jurisdiction, such as a country, state, or regulatory body forum.","domain":"Legal","icon":"GlobeIcon","primary_color":"#6D4C41","index":["name","forum"],"sali_locale":"?string","parent":"Thing","shape":"sphere","country":"?string","sali_court_code":"?string","description_key":"forum","parent_ref_id":"?string","appeal_path_ref_id":"?string","title_key":"name","ref_id":"f08db6ef-c471-400f-b418-41a5b7a7ad2e","circuit":"?string","jurisdiction_kind":"?string"},{"icon":"BookIcon","index":"name","domain":"KnowledgeArtifact","type_description":"An abstract parent for AI-generated and user-facing knowledge nodes.","ref_id":"715266b4-4e95-47c1-800c-5591608fdd69","parent":"Thing","type":"KnowledgeArtifact"},{"icon":"NodesIcon","index":"name","description_key":"name","title_key":"name","name":"string","domain":"CodeArtifact","type_description":"A programming language used in the repository.","ref_id":"aef66983-e555-4fbd-8d18-bf1675656503","parent":"CodeArtifact","node_key":"language-name","shape":"sphere","type":"Language"},{"icon":"BookIcon","index":["name","description"],"parent":"CodeArtifact","node_key":"learning-name","shape":"sphere","type":"Learning","description_key":"description","title_key":"name","description":"?string","name":"string","domain":"CodeArtifact","type_description":"A learning resource or educational content item associated with a codebase.","ref_id":"2942e22b-8c6c-4189-bfc6-a2f769a69f51"},{"icon":"HomeIcon","lessee":"?string","primary_color":"#6D4C41","index":["name","lessor","lessee","property_address","lease_term"],"lessor":"?string","parent":"Agreement","node_key":"leaseagreement-id","property_address":"?string","secondary_color":"#D7CCC8","shape":"sphere","type":"LeaseAgreement","security_deposit":"?float","id":"string","description_key":"property_address","title_key":"name","monthly_rent":"?float","name":"?string","domain":"Legal","type_description":"A lease agreement specifying terms between a lessor and lessee for a property.","ref_id":"151c0569-88b7-4780-a822-e67832506dd4","lease_term":"?string"},{"icon":"ScalesIcon","primary_color":"#6D4C41","index":["name"],"parent":"Thing","secondary_color":"#D7CCC8","shape":"sphere","type":"Legal","description_key":"description","title_key":"name","description":"?string","name":"?string","domain":"Legal","type_description":"Domain anchor for all Legal entity types in the knowledge graph.","ref_id":"a08a10c6-d169-4924-8565-28533ffa9985"},{"node_key":"legalargument-matter_slug-argument_id","secondary_color":"#D7CCC8","resolution":"?string","type":"LegalArgument","source_document":"?string","priority":"?string","type_description":"A legal argument, statutory position, citation, or evidentiary issue identified in a litigation document.","domain":"Legal","raised_by":"?string","argument_id":"string","icon":"ScaleIcon","primary_color":"#6D4C41","statute_or_case":"?string","index":["matter_slug","argument_kind","statute_or_case"],"parent":"Legal","weakness_flag":"?boolean","severity":"?string","shape":"sphere","assertion":"string","description_key":"argument_kind","title_key":"assertion","ref_id":"081b2c0d-4f76-44f4-ba9b-51b2b8ab336a","notes":"?string","argument_kind":"string","matter_slug":"string"},{"icon":"LockClosedIcon","primary_color":"#6D4C41","next_refresh":"?string","index":["matter_slug","status","issued_date"],"last_refresh":"?datetime","scope":"?string","status":"?string","parent":"Thing","node_key":"legalhold-matter_slug","secondary_color":"#D7CCC8","shape":"sphere","type":"LegalHold","issued_by":"?string","released":"?boolean","description_key":"scope","title_key":"matter_slug","issued_date":"?string","release_date":"?datetime","domain":"Legal","type_description":"A legal hold (litigation hold) preserving documents and data relevant to anticipated or ongoing litigation.","ref_id":"af04c6fd-58fd-416c-815c-c66fa7de8eb4","matter_slug":"string"},{"player_role":"string","node_key":"legalparty-matter_slug-entity_id-player_role","secondary_color":"#D7CCC8","type":"LegalParty","entity_id":"string","end_date":"?datetime","side":"?string","type_description":"A matter-scoped player (person or organization) with a specific role in a legal matter. Implements the SALI LMSS Player model with player_role and representation_role separation.","domain":"Legal","firm_name":"?string","icon":"UserCircleIcon","representation_role":"?string","primary_color":"#6D4C41","index":["player_role","representation_role","matter_slug"],"entity_kind":"string","parent":"Legal","shape":"sphere","entity_name":"string","description_key":"player_role","bar_number":"?string","title_key":"entity_name","ref_id":"ad1cd3b9-6230-42bb-9dc2-2b38cbac7022","is_primary":"?boolean","notes":"?string","start_date":"?datetime","matter_slug":"string"},{"body":"?string","index":["name","body"],"parent":"CodeArtifact","node_key":"library-name-file","type_descrioption":"A reusable collection of code or modules providing functionality that can be imported and used in other projects.","type":"Library","description_key":"body","title_key":"name","start":"?int","file":"string","name":"string","domain":"CodeArtifact","ref_id":"5714a98a-d44b-4b09-b3c4-841963535f10","end":"?int"},{"icon":"ClockIcon","primary_color":"#6D4C41","index":["jurisdiction","matter_type"],"parent":"Legal","node_key":"limitationstatute-jurisdiction-matter_type","limitation_years":"float","secondary_color":"#D7CCC8","shape":"sphere","jurisdiction":"string","type":"LimitationStatute","description_key":"jurisdiction","title_key":"matter_type","matter_type":"string","domain":"Legal","type_description":"A statute of limitations applicable to a given matter type within a jurisdiction.","ref_id":"8f8e1d3d-ddbe-484a-9998-0bdf4a4e5b6c","notes":"?string","discovery_rule":"boolean"},{"icon":"BookTextIcon","primary_color":"#1D3140","index":["name","definition"],"definition":"?string","parent":"Thing","node_key":"lingo-name","secondary_color":"#4FA7D9","shape":"sphere","type":"Lingo","lingo_type":"?string","description_key":"definition","title_key":"name","name":"string","domain":"Entity","type_description":"A domain-specific term or vocabulary entry","ref_id":"425b3de0-fb58-4144-a334-32e6c86497bb"},{"icon":"PlaceIcon","primary_color":"#2A2545","index":["name","description"],"parent":"Thing","node_key":"location-name","secondary_color":"#9368FB","shape":"sphere","type":"Location","description_key":"description","title_key":"name","description":"?string","name":"string","domain":"Entity","type_description":"A physical or virtual location","ref_id":"7420f347-3b7a-4b06-b024-a0a5630eeb75"},{"next_action":"?string","closed_date":"?datetime","limitation_deadline":"?datetime","risk_likelihood":"?string","node_key":"matter-slug","secondary_color":"#D7CCC8","jurisdiction":"?string","type":"Matter","instruction_ledger":"?string","damages_calculation":"?string","stage":"?string","initial_posture":"?string","termination_kind":"?string","our_role":"?string","file_no":"?string","name":"?string","next_action_date":"?datetime","type_description":"A legal matter or case, including litigation, regulatory investigation, or transactional matter.","domain":"Legal","outside_counsel":"?string","last_touched":"?datetime","conflict_check_done":"?boolean","client_name":"?string","opened_date":"?datetime","icon":"BriefcaseIcon","statutory_exceptions":"?string","primary_color":"#6D4C41","index":["slug","name","matter_type","status"],"status":"?string","parent":"Thing","shape":"sphere","outcome":"?string","exposure_range":"?string","description_key":"matter_type","title_key":"name","matter_type":"?string","confidentiality":"?string","risk_severity":"?string","ref_id":"c327a21e-6b39-4139-a361-cb3ead2eb56c","slug":"string","materiality":"?string","final_cost":"?string"},{"icon":"GeneratedStepIcon","primary_color":"#38243C","index":"content","parent":"Workflow","memory_id":"string","node_key":"memory-memory_id","secondary_color":"#F468D4","shape":"sphere","type":"Memory","content":"string","description_key":"content","title_key":"memory_id","domain":"Workflow","type_description":"A memory unit for storing information and context learned by an Agent.","ref_id":"35e2971d-468d-44b7-8c0d-085e5c3239ca"},{"media_type":"?string","chat_pubkey":"?string","node_key":"message-uuid","secondary_color":"#54AC52","media_token":"?string","date":"int","type":"Message","kind":"?int","amount":"?int","sender":"string","media_key":"?string","type_description":" A communication conveyed through text, speech, or signals","domain":"Content","reply":"?string","thread_uuid":"?string","icon":"MessageIcon","primary_color":"#22362A","index":"content","parent":"Content","shape":"sphere","content":"string","description_key":"content","title_key":"content","ref_id":"7df3f6c6-afc0-4e30-97f7-494fcab47632","uuid":"string"},{"body":"?string","index":["name","body"],"parent":"CodeArtifact","node_key":"mock-name","mocked":"boolean","type":"Mock","description_key":"body","title_key":"name","start":"?int","file":"?string","name":"string","domain":"CodeArtifact","type_description":"A mock object or function used for testing purposes, simulating the behavior of real components.","ref_id":"0fefd66a-92c5-4a82-b90b-31c36db85fa2","end":"?int"},{"icon":"DocumentIcon","primary_color":"#2A2545","index":"source_link","parent":"Content","node_key":"multimedia-source_link","secondary_color":"#9368FB","shape":"sphere","type":"Multimedia","description_key":"source_link","title_key":"source_link","domain":"Content","type_description":"A generic type of content","ref_id":"3a74c3eb-73ff-46a1-86e7-d3de66775eed","source_link":"string"},{"firm_size":"?string","node_key":"organization-name","secondary_color":"#C25AF3","type":"Organization","practice_areas":"?string","court_system":"?string","image_url":"?string","description":"?string","name":"string","type_description":"A structured group of people with a collective purpose","domain":"Entity","org_kind":"?string","enabling_statute":"?string","court_level":"?string","icon":"OrganizationIcon","sali_govt_code":"?string","primary_color":"#302342","index":["name","description"],"sali_industry_code":"?string","acronym":"?string","parent":"Thing","primary_jurisdiction":"?string","shape":"sphere","sali_court_code":"?string","description_key":"description","title_key":"name","ref_id":"f9cae1c9-aab6-4d7a-bcdd-4d867e1ebc6f","circuit":"?string"},{"icon":"NodesIcon","body":"?string","index":["name","body"],"parent":"CodeArtifact","node_key":"package-name-file","shape":"sphere","type":"Package","description_key":"body","title_key":"name","start":"?int","file":"string","name":"string","domain":"CodeArtifact","type_description":"A package or module grouping related source files and dependencies within a repository.","ref_id":"b58ce83c-582c-45c2-a3c7-3ee4b61a7a31","end":"?int"},{"body":"?string","index":["name","body"],"parent":"CodeArtifact","node_key":"page-name-file","type":"Page","description_key":"body","title_key":"name","start":"?int","file":"string","name":"string","domain":"CodeArtifact","type_description":"A webpage or route within an application, representing a specific view or section of the system. It can serve as the starting point for a codemap.","ref_id":"45ed4c69-359f-4a24-8edf-3df33c09f9ee","end":"?int"},{"certification_number":"?string","icon":"PersonIcon","primary_color":"#362429","bar_state":"?string","index":["name","description"],"alias":"?string","bar_admitted_date":"?datetime","twitter_handle":"?string","parent":"Thing","node_key":"person-name","secondary_color":"#D25353","shape":"sphere","type":"Person","title":"?string","bar_number":"?string","description_key":"description","title_key":"name","image_url":"?string","expertise_domain":"?string","description":"?string","name":"string","domain":"Entity","type_description":"A human being regarded as an individual","ref_id":"3b7acdb2-3238-4ce9-b595-01f68d2aaee0"},{"icon":"PlaceIcon","primary_color":"#2A2545","index":["name","description"],"parent":"Thing","node_key":"place-name","secondary_color":"#9368FB","shape":"sphere","type":"Place","description_key":"description","title_key":"name","image_url":"?string","description":"?string","name":"string","domain":"Entity","type_description":"A particular position, point, or area in space","ref_id":"392aa4ca-b1d5-4c66-8e36-3f41f602165d"},{"icon":"BookmarkIcon","primary_color":"#6D4C41","index":["scope","clause_type","severity"],"scope":"string","parent":"Legal","node_key":"playbookentry-scope-clause_type","severity":"string","suggested_text":"?string","secondary_color":"#D7CCC8","shape":"sphere","fallback_position":"?string","type":"PlaybookEntry","clause_type":"string","red_line":"boolean","description_key":"firm_position","title_key":"clause_type","firm_position":"string","domain":"Legal","type_description":"A negotiation playbook entry specifying firm positions and fallback positions for a contract clause type.","ref_id":"1829e31d-421d-49fa-8078-6685e113519d","notes":"?string"},{"link":"?string","node_key":"podcast-episode_title-timestamp","secondary_color":"#4FA7D9","sentiment_score":"?float","date":"?datetime","type":"Podcast","timestamp":"string","image_url":"?string","description":"?string","type_description":"A digital audio program made up of episodic recordings","domain":"Content","source_link":"?string","pub_key":"?string","icon":"AudioIcon","primary_color":"#1D3140","text":"?string","index":["episode_title","text","description"],"episode_title":"string","media_url":"string","parent":"Episode","show_title":"?string","shape":"sphere","num_boost":"?int","description_key":"description","title_key":"episode_title","english_translation":"?string","ref_id":"3ed41af8-6d8e-4d0b-a799-8e74712e6f8a","boost":"?int","language":"?string"},{"icon":"DocumentTextIcon","primary_color":"#6D4C41","index":["name"],"parent":"Thing","node_key":"policy-name","secondary_color":"#D7CCC8","shape":"sphere","type":"Policy","description_key":"description","title_key":"name","description":"?string","name":"string","domain":"Legal","type_description":"An internal or external policy document governing organizational conduct.","ref_id":"87ab2b1b-db8c-4083-86d9-c1a4b70c53c2"},{"icon":"DatabaseIcon","primary_color":"#6D4C41","index":["name","legal_basis","regime"],"parent":"Thing","node_key":"processingactivity-name","secondary_color":"#D7CCC8","shape":"sphere","purpose":"?string","type":"ProcessingActivity","description_key":"purpose","title_key":"name","legal_basis":"?string","name":"string","domain":"Legal","type_description":"A data processing activity subject to privacy regulations such as GDPR or CCPA.","ref_id":"6b70e0dd-d633-49df-9bd5-5563a021bd8d","triage_result":"?string","regime":"?string"},{"primary_color":"#353124","index":"name","description_key":"name","title_key":"name","name":"string","domain":"Entity","type_description":"A product or item","ref_id":"9fe7badd-c23a-42ca-9638-a22c47d1e15a","parent":"Thing","node_key":"product-name","secondary_color":"#BA9D39","type":"Product"},{"icon":"NodesIcon","body":"?string","index":["name","description","body"],"parent":"Workflow","node_key":"prompt-id","shape":"sphere","type":"Prompt","id":"string","description_key":"description","title_key":"name","description":"?string","name":"?string","domain":"Workflow","type_description":"A prompt template used within workflow definitions.","ref_id":"915b2c28-4905-4dc6-a9cd-9ed43cecbdfa","customer_id":"?int"},{"summary":"?string","fix_type":"string","node_key":"proposedfix-fix_id","secondary_color":"#E09242","before_score":"?string","type":"ProposedFix","criterion_title":"?string","stakwork_run_id":"?string","new_prompt_version_id":"?string","fix_id":"string","prompt_name":"?string","rerun_run_id":"?string","prompt_id":"?string","resolved_by":"?string","type_description":"A fix-scoped, fix-type-polymorphic node representing any eval-driven improvement. One node per fix, identified by a caller-generated, globally-unique fix_id (NOT one node per criterion). fix_type is an open string; conventional values: prompt | workflow | architecture | schema | other — new fix kinds require no migration. Criterion and prompt fields are optional; populate them only when fix_type=prompt. rerun_run_id references the upstream evaluation run id (e.g. EvalTriggerOutput.id) that produced this fix proposal — it is NOT an EvalRun.id reference (EvalRun is deprecated from the canonical model as of migration 084). Anchored to the unified eval chain: EvalSet → EvalRequirement → EvalTrigger → EvalTriggerOutput → CriterionResult → ProposedFix. Duplicate fix_id values are silently merged (not rejected) by the node_key migration helper; callers must ensure global uniqueness. OUTCOME FIELD — eval_status (canonical): the accept/reject outcome of this fix. Lifecycle: pending → accepted | rejected. Exact allowed set only — downstream readers and writers MUST validate against this fixed set before acting on it; a malformed or unexpected value would silently mis-branch accept/reject logic in the recursion loop (accepted = trunk node, rejected = dead-end leaf). LEGACY FIELD — status: retained for compatibility; no longer the outcome signal. Do not use status for accept/reject branching in new code; use eval_status instead. FIX LINEAGE — DERIVED_FROM edge (child → parent, append-only, git-commit-parent style): accepted fixes form a linear trunk (latest accepted = the tip, i.e. the accepted node with no accepted child pointing to it); a rejected fix is a dead-end leaf pointing at the accepted parent it was tried against. Only the accepted trunk is linearly ordered by topology; rejected siblings off one accepted parent are an unordered set by design — no timestamp or sequence field is added. PARENT LOOKUP — parent_fix_id: a denormalized, edge-free mirror of the DERIVED_FROM parent (analogous to rerun_run_id). The DERIVED_FROM edge is the source of truth; keeping parent_fix_id consistent with the edge and rejecting cycles is the responsibility of the sibling writer feature, not enforced by this ontology. TRAVERSAL SAFETY CONTRACT: no acyclicity or depth guarantee exists at the ontology layer. Downstream chain-walkers (recursion cron, eval-runner) MUST bound traversal depth and reject cycles — e.g. validate parent_fix_id lineage before writing a new DERIVED_FROM edge — otherwise a cycle written later could loop a walker unbounded. TARGET SNAPSHOT (generic before/after for any fix kind) — five optional fields added by migration 105: target_type, target_name, target_version, old_value, new_value. old_value/new_value each hold ONE JSON object serialized to a JSON string via json.dumps — never a raw object (both are typed ?string, so validate_by_schema rejects non-string values). Conventional envelope shapes by target_type: prompt -> {\"text\": ...}; concept -> {\"name\": ..., \"documentation\": ...} — readers MUST accept either \"documentation\" or \"docs\" as the concept body key (Concept's body field may be renamed from documentation to docs in a separate in-flight change; this convention is forward-compatible with either); workflow -> the workflow's JSON definition. These shapes are a documented convention only, NOT runtime-validated at the schema layer — readers must tolerate a missing or unparseable envelope gracefully (render the raw text and flag it, never throw). DISCRIMINATOR PRECEDENCE: target_type is authoritative for interpreting the snapshot envelope; fix_type remains the existing fix-kind label. The two are not schema-enforced to agree. When target_type is absent (true for every pre-existing ProposedFix node — no backfill is performed), readers fall back to fix_type for labelling and render an empty-snapshot state. RELATION TO EXISTING BEFORE/AFTER FIELDS (none deprecated by 105): failing_value/passing_value/delta are criterion-level observed values; before_score/after_score/score_delta are numeric eval scores; old_value/new_value are the full target-artifact snapshot — a diff renderer should read only old_value/new_value. DENORMALIZED IDENTITY: target_ref remains the source of truth for target identity; target_name/target_version are edge-free display mirrors (same spirit as parent_fix_id) that may go stale — keeping them consistent is the writer's responsibility, not enforced here. For fix_type=prompt, prompt_name/prompt_version_id/new_prompt_version_id remain canonical; target_name/target_version merely mirror them. WRITE PATH: attach a snapshot to an existing ProposedFix via POST /v2/nodes with reprocess=true (in-place update, preserves DERIVED_FROM lineage); never force_delete (DETACH DELETE destroys lineage) and never allow_scratchpad=true (a rejected write would be durably parked as a ScratchpadEntry under a different access-control model — undesirable for large snapshot payloads). SECRET HYGIENE: workflow-target JSON snapshots can embed credentials/secrets; old_value/new_value are deliberately publicly readable (no paid_properties gating), so producers MUST redact credentials/secret values before writing a workflow-targeted snapshot.","domain":"CodeArtifact","target_version":"?string","criterion_id":"?string","parent_fix_id":"?string","after_score":"?string","icon":"PencilAltIcon","rerun_status":"?string","primary_color":"#392828","index":["fix_id","fix_type","summary","status","task_slug"],"new_value":"?string","target_name":"?string","status":"?string","delta":"?string","parent":"Thing","shape":"sphere","target_ref":"?string","resolved_at":"?string","eval_status":"?string","task_slug":"?string","passing_value":"?string","reasoning":"string","prompt_version_id":"?string","title_key":"summary","old_value":"?string","rubric_criterion_ref":"?string","score_delta":"?string","ref_id":"9f787d04-0aa0-4131-b284-548245517792","target_type":"?string","failing_value":"?string"},{"icon":"NodesIcon","index":["name","description"],"state":"?string","parent":"Repository","node_key":"pullrequest-name","number":"?int","shape":"sphere","type":"PullRequest","namespace":"?string","description_key":"description","title_key":"name","description":"?string","name":"string","domain":"CodeArtifact","type_description":"A pull request created by a developer to merge changes into the main branch.","ref_id":"e9eed9da-2487-4ab3-beca-702c04e6c4a6","created_at":"?string","source_link":"?string","user":"?string"},{"icon":"BookOpenIcon","primary_color":"#6D4C41","index":["name","agency","regime"],"status":"?string","parent":"Thing","agency":"?string","status_verified":"?boolean","node_key":"regulation-name","secondary_color":"#D7CCC8","shape":"sphere","type":"Regulation","relevance_hook":"?string","description_key":"regime","title_key":"name","name":"string","domain":"Legal","type_description":"A law, regulation, or regulatory framework applicable to the organization (e.g. GDPR, CCPA, SOX).","ref_id":"a5e50fb4-1b08-4679-bd56-6927d469c39e","effective_date":"?string","regime":"?string","item_type":"?string"},{"link":"?string","node_key":"regulatoryitem-id","secondary_color":"#D7CCC8","type":"RegulatoryItem","decision":"?string","id":"string","title":"?string","type_description":"A discrete regulatory requirement, rule, or guidance item issued under a Regulation.","domain":"Legal","filed_at":"?datetime","detected":"?datetime","item_type":"?string","icon":"ClipboardListIcon","citation":"?string","primary_color":"#6D4C41","index":["id","item_type","agency","materiality_tier"],"materiality_tier":"?string","parent":"Thing","agency":"?string","shape":"sphere","description_key":"item_type","title_key":"title","ref_id":"c80b1515-af2d-41ea-8dba-d19bebf857ba","effective_date":"?datetime","owner_slack":"?string","comment_deadline":"?string"},{"business_owner":"?string","icon":"RefreshIcon","primary_color":"#6D4C41","renewal_mechanism":"?string","index":["counterparty","signed_date","status"],"cancel_by":"?datetime","signed_date":"string","status":"string","notice_period_days":"?int","initial_term_end":"?datetime","parent":"Legal","node_key":"renewalentry-counterparty-signed_date","secondary_color":"#D7CCC8","shape":"sphere","price_on_renewal":"?string","type":"RenewalEntry","counterparty":"string","description_key":"status","title_key":"counterparty","domain":"Legal","type_description":"A contract renewal record tracking key renewal dates, terms, and owners.","ref_id":"dda88769-ae75-41df-9cce-accd9d5cb4de","annual_value":"?string","clm_id":"?string"},{"icon":"HomeIcon","body":"?string","index":["name","body"],"hash":"?string","parent":"Thing","node_key":"repository-name-file-start","shape":"sphere","type":"Repository","description_key":"body","title_key":"name","start":"int","file":"string","name":"string","domain":"CodeArtifact","type_description":"A code repository that contains source files, directories, and version history.","ref_id":"35d0b681-fa57-4289-bc73-cceed785fcae","source_link":"?string","end":"?int"},{"summary":"?string","body":"?string","node_key":"request-name-file-verb","type":"Request","namespace":"?string","verb":"string","description":"?string","file":"string","name":"string","type_description":"An HTTP request representation, defining interactions with an API or web service.","domain":"CodeArtifact","source_link":"?string","end":"?int","icon":"ConstructionIcon","text":"?string","index":["name","summary","description"],"hash":"?string","parent":"CodeArtifact","shape":"sphere","description_key":"summary","title_key":"name","start":"?int","ref_id":"c71ceadd-e1d6-43b4-a23e-167e3366d6b4","method":"?string","handler":"?string"},{"icon":"RunIcon","primary_color":"#36292D","index":["project_id","workflow_state"],"parent":"Workflow","node_key":"run-project_id","secondary_color":"#A96755","shape":"sphere","type":"Run","evaluation":"?boolean","description_key":"workflow_state","title_key":"project_id","workflow_state":"?string","project_id":"int","domain":"Workflow","type_description":"An execution instance of a workflow or process","ref_id":"0127e76b-39f5-4e7f-b12c-4b29ab2eddbe"},{"icon":"StepIcon","primary_color":"#362429","index":["description","step_unique_id"],"output_json":"?string","parent":"Workflow","node_key":"run_step-step_unique_id","secondary_color":"#D25353","shape":"sphere","input_json":"?string","type":"Run_step","step_unique_id":"string","id":"string","description_key":"description","title_key":"step_unique_id","description":"?string","domain":"Workflow","type_description":"An individual step within a workflow run execution","ref_id":"6a640450-9511-45e7-8d42-95c7b8eae72f"},{"icon":"NodesIcon","index":["name","description"],"parent":"KnowledgeArtifact","node_key":"scope-name","shape":"sphere","type":"Scope","description_key":"description","title_key":"name","description":"?string","name":"string","domain":"KnowledgeArtifact","type_description":"A scope label that groups related learnings, such as a technology, pattern, or area of the codebase.","ref_id":"806755c4-2080-419e-9cd5-bd904bc8e3bb"},{"icon":"PencilAltIcon","index":["intended_type","name"],"entry_hash":"string","intended_type":"string","parent":"Thing","node_key":"scratchpadentry-intended_type-entry_hash","shape":"sphere","rejection_reason":"?string","type":"ScratchpadEntry","payload_json":"?string","title_key":"name","name":"?string","rejection_detail":"?string","domain":"Scratchpad","type_description":"A write that did not match the strict ontology, preserved verbatim instead of being rejected. intended_type records the node type the caller tried to create; payload_json holds the original node_data as a JSON string (the ontology validators reject undeclared attributes, so the payload cannot be spread into real properties). entry_hash is a sha256 of that payload, so a writer retrying the same rejected request repeatedly produces one node, not one per try. The Scratchpad domain is system-hidden: these nodes are excluded from search and are never offered to the extraction agent as a target type. INVARIANT: a ScratchpadEntry may be the SOURCE of an edge (so an entry keeps context by pointing at canonical nodes) but never the TARGET, so nothing traversing the canonical graph can walk into ungoverned data. Promotion of entries into real node types is deliberately out of scope; this tier is a staging area and a record of which node types the ontology is missing.","ref_id":"9b433ec6-e502-4cab-aabe-6b7ae0eadee3"},{"icon":"TaskIcon","primary_color":"#1B3134","body":"?string","index":["name","description","body"],"parent":"Workflow","node_key":"script-id","secondary_color":"#21B38A","shape":"sphere","type":"Script","id":"int","description_key":"description","title_key":"name","description":"?string","name":"?string","domain":"Workflow","type_description":"A script or code block used within workflow execution","ref_id":"7d605ac2-d97f-4c44-85b1-d1fbb3910c28","customer_id":"?int"},{"icon":"TaskIcon","primary_color":"#1B3134","usage_count":"?int","index":["name","description"],"parent":"Thing","node_key":"secret-id","secondary_color":"#21B38A","shape":"sphere","type":"Secret","id":"int","description_key":"description","title_key":"name","description":"string","name":"string","domain":"Workflow","type_description":"A named credential or sensitive value optionally scoped to a skill and customer.","usage_count_30d":"?int","ref_id":"9dfc3e87-4d02-454f-8c41-35d9cfb549d0","skill_id":"?int","customer_id":"?int"},{"summary":"?string","icon":"DocumentIcon","primary_color":"#2A2545","index":["text","source_link"],"text":"string","parent":"Document","node_key":"section-text","secondary_color":"#9368FB","shape":"sphere","type":"Section","description_key":"text","title_key":"text","domain":"Content","type_description":"A distinct part or subdivision of a document","ref_id":"7099575b-ee14-4e40-82e9-31668c8933c8","source_link":"?string"},{"icon":"VideoIcon","primary_color":"#38243C","index":"show_title","parent":"Content","node_key":"show-show_title","show_title":"string","secondary_color":"#F468D4","shape":"sphere","type":"Show","description_key":"show_title","title_key":"show_title","image_url":"?string","domain":"Content","type_description":" A podcast is a digital medium consisting of audio (or video) episodes that relate to a specific theme","ref_id":"6e6cd66e-9c96-412a-a0db-6330a55e98f1"},{"icon":"TaskIcon","primary_color":"#1D3140","usage_count":"?int","index":["name","description","input_schema","output_schema"],"graph_description":"?string","input_schema":"?string","output_schema":"?string","parent":"Workflow","node_key":"skill-name","secondary_color":"#4FA7D9","shape":"sphere","type":"Skill","id":"?int","description_key":"description","title_key":"name","description":"?string","name":"string","domain":"Workflow","type_description":"A reusable capability or function that can be composed into workflows","usage_count_30d":"?int","ref_id":"2af571af-d21a-412d-8177-3ce792e46317","skill_id":"?int","mockable":"?boolean"},{"icon":"StrategyIcon","primary_color":"#353124","index":["name","steps_list"],"LLM_response_id":"?int","parent":"Workflow","node_key":"strategy-strategy_id","secondary_color":"#BA9D39","shape":"sphere","type":"Strategy","description_key":"steps_list","title_key":"name","steps_list":"?string","name":"?string","domain":"Workflow","type_description":"A plan or approach for accomplishing a specific goal or set of objectives","ref_id":"b5c26d54-ad93-4685-aa22-dbc59d281bc2","strategy_id":"int","success":"?boolean"},{"icon":"TableIcon","primary_color":"#6D4C41","index":["column_name","state","column_type"],"column_type":"string","location":"?string","state":"string","parent":"Legal","node_key":"tabularreviewcell-column_name-column_type-state","secondary_color":"#D7CCC8","shape":"sphere","type":"TabularReviewCell","column_name":"string","description_key":"value","title_key":"column_name","quote":"?string","domain":"Legal","value":"?string","type_description":"A single cell in a tabular contract or document review, capturing a named column value for a specific document.","ref_id":"1459218f-3d70-4b21-8533-0d0cee7c1266"},{"taskId":"?string","icon":"TaskIcon","primary_color":"#2A3229","index":"task","status":"?string","task":"?string","task_id":"int","parent":"Workflow","node_key":"task-task_id","secondary_color":"#96BD3F","shape":"sphere","type":"Task","description_key":"task","title_key":"task","project_id":"?int","domain":"Workflow","type_description":"A specific work item or unit of work that needs to be completed","ref_id":"ff186ad2-b21e-427f-850e-8a6b346575c2","success":"?boolean"},{"icon":"ConstructionIcon","index":"name","domain":"CodeArtifact","type_description":"An abstract parent for all test types (unit, integration, e2e).","ref_id":"058238a1-f4bb-430f-a682-1ce9d8911b95","parent":"CodeArtifact","type":"Test"},{"unique_source_id":"?string","icon":"NodesIcon","primary_color":"#36292D","index":["name","description"],"weight":"?float","node_key":"thing-name","secondary_color":"#A96755","shape":"sphere","type":"Thing","description_key":"description","title_key":"name","image_url":"?string","description":"?string","name":"string","is_muted":"?boolean","type_description":"The highest-level node in the ontology hierarchy, representing an abstract concept with no direct individual instances","ref_id":"2f8b346c-74e3-43c2-9700-ce22c397c2ce"},{"icon":"CalendarIcon","primary_color":"#6D4C41","index":["matter_slug","entry_date","entry_type"],"parent":"Legal","node_key":"timelineentry-matter_slug-entry_date","entry_type":"string","secondary_color":"#D7CCC8","shape":"sphere","type":"TimelineEntry","author":"string","description_key":"entry_type","title_key":"description","source":"string","email_thread_id":"?string","description":"string","domain":"Legal","type_description":"A dated event or milestone on a legal matter timeline.","ref_id":"d52c3dfe-14c0-46c8-b31e-93a9aad85617","entry_date":"datetime","matter_slug":"string"},{"icon":"BookIcon","primary_color":"#1D3140","index":["name","description"],"parent":"Thing","node_key":"topic-name","secondary_color":"#4FA7D9","shape":"sphere","type":"Topic","description_key":"description","title_key":"name","image_url":"?string","description":"?string","name":"string","is_muted":"?boolean","domain":"Content","relevancy_score":"?float","type_description":"A subject or theme of discussion, study, or interest","ref_id":"83819187-c84f-492d-a112-f64e8ea62adc"},{"body":"?string","index":["name","body"],"parent":"CodeArtifact","node_key":"trait-name-file","type":"Trait","description_key":"body","title_key":"name","start":"?int","file":"string","name":"string","domain":"CodeArtifact","type_description":"A reusable set of properties or behaviors in source code, often used in object-oriented or functional programming.","ref_id":"594ae6bb-c5ac-42d4-ab8f-e4b31a5eafb8","end":"?int"},{"icon":"StepIcon","primary_color":"#2A2545","index":["content","tool"],"tool":"?string","parent":"Workflow","node_key":"turn-turn_id","secondary_color":"#9368FB","shape":"sphere","type":"Turn","turn_id":"string","outcome":"?string","content":"?string","turn_type":"?string","description_key":"content","title_key":"tool","order":"?int","domain":"Workflow","type_description":"A single turn in an agent session — a tool call, thought, response, user input, or error.","ref_id":"6888e270-a3fd-4aa0-b3cf-c447b747b84f","tokens":"?int"},{"quote_count":"?string","tweet_id":"string","twitter_handle":"?string","node_key":"tweet-tweet_id","secondary_color":"#D25353","date":"?datetime","type":"Tweet","followers":"?string","impression_count":"?string","image_url":"?string","description":"?string","verified":"?boolean","name":"?string","type_description":"A short message posted on a social media platform","domain":"Content","source_link":"?string","icon":"TwitterIcon","primary_color":"#362429","text":"?string","index":["text","twitter_handle"],"reply_count":"?string","status":"?string","media_url":"?string","parent":"Content","shape":"sphere","pubkey":"?string","description_key":"text","title_key":"twitter_handle","like_count":"?string","project_id":"?string","ref_id":"d7103144-1c0a-4ec9-91ee-713a84335514","retweet_count":"?string","bookmark_count":"?string"},{"icon":"TwitterIcon","primary_color":"#362429","index":["twitter_handle","name"],"verified_type":"?string","twitter_handle":"string","parent":"Thing","node_key":"twitteraccount-twitter_handle","secondary_color":"#D25353","shape":"sphere","type":"TwitterAccount","is_identity_verified":"?boolean","description_key":"name","title_key":"twitter_handle","image_url":"?string","verified":"?boolean","name":"?string","domain":"Content","type_description":"A Twitter/X account associated with a person or organization","ref_id":"96f8744c-554e-4f9b-9e10-01965d83e544","author_id":"?string"},{"icon":"NodesIcon","body":"?string","index":["name","body"],"parent":"Test","node_key":"unittest-name-file","shape":"sphere","type":"UnitTest","description_key":"body","title_key":"name","start":"?int","file":"string","name":"string","domain":"CodeArtifact","type_description":"A unit test verifying a single function or module in isolation.","ref_id":"1af06b0b-d6f1-4944-b330-89d6524f1842","end":"?int"},{"icon":"TargetIcon","index":["name","description"],"parent":"KnowledgeArtifact","node_key":"userobjective-name","shape":"sphere","type":"UserObjective","description_key":"description","title_key":"name","description":"?string","name":"string","is_muted":"?boolean","domain":"KnowledgeArtifact","type_description":"A user-defined objective or goal to track","ref_id":"2c22ea3f-a917-4116-9e01-08453ad691fd"},{"body":"?string","index":["name","body"],"parent":"CodeArtifact","node_key":"var-name-file","type":"Var","description_key":"body","title_key":"name","start":"?int","file":"string","name":"string","domain":"CodeArtifact","type_description":"A variable declaration or usage in source code, representing data storage and manipulation within a program.","ref_id":"a7f02c51-eb83-41e2-8c2c-cf8289ed8471","end":"?int"},{"link":"?string","node_key":"video-episode_title-timestamp","secondary_color":"#21B38A","sentiment_score":"?float","date":"?datetime","type":"Video","timestamp":"string","image_url":"?string","description":"?string","type_description":"A recording of moving visual images","domain":"Content","source_link":"?string","pub_key":"?string","icon":"VideoIcon","primary_color":"#1B3134","text":"?string","index":["episode_title","text","description"],"episode_title":"string","media_url":"string","parent":"Episode","show_title":"?string","shape":"sphere","num_boost":"?int","description_key":"description","title_key":"episode_title","english_translation":"?string","ref_id":"36dcd4bc-25c5-4c71-9dc8-243ca3dc7185","boost":"?int","language":"?string"},{"body":"?string","workflow_version":"?int","node_key":"workflow-workflow_id","secondary_color":"#54AC52","type":"Workflow","description":"?string","name":"?string","workflow_id":"?int","type_description":"An abstract parent for all workflow automation execution types.","domain":"Workflow","usage_count_30d":"?int","published_workflow_version_id":"?int","icon":"TaskIcon","usage_count":"?int","primary_color":"#22362A","index":["name","description","body","input_schema","output_schema"],"input_schema":"?string","output_schema":"?string","parent":"Thing","workflow_json":"?string","shape":"sphere","description_key":"description","title_key":"name","parent_version_id":"?int","ref_id":"82793c01-c13a-4175-a2fc-86df96dd421b","branch":"?string","customer_id":"?int"},{"body":"?string","node_key":"workflow_version-workflow_id-workflow_version_id","secondary_color":"#E09242","type":"Workflow_version","description":"?string","name":"?string","workflow_id":"int","type_description":"A specific version of a workflow configuration with defined steps and parameters","domain":"Workflow","published":"?boolean","icon":"WorkflowIcon","primary_color":"#392828","index":["name","description","body","input_schema","output_schema"],"workflow_version_id":"int","input_schema":"?string","output_schema":"?string","parent":"Workflow","workflow_json":"?string","shape":"sphere","published_at":"?string","description_key":"description","title_key":"name","ref_id":"cb32dd65-19cb-4e15-8af1-f2d9a9c7d013","branch":"?string","success":"?boolean","customer_id":"?int"}],"edge_schemas":[{"source":"AISystem","edge":"HAS_DEADLINE","target":"Deadline","props":{"ref_id":"bfc2d84d-c01c-4f70-92f3-1d195719a5c9"}},{"source":"AISystem","edge":"IMPACT_ASSESSED_BY","target":"ProcessingActivity","props":{"ref_id":"209ca84b-7233-4753-b756-340ceea66311"}},{"source":"AISystem","edge":"SUBJECT_TO","target":"Regulation","props":{"ref_id":"f357bdaf-2807-49ea-99b8-3752d3421bf0"}},{"source":"AISystem","edge":"VENDOR_COVERED_BY","target":"Agreement","props":{"ref_id":"22f1cdea-87a0-48ab-881e-c8998d7cd857"}},{"source":"AgentRole","edge":"HAS_SESSION","target":"AgentSession","props":{"ref_id":"ce7e4dfb-cc16-4efd-86b9-69cf7627b186"}},{"source":"AgentSession","edge":"HAS_ABSTRACTION","target":"Abstraction","props":{"ref_id":"3ba0f08b-ce81-482a-9632-af9989b0e219"}},{"source":"AgentSession","edge":"HAS_TURN","target":"Turn","props":{"ref_id":"43eca24e-e4c7-4875-bf12-cbb8667ae5b9"}},{"source":"AgentSession","edge":"NEXT","target":"AgentSession","props":{"ref_id":"0dfd7a8d-54cf-4525-8de8-68264893dcad"}},{"source":"Agreement","edge":"AMENDS","target":"Agreement","props":{"ref_id":"bc8ec2a1-21eb-4f91-8030-9f2b3dc8d5f0"}},{"source":"Agreement","edge":"APPLIED_TO","target":"ComputedFigure","props":{"ref_id":"08863969-6fbe-4d41-8ebc-ca651614907f"}},{"source":"Agreement","edge":"CONTAINS_REQUEST","target":"DDRequestItem","props":{"ref_id":"ea3b3f26-0a0c-497f-bb78-69a7225b006a"}},{"source":"Agreement","edge":"DEFINES","target":"DefinedTerm","props":{"ref_id":"d729e3cd-4e5c-41c4-a9f0-d3fe478e6e25"}},{"source":"Agreement","edge":"GOVERNED_BY_LAW","target":"Country","props":{"state":"?string","ref_id":"6a415e72-e7de-4c18-8298-aaaf310f43f6"}},{"source":"Agreement","edge":"GOVERNED_BY_LAW","target":"Location","props":{"state":"?string","ref_id":"dcc0e542-b28b-4feb-b101-35398f746170"}},{"source":"Agreement","edge":"GOVERNS","target":"IPAsset","props":{"ref_id":"22c960f6-ad5f-44b0-b778-3f012288ccaf"}},{"source":"Agreement","edge":"HAS_CLAUSE","target":"ContractClause","props":{"ref_id":"223dec2d-5c5f-4621-a4d5-344aa03cbbe5"}},{"source":"Agreement","edge":"HAS_DEADLINE","target":"Deadline","props":{"ref_id":"a55e76a6-308b-4095-8f7a-995beadc0d66"}},{"source":"Agreement","edge":"HAS_RENEWAL_ENTRY","target":"RenewalEntry","props":{"ref_id":"dec5188d-b689-499a-be2f-6cd18b3e44fc"}},{"source":"Agreement","edge":"REFERENCES","target":"Agreement","props":{"ref_id":"c936009f-4f5f-413c-859e-184ee1581b03"}},{"source":"Agreement","edge":"REVIEWED_IN","target":"TabularReviewCell","props":{"ref_id":"0f5b82a7-2e31-47a2-9a82-d175f7d45b98"}},{"source":"Belief","edge":"REFERS_TO","target":"Thing","props":{"ref_id":"4da1dfd6-4733-4944-8925-736623c1087e"}},{"source":"BenchmarkFailureCause","edge":"AFFECTS","target":"EvalRequirement","props":{"ref_id":"aef65a04-d96f-4259-b6ba-9376a4817e68"}},{"source":"Cause","edge":"CAUSE_CHILD_OF","target":"Cause","props":{"ref_id":"67466570-1d4a-4259-9785-95bab2e5ace2","cardinality":"many"}},{"source":"Check","edge":"SUPERSEDES","target":"Check","props":{"ref_id":"0a79f10f-ee33-4646-b9ed-33be78d14a67"}},{"source":"Check","edge":"TESTS","target":"Claim","props":{"ref_id":"7963757b-3491-4ce4-b068-931b047b6010"}},{"source":"Claim","edge":"ABOUT","target":"Thing","props":{"ref_id":"fc24db78-a30a-488f-aa5c-7817c0f81468"}},{"source":"Claim","edge":"CONTRADICTS","target":"Claim","props":{"ref_id":"d5881f57-b95d-4212-b8c1-612fb6c576fa"}},{"source":"Claim","edge":"DERIVED_FROM","target":"Claim","props":{"ref_id":"14ec537e-7714-4174-99eb-b258b7e6b157"}},{"source":"Claim","edge":"EVIDENCED_BY","target":"Evidence","props":{"strength":"?float","ref_id":"dc4c6f37-71dc-47f4-b6b2-0124a5b58d7b"}},{"source":"Claim","edge":"PARENT_OF","target":"Claim","props":{"ref_id":"ec7818b9-e379-4691-adf3-ab8b8407841a"}},{"source":"Claim","edge":"SOURCE","target":"Chapter","props":{"ref_id":"1824e0af-b190-4548-bf91-97615077b26c"}},{"source":"Claim","edge":"SOURCE","target":"Section","props":{"ref_id":"83315901-2e1f-427d-9c31-d93900f855e8"}},{"source":"Claim","edge":"SUPERSEDES","target":"Claim","props":{"ref_id":"30914867-6ade-4d7e-8129-990b276700c9"}},{"source":"Claim","edge":"SUPPORTS","target":"Claim","props":{"ref_id":"1b7576ee-1e9f-4f01-a035-72b239133f30"}},{"source":"Class","edge":"CALLS","target":"Class","props":{"ref_id":"162d5620-fbe6-4eee-a989-28c6fe925c11","call_start":"?int","call_end":"?int","operand":"?string"}},{"source":"Class","edge":"CONTAINS","target":"Datamodel","props":{"ref_id":"674805f9-8f7c-4cea-a949-e93fdc340d4a"}},{"source":"Class","edge":"IMPORTS","target":"Class","props":{"ref_id":"d2c979b6-259d-4231-99e7-46376c6f887e"}},{"source":"Class","edge":"OPERAND","target":"Function","props":{"ref_id":"c488fbdc-ad8f-4a3c-8662-a6a0ad69ffbf"}},{"source":"Class","edge":"PARENT_OF","target":"Class","props":{"ref_id":"710af56b-8f2f-4181-bb37-4c1dcf0708e7"}},{"source":"Clip","edge":"RELATED_TO","target":"Topic","props":{"ref_id":"6d1b3221-514e-469a-92ba-7f314f6e45de"}},{"source":"Commit","edge":"TOUCHES","target":"Concept","props":{"ref_id":"9b01949b-74c4-4422-99ef-1e7ad9f175c9"}},{"source":"Commit","edge":"TOUCHES","target":"Feature","props":{"ref_id":"bacb4e3d-aab0-4bba-a98d-622f997718ea"}},{"source":"ComputedFigure","edge":"APPLIED_TO","target":"Matter","props":{"ref_id":"db0159b0-5552-4c64-a25c-3b8063555e28"}},{"source":"ComputedFigure","edge":"CONTRADICTS","target":"Deadline","props":{"contradiction_type":"?string","ref_id":"ce7fe9ef-641a-4dde-9896-90452cd97728","contradiction_reason":"?string"}},{"source":"ComputedFigure","edge":"DERIVED_FROM","target":"Excerpt","props":{"ref_id":"e2bac065-b2f1-460d-8334-d55563d91752"}},{"source":"ComputedFigure","edge":"DERIVED_FROM","target":"Figure","props":{"ref_id":"6f83d676-a339-4a59-b880-3f5de370e76f"}},{"source":"ComputedFigure","edge":"GOVERNED_BY","target":"RegulatoryItem","props":{"ref_id":"0c0464b5-43d4-4d2a-a291-124c8519a96b"}},{"source":"ComputedFigure","edge":"HAS_COMPONENT","target":"FormulaComponent","props":{"ref_id":"4b84cc0a-f72b-4cc9-9cba-4538d8a3cee3"}},{"source":"ComputedFigure","edge":"QUANTIFIES","target":"DefinedTerm","props":{"field_name":"?string","value_as_stated":"?string","ref_id":"65dcc3b9-9a38-4e3d-b687-afe6c4d5417d","notes":"?string"}},{"source":"ComputedFigure","edge":"QUANTIFIES","target":"PlaybookEntry","props":{"field_name":"?string","value_as_stated":"?string","ref_id":"6cce34d1-2608-4a66-81eb-0e79177fe332","notes":"?string"}},{"source":"ComputedFigure","edge":"VALIDATES","target":"Figure","props":{"ref_id":"3e97ceb0-36d6-4e5c-8480-6c2a8a800a61"}},{"source":"ComputedFigure","edge":"VALIDATES","target":"TabularReviewCell","props":{"ref_id":"f3499d0f-ca47-44e3-ab77-ffb0bcf9e8f6"}},{"source":"Concept","edge":"IN_REPO","target":"Repository","props":{"ref_id":"49bbf792-f9aa-434b-b2b2-fdf2bfa6f1d6"}},{"source":"Concept","edge":"MODIFIES","target":"File","props":{"importance":"?float","ref_id":"c70e1a56-381a-4a1a-b36e-6838c286bdf1"}},{"source":"Concept","edge":"PARENT_OF","target":"Concept","props":{"ref_id":"cb56c71e-190d-40a1-a553-7abfdb89ddb6","cardinality":"many"}},{"source":"ContractClause","edge":"CONFLICTS_WITH","target":"Regulation","props":{"ref_id":"a743e310-cdc7-400e-a5a2-1b156d46d2ae"}},{"source":"ContractClause","edge":"CONTRADICTS","target":"ContractClause","props":{"ref_id":"d7d565c8-f190-4be7-b95c-0a006495e9a7"}},{"source":"ContractClause","edge":"DEFINES","target":"DefinedTerm","props":{"ref_id":"1b439211-627c-4eac-aacc-87af66663d63"}},{"source":"ContractClause","edge":"DEVIATES_FROM","target":"PlaybookEntry","props":{"ref_id":"278df46c-8d46-450e-8f93-bf15ca760e69"}},{"source":"ContractClause","edge":"HAS_EXCERPT","target":"Excerpt","props":{"ref_id":"1cf871f9-9664-4e1c-80b4-a2c246f550f1"}},{"source":"ContractClause","edge":"HAS_GAP","target":"GapItem","props":{"ref_id":"07ffd9af-7fb0-49af-a160-fa9af03ca290"}},{"source":"ContractClause","edge":"HAS_TYPE","target":"ClauseType","props":{"ref_id":"7bb7e3ae-c7a4-4517-88b0-d900f4f500c5"}},{"source":"ContractClause","edge":"SUPERSEDES","target":"ContractClause","props":{"ref_id":"d93d2267-12a8-4895-8320-62d8eb3427f0"}},{"source":"Corporation","edge":"EVIDENCED_BY","target":"Excerpt","props":{"ref_id":"237c39b6-c8f4-4219-97e8-e47026abe771"}},{"source":"Corporation","edge":"GOVERNED_BY","target":"Regulation","props":{"ref_id":"75cd81c8-064a-4489-9e95-ac8f07302834"}},{"source":"Corporation","edge":"INVOLVED_IN","target":"TimelineEntry","props":{"ref_id":"d21fe49c-cbfd-4107-8beb-2a00e1a6e37e"}},{"source":"Corporation","edge":"OUTSIDE_COUNSEL","target":"Corporation","props":{"ref_id":"181e0874-7ac6-4629-9729-72e35f61830d"}},{"source":"Corporation","edge":"REFERENCED_IN","target":"Excerpt","props":{"ref_id":"0250cbf4-d420-4e63-8d84-5b4db937f5f5"}},{"source":"Corporation","edge":"TRUSTEE_OF","target":"Entity","props":{"ref_id":"7f31b1db-2cb3-4ee0-8dd0-b5a8b43ad32b"}},{"source":"Country","edge":"HAS_CAPITAL","target":"Location","props":{"volatility":"STABLE","confidence_score":"?float","fluent":true,"invalid_at":"?datetime","temporal":true,"valid_at":"?datetime","ref_id":"57cae04d-0a5d-4cd5-a7fb-8b24ba98e15a","last_confirmed_at":"?datetime","invalidated_by":"?string","expired_at":"?datetime","cardinality":"single"}},{"source":"CriterionResult","edge":"HAS","target":"Cause","props":{"ref_id":"91f207a0-1c99-4336-a71c-dccb616b05b4","cardinality":"many"}},{"source":"CriterionResult","edge":"HAS_PROPOSED_FIX","target":"ProposedFix","props":{"volatility":"EVOLVING","ref_id":"e722f757-07cf-4827-9b94-76a936ba01e5"}},{"source":"DSARRequest","edge":"SUBMITTED_BY","target":"Person","props":{"ref_id":"0f92bb3f-c906-46cf-ae34-7c3007f1c82c"}},{"source":"DSARRequest","edge":"SUBMITTED_TO","target":"Organization","props":{"ref_id":"0705993b-a2a4-4c04-859a-acb1a99554a6"}},{"source":"DataAnomalyRecord","edge":"FLAGS","target":"Concept","props":{"anomaly_reason":"?string","ref_id":"9cd73dd2-1383-4584-b164-660ef3e34c0b","severity":"?string","flag_category":"?string"}},{"source":"DataAnomalyRecord","edge":"FLAGS","target":"ContractClause","props":{"anomaly_reason":"?string","ref_id":"fd147673-4055-4cc2-9188-d2f6c0539cb0","severity":"?string","flag_category":"?string"}},{"source":"DataAnomalyRecord","edge":"FLAGS","target":"Document","props":{"anomaly_reason":"?string","ref_id":"3bf34751-cb6a-4cc8-a6e4-fb9f40507df2","severity":"?string","flag_category":"?string"}},{"source":"DataAnomalyRecord","edge":"FLAGS","target":"Excerpt","props":{"anomaly_reason":"?string","ref_id":"b547d12c-fe1e-4ff9-a769-8815b1244e32","severity":"?string","flag_category":"?string"}},{"source":"DataAnomalyRecord","edge":"FLAGS","target":"Figure","props":{"anomaly_reason":"?string","ref_id":"7eb2aaa0-387b-4795-a05e-a0e6bd8b10ff","severity":"?string","flag_category":"?string"}},{"source":"DataAnomalyRecord","edge":"FLAGS","target":"TimelineEntry","props":{"anomaly_reason":"?string","ref_id":"f4558b0d-6273-4174-8399-a123e75b5c4c","severity":"?string","flag_category":"?string"}},{"source":"Deadline","edge":"COINCIDES_WITH","target":"Deadline","props":{"ref_id":"837b3681-0064-423a-9455-959bd7a138f2","coincidence_date":"?string","note":"?string"}},{"source":"Deadline","edge":"CONTRADICTS","target":"Deadline","props":{"contradiction_type":"?string","ref_id":"0367da1f-512d-4193-89aa-c2dc71eb6f58","contradiction_reason":"?string"}},{"source":"DefinedTerm","edge":"CONFLICTS_WITH","target":"DefinedTerm","props":{"field_name":"?string","delta":"?string","ref_id":"020f1597-fe49-4cd6-a063-11b744beed25","doc_a_value":"?string","doc_b_value":"?string"}},{"source":"DefinedTerm","edge":"LOCATED_IN","target":"Place","props":{"ref_id":"a366664d-f122-419b-b7e6-9ea56041d78a"}},{"source":"DefinedTerm","edge":"RELATED_TO","target":"Lingo","props":{"ref_id":"aa96b836-7db6-42ec-8479-f5ca14e9e1e0"}},{"source":"DefinedTerm","edge":"USED_IN","target":"Agreement","props":{"ref_id":"4c86eaaa-3b80-44c4-86d2-d6767233fd6e"}},{"source":"DefinedTerm","edge":"USED_IN","target":"Document","props":{"ref_id":"5361a962-ef96-4f58-acae-3a1055008c33"}},{"source":"DeliverableSchema","edge":"APPLIES_TO","target":"Matter","props":{"ref_id":"34b5ccbb-e0d5-41e2-8258-ed10f291403b"}},{"source":"DiligenceIssue","edge":"BLOCKS","target":"Deadline","props":{"ref_id":"ffb0007a-2e65-408d-8ee5-fedd7e67b848"}},{"source":"DiligenceIssue","edge":"EVIDENCED_BY","target":"Figure","props":{"ref_id":"a7cd9801-c826-459c-bb91-a195a2a26ed6"}},{"source":"DiligenceIssue","edge":"TRIGGERED_BY","target":"RegulatoryItem","props":{"ref_id":"a717795f-22c6-42bc-8930-d7e7a4f211cf"}},{"source":"Directory","edge":"CONTAINS","target":"File","props":{"ref_id":"2e39bb19-4cb3-4097-805c-53cd4c4149d4"}},{"source":"Doctrine","edge":"APPLIES_IN","target":"Jurisdiction","props":{"ref_id":"30fff9b4-5b30-4a82-b912-5d37fbe75bd5"}},{"source":"Doctrine","edge":"GOVERNS","target":"ClauseType","props":{"ref_id":"254fc04a-5f6d-41ff-a805-d67fa14ecf86"}},{"source":"Document","edge":"AMENDS","target":"Document","props":{"ref_id":"2acbbd4b-99d3-4eee-bd1c-1e61f890bd31"}},{"source":"Document","edge":"DEFINES","target":"DefinedTerm","props":{"ref_id":"dd5a9ba9-3cf7-459c-938a-4be6f1f1b9b8"}},{"source":"Document","edge":"HAS","target":"Section","props":{"ref_id":"36c4ba60-2141-40bf-9b4c-525bb347342e"}},{"source":"Document","edge":"HAS_COMPONENT","target":"FormulaComponent","props":{"ref_id":"47adeda8-5fc9-4b8e-9fd8-8111741de995"}},{"source":"Document","edge":"SUPPLEMENTS","target":"Document","props":{"ref_id":"8f4ad736-5252-451d-8a39-d7b5b9549f61"}},{"source":"E2etest","edge":"CALLS","target":"Function","props":{"ref_id":"ba574e17-d3a6-45fe-8fd4-6661d96733e5","call_start":"?int","call_end":"?int","operand":"?string"}},{"source":"Email","edge":"HAS","target":"Section","props":{"ref_id":"1decf156-eae4-4388-bdc4-346305208676"}},{"source":"Email","edge":"HAS_ATTACHMENT","target":"Attachment","props":{"ref_id":"62b2d6ff-a953-4cbc-845a-3d6ca0acae03"}},{"source":"Email","edge":"HAS_INVITE","target":"EmailInvite","props":{"ref_id":"ff8dddb5-eeae-448b-ac6c-f6b685f0cba6"}},{"source":"Email","edge":"PART_OF_THREAD","target":"Email","props":{"ref_id":"2b17d074-3ef8-4c8c-8183-fe0e1079fd96"}},{"source":"Email","edge":"REPLY_TO","target":"Email","props":{"ref_id":"2a3cfba7-271d-4d2c-9abf-d1543f82735d"}},{"source":"EmailInvite","edge":"LOCATED_AT","target":"Location","props":{"ref_id":"57473a78-fe24-46e0-bba4-076f650d56cf"}},{"source":"EmailInvite","edge":"RELATED_TO","target":"Event","props":{"ref_id":"bee56d0e-7682-4123-bc8a-6854b0960f57"}},{"source":"Endpoint","edge":"CALLS","target":"Function","props":{"ref_id":"15e1e05e-0651-4555-b1ab-ea5818b134f9"}},{"source":"Endpoint","edge":"HANDLER","target":"Function","props":{"ref_id":"36cc8137-09cf-4d2e-a08c-37e9767c8528"}},{"source":"Entity","edge":"INVOLVED_IN","target":"TimelineEntry","props":{"ref_id":"500aa8a8-e962-45b1-a9cc-31cba87b0b38"}},{"source":"Entity","edge":"REFERENCED_IN","target":"Excerpt","props":{"ref_id":"4cda2746-4f89-466f-8e55-87f9d8e5c31c"}},{"source":"Episode","edge":"HAS","target":"Chapter","props":{"ref_id":"23551de1-77ab-4c95-9423-221ef6089ae2"}},{"source":"Episode","edge":"HAS","target":"Clip","props":{"ref_id":"6bf30640-6a6c-42b4-9daf-a15ff1f699f1"}},{"source":"Episode","edge":"HAS","target":"Podcast","props":{"ref_id":"5143a0cc-5f02-4997-a545-31d90084a3c6"}},{"source":"Episode","edge":"HAS","target":"Video","props":{"ref_id":"5403cdc2-fcc6-4f64-90e5-1d483e98bda1"}},{"source":"Episode","edge":"MENTIONS","target":"Organization","props":{"ref_id":"963ee4c6-64e9-4280-a2a0-d3d788dfc44d"}},{"source":"Episode","edge":"MENTIONS","target":"Place","props":{"ref_id":"2f63340a-b40f-4531-a958-2faeb7f728d1"}},{"source":"Episode","edge":"MENTIONS","target":"Product","props":{"ref_id":"afb13bed-4415-48e1-908f-374fa3b2c36a"}},{"source":"Episode","edge":"MENTIONS","target":"Topic","props":{"ref_id":"58d4d5dd-c492-488f-9917-2fbada672f7f"}},{"source":"ErrorIssue","edge":"REFERENCES","target":"File","props":{"ref_id":"52eec5f9-8d1b-498b-aaf9-f1f9f81b7f37"}},{"source":"ErrorIssue","edge":"REFERENCES","target":"Function","props":{"ref_id":"05f550a4-f31b-4b9b-bfa1-8e6161b64cbc"}},{"source":"EscalationRecord","edge":"GOVERNED_BY","target":"Doctrine","props":{"ref_id":"87e22c36-e8b8-4e72-bf10-7195c7048e65"}},{"source":"EscalationRecord","edge":"TRIGGERED_BY","target":"LegalArgument","props":{"ref_id":"1b3f5dbd-648b-4d37-a16d-b6bae7c93887"}},{"source":"EvalRequirement","edge":"HAS_CRITERION_RESULT","target":"CriterionResult","props":{"ref_id":"d4606913-b5d1-4720-997e-90fa6079db85"}},{"source":"EvalRequirement","edge":"HAS_TRIGGER","target":"EvalTrigger","props":{"ref_id":"8cb0ac92-848e-4ae4-8105-28c637825619"}},{"source":"EvalSet","edge":"HAS_BASELINE_TRIGGER","target":"EvalTrigger","props":{"ref_id":"11a40913-f560-4c34-8137-049e0f7f19a4"}},{"source":"EvalSet","edge":"HAS_REQUIREMENT","target":"EvalRequirement","props":{"order":"?int","ref_id":"42fec7d0-4767-4868-81ca-dd09f634ebd7"}},{"source":"EvalSet","edge":"HAS_SUBSET","target":"EvalSet","props":{"ref_id":"d75d1988-b70a-4886-84ea-0caa440e80ac"}},{"source":"EvalSet","edge":"HAS_TRIGGER","target":"EvalTrigger","props":{"ref_id":"5d596d4a-d950-4486-be23-1e15997c4602"}},{"source":"EvalTrigger","edge":"ATTRIBUTED_TO","target":"HiveAgent","props":{"ref_id":"d6dea5d2-195e-4e93-9e30-a9ede0b18a4a"}},{"source":"EvalTrigger","edge":"EVALUATED","target":"AgentSession","props":{"ref_id":"536274c5-116b-45c4-bb6b-0a1b56a0308e"}},{"source":"EvalTrigger","edge":"HAS_OUTPUT","target":"EvalTriggerOutput","props":{"ref_id":"4f0bca60-7cdc-474e-b019-a71bc17723a8"}},{"source":"EvalTrigger","edge":"HAS_PROPOSED_FIX","target":"ProposedFix","props":{"volatility":"EVOLVING","ref_id":"bfc07a6e-9ced-4464-8dca-c6c6fbe1b7a6"}},{"source":"EvalTriggerOutput","edge":"ATTRIBUTED_TO","target":"BenchmarkFailureCause","props":{"ref_id":"865b439f-7a77-4bd3-a166-05e3e3953e2c"}},{"source":"EvalTriggerOutput","edge":"HAS_CRITERION_RESULT","target":"CriterionResult","props":{"ref_id":"03a5ea7c-ee89-4f7c-b355-3cc63965fdfb"}},{"source":"Evidence","edge":"ABOUT","target":"Thing","props":{"ref_id":"b19e33bc-a342-4b34-afb0-e697a5838ecb"}},{"source":"Evidence","edge":"HAS_SOURCE","target":"Thing","props":{"end_time":"?float","post_url":"?string","context":"?string","ref_id":"e71e06da-d9a2-4553-8204-393336eadcb8","start_time":"?float","created_at":"?datetime","message_id":"?string","page_reference":"?string","authority_level":"?string"}},{"source":"Evidence","edge":"PRODUCED_BY","target":"Check","props":{"ref_id":"52a15d77-15d6-46d6-967d-7e39102e7bd9"}},{"source":"Excerpt","edge":"CONFLICTS_WITH","target":"Excerpt","props":{"ref_id":"45cdf025-e5d9-4697-8916-80f9467d03c5"}},{"source":"Excerpt","edge":"DESCRIBES","target":"Agreement","props":{"ref_id":"2b64e4e8-4cc9-4873-862f-0e448671fc7f"}},{"source":"Excerpt","edge":"DESCRIBES","target":"Corporation","props":{"ref_id":"070b5aa9-4f49-4072-8922-87b61f6e63a3"}},{"source":"Excerpt","edge":"DESCRIBES","target":"Organization","props":{"ref_id":"e39bddf1-29fb-4865-b1ce-599c142b8da6"}},{"source":"Excerpt","edge":"EVIDENCED_BY","target":"LegalArgument","props":{"ref_id":"67dd377d-1bb3-4020-9a12-bd7a4eccf5ce"}},{"source":"Excerpt","edge":"REFERENCED_IN","target":"Person","props":{"ref_id":"25b8f668-13a9-40b5-aceb-2ea30a6696df"}},{"source":"Feature","edge":"MODIFIES","target":"File","props":{"importance":"?float","ref_id":"c249176d-0d55-4623-9750-3742fa67c7bf"}},{"source":"Figure","edge":"APPLIED_TO","target":"Matter","props":{"ref_id":"69511a87-2d74-4b62-962f-b87911f8a839"}},{"source":"Figure","edge":"CONFLICTS_WITH","target":"Figure","props":{"field_name":"?string","delta":"?string","ref_id":"8bc3847c-a077-46f8-9e02-e3bb44cf204e","doc_a_value":"?string","doc_b_value":"?string"}},{"source":"Figure","edge":"DERIVED_FROM","target":"Figure","props":{"ref_id":"9fb43204-5e27-4d98-96dd-61cef31b1d74"}},{"source":"Figure","edge":"DESCRIBES","target":"Organization","props":{"ref_id":"8a2b54fb-1f75-4090-bc65-4e33e3d468fc"}},{"source":"Figure","edge":"EXTRACTED_FROM","target":"Document","props":{"ref_id":"ad6790ce-c807-4f87-a3ef-30d64de1050a"}},{"source":"Figure","edge":"EXTRACTED_FROM","target":"Excerpt","props":{"ref_id":"a164bdc3-73a1-414e-8f56-9171173097ed"}},{"source":"Figure","edge":"EXTRACTED_FROM","target":"Section","props":{"ref_id":"da9dd4a0-36a0-41a2-8452-0e111ac18858"}},{"source":"Figure","edge":"GOVERNED_BY","target":"RegulatoryItem","props":{"ref_id":"e87d8393-b9b4-4b7b-bb7e-ef55cb8c7650"}},{"source":"Figure","edge":"QUANTIFIES","target":"PlaybookEntry","props":{"field_name":"?string","value_as_stated":"?string","ref_id":"1aca7996-efdb-4e37-8249-9371a3ee9bbf","notes":"?string"}},{"source":"Figure","edge":"QUANTIFIES","target":"Product","props":{"field_name":"?string","value_as_stated":"?string","ref_id":"e64e4f2a-9517-4569-bbed-03d6738c0f2d","notes":"?string"}},{"source":"File","edge":"CONTAINS","target":"Function","props":{"ref_id":"ef261cb7-ed12-4a93-b3d5-8730928cc908"}},{"source":"File","edge":"CONTAINS","target":"Trait","props":{"ref_id":"1bbab2ab-d8a0-4578-acd3-5795adc5f56f"}},{"source":"File","edge":"CONTAINS","target":"Var","props":{"ref_id":"35c38374-467e-4bce-8615-cb7631e34301"}},{"source":"File","edge":"IMPORTS","target":"File","props":{"ref_id":"581d4393-f5be-4136-9fb8-f0f18acc283e"}},{"source":"File","edge":"IMPORTS","target":"Library","props":{"ref_id":"d861dad0-7e9e-4fbd-8804-12536f8c5f5e"}},{"source":"Fluent","edge":"CURRENT_VALUE","target":"Thing","props":{"volatility":"EVOLVING","ref_id":"f149065f-0bc3-418b-87b6-881a6b185e30","cardinality":"single"}},{"source":"Fluent","edge":"HAS_EVENT","target":"FluentEvent","props":{"volatility":"STATIC","ref_id":"f3b10977-276d-43b6-9c53-f6cb5e4894e0","cardinality":"many"}},{"source":"FormulaComponent","edge":"DERIVED_FROM","target":"Figure","props":{"ref_id":"822fa443-6f83-410b-9507-363fad811dc6"}},{"source":"Function","edge":"CALLS","target":"Function","props":{"ref_id":"f221be8f-3833-4585-813e-52be78b8553f","call_start":"?int","call_end":"?int","operand":"?string"}},{"source":"Function","edge":"CONTAINS","target":"Datamodel","props":{"ref_id":"63cf80fa-6b21-4815-b962-f88767084250"}},{"source":"Function","edge":"CONTAINS","target":"Var","props":{"ref_id":"88155f12-bda8-4fa2-bc14-07b337fcb014"}},{"source":"Function","edge":"USES","target":"Function","props":{"ref_id":"8ced93d6-608a-43d8-9553-1b45c290396a","call_start":"?int","call_end":"?int","operand":"?string"}},{"source":"GapItem","edge":"BLOCKS","target":"AISystem","props":{"ref_id":"cbe92d6a-6c29-4205-9743-3504b8b29878"}},{"source":"GapItem","edge":"FLAGS","target":"Excerpt","props":{"undefined_term":"?string","ref_id":"566ad0c2-e819-476b-88cb-5ce7680c5f86","flag_category":"?string","gap_reason":"?string"}},{"source":"GapItem","edge":"GOVERNED_BY","target":"Regulation","props":{"ref_id":"5318adde-4c7e-4ef5-9041-6b52ada1896a"}},{"source":"GapItem","edge":"PROMPTED","target":"CommentPeriod","props":{"ref_id":"f6e07928-da14-48ec-8f1f-413c0dfbb148"}},{"source":"Generated_step","edge":"NEXT","target":"Generated_step","props":{"ref_id":"032251fd-81a6-4dc0-941a-ce5f7ac49c8c"}},{"source":"GitHubRepo","edge":"HAS","target":"Commits","props":{"ref_id":"976f4f49-aca0-4000-85f4-0906dc7bb39d"}},{"source":"GitHubRepo","edge":"HAS","target":"Issues","props":{"ref_id":"d9962b0d-7863-4d80-8f1d-386c9c5e3d62"}},{"source":"HiveAgent","edge":"HAS_PROMPT","target":"Prompt","props":{"ref_id":"a32530af-3f0e-48ff-8b80-b263ab2ed83f"}},{"source":"HiveFeature","edge":"HAS_MESSAGE","target":"HiveChatMessage","props":{"ref_id":"894aa11c-2e9e-4f7b-a9a8-c4dc65582eb6"}},{"source":"HiveFeature","edge":"HAS_TASK","target":"HiveTask","props":{"ref_id":"7b2e883c-ab57-4239-9994-5976d413ed8d"}},{"source":"HiveInitiative","edge":"HAS_MILESTONE","target":"HiveMilestone","props":{"ref_id":"32ae8f02-5fae-4bfc-9faa-c93a83bb2f02"}},{"source":"HiveInitiative","edge":"HAS_RESEARCH","target":"HiveResearch","props":{"ref_id":"5f04cef4-9209-4ac7-af09-b22c0e8e7b67"}},{"source":"HiveMilestone","edge":"HAS_RESEARCH","target":"HiveResearch","props":{"ref_id":"81453783-6945-4407-8f66-8d97c00f2d48"}},{"source":"HiveTask","edge":"HAS_MESSAGE","target":"HiveChatMessage","props":{"ref_id":"5073c5ec-e2ec-4f45-8f2c-778e46edbf98"}},{"source":"HiveTask","edge":"RESULTED_IN","target":"PullRequest","props":{"ref_id":"b1602bd9-84ca-4789-b2e9-a29e8fa3adf0"}},{"source":"HiveWorkspace","edge":"BEST_PRACTICE","target":"Concept","props":{"ref_id":"cbdeefa9-896a-44d4-9d7d-277c832d9f25"}},{"source":"HiveWorkspace","edge":"GOTCHA","target":"Concept","props":{"ref_id":"39fbd7fc-75bf-4a16-b11a-907f0a4688c6"}},{"source":"HiveWorkspace","edge":"HAS_CONCEPT","target":"Concept","props":{"ref_id":"cac9c2ea-1aec-4745-9895-a28d4faf9246"}},{"source":"HiveWorkspace","edge":"HAS_MEMBER","target":"HiveWorkspaceMember","props":{"ref_id":"0d55155b-a081-4b67-b75b-c444278ad2b4"}},{"source":"HiveWorkspace","edge":"PREFERENCE","target":"Concept","props":{"ref_id":"53fd6375-0d2d-4b73-808f-6825c6c15b2e"}},{"source":"HiveWorkspace","edge":"PROCESS","target":"Concept","props":{"ref_id":"31e7b53b-aaf7-4aa7-b723-5df7b4eaa1ab"}},{"source":"HiveWorkspaceMember","edge":"APPROVED","target":"Concept","props":{"ref_id":"d741793f-f43b-4d3f-ab33-f37dfc899148"}},{"source":"HiveWorkspaceMember","edge":"PREFERENCE","target":"Concept","props":{"ref_id":"03714449-6c25-4410-aca7-eddb21ed6d4e"}},{"source":"IPAsset","edge":"HAS_DEADLINE","target":"Deadline","props":{"ref_id":"434d38a0-3208-4afa-90cb-dcd766158ed9"}},{"source":"IPAsset","edge":"LICENSED_UNDER","target":"ContractClause","props":{"ref_id":"785487da-5911-4dc7-b0cc-ec1da1b2f8cc"}},{"source":"IPAsset","edge":"REGISTERED_IN","target":"Jurisdiction","props":{"filing_status":"?string","ref_id":"46398383-d39b-428a-8995-1b4d0638227a","filing_date":"?string","application_number":"?string"}},{"source":"IPAsset","edge":"RENEWAL_TRACKED_BY","target":"RenewalEntry","props":{"ref_id":"054b4fef-773f-46e7-abec-be3391a6f2d0"}},{"source":"IPAsset","edge":"SUPPORTED_BY","target":"Excerpt","props":{"support_type":"?string","ref_id":"8dc2e601-e309-45b0-b4f6-7957ed2dbd4b","support_reason":"?string"}},{"source":"Import","edge":"IMPORTS","target":"Class","props":{"ref_id":"462dc055-f4a7-402a-9ab4-4fa304ad802c"}},{"source":"Import","edge":"IMPORTS","target":"Datamodel","props":{"ref_id":"de64d06b-9a17-47c0-8953-7c371e54df31"}},{"source":"Import","edge":"IMPORTS","target":"Function","props":{"ref_id":"4e3203d0-3c85-449a-9a43-321013103f15"}},{"source":"Instance","edge":"OF","target":"Class","props":{"ref_id":"745d6921-045e-4e55-a56b-35030f84cfb1","call_start":"?int","call_end":"?int","operand":"?string"}},{"source":"IntegrationTest","edge":"CALLS","target":"Endpoint","props":{"ref_id":"df5b3667-bb00-4ed3-bd8e-607243e8f89e","call_start":"?int","call_end":"?int","operand":"?string"}},{"source":"IntegrationTest","edge":"CALLS","target":"Function","props":{"ref_id":"8a2a316f-e425-489b-b981-8090204ba1c7","call_start":"?int","call_end":"?int","operand":"?string"}},{"source":"Jargon","edge":"DEFINES","target":"Organization","props":{"ref_id":"83728110-7775-45e5-b084-b4a6afa316d6"}},{"source":"Jargon","edge":"DEFINES","target":"Person","props":{"ref_id":"2b1b2e2a-7369-4e60-98bc-87a6d286e0db"}},{"source":"Jargon","edge":"DEFINES","target":"Thing","props":{"ref_id":"24d9b6ab-4346-4bae-9e7d-8f29f15534ae"}},{"source":"Jargon","edge":"DEFINES","target":"Topic","props":{"ref_id":"a8f2d745-11df-4a77-9842-5ad6348ac41d"}},{"source":"Jurisdiction","edge":"PART_OF","target":"Jurisdiction","props":{"ref_id":"4cd96c6b-674f-46f4-b4f7-d61a982226b7"}},{"source":"LeaseAgreement","edge":"HAS_CLAUSE","target":"ContractClause","props":{"ref_id":"6ebb738a-a825-47c9-9b37-ab053de9bfc2"}},{"source":"LegalArgument","edge":"APPLIES_IN","target":"Jurisdiction","props":{"ref_id":"b233c7a1-7a00-4972-a02c-80b90b9e508f"}},{"source":"LegalArgument","edge":"APPLIES_TO","target":"Matter","props":{"ref_id":"1aaf8e7e-0d48-4cf9-8ad0-caae96a0727c"}},{"source":"LegalArgument","edge":"BLOCKS","target":"Deadline","props":{"ref_id":"4309fdc8-da66-4f5b-9294-7f73d72e9929"}},{"source":"LegalArgument","edge":"CONTRADICTS","target":"LegalArgument","props":{"ref_id":"1cfb7e8a-37bb-4870-9149-6504b74a1dff"}},{"source":"LegalArgument","edge":"GROUNDED_IN","target":"Doctrine","props":{"ref_id":"3e79fd6c-f6fd-45f2-95fc-68e71c915829"}},{"source":"LegalArgument","edge":"REFERENCES_DATE","target":"Deadline","props":{"ref_id":"f459b3a8-67fc-4fe5-ac69-7c29ba45cef5"}},{"source":"LegalArgument","edge":"SUPPORTED_BY","target":"Excerpt","props":{"ref_id":"27fba9fc-78b6-467e-8071-189d38d514fc"}},{"source":"LegalArgument","edge":"SUPPORTED_BY","target":"FormulaComponent","props":{"support_type":"?string","ref_id":"4ceb522f-0934-49fb-bd4f-788ad7dce399","support_reason":"?string"}},{"source":"LegalArgument","edge":"SUPPORTED_BY","target":"LegalArgument","props":{"ref_id":"e885870c-a2ec-4f99-a4b3-b6ed12d27163"}},{"source":"LegalArgument","edge":"SUPPORTED_BY","target":"TimelineEntry","props":{"support_type":"?string","ref_id":"8d0e9511-1a0e-4091-840a-ca8e065d97bf","support_reason":"?string"}},{"source":"LegalHold","edge":"IS_CUSTODIAN","target":"Person","props":{"ref_id":"b50c7e74-71b5-4794-8b6c-1d98a9f720fa"}},{"source":"LegalParty","edge":"REPRESENTS_ORG","target":"Organization","props":{"ref_id":"55e3c758-ca01-4c40-a33e-2fcee51e5e2d"}},{"source":"LegalParty","edge":"REPRESENTS_PERSON","target":"Person","props":{"ref_id":"30d73f9b-2b77-4cdc-b65b-a7915d767bd0"}},{"source":"LimitationStatute","edge":"APPLIES_IN","target":"Jurisdiction","props":{"ref_id":"48bb5691-f214-4a5c-bf89-98b867d6f887"}},{"source":"Lingo","edge":"RELATED_TO","target":"Lingo","props":{"ref_id":"8b0603f3-5522-40f4-9376-7ed69569cc2a"}},{"source":"Location","edge":"HAS_WEATHER","target":"Thing","props":{"volatility":"VOLATILE","confidence_score":"?float","invalid_at":"?datetime","temporal":true,"valid_at":"?datetime","ref_id":"41f7b326-4862-4856-81ff-106586cbe0ec","last_confirmed_at":"?datetime","invalidated_by":"?string","expired_at":"?datetime","cardinality":"single"}},{"source":"Location","edge":"MENTIONED_IN","target":"Section","props":{"ref_id":"87bba499-48ff-4a11-8e00-f9cc4d321d9b"}},{"source":"Matter","edge":"ASSIGNED_TO","target":"Person","props":{"ref_id":"0dd0bbae-c1a1-482b-ae3c-395ebba2dc80"}},{"source":"Matter","edge":"CONCERNS","target":"IPAsset","props":{"ref_id":"f0261684-1775-4a9c-9bfc-3c3d422dcca8"}},{"source":"Matter","edge":"CONTAINS_REQUEST","target":"DDRequestItem","props":{"ref_id":"520aeb11-8824-4f1f-bd41-2ab222d3929f"}},{"source":"Matter","edge":"FILED_IN","target":"Jurisdiction","props":{"ref_id":"d5a4e919-3eab-4753-84b8-559d35118c99"}},{"source":"Matter","edge":"HAS_ARGUMENT","target":"LegalArgument","props":{"ref_id":"07736aea-a61d-448b-b6ac-5f4275fcddf6"}},{"source":"Matter","edge":"HAS_CONFLICT_CHECK","target":"ConflictCheck","props":{"ref_id":"cc7343c4-659c-4021-becf-ef0d84c709de"}},{"source":"Matter","edge":"HAS_DEADLINE","target":"Deadline","props":{"ref_id":"d9781ea8-2f36-4621-8c93-4625aa2db362"}},{"source":"Matter","edge":"HAS_DILIGENCE_ISSUE","target":"DiligenceIssue","props":{"ref_id":"f85ab362-b75a-48a9-9b1f-a98b190d418a"}},{"source":"Matter","edge":"HAS_ESCALATION","target":"EscalationRecord","props":{"ref_id":"21158a8c-59cb-4f05-9556-45b2efe11d4e"}},{"source":"Matter","edge":"HAS_INVESTIGATION","target":"InvestigationLog","props":{"ref_id":"9dfb693a-e7b3-433f-8535-1a207be3d09a"}},{"source":"Matter","edge":"HAS_LEGAL_HOLD","target":"LegalHold","props":{"ref_id":"c3174343-8f92-4dd7-9b96-0f4e7a8e1cac"}},{"source":"Matter","edge":"HAS_PARTY","target":"LegalParty","props":{"ref_id":"9ad28e08-adfd-4236-817a-fb42ebf93670"}},{"source":"Matter","edge":"HAS_TIMELINE_ENTRY","target":"TimelineEntry","props":{"volatility":"STABLE","confidence_score":"?float","invalid_at":"?datetime","temporal":true,"valid_at":"?datetime","ref_id":"1c0521db-37e5-430e-bb13-700bdca2ab84","last_confirmed_at":"?datetime","invalidated_by":"?string","expired_at":"?datetime"}},{"source":"Matter","edge":"INVOLVES_PARTY","target":"Organization","props":{"ref_id":"bef4c280-0d8a-49ef-96de-08218024d580"}},{"source":"Matter","edge":"OUTSIDE_COUNSEL","target":"Organization","props":{"ref_id":"2a7381bf-cb01-4b62-843a-a933f5b378f8"}},{"source":"Message","edge":"RELATED_TO","target":"Topic","props":{"ref_id":"c7271484-894a-4b91-8610-7211fb92f833"}},{"source":"Organization","edge":"BACKED_BY","target":"Organization","props":{"ref_id":"563e643a-8d43-4795-9e09-9ab6ea2a0a8c"}},{"source":"Organization","edge":"CONDUCTS","target":"ProcessingActivity","props":{"ref_id":"124a65f7-a774-484c-ba42-3efd839cfe4a"}},{"source":"Organization","edge":"CONFLICTS_WITH","target":"Organization","props":{"doc_b_name":"?string","entity_reference":"?string","doc_a_source":"?string","ref_id":"9d851420-5a01-451e-ad2e-0eea97c77e64","doc_b_source":"?string","conflict_type":"?string","doc_a_name":"?string"}},{"source":"Organization","edge":"FINANCES","target":"Organization","props":{"amount":"?string","financing_type":"?string","ref_id":"46681ac2-7e56-4756-804d-5d12ea37e4b3"}},{"source":"Organization","edge":"HAS","target":"Repository","props":{"ref_id":"a3c4cf30-a912-405b-9d3b-510dc958a64d"}},{"source":"Organization","edge":"HAS_JURISDICTION","target":"Jurisdiction","props":{"ref_id":"97e6147d-9ab7-4477-be9a-a64b8e99cfb2"}},{"source":"Organization","edge":"HAS_OFFICE_IN","target":"Place","props":{"ref_id":"7bb26425-ba31-444e-ad2d-8294b4618ef8"}},{"source":"Organization","edge":"HOLDS_SHARES_IN","target":"Corporation","props":{"ref_id":"6c723ae8-e641-4038-8daa-b716e2723d8d"}},{"source":"Organization","edge":"IDENTIFIED_AS","target":"TwitterAccount","props":{"ref_id":"ebc97663-4168-46b4-bf7d-e8052d168767"}},{"source":"Organization","edge":"INCORPORATED_IN","target":"Country","props":{"ref_id":"89052d86-ed5f-4a4c-8cf2-41ceba749bc2"}},{"source":"Organization","edge":"IS_PARTY_TO","target":"Agreement","props":{"ref_id":"ae9c5bbc-fbbc-4d26-9c23-e05a66e26941"}},{"source":"Organization","edge":"IS_PARTY_TO","target":"LeaseAgreement","props":{"ref_id":"838e5d51-5375-4ace-bd78-8dadc15f1a9c"}},{"source":"Organization","edge":"MENTIONED_IN","target":"Agreement","props":{"ref_id":"6368bed1-66bc-47ec-aa47-da060017e386"}},{"source":"Organization","edge":"MENTIONED_IN","target":"Section","props":{"ref_id":"ca372235-3bcd-43a4-98e2-e34c995a1ade"}},{"source":"Organization","edge":"NOMINEE_FOR","target":"Person","props":{"ref_id":"ad98ad97-4e3a-4db4-a7e9-441ad7aa2fde"}},{"source":"Organization","edge":"OPERATES","target":"AISystem","props":{"ref_id":"b614da8e-be3f-4d67-93d4-c6d215862709"}},{"source":"Organization","edge":"OWNS","target":"IPAsset","props":{"ref_id":"e4d52a6d-1bdd-43bf-a710-30311327129d"}},{"source":"Organization","edge":"REGISTERED_AGENT_OF","target":"Corporation","props":{"ref_id":"93a73a1d-81df-41b0-a808-b78c162e9a2f"}},{"source":"Page","edge":"RENDERS","target":"Function","props":{"ref_id":"86016133-64c8-47ba-9466-487edc177e8e"}},{"source":"Person","edge":"ACCEPTED","target":"EmailInvite","props":{"ref_id":"0cc03b61-a81b-47da-9352-7d0c5bb17751"}},{"source":"Person","edge":"AUTHORED_BY","target":"Document","props":{"ref_id":"1c7e5314-f352-4af2-a687-642e9ce1e7eb"}},{"source":"Person","edge":"BELIEVES","target":"Belief","props":{"ref_id":"0a675e4c-22b7-4f39-adcf-8083ac9f2eaf"}},{"source":"Person","edge":"BENEFICIAL_OWNER_OF","target":"Corporation","props":{"ref_id":"52e0beca-7782-4fdb-8249-8a8560e40a14"}},{"source":"Person","edge":"BORN_ON","target":"Thing","props":{"volatility":"STATIC","confidence_score":"?float","invalid_at":"?datetime","temporal":true,"valid_at":"?datetime","ref_id":"01146b8d-6fba-4568-b44f-fc00c7b50d85","last_confirmed_at":"?datetime","invalidated_by":"?string","expired_at":"?datetime","cardinality":"single"}},{"source":"Person","edge":"CC_ON","target":"Email","props":{"ref_id":"b6178c78-7f1e-45dd-8473-17cee3e78b9e"}},{"source":"Person","edge":"COMPLAINANT_IN","target":"InvestigationLog","props":{"ref_id":"74fd1460-060c-4336-89c9-c4588e56f0a3"}},{"source":"Person","edge":"CONFLICTS_WITH","target":"Person","props":{"doc_b_name":"?string","entity_reference":"?string","doc_a_source":"?string","ref_id":"7580ca16-6934-49d4-88ab-d3fdecca1e64","doc_b_source":"?string","conflict_type":"?string","doc_a_name":"?string"}},{"source":"Person","edge":"DECLINED","target":"EmailInvite","props":{"ref_id":"43fc6f77-fe05-43dc-9182-1d5ae205eca4"}},{"source":"Person","edge":"DIRECTOR_OF","target":"Corporation","props":{"ref_id":"7f35c801-ef6a-48ef-86e6-6e70dfb80094"}},{"source":"Person","edge":"EMPLOYED_BY","target":"Organization","props":{"volatility":"EVOLVING","confidence_score":"?float","invalid_at":"?datetime","temporal":true,"valid_at":"?datetime","ref_id":"808bcf4e-fbc9-412a-9581-9e7c835c7c22","last_confirmed_at":"?datetime","invalidated_by":"?string","expired_at":"?datetime"}},{"source":"Person","edge":"HAS_JURISDICTION","target":"Country","props":{"ref_id":"db515035-9bf3-416c-a1c7-2e21237b16d2"}},{"source":"Person","edge":"HOLDS_SHARES_IN","target":"Corporation","props":{"ref_id":"99827a3d-8207-4356-a959-f3eb1de30688"}},{"source":"Person","edge":"IDENTIFIED_AS","target":"TwitterAccount","props":{"ref_id":"decff953-2493-47aa-ba00-9ca9f38fc42e"}},{"source":"Person","edge":"INVENTED","target":"IPAsset","props":{"ref_id":"3b40b8ca-95ce-4e56-ab28-7ff303026f3a"}},{"source":"Person","edge":"INVITED_TO","target":"EmailInvite","props":{"ref_id":"444810bf-5a78-4d9b-8838-0d7c35fff09b"}},{"source":"Person","edge":"INVOLVED_IN","target":"TimelineEntry","props":{"ref_id":"b5ee66fc-cba4-4cf0-9622-01624f90166e"}},{"source":"Person","edge":"IS_GUEST","target":"Episode","props":{"ref_id":"fd4766a0-082e-4ca5-8a0b-c358a1335257"}},{"source":"Person","edge":"IS_HOST","target":"Episode","props":{"ref_id":"26e7be2d-18de-4cda-ba46-53d8a173de05"}},{"source":"Person","edge":"IS_PARTY_TO","target":"Agreement","props":{"ref_id":"edab5904-037a-4c65-97a8-cb5993c7fe54"}},{"source":"Person","edge":"IS_SPEAKER","target":"Episode","props":{"ref_id":"305b9541-0006-4075-9e88-fd711f4d1671"}},{"source":"Person","edge":"MADE_CLAIM","target":"Claim","props":{"ref_id":"e509bd4e-c33e-472e-a734-fcc42774869f"}},{"source":"Person","edge":"MENTIONED","target":"Episode","props":{"ref_id":"2040360d-78f9-405e-ae86-980042d3f7f9"}},{"source":"Person","edge":"MENTIONED_IN","target":"Agreement","props":{"ref_id":"5ab5df36-8151-403a-9829-08872d45df5d"}},{"source":"Person","edge":"MENTIONED_IN","target":"Section","props":{"ref_id":"5457a4f7-b2b5-45db-b785-60aadb693c74"}},{"source":"Person","edge":"OFFICER_OF","target":"Corporation","props":{"ref_id":"ff4fa570-ee51-456c-a508-66851e9d1b97"}},{"source":"Person","edge":"ORGANIZED","target":"EmailInvite","props":{"ref_id":"bb8820bc-9214-411c-b7b9-e2dfd0c73574"}},{"source":"Person","edge":"POSTED","target":"Tweet","props":{"ref_id":"9c86a75f-bf88-4aa6-bd7f-ba94111af71f"}},{"source":"Person","edge":"RECEIVED","target":"Email","props":{"ref_id":"24a6afbc-535e-4f75-94ee-77dc9c3d3884"}},{"source":"Person","edge":"REFERENCED_IN","target":"Excerpt","props":{"ref_id":"0798600b-1540-4324-8e26-626279598035"}},{"source":"Person","edge":"RESPONDENT_IN","target":"InvestigationLog","props":{"ref_id":"e7f7a0da-fdc7-4d8d-ba71-f48301659749"}},{"source":"Person","edge":"SAME_AS","target":"Person","props":{"basis":"?string","doc_b_name":"?string","ref_id":"9d91368d-1b03-49f0-85b1-00c8cc6676a4","doc_a_name":"?string"}},{"source":"Person","edge":"SENT","target":"Email","props":{"ref_id":"a9e89780-2acb-4e63-a9af-d0f898798fac"}},{"source":"Person","edge":"SENT","target":"Message","props":{"ref_id":"47592886-1f38-443a-b653-2b544a8e5a31"}},{"source":"Person","edge":"TENTATIVE","target":"EmailInvite","props":{"ref_id":"54c96cfa-24e3-4cd8-bc16-e990284220e9"}},{"source":"Person","edge":"WORKS_AT","target":"Organization","props":{"volatility":"EVOLVING","confidence_score":"?float","fluent":true,"invalid_at":"?datetime","temporal":true,"valid_at":"?datetime","ref_id":"e0963238-68fa-46a9-84ca-71a5ea3ea62a","last_confirmed_at":"?datetime","invalidated_by":"?string","expired_at":"?datetime","cardinality":"single"}},{"source":"PlaybookEntry","edge":"APPLIES_IN","target":"Jurisdiction","props":{"ref_id":"06eb7475-d515-4c11-8e15-3ce056c84614"}},{"source":"PlaybookEntry","edge":"CALIBRATED_FOR","target":"Matter","props":{"ref_id":"8c432863-f91b-400a-91c2-51b78fddc86e"}},{"source":"PlaybookEntry","edge":"EVIDENCED_BY","target":"Excerpt","props":{"ref_id":"06b032f8-4d88-409c-aedb-f6c7dc36b41a"}},{"source":"PlaybookEntry","edge":"GOVERNED_BY","target":"Regulation","props":{"ref_id":"1c0d688c-c041-428e-81cc-03904bd11b0a"}},{"source":"PlaybookEntry","edge":"HAS_COMPONENT","target":"FormulaComponent","props":{"ref_id":"edfdd5a8-68ba-4a3b-8090-2f2a89218d1d"}},{"source":"PlaybookEntry","edge":"HAS_DEADLINE","target":"Deadline","props":{"ref_id":"3883f8e3-f19f-48de-8e56-e8b13fcbd00a"}},{"source":"Podcast","edge":"RELATED_TO","target":"Topic","props":{"ref_id":"d7872ab6-abe8-4806-a354-3110c1bd99ea"}},{"source":"Policy","edge":"HAS_CLAUSE","target":"PlaybookEntry","props":{"ref_id":"e2f694a3-8bf8-4fed-99e4-401cdeb228e7"}},{"source":"Policy","edge":"HAS_GAP","target":"GapItem","props":{"ref_id":"22480af1-55d7-4207-b0e0-f66d727cf35e"}},{"source":"Policy","edge":"IMPLEMENTS","target":"Regulation","props":{"ref_id":"aca113aa-cbe4-4e47-a9dd-3698c6d2ff03"}},{"source":"ProcessingActivity","edge":"GOVERNED_BY","target":"Regulation","props":{"ref_id":"b3d4902c-00f5-44eb-bf9f-28fa2b993434"}},{"source":"Product","edge":"MENTIONED_IN","target":"Section","props":{"ref_id":"8d1a2321-9325-4d6b-a5df-b93dbaa65480"}},{"source":"ProposedFix","edge":"DERIVED_FROM","target":"ProposedFix","props":{"ref_id":"f0db92c8-58f8-45c6-ade8-0553cbd0c377"}},{"source":"ProposedFix","edge":"PRODUCED_BY","target":"EvalTriggerOutput","props":{"ref_id":"acbd6127-92c8-4555-a47d-24a402227668"}},{"source":"ProposedFix","edge":"TARGETS_CAUSE","target":"Cause","props":{"ref_id":"40edf25c-96cd-4db9-bc8a-6df92d21ad2b","cardinality":"many"}},{"source":"ProposedFix","edge":"TARGETS_CONCEPT","target":"Concept","props":{"ref_id":"c06ce15f-f067-493e-b733-46fff1c9b200","cardinality":"many"}},{"source":"PullRequest","edge":"CREATED_BY","target":"Contributor","props":{"ref_id":"63b9fc60-3074-4044-95d1-c74d5566732b"}},{"source":"PullRequest","edge":"TOUCHES","target":"Concept","props":{"ref_id":"0f148c19-132a-4a22-8246-34d53db137fc"}},{"source":"PullRequest","edge":"TOUCHES","target":"Feature","props":{"ref_id":"8df5e682-1c79-48fe-93e3-8fc7c251c1bf"}},{"source":"Regulation","edge":"EVIDENCED_BY","target":"Excerpt","props":{"ref_id":"e1302f97-a20b-40fe-a996-4256fa8d0544"}},{"source":"Regulation","edge":"HAS_COMMENT_PERIOD","target":"CommentPeriod","props":{"ref_id":"e4cd5f7e-1675-4ef2-ad49-a0d1af68ea47"}},{"source":"Regulation","edge":"HAS_GAP","target":"GapItem","props":{"ref_id":"db90c7e9-725b-4cf6-bfa6-2c424844380c"}},{"source":"Regulation","edge":"ISSUED_UNDER","target":"RegulatoryItem","props":{"ref_id":"6987d8fd-6040-415b-9a9b-cfeef7a66a2e"}},{"source":"RegulatoryItem","edge":"EVIDENCED_BY","target":"Excerpt","props":{"ref_id":"60e71f30-9d2b-4a01-8f69-765440ef82c8"}},{"source":"Repository","edge":"HAS","target":"PullRequest","props":{"ref_id":"63836bcc-e8ae-4c4d-8b5d-63667657ed69"}},{"source":"Request","edge":"CALLS","target":"Endpoint","props":{"ref_id":"ec466219-824b-48a6-ac77-0e15fe1a51a2"}},{"source":"Run","edge":"START","target":"Run_step","props":{"ref_id":"9ff4f755-8138-4e9b-bbe2-b0810e638ae6"}},{"source":"Run_step","edge":"START","target":"Run_step","props":{"accurate":"?boolean","ref_id":"a684b113-96f1-4eab-a01a-a7c58c1d9322"}},{"source":"Section","edge":"AUTHORED_BY","target":"Person","props":{"ref_id":"c0f4ac4d-0786-42ec-99d2-05b25e7d5a35"}},{"source":"Section","edge":"HAS_COMPONENT","target":"FormulaComponent","props":{"ref_id":"346399d1-6773-46a5-ab10-748acc76cc18"}},{"source":"Section","edge":"RELATED_TO","target":"Topic","props":{"ref_id":"08dbd412-02d3-4ce8-8c2a-472df7f78cd0"}},{"source":"Show","edge":"HAS","target":"Episode","props":{"ref_id":"23541d77-d7f0-4256-88a5-604ce3468a12"}},{"source":"Show","edge":"HAS_CLAIM","target":"Claim","props":{"ref_id":"be64a895-db5e-4ed4-9784-62cc8200004c"}},{"source":"TabularReviewCell","edge":"CELL_OF","target":"Document","props":{"ref_id":"8d8247dd-ebcd-46ac-9e48-eb357663ed74"}},{"source":"TabularReviewCell","edge":"CONFLICTS_WITH","target":"TabularReviewCell","props":{"field_name":"?string","delta":"?string","ref_id":"8cd10718-a111-4f9d-97e5-d3d36cdb15aa","doc_a_value":"?string","doc_b_value":"?string"}},{"source":"Task","edge":"GLOBAL_MEMORY","target":"Memory","props":{"ref_id":"52f96a78-baf6-4402-9d98-a072d282473a"}},{"source":"Thing","edge":"HAS_FLUENT","target":"Fluent","props":{"volatility":"STATIC","ref_id":"50efb113-9403-4af4-ab78-7b1c0d4377da","cardinality":"many"}},{"source":"Thing","edge":"HAS_PRICE","target":"Thing","props":{"volatility":"INSTANTANEOUS","confidence_score":"?float","invalid_at":"?datetime","temporal":true,"valid_at":"?datetime","ref_id":"900689aa-fbaf-4fac-9d4a-5f9f81492059","last_confirmed_at":"?datetime","invalidated_by":"?string","expired_at":"?datetime","cardinality":"single"}},{"source":"TimelineEntry","edge":"CONTRADICTS","target":"TimelineEntry","props":{"contradiction_type":"?string","ref_id":"596a983c-820c-4c99-86d7-203a4453f51f","contradiction_reason":"?string"}},{"source":"Topic","edge":"MENTIONED_IN","target":"Section","props":{"ref_id":"a49ce91c-1414-47a9-b21a-ad0a9bbcc068"}},{"source":"Trait","edge":"OPERAND","target":"Function","props":{"ref_id":"1220754e-8a14-46e2-958f-a72456c4c51b"}},{"source":"Turn","edge":"NEXT","target":"Turn","props":{"ref_id":"fcb0bd8b-47c5-4529-9c61-68b61e51031c"}},{"source":"Tweet","edge":"RELATED_TO","target":"Topic","props":{"ref_id":"360fc4f1-5850-42de-932d-3e70f2cc5ad2"}},{"source":"Tweet","edge":"THREAD_PART","target":"Tweet","props":{"ref_id":"10cac5be-f244-4a69-bc02-be160f5ce66a"}},{"source":"TwitterAccount","edge":"POSTED","target":"Tweet","props":{"ref_id":"46d8fb7a-cbca-43cf-b602-7579202b3303"}},{"source":"UnitTest","edge":"CALLS","target":"Class","props":{"ref_id":"fa7c23cd-c436-4cd3-b76f-4f50b50b731f","call_start":"?int","call_end":"?int","operand":"?string"}},{"source":"UnitTest","edge":"CALLS","target":"Endpoint","props":{"ref_id":"cf9bb952-bd78-4904-b909-8b82096e37e2","call_start":"?int","call_end":"?int","operand":"?string"}},{"source":"UnitTest","edge":"CALLS","target":"Function","props":{"ref_id":"2c966683-8994-4e52-a46d-83555bd87238","call_start":"?int","call_end":"?int","operand":"?string"}},{"source":"Var","edge":"CONTAINS","target":"Var","props":{"ref_id":"7419dc30-047a-460b-9c88-b244b86ff3b7"}},{"source":"Video","edge":"RELATED_TO","target":"Topic","props":{"ref_id":"30369268-5a01-4c90-9c52-b60e002ef609"}},{"source":"Workflow_version","edge":"START","target":"Generated_step","props":{"ref_id":"923240c0-8f03-4571-95cf-74bc58ecb5a8"}}],"hidden_domains":["Scratchpad"]}; +export const JARVIS_ONTOLOGY: OntologyFixture = {"version":"m125","source":"jarvis-backend local default seed (sphinxlightning/sphinx-neo4j) at migration 125 (Check node + ABOUT/TESTS/PRODUCED_BY pairs), read-only dump","schemas":[{"ref_id":"83bb6c45-40c5-45de-b76f-8aeb5ee75f33","type":"*","is_system":true},{"next_review":"?datetime","node_key":"aisystem-name","secondary_color":"#D7CCC8","type":"AISystem","obligations_assessed":"?boolean","workflow_position":"?string","review_trigger":"?string","risk_tier":"?string","description":"?string","name":"string","governance_tier":"?string","type_description":"An AI or automated decision-making system subject to governance and regulatory obligations.","domain":"Legal","role":"?string","icon":"ChipIcon","primary_color":"#6D4C41","index":["ref_id","name","risk_tier","regulatory_regime"],"regulatory_regime":"?string","status":"?string","parent":"Thing","shape":"sphere","eu_nexus":"?boolean","human_in_loop":"?boolean","description_key":"description","title_key":"name","classification":"?string","ref_id":"1c93f74c-b212-4493-98b9-833decb96315","obligations_note":"?string","affected_population":"?string","output_type":"?string","tier_basis":"?string"},{"icon":"BookIcon","primary_color":"#222B48","index":["text","level"],"text":"string","abstraction_id":"string","parent":"Workflow","node_key":"abstraction-abstraction_id","secondary_color":"#5E84F8","shape":"sphere","type":"Abstraction","level":"string","description_key":"text","title_key":"level","domain":"Workflow","type_description":"A named level of abstraction for an agent session — title, narrative, or decision — with optional embedding for retrieval.","ref_id":"31ba479a-5928-4ad1-b074-1dedb265036e","embedding":"?string"},{"action_id":"string","icon":"GeneratedStepIcon","primary_color":"#38243C","index":["name","description"],"status":"?string","parent":"Workflow","node_key":"action-action_id","secondary_color":"#F468D4","shape":"sphere","type":"Action","description_key":"description","title_key":"name","description":"?string","name":"?string","domain":"Workflow","type_description":"Represents a single action or procedural step within a broader strategy.","ref_id":"28159b06-14d2-4df3-b0e1-bace578f0320"},{"icon":"GeneratedStepIcon","primary_color":"#38243C","index":["agent_id","role"],"parent":"Workflow","node_key":"agent-agent_id","secondary_color":"#F468D4","shape":"sphere","agent_id":"int","type":"Agent","description_key":"role","title_key":"agent_id","domain":"Workflow","type_description":"An autonomous entity that can perform actions and make decisions.","ref_id":"e54fef17-be5f-4893-8bee-9f1da0bab9b2","role":"?string"},{"icon":"PersonIcon","primary_color":"#222B48","index":["source"],"parent":"Workflow","node_key":"agentrole-source","secondary_color":"#5E84F8","shape":"sphere","type":"AgentRole","description_key":"source","title_key":"source","source":"string","domain":"CodeArtifact","type_description":"A named agent type (e.g. plan-agent, coding-agent) that groups its execution sessions.","ref_id":"cd4025c7-575c-4fd2-8f18-e162bafd0eea"},{"model":"?string","session_id":"string","output_tokens":"?int","total_tokens":"?int","task_id":"?string","duration_ms":"?int","node_key":"agentsession-session_id","log_url":"?string","secondary_color":"#C25AF3","type":"AgentSession","repo":"?string","feature_id":"?string","error_message":"?string","type_description":"A single agent execution run, keyed by per-run UUID.","domain":"CodeArtifact","created_at":"?datetime","icon":"GeneratedStepIcon","primary_color":"#302342","index":["source","status","repo"],"status":"?string","cache_read_tokens":"?int","parent":"Workflow","provider":"?string","input_tokens":"?int","shape":"sphere","description_key":"status","title_key":"source","source":"string","end_time":"?int","ref_id":"e0eace93-0e5c-4f27-bd28-ec94a0f1b17a","start_time":"?int","cache_write_tokens":"?int"},{"agreement_type":"?string","icon":"DocumentIcon","primary_color":"#6D4C41","index":["name","agreement_type","effective_date","governing_law"],"status":"?string","governing_law":"?string","parent":"Legal","node_key":"agreement-id","secondary_color":"#D7CCC8","shape":"sphere","type":"Agreement","id":"string","description_key":"agreement_type","title_key":"name","execution_date":"?string","expiration_date":"?string","name":"?string","domain":"Legal","type_description":"A legally binding contract between two or more parties. Matches the Agreement label produced by the graphrag-contract-review ingestion pipeline.","ref_id":"718a2c7e-fe85-44ae-90ea-847974f6fa78","effective_date":"?string"},{"icon":"PaperClipIcon","primary_color":"#1A3A52","size_bytes":"?int","index":["filename","content_type"],"parent":"Content","node_key":"attachment-filename","secondary_color":"#5BA4CF","shape":"sphere","type":"Attachment","description_key":"content_type","title_key":"filename","domain":"Content","type_description":"A file attached to an email message.","ref_id":"4bbd7399-656d-48b3-9718-8e47ed63c49c","filename":"string","source_link":"?string","content_type":"?string"},{"icon":"NodesIcon","primary_color":"#2A3229","index":"user_reference","update_type":"string","parent":"KnowledgeArtifact","node_key":"belief-user_reference-referenced_id","refutes_supports":"float","date_created":"datetime","secondary_color":"#96BD3F","shape":"sphere","type":"Belief","decay_curve":"?string","confidence_score":"float","user_reference":"string","description_key":"user_reference","title_key":"user_reference","update_trigger":"?string","graph_url":"?string","domain":"KnowledgeArtifact","type_description":"A user epistemic position on a referenced graph node, with confidence scoring, support/refutation polarity, and configurable decay or trigger-based update logic","ref_id":"980dd66a-e226-4bab-9768-0c64be03d14c","referenced_id":"string"},{"cause_detail":"string","icon":"ExclamationCircleIcon","primary_color":"#6D4C41","index":["cause_type","task_slug_prefix","dedup_hash"],"first_seen_run_id":"?string","cause_summary":"string","parent":"Legal","suggested_fix":"?string","node_key":"benchmarkfailurecause-dedup_hash","secondary_color":"#D7CCC8","issue_group":"?string","shape":"sphere","type":"BenchmarkFailureCause","cause_type":"string","dedup_hash":"string","log_evidence":"?string","description_key":"cause_detail","title_key":"cause_summary","last_seen_run_id":"?string","domain":"Legal","type_description":"A classified root cause of failure for one or more Harvey LAB benchmark criteria. One node per unique cause_type + task_slug_prefix + issue_group combination, deduped via SHA-256 hash. Linked to EvalTriggerOutput nodes of all runs that exhibited this cause via ATTRIBUTED_TO, and to the EvalRequirement it affects via AFFECTS. occurrence_count is incremented on each association. Cause types: CALCULATION_ERROR, THRESHOLD_NOT_APPLIED, MISSING_DOWNSTREAM_CONCLUSION, JURISDICTION_RULE_MISSING, MULTI_JURISDICTION_INCOMPLETE, SCOPE_GAP_NOT_IDENTIFIED, CROSS_DOCUMENT_CONFLICT_MISSED, HEADCOUNT_ATTRIBUTION_ERROR, MISSING_STATUTORY_CITATION, PRIVILEGE_MISCLASSIFICATION, AGENT_REASONING_GAP, RETRIEVAL_FAILURE.","ref_id":"4edc2855-3f17-4d1a-bb36-207c07a9b0e5","occurrence_count":"?int","task_slug_prefix":"?string"},{"one_sentence_summary":"?string","phase_priority":"?int","org_uuid":"?string","bounty_type":"?string","node_key":"bounty-bounty_id","show":"?boolean","secondary_color":"#54AC52","estimated_completion_date":"?string","type":"Bounty","bounty_id":"int","estimated_session_length":"?string","title":"?string","deliverables":"?string","paid":"?boolean","created":"?int","updated":"?string","description":"?string","type_description":"A reward offered for completing a task or challenge","domain":"Entity","phase_uuid":"?string","github_description":"?boolean","bounty_expires":"?string","completed":"?boolean","primary_color":"#22362A","workspace_uuid":"?string","index":["description","title"],"ticket_url":"?string","tribe":"?string","assigned_hours":"?int","commitment_fee":"?int","parent":"Thing","assignee":"?string","shape":"sphere","wanted_type":"?string","price":"?int","description_key":"description","title_key":"title","owner_id":"?string","ref_id":"704f1683-7a0d-4792-b772-7c317f4514cb","coding_languages":"?string"},{"icon":"EpisodeIcon","primary_color":"#222B48","index":["episode_title","description"],"status":"?string","episode_title":"?string","media_url":"?string","parent":"Show","node_key":"call-source_link","show_title":"?string","secondary_color":"#5E84F8","shape":"sphere","date":"?datetime","type":"Call","pubkey":"?string","description_key":"description","title_key":"episode_title","image_url":"?string","description":"?string","project_id":"?string","domain":"Content","type_description":"A single installment in a series of related productions e.g Show","ref_id":"1d02e951-e415-4e3f-beb4-b777778501c1","source_link":"string"},{"icon":"ExclamationCircleIcon","primary_color":"#362429","index":["cause_type","severity"],"parent":"Thing","node_key":"cause-id","severity":"?string","secondary_color":"#D25353","shape":"sphere","type":"Cause","cause_type":"?string","id":"string","title":"string","description_key":"description","title_key":"title","resolved":"?boolean","description":"?string","domain":"CodeArtifact","type_description":"A structured root cause attributed to one or more CriterionResult failures. Supports hierarchical grouping via CAUSE_CHILD_OF. cause_type values: prompt_gap | reasoning_error | missing_context | format_violation. severity values: critical | high | medium | low.","ref_id":"a5d69c3a-5208-4cae-8063-5a80493503d0","created_at":"?datetime"},{"transcript":"?string","index":["name","description"],"parent":"Content","node_key":"chapter-name-timestamp-source_link","type":"Chapter","is_favorite":"?boolean","timestamp":"string","description_key":"description","title_key":"name","paid_properties":["transcript"],"is_ad":"?boolean","description":"?string","name":"string","domain":"Content","ref_id":"babd19b8-9d80-46ed-b4b6-0d8472b5fa5a","source_link":"string"},{"retired_at":"?datetime","node_key":"check-id","secondary_color":"#4FA7D9","type":"Check","step_type":"?string","publisher":"?string","id":"string","step_config":"?string","description":"?string","name":"string","type_description":"One instrument that can test one Claim (migration 125) — the node the epistemic layer first held off on. A Claim is the statement, a Check is a way of testing it, Evidence is what one test observed: Check -[TESTS]-> Claim, and the Evidence a check yields points back via Evidence -[PRODUCED_BY]-> Check. A node rather than attributes on the Claim because one claim can have SEVERAL checks (a free script on every run, a model judge on change, a person once per version), each with its own policy, cost and evidence stream, and a check can be replaced without touching the statement. step_type names the executable instrument in the producer's registry and step_config is its JSON config; step_type ABSENT means an EXTERNAL check — answered by a person or an outside system, usually by filling a planned Evidence slot (Evidence.evidence_status) — and description then says what to look at and why code cannot. run_when: run | publish — whether the check fires on an execution of the subject or when a new version of it is published. policy: always | on_change | sample | manual — how often a run check fires; freshness_days bounds on_change (re-run when the latest evidence is older, catching environment drift) and sample_rate is the fraction of runs for sample. publisher records who wrote the check (ai, a person, a seeder). A check is IMMUTABLE once it has evidence: editing it creates a new Check that SUPERSEDES the old one and sets the old node's retired_at — a changed instrument has measured nothing yet, so a retired check's evidence stays in the graph but no longer counts. Active = retired_at unset (there is no status attribute: `status` is a reserved name). run_when and policy are documented contracts, not DB-enforced enums (the Claim.verdict / Evidence.evidence_status convention); readers must treat any other value as unknown/unspecified.","domain":"Epistemic","created_at":"datetime","run_when":"?string","icon":"TaskIcon","primary_color":"#1D3140","index":["name","description"],"sample_rate":"?float","parent":"Thing","shape":"sphere","description_key":"description","title_key":"name","ref_id":"c4902dcf-4a44-4d38-9389-361d43d24bef","policy":"?string","freshness_days":"?int"},{"answer_volatility":"?string","claim_text":"string","valid_from":"?datetime","node_key":"claim-id","type":"Claim","id":"string","polarity":"?string","name":"string","type_description":"An assertion whose truth can be evaluated — the unit of knowing in the epistemic layer (Claim / Evidence, migration 119). Extracted claims record a speaker's statement; the epistemic attributes score ANY claim by its evidence. answer_volatility uses the temporal-layer classes (STATIC | STABLE | EVOLVING | VOLATILE | INSTANTANEOUS): STATIC is the static-vs-dynamic dimension's static pole, everything else is dynamic (named answer_volatility because bare `volatility` is a schema-level core property the read path swallows out of attributes). derivation: atomic | calculated — calculated claims point at their inputs via DERIVED_FROM. polarity: affirms | negates — whether the claim asserts or denies its proposition. Bitemporal fields split ontic from epistemic time: valid_from/valid_to is when the claim is true IN THE WORLD; belief_valid_from/belief_valid_to is when the graph believed it (closed by supersession or retraction). verdict: known | likely | contested | unknown | stale, with confidence_score in [0.0, 1.0] as of assessed_at. Evidence hangs off EVIDENCED_BY {strength: -1.0 disproves .. +1.0 proves}; compound claims decompose via PARENT_OF; claim-to-claim relations use the existing SUPPORTS / CONTRADICTS / SUPERSEDES edges.","triplicate_object":"?string","verdict":"?string","domain":"Epistemic","belief_valid_from":"?datetime","belief_valid_to":"?datetime","valid_to":"?datetime","speaker_name":"?string","assessed_at":"?datetime","index":["name","claim_text","speaker_name"],"triplicate_subject":"?string","parent":"Thing","triplicate":"?string","confidence_score":"?float","source_role":"?string","derivation":"?string","triplicate_predicate":"?string","description_key":"claim_text","title_key":"name","paid_properties":[],"ref_id":"67fcc508-e296-4411-896b-6f431e8c0c9d"},{"icon":"NodesIcon","body":"?string","index":["name","body"],"parent":"CodeArtifact","node_key":"class-name-file","shape":"sphere","type":"Class","description_key":"body","title_key":"name","start":"?int","file":"string","name":"string","domain":"CodeArtifact","type_description":"A class definition in source code, representing an object-oriented structure with attributes and methods.","ref_id":"1738aaf1-b30a-4f7d-9a76-4cc88c4c367f","end":"?int"},{"icon":"TagIcon","primary_color":"#6D4C41","index":["name"],"parent":"Thing","node_key":"clausetype-name","secondary_color":"#D7CCC8","shape":"sphere","type":"ClauseType","description_key":"description","title_key":"name","description":"?string","name":"string","domain":"Legal","type_description":"A classification label for a ContractClause (e.g. indemnification, termination, confidentiality).","ref_id":"924bb19a-b6f4-4aa2-92a6-832f9dc96a46"},{"transcript":"?string","link":"?string","node_key":"clip-episode_title-timestamp","secondary_color":"#4FA7D9","sentiment_score":"?float","date":"?datetime","type":"Clip","timestamp":"string","image_url":"?string","description":"?string","type_description":"A short audio or video segment extracted from a longer episode","domain":"Content","source_link":"?string","pub_key":"?string","icon":"AudioIcon","primary_color":"#1D3140","text":"?string","index":["episode_title","text","description"],"episode_title":"string","media_url":"string","parent":"Episode","show_title":"?string","shape":"sphere","num_boost":"?int","description_key":"description","title_key":"episode_title","english_translation":"?string","ref_id":"788d5a44-1a5e-4533-8de4-ceaf887ede41","boost":"?int","language":"?string"},{"icon":"ConstructionIcon","index":"name","domain":"CodeArtifact","type_description":"An abstract parent for all source code constructs within a repository.","ref_id":"b9d1bbef-bf58-4877-9181-9e058af71078","parent":"Thing","type":"CodeArtifact"},{"summary":"?string","icon":"ChatAltIcon","primary_color":"#6D4C41","index":["regulation_name","comment_deadline","decision"],"link":"?string","parent":"Legal","node_key":"commentperiod-regulation_name-comment_deadline","regulation_name":"string","secondary_color":"#D7CCC8","shape":"sphere","type":"CommentPeriod","decision":"string","description_key":"decision","title_key":"regulation_name","owner":"?string","domain":"Legal","type_description":"A public comment period for a proposed regulation or rule, with tracking of the organization's response.","ref_id":"9e9c1a31-cf54-4162-8a63-4bff2bdeb952","filed_at":"?datetime","comment_deadline":"datetime","rationale":"?string","notes":"?string"},{"summary":"?string","icon":"NodesIcon","index":["name","message","summary"],"committed_at":"?string","sha":"?string","parent":"Repository","node_key":"commit-sha","shape":"sphere","type":"Commit","url":"?string","namespace":"?string","message":"?string","author":"?string","description_key":"summary","title_key":"name","name":"string","domain":"CodeArtifact","type_description":"An individual git commit, including its message, author, and a summary of the change.","ref_id":"6b564e70-e0c7-4111-8fc1-47a56b689153","source_link":"?string"},{"icon":"NodesIcon","index":"name","count":"?int","parent":"Repository","node_key":"commits-name","shape":"sphere","type":"Commits","namespace":"?string","description_key":"name","title_key":"name","name":"string","domain":"CodeArtifact","type_description":"A collection of individual commit nodes belonging to a repository.","ref_id":"dfe13962-8ead-400c-9145-444acd917242"},{"icon":"CalculatorIcon","primary_color":"#6D4C41","result":"?float","index":["label","matter_slug","discrepancy_flag"],"computed_by":"?string","parent":"Legal","node_key":"computedfigure-label","label":"string","secondary_color":"#D7CCC8","shape":"sphere","type":"ComputedFigure","discrepancy_note":"?string","discrepancy_flag":"boolean","description_key":"formula","title_key":"label","inputs":"?string","verified":"boolean","domain":"Legal","type_description":"An independently-derived numerical calculation with its formula, inputs (Excerpt refs), and result — used by the computation verifier agent to cross-check figures extracted by research agents and flag discrepancies.","ref_id":"434f593f-c719-4010-a5e5-4537e1abce6f","result_string":"?string","statutory_basis":"?string","formula":"string"},{"icon":"NodesIcon","index":["name","description","docs"],"docs":"?string","pr_numbers":"?string","parent":"Thing","node_key":"concept-name","commit_shas":"?string","shape":"sphere","type":"Concept","id":"?string","description_key":"description","title_key":"name","repo":"?string","description":"?string","file":"?string","name":"string","documentation":"?string","domain":"General","type_description":"A reusable unit of knowledge or capability — a codebase capability, a legal methodology, a domain practice. Cross-domain by design, which is why it is homed in General rather than CodeArtifact. BODY FIELD — `docs` is the canonical long-form body (migration 106). stakgraph's lab/concepts pipeline writes `docs` directly over a bolt session (bypassing this API and its schema validation) and its nodeToConcept() reads only `docs`, so `docs` is the field that actually carries nearly every live Concept's content. DEPRECATED — `documentation` is the pre-106 body field. It is still declared so existing API writers do not hard-fail, but it is NO LONGER INDEXED: content written there is invisible to both the composite Data_Bank fulltext index and text_embeddings, and invisible to stakgraph. Write `docs`, not `documentation`. Migration 106 backfilled existing `documentation` bodies into `docs`; removing the attribute outright requires a coordinated writer migration first (a removal would 400 any payload still sending it).","ref_id":"a530f22b-b0aa-46d6-bf6c-3e7e1afa1111","created_at":"?string","last_updated":"?string"},{"conflicts":"?string","icon":"ShieldCheckIcon","primary_color":"#6D4C41","result":"string","index":["matter_slug","checked_date","result"],"parent":"Legal","node_key":"conflictcheck-matter_slug-checked_date","checked_by":"string","secondary_color":"#D7CCC8","shape":"sphere","type":"ConflictCheck","description_key":"result","title_key":"matter_slug","domain":"Legal","type_description":"A conflict-of-interest check performed before or during a legal matter.","ref_id":"6e875c60-3757-4011-8b05-a4f749f97dfe","checked_date":"datetime","notes":"?string","matter_slug":"string"},{"icon":"InterestsIcon","index":"name","domain":"Content","type_description":"Any form of media, including text, images, or videos","ref_id":"60883d1a-6b68-44d5-b0c5-d06bbf9c84f5","parent":"Thing","type":"Content"},{"summary":"?string","icon":"ClipboardIcon","primary_color":"#6D4C41","index":["clause_type","risk_level"],"parent":"Thing","recommendation":"?string","node_key":"contractclause-id","secondary_color":"#D7CCC8","shape":"sphere","confidence":"?float","type":"ContractClause","clause_type":"?string","id":"string","description_key":"risk_level","title_key":"clause_type","risk_level":"?string","priority":"?string","domain":"Legal","type_description":"A discrete clause or provision within a legal agreement, categorised by type and risk level.","ref_id":"8e304fe3-8cd5-43ba-bccf-3aa47af2652e"},{"location":"?string","node_key":"contributor-username","type":"Contributor","namespace":"?string","followers":"?int","following":"?int","username":"string","image_url":"?string","description":"?string","public_repos":"?int","name":"string","type_description":"A person who contributes to a project or repository, including authors and maintainers.","domain":"Entity","icon":"PersonIcon","index":["username","description","bio"],"parent":"Person","shape":"sphere","account_created_at":"?datetime","description_key":"description","title_key":"username","bio":"?string","email":"?string","company":"?string","ref_id":"858f9367-a600-486e-99e4-120a55cc90cf","role_name":"?string"},{"icon":"CorporationIcon","primary_color":"#222B48","index":["name","description"],"parent":"Organization","node_key":"corporation-name","secondary_color":"#5E84F8","shape":"sphere","type":"Corporation","description_key":"description","title_key":"name","image_url":"?string","description":"?string","name":"string","domain":"Entity","type_description":"A legally recognized business entity or company","ref_id":"ccc1a080-92f0-473b-82c1-331cd670346e"},{"icon":"PlaceIcon","primary_color":"#2A2545","index":["name","iso_code"],"iso_code":"?string","parent":"Thing","node_key":"country-name","secondary_color":"#9368FB","shape":"sphere","type":"Country","description_key":"name","title_key":"name","image_url":"?string","name":"string","domain":"Entity","type_description":"A sovereign nation or country, used e.g. as a place of incorporation or governing-law jurisdiction","ref_id":"3a892221-8210-4031-ad89-182677d3c035"},{"icon":"CheckCircleIcon","primary_color":"#36292D","index":["criterion_id","verdict"],"flagged":"?boolean","parent":"Thing","node_key":"criterionresult-id","secondary_color":"#A96755","shape":"sphere","type":"CriterionResult","contested":"?boolean","document_excerpt":"?string","id":"string","llm_flag_reason":"?string","title":"?string","reasoning":"?string","description_key":"reasoning","title_key":"title","verdict":"?string","domain":"CodeArtifact","type_description":"A generic per-criterion, per-run verdict node — the domain-neutral form of RubricCriterion. Records a judge's verdict, reasoning, and flag metadata for a single criterion within one EvalTriggerOutput scored attempt. Used by both Hive prompt/agent evals and the Harvey benchmark unified model.","ref_id":"13959bfa-6d96-4106-b490-34316bb311e5","criterion_id":"string","agent_thinking_excerpt":"?string"},{"icon":"ClipboardListIcon","primary_color":"#6D4C41","index":["request_id","status","category"],"status":"?string","request_text":"?string","parent":"Legal","node_key":"ddrequestitem-request_id","secondary_color":"#D7CCC8","shape":"sphere","type":"DDRequestItem","category":"?string","description_key":"category","request_id":"string","title_key":"request_text","fulfilled_date":"?datetime","responding_party":"?string","domain":"Legal","type_description":"A discrete line item within a due diligence request list, tracking the request, its status, and the responding party.","ref_id":"ca6bd1b2-4177-4a09-bc1f-a3841383c5f6","due_date":"?datetime","notes":"?string"},{"exemptions":"?string","deadline_statutory":"?datetime","node_key":"dsarrequest-id","secondary_color":"#D7CCC8","type":"DSARRequest","date_responded":"?datetime","what_produced":"?string","id":"string","deadline_internal":"?datetime","type_description":"A Data Subject Access Request (DSAR) submitted under a privacy regulation.","domain":"Legal","regime":"?string","icon":"IdentificationIcon","primary_color":"#6D4C41","index":["id","right_invoked","regime","status"],"status":"?string","date_received":"?datetime","parent":"Thing","date_identity_verified":"?datetime","shape":"sphere","identity_verified":"?boolean","description_key":"right_invoked","title_key":"id","handled_by":"?string","ref_id":"adffcca1-968d-46c3-b7aa-066899b9c5dd","right_invoked":"?string"},{"field_name":"string","observed_value":"?string","icon":"ExclamationIcon","primary_color":"#6D4C41","index":["anomaly_type","source_doc_ref","resolved"],"parent":"Legal","node_key":"dataanomalyrecord-source_doc_ref-field_name","severity":"?string","secondary_color":"#D7CCC8","shape":"sphere","type":"DataAnomalyRecord","source_doc_ref":"string","description_key":"anomaly_type","title_key":"field_name","detected_at":"datetime","resolved":"boolean","expected_value_or_rule":"?string","domain":"Legal","type_description":"A data quality anomaly detected at document ingest time — impossible dates, missing required fields, stale denominators, or cross-document value mismatches. Also covers one-sided findings (observed_value and expected_value_or_rule are both optional): unexpected-location facts (anomaly_type='unexpected_location' — a substantive fact appearing in a document where it is not expected, or a controlling primary record differing from the citing document; observed_value=actual location, expected_value_or_rule=expected location), absent clause types (anomaly_type='missing_clause_type'), figures asserted without derivation (anomaly_type='asserted_without_derivation'), and intra-section self-contradictions (anomaly_type='self_contradiction'). Anchor to the relevant node via FLAGS (TimelineEntry, ContractClause, Figure, Document, Excerpt, or a clause-type Concept for absence findings). Seeded before research rounds begin so all agents are aware of adversarial data traps.","ref_id":"921bc872-85f1-45aa-98b9-4ded0b027362","anomaly_type":"string"},{"icon":"NodesIcon","body":"?string","index":["name","body"],"parent":"CodeArtifact","node_key":"datamodel-name-file","shape":"sphere","type":"Datamodel","description_key":"body","title_key":"name","start":"?int","file":"string","name":"string","domain":"CodeArtifact","type_description":"A structured representation of data within a system, typically defining entities, relationships, attribute types, and corresponding SQL table definitions.","ref_id":"a76bdcfb-652e-4568-ab51-949e97f4543d","end":"?int"},{"icon":"CalendarIcon","primary_color":"#6D4C41","index":["deadline_type","matter_slug","due_date","status"],"status":"?string","parent":"Thing","node_key":"deadline-deadline_type-matter_slug-due_date","secondary_color":"#D7CCC8","shape":"sphere","type":"Deadline","description_key":"due_date","title_key":"deadline_type","deadline_type":"string","description":"?string","warning_days":"?int","owner":"?string","domain":"Legal","type_description":"A legal or regulatory deadline associated with a matter, agreement, IP asset, or AI system.","ref_id":"45edc8b5-a569-40f2-9470-152940e688e3","due_date":"string","matter_slug":"string"},{"icon":"BookOpenIcon","primary_color":"#6D4C41","index":["term","matter_slug","source_ref","scope"],"scope":"?string","definition_text":"string","parent":"Legal","node_key":"definedterm-matter_slug-source_ref-term","source_ref":"string","secondary_color":"#D7CCC8","shape":"sphere","first_used_section":"?string","type":"DefinedTerm","description_key":"definition_text","title_key":"term","term":"string","domain":"Legal","type_description":"A term as defined by one specific document — the per-document definition record, distinct from Lingo (the global vocabulary entry). One node per (matter_slug, source_ref, term), so two documents defining the same term differently yield two nodes; definitional divergence is asserted via DefinedTerm-[CONFLICTS_WITH]->DefinedTerm, and cross-document borrowing (a document using a term it does not itself define) via DefinedTerm-[USED_IN]->the borrowing document.","ref_id":"b7017069-4ffa-4851-847b-115aead96392","matter_slug":"string"},{"icon":"ClipboardCheckIcon","primary_color":"#6D4C41","index":["deliverable_type"],"parent":"Legal","node_key":"deliverableschema-deliverable_type","required_sections":"?string","deliverable_type":"string","secondary_color":"#D7CCC8","shape":"sphere","type":"DeliverableSchema","required_tabs":"?string","description_key":"deliverable_type","title_key":"deliverable_type","placeholder_patterns":"?string","domain":"Legal","type_description":"Specifies the required structure of a task output deliverable — tabs, columns, required sections, and placeholder patterns. Used by the deliverable schema enforcer to validate synthesized outputs before scoring.","required_columns":"?string","ref_id":"f66c86cd-a615-42d7-afad-da26efa1a355","formatting_rules":"?string"},{"icon":"ExclamationCircleIcon","primary_color":"#6D4C41","index":["category","severity","status"],"status":"string","parent":"Legal","node_key":"diligenceissue-category-description","severity":"string","secondary_color":"#D7CCC8","shape":"sphere","resolution":"?string","type":"DiligenceIssue","category":"string","description_key":"category","title_key":"description","description":"string","domain":"Legal","type_description":"A due-diligence issue identified during a deal or transaction review.","ref_id":"bcce77bc-1cc4-409f-bb93-64bd977da832","source_doc":"?string","materiality":"?string"},{"body":"?string","index":["name","description"],"parent":"Repository","node_key":"directory-name-file","shape":"sphere","type":"Directory","description_key":"description","title_key":"name","start":"?int","description":"?string","file":"string","name":"string","domain":"CodeArtifact","type_description":"A folder within a repository that organizes files and subdirectories.","ref_id":"350dee1e-e4be-4366-b878-2dcda901d3f1","source_link":"?string","end":"?int"},{"icon":"BookOpenIcon","primary_color":"#6D4C41","practice_area":"?string","index":["name","jurisdiction_ref","authority_level","practice_area"],"superseded_by":"?string","parent":"Legal","node_key":"doctrine-jurisdiction_ref-name","secondary_color":"#D7CCC8","shape":"sphere","type":"Doctrine","authority_level":"?string","jurisdiction_ref":"string","description_key":"rule_text","title_key":"name","source_citation":"?string","rule_text":"string","name":"string","domain":"Legal","type_description":"A standing legal rule or doctrine scoped to a jurisdiction — e.g. Third Circuit dominant-purpose test, post-TCJA 80% NOL cap. Distinct from LegalArgument (per-matter finding) and LegalDocument (case citation). Allows agents to retrieve jurisdiction-specific legal rules directly from the graph.","ref_id":"56f872ad-b980-4aea-8cac-79cd0ed583cc","effective_date":"?string"},{"summary":"?string","icon":"DocumentIcon","primary_color":"#302342","index":["source_link","title"],"status":"?string","parent":"Content","node_key":"document-source_link","secondary_color":"#C25AF3","shape":"sphere","type":"Document","pubkey":"?string","author":"?string","title":"?string","description_key":"summary","title_key":"title","domain":"Content","type_description":"A written, printed, or digital record of information","ref_id":"cde66016-4d46-4d55-b5b6-285ddcc5cfff","source_link":"string","content_type":"?string"},{"icon":"DocumentSearchIcon","primary_color":"#6D4C41","index":["document_subtype"],"parent":"Legal","example_values":"?string","node_key":"documenttypetemplate-document_subtype","secondary_color":"#D7CCC8","shape":"sphere","type":"DocumentTypeTemplate","description_key":"document_subtype","title_key":"document_subtype","mandatory_fields":"string","domain":"Legal","type_description":"Maps a legal document subtype to its mandatory quantitative fields — used by specificsSweep to generate targeted extraction queries per document type at task start, ensuring policy parameters (e.g. RWI limit + retention) are always seeded as findings even if no research agent explicitly queries for them.","ref_id":"631316a5-10e8-4ed8-83e3-75f7b91647df","document_subtype":"string"},{"body":"?string","index":["name","body"],"parent":"Test","node_key":"e2etest-name-file","type":"E2etest","description_key":"body","title_key":"name","start":"?int","file":"string","name":"string","domain":"CodeArtifact","type_description":"An end-to-end test that validates the entire system functionality by simulating real-world interactions.","ref_id":"15fed8c3-c844-407d-bd3a-e0e9049d2c5f","end":"?int"},{"icon":"MailIcon","primary_color":"#1A3A52","index":["message_id","subject","thread_id"],"subject":"string","parent":"Message","message_id":"string","node_key":"email-message_id","secondary_color":"#5BA4CF","shape":"sphere","type":"Email","in_reply_to":"?string","references":"?string","description_key":"message_id","title_key":"subject","domain":"Content","type_description":"An email message in the knowledge graph.","ref_id":"56eacec5-cd7c-4cd7-a581-4a5c4a6c75f3","thread_id":"?string"},{"body":"?string","subject":"string","node_key":"emailinvite-message_id","secondary_color":"#5BA4CF","conference_platform":"?string","type":"EmailInvite","timezone":"?string","type_description":"A calendar invitation delivered via email (iCalendar / .ics attachment).","domain":"Content","conference_url":"?string","icon":"CalendarIcon","primary_color":"#1A3A52","index":["message_id","subject","start_datetime"],"location_type":"?string","end_datetime":"?datetime","status":"?string","organizer":"?string","parent":"Message","message_id":"string","shape":"sphere","start_datetime":"?datetime","description_key":"start_datetime","recurrence":"?string","title_key":"subject","ref_id":"4d3f887d-6268-4683-8811-b9b2ca5cbb9f"},{"summary":"?string","body":"?string","node_key":"endpoint-name-file-verb","type":"Endpoint","namespace":"?string","verb":"string","description":"?string","file":"string","name":"string","type_description":"A defined entry point for accessing functionality within an application or service, typically through an API.","domain":"CodeArtifact","source_link":"?string","end":"?int","icon":"ConstructionIcon","text":"?string","index":["name","summary","description"],"hash":"?string","parent":"CodeArtifact","shape":"sphere","description_key":"summary","title_key":"name","start":"?int","ref_id":"87dcc921-01cb-4552-a710-ab06dc994260","method":"?string","handler":"?string"},{"icon":"NodesIcon","primary_color":"#1B3134","index":"entity","trusted":"?boolean","entity":"string","parent":"Thing","node_key":"entity-entity","secondary_color":"#21B38A","shape":"sphere","type":"Entity","entity_lower":"?string","description_key":"entity","title_key":"entity","domain":"Entity","type_description":"A general entity that can represent any identified concept or object","ref_id":"5b8aea7c-1ffd-433d-989f-6be32a0d6788","metaphone3":"?string"},{"summary":"?string","transcript":"?string","node_key":"episode-source_link","secondary_color":"#5E84F8","date":"?datetime","type":"Episode","image_url":"?string","description":"?string","type_description":"A single installment in a series of related productions e.g Show","domain":"Content","source_link":"string","icon":"EpisodeIcon","primary_color":"#222B48","index":["episode_title","description","summary"],"status":"?string","episode_title":"?string","media_url":"?string","parent":"Show","show_title":"?string","shape":"sphere","pubkey":"?string","duration":"?string","description_key":"description","title_key":"episode_title","paid_properties":["media_url","transcript"],"project_id":"?string","ref_id":"79c0a059-e819-42ec-bc69-d274076e1e62"},{"repo_key":"?string","icon":"ConstructionIcon","primary_color":"#2A2545","exceptionType":"?string","index":["title","exceptionType","fingerprint","status"],"first_seen_at":"?string","status":"?string","workspace_id":"?string","parent":"CodeArtifact","node_key":"errorissue-fingerprint","secondary_color":"#C25AF3","shape":"sphere","type":"ErrorIssue","repository_id":"?string","occurrenceCount":"?int","fingerprint":"string","title":"?string","description_key":"exceptionType","title_key":"title","last_seen_at":"?string","domain":"CodeArtifact","type_description":"A tracked error or exception in a codebase, identified by a unique fingerprint and associated with files and functions in the call stack.","ref_id":"afd6193e-e613-4ea0-a7cc-3cfa3d681145"},{"icon":"ExclamationCircleIcon","primary_color":"#6D4C41","index":["matter_slug","escalation_type","status"],"status":"string","trigger_finding_ref":"string","parent":"Legal","node_key":"escalationrecord-matter_slug-trigger_finding_ref","secondary_color":"#D7CCC8","shape":"sphere","type":"EscalationRecord","rpc_rule_ref":"?string","escalation_type":"string","description_key":"matter_slug","title_key":"escalation_type","resolved_by":"?string","domain":"Legal","type_description":"A structured record of a legal ethics or crime-fraud escalation triggered by a finding — capturing the escalation type, recommended actions (senior counsel / in camera / ethics consult), and the RPC rule that mandates it.","ref_id":"02e1b372-1816-4381-b54e-c5c1f927d640","recommended_actions":"?string","notes":"?string","matter_slug":"string"},{"icon":"StepIcon","primary_color":"#1B3134","index":["name","description"],"positive_cases":"?list","negative_cases":"?list","parent":"Thing","node_key":"evalrequirement-id","secondary_color":"#21B38A","shape":"sphere","type":"EvalRequirement","contested":"?boolean","id":"string","deliverables":"?list","updated_at":"?datetime","description_key":"description","title_key":"name","prompt_snippet":"?string","description":"?string","name":"?string","domain":"CodeArtifact","type_description":"A success criterion (test case) with positive and negative examples, captured from a real agent interaction.","ref_id":"3c1385ec-7602-4a68-9605-780ab678a97a","created_at":"?datetime"},{"icon":"TaskIcon","primary_color":"#1D3140","index":["name","description"],"parent":"Thing","node_key":"evalset-id","secondary_color":"#4FA7D9","shape":"sphere","type":"EvalSet","id":"string","updated_at":"?datetime","description_key":"description","title_key":"name","description":"?string","project_id":"?int","name":"?string","domain":"CodeArtifact","type_description":"A dataset (suite) grouping related test cases (EvalRequirements) for validating agent behaviour.","ref_id":"3e5e8c3d-0819-4659-8cff-ff7ad6f9a7ee","created_at":"?datetime","recursion":"?boolean"},{"body":"?string","start_point":"?string","workflow_input":"?string","prompts":"?list","node_key":"evaltrigger-id","secondary_color":"#BA9D39","type":"EvalTrigger","id":"string","prompt_id":"?string","workflow_id":"?string","type_description":"A captured, replayable input configuration — the source event that gave rise to an EvalRequirement.","domain":"CodeArtifact","icon":"GeneratedStepIcon","primary_color":"#353124","positive_cases":"?list","index":["agent","environment","change_type"],"end_point":"?string","negative_cases":"?list","workflow_version_id":"?string","parent":"Thing","shape":"sphere","change_type":"?string","agent":"?string","endpoint_url":"?string","prompt_version_id":"?string","run_count":"?int","description_key":"change_type","environment":"?string","title_key":"agent","source":"?string","paid_properties":["workflow_input"],"project_id":"?string","ref_id":"0b3c193c-6b9a-4020-96eb-c798b645cccd"},{"result":"string","judge_notes":"?string","judge_model":"?string","score":"?float","node_key":"evaltriggeroutput-id","secondary_color":"#E09242","type":"EvalTriggerOutput","id":"string","n_passed":"?int","n_total":"?int","type_description":"The result of a single evaluation run attempt: score, verdict, and judge notes. report_url, when present, is the URL of the run report bundle for this scored attempt — an https:// Stakwork-hosted bundle URL; optional and null on historical nodes. Consumers must treat it as untrusted input and must validate scheme and host before fetching (SSRF caution). The concept-analysis consumer must read report_url via an authenticated/proxied route, as it is a paid property and is silently stripped to null for unauthenticated readers.","verdict":"?string","domain":"CodeArtifact","max_score":"?float","icon":"StepIcon","primary_color":"#392828","index":"evaltriggeroutput-id","attempt_number":"?int","parent":"Thing","shape":"sphere","endpoint_url":"?string","description_key":"judge_notes","title_key":"result","report_url":"?string","paid_properties":["report_url"],"ref_id":"1826ff32-dfe6-409e-857d-187142aff915"},{"icon":"EventIcon","primary_color":"#38243C","index":["name","description"],"parent":"Thing","node_key":"event-name","secondary_color":"#F468D4","shape":"sphere","type":"Event","description_key":"description","title_key":"name","image_url":"?string","description":"?string","name":"string","domain":"Entity","type_description":"A thing that happens or takes place, especially one of importance","ref_id":"431687d4-a420-46fb-93b2-0acc412559e1"},{"icon":"DocumentIcon","primary_color":"#222B48","index":["name","description","content"],"parent":"Thing","node_key":"evidence-id","secondary_color":"#5E84F8","shape":"sphere","type":"Evidence","evidence_mode":"?string","content":"?string","observed_at":"?datetime","id":"string","confidence_score":"?float","description_key":"description","title_key":"name","description":"?string","name":"string","domain":"Epistemic","type_description":"One captured datum backing a Claim — a quote, reading, attestation, or record, captured AS OBSERVED (the Figure discipline from the Legal domain: capture first, derive later). content holds the observed value, statement, or excerpt — ON THE NODE, where it is indexed and searchable; where-in-the-source locators (timestamps, message id, page, url) ride the HAS_SOURCE edge instead. observed_at is when the datum was true in the world — the anchor for freshness against the claim's answer_volatility. evidence_mode is the asserted-vs-observed dimension: observed | asserted — observed means we or an instrument measured it, asserted means someone said it. Provenance: this Evidence -[HAS_SOURCE {authority_level, locators}]-> the canonical entity it came from (Person, Organization, Document, ...); a Claim points here via EVIDENCED_BY {strength}. Independent corroboration is counted over DISTINCT source entities, not Evidence rows. confidence_score is this datum's own trustworthiness in [0.0, 1.0], consistent with Belief and temporal-edge confidence. evidence_status is the collection lifecycle: planned means the slot has been named via name/description but content is still empty; collected means content has been populated. The allowed set is exactly {'planned', 'collected'} — a documented contract, not a DB-enforced enum (same convention as Claim.verdict and ProposedFix.eval_status); readers must treat any other value as unknown/unspecified.","ref_id":"d6ad0728-1710-4e49-a237-c684bc8ca70a","evidence_status":"?string"},{"icon":"QuoteIcon","primary_color":"#6D4C41","index":["text"],"text":"string","is_verbatim":"?boolean","page_number":"?int","parent":"Thing","node_key":"excerpt-text","secondary_color":"#D7CCC8","shape":"sphere","confidence":"?float","type":"Excerpt","bbox_y1":"?float","section":"?string","bbox_y0":"?float","bbox_x1":"?float","bbox_x0":"?float","description_key":"text","title_key":"text","domain":"Legal","type_description":"A verbatim text excerpt from a legal document. May carry a dual embedding: jarvis 384-dim text_embeddings and a graphrag-contract-review 1536-dim embedding property.","ref_id":"4a8dda06-3855-4be4-83c6-1b0de2c222ef"},{"icon":"NodesIcon","index":["name","description","documentation"],"pr_numbers":"?string","parent":"CodeArtifact","node_key":"feature-name","commit_shas":"?string","shape":"sphere","type":"Feature","description_key":"description","title_key":"name","repo":"?string","description":"?string","file":"?string","name":"string","documentation":"?string","domain":"CodeArtifact","type_description":"A specific capability or functionality within the application or codebase.","ref_id":"0fb370dc-4a4b-4caf-b3d7-a56149cdc366","created_at":"?string","last_updated":"?string"},{"page_number":"?int","node_key":"figure-matter_slug-source_ref-locator","secondary_color":"#D7CCC8","source_ref":"string","type":"Figure","currency":"?string","value_as_stated":"string","value_normalized":"?float","cell_ref":"?string","sheet_name":"?string","type_description":"The primary, as-stated datum captured verbatim from one specific source location — PRE-COMPUTATION and PRE-DERIVATION. NOT a ComputedFigure (a derived calculation) and NOT a FormulaComponent (a named formula input). ComputedFigure and FormulaComponent should link here via DERIVED_FROM edges to trace every calculated result back to its primary source.\n\nSOURCE_REF / LOCATOR GRAMMAR (agents MUST emit this exact form — punctuation and case are stripped before keying, so an inconsistent rendering creates a duplicate node for the same cell):\n source_ref = workbook or document filename exactly as ingested (e.g. 'RateCard_2024.xlsx').\n locator = ! for spreadsheets (e.g. 'RateCard!C2') OR p\\u00a7
for prose (e.g. 'p12\\u00a74.2').\n\nRE-INGEST SEMANTICS: re-ingest updates the node only when the caller passes reprocess=True (per create_or_merge_node in api/helper/schema_node_helper.py); non-key fields are last-write-wins (ON MATCH SET).","domain":"Legal","icon":"DocumentIcon","primary_color":"#6D4C41","locator":"string","index":["label","matter_slug","source_ref","locator","sheet_name","cell_ref","page_number","section","value_as_stated"],"parent":"Legal","label":"string","shape":"sphere","section":"?string","unit":"?string","extracted_by":"?string","description_key":"value_as_stated","title_key":"label","ref_id":"35aa277c-080f-41ba-8964-8d1d882ea91c","matter_slug":"string"},{"summary":"?string","icon":"ConstructionIcon","body":"?string","index":["name","summary"],"text":"?string","hash":"?string","parent":"Directory","node_key":"file-name-file","code":"?string","shape":"sphere","type":"File","description_key":"summary","title_key":"name","start":"?int","file":"string","name":"string","domain":"CodeArtifact","type_description":"A file within a repository, containing source code, configuration, or other project-related content.","ref_id":"1edd4f6d-b07c-4309-b40b-c4997cf35830","source_link":"?string","end":"?int"},{"current_value":"?string","index":["fluent_of","fluent_property"],"fluent_of":"string","domain":"entity","ref_id":"4c3db758-aec4-411e-bd5f-5b4fd78f6ccd","parent":"Thing","node_key":"fluent-fluent_of-fluent_property","type":"Fluent","fluent_property":"string"},{"value_ref_id":"string","asserted_by":"?string","index":["fluent_ref_id","valid_from"],"valid_from":"datetime","domain":"entity","ref_id":"3da3f8ca-7826-4137-ab3e-fe1a1f40fdf1","parent":"Thing","node_key":"fluentevent-fluent_ref_id-valid_from","confidence":"?float","fluent_ref_id":"string","type":"FluentEvent","valid_to":"?datetime"},{"icon":"CalculatorIcon","primary_color":"#6D4C41","index":["label"],"parent":"Legal","node_key":"formulacomponent-label","label":"string","secondary_color":"#D7CCC8","shape":"sphere","type":"FormulaComponent","unit":"?string","description_key":"description","title_key":"label","source":"?string","description":"?string","domain":"Legal","value":"?float","type_description":"A named, typed numeric input to a formula — carries its raw value, unit, source attribution, and plain-language description.","ref_id":"66362f5a-19d8-46cc-8f5b-faf53d10cc03"},{"summary":"?string","icon":"ConstructionIcon","body":"?string","index":["name","summary","description"],"text":"?string","docs":"?string","parent":"CodeArtifact","node_key":"function-name-file","code":"?string","shape":"sphere","type":"Function","operand":"?string","description_key":"summary","title_key":"name","output_data_type":"?string","start":"?int","description":"?string","file":"string","name":"string","domain":"CodeArtifact","type_description":"A function or method definition in source code, representing executable logic within a program, including backend logic and frontend components.","ref_id":"2c2b38fb-3bc9-415e-ac9d-af2d7326b153","source_link":"?string","end":"?int"},{"gap_type":"?string","remediation_plan":"?string","node_key":"gapitem-id","secondary_color":"#D7CCC8","resolution":"?string","type":"GapItem","id":"string","significance":"?string","description":"?string","priority":"?string","type_description":"A compliance gap — a requirement not yet met by the organization, with remediation tracking.","domain":"Legal","notified":"?boolean","opened":"?datetime","comment_tracker_id":"?string","icon":"ExclamationIcon","primary_color":"#6D4C41","policy_affected":"?string","index":["id","gap_type","owner","status"],"requirement":"?string","status":"?string","parent":"Thing","status_verified":"?boolean","shape":"sphere","change_needed":"?string","description_key":"gap_type","title_key":"requirement","owner":"?string","regulation":"?string","ref_id":"54743019-f3eb-4c15-b9ca-0ab5cece8753","due":"?string"},{"output_json":"?string","node_key":"generated_step-step_unique_id","secondary_color":"#F468D4","type":"Generated_step","workflow_position":"?int","id":"string","description":"?string","name":"string","type_description":"A dynamically generated step in a workflow with specific configuration and parameters","domain":"Workflow","skill_name":"?string","skill_id":"?int","icon":"GeneratedStepIcon","primary_color":"#38243C","index":["name","description"],"parent":"Workflow","input_json":"?string","shape":"sphere","params":"?string","step_unique_id":"string","description_key":"description","title_key":"name","step_json":"?string","ref_id":"72935346-72fa-41e8-b1d2-b05392010461","attributes":"?string"},{"icon":"NodesIcon","index":["name","description"],"parent":"Repository","node_key":"githubrepo-name","shape":"sphere","type":"GitHubRepo","namespace":"?string","forks":"?int","description_key":"description","title_key":"name","description":"?string","stars":"?int","age_years":"?float","name":"string","domain":"CodeArtifact","type_description":"A GitHub repository containing metadata such as stars, forks, description, and language information.","ref_id":"ca6c9c0b-3bad-4421-993e-aedb7dbcd783","language":"?string"},{"index":["name","description"],"twitter_handle":"?string","parent":"Person","node_key":"guest-name","type":"Guest","is_favorite":"?boolean","description_key":"description","title_key":"name","image_url":"?string","description":"?string","name":"string","domain":"Entity","ref_id":"dde71be2-df05-4fa4-a47e-8ba8a4575a0b"},{"icon":"NodesIcon","index":["ref_id","question","answer"],"answer":"?string","parent":"KnowledgeArtifact","node_key":"hint-ref_id","shape":"sphere","type":"Hint","description_key":"answer","title_key":"ref_id","domain":"KnowledgeArtifact","type_description":"A question and answer pair generated from exploring the codebase to capture contextual understanding.","ref_id":"db4b0f4c-d1df-4188-813c-ba2b928085e3","question":"?string"},{"icon":"NodesIcon","primary_color":"#1B3134","index":["name","display_name","description"],"default_model":"?string","parent":"Thing","node_key":"hiveagent-name","secondary_color":"#21B38A","shape":"sphere","type":"HiveAgent","display_name":"?string","updated_at":"?string","description_key":"description","title_key":"display_name","description":"?string","name":"string","domain":"Hive","type_description":"An AI agent in the Hive agent catalog, mirrored from the gateway registry.","ref_id":"6704bd70-20b1-4891-8fb7-2689751f9e97"},{"icon":"MessageIcon","primary_color":"#1D3140","index":["name","message"],"status":"?string","task_id":"?string","parent":"Thing","message_id":"string","node_key":"hivechatmessage-message_id","secondary_color":"#4FA7D9","shape":"sphere","type":"HiveChatMessage","message":"string","updated_at":"?string","description_key":"message","title_key":"name","feature_id":"?string","name":"string","domain":"Hive","type_description":"A chat message in a Hive task/feature conversation, mirrored from Postgres.","ref_id":"4ca85386-86da-49fc-b85d-53452dac07e9","role":"?string","created_at":"?string","user_id":"?string"},{"decision_id":"string","icon":"MessageIcon","primary_color":"#302342","index":["name","text"],"text":"?string","canvas_ref":"?string","parent":"Thing","node_key":"hivedecision-decision_id","secondary_color":"#C25AF3","shape":"sphere","type":"HiveDecision","description_key":"text","title_key":"name","name":"string","domain":"Hive","type_description":"A decision extracted from a Hive canvas, mirrored from Postgres.","ref_id":"8694bce9-a70b-4922-8bed-4e86733cbfa5","y":"?float","x":"?float"},{"icon":"NodesIcon","primary_color":"#2A2545","index":["name","brief","requirements","architecture"],"status":"?string","workspace_id":"?string","parent":"Thing","node_key":"hivefeature-feature_id","secondary_color":"#9368FB","shape":"sphere","architecture":"?string","type":"HiveFeature","requirements":"?string","updated_at":"?string","description_key":"brief","title_key":"name","assignee_id":"?string","priority":"?string","feature_id":"string","name":"string","domain":"Hive","type_description":"A roadmap feature in the Hive PM app, mirrored from Postgres.","ref_id":"b9c9f00c-40dd-48a8-8c38-656fdfa325d7","created_at":"?string","brief":"?string"},{"icon":"NodesIcon","primary_color":"#22362A","index":["name","description"],"completed_at":"?string","status":"?string","parent":"Thing","node_key":"hiveinitiative-initiative_id","secondary_color":"#54AC52","shape":"sphere","type":"HiveInitiative","org_id":"?string","updated_at":"?string","description_key":"description","title_key":"name","assignee_id":"?string","description":"?string","name":"string","initiative_id":"string","domain":"Hive","type_description":"An org-level initiative in the Hive PM app, mirrored from Postgres.","ref_id":"abebfe52-8b71-487c-84ce-6c7048e49f04","target_date":"?string","created_at":"?string","start_date":"?string"},{"milestone_id":"string","icon":"NodesIcon","primary_color":"#2A3229","index":["name","description"],"completed_at":"?string","status":"?string","parent":"Thing","node_key":"hivemilestone-milestone_id","secondary_color":"#96BD3F","shape":"sphere","type":"HiveMilestone","updated_at":"?string","description_key":"description","title_key":"name","assignee_id":"?string","description":"?string","sequence":"?int","name":"string","initiative_id":"?string","domain":"Hive","type_description":"A milestone within a Hive initiative, mirrored from Postgres.","ref_id":"8b0a7cf1-4d62-4470-a360-768874a9686b","due_date":"?string","created_at":"?string"},{"icon":"MessageIcon","primary_color":"#38243C","index":["name","text"],"text":"?string","canvas_ref":"?string","parent":"Thing","node_key":"hivenote-note_id","secondary_color":"#F468D4","shape":"sphere","type":"HiveNote","description_key":"text","title_key":"name","note_id":"string","name":"string","domain":"Hive","type_description":"A note extracted from a Hive canvas, mirrored from Postgres.","ref_id":"28f166cc-6b8e-411b-b6fe-fd2f8e432a18","y":"?float","x":"?float"},{"summary":"?string","topic":"?string","icon":"NodesIcon","primary_color":"#36292D","index":["name","topic","summary","content"],"parent":"Thing","node_key":"hiveresearch-research_id","secondary_color":"#A96755","shape":"sphere","type":"HiveResearch","content":"?string","org_id":"?string","updated_at":"?string","description_key":"summary","title_key":"name","name":"string","research_id":"string","initiative_id":"?string","domain":"Hive","type_description":"A research document in the Hive PM app, mirrored from Postgres.","ref_id":"486de1e8-9fe2-4509-bbf7-cfdc15c3cecd","created_at":"?string","slug":"?string"},{"summary":"?string","task_id":"string","node_key":"hivetask-task_id","source_type":"?string","secondary_color":"#5E84F8","type":"HiveTask","repository_id":"?string","assignee_id":"?string","description":"?string","priority":"?string","feature_id":"?string","name":"string","type_description":"A task / work item in the Hive PM app, mirrored from Postgres.","domain":"Hive","created_at":"?string","phase_id":"?string","icon":"TaskIcon","primary_color":"#222B48","index":["name","description","summary"],"status":"?string","workspace_id":"?string","parent":"Thing","shape":"sphere","updated_at":"?string","description_key":"description","title_key":"name","ref_id":"4c420f55-a788-443a-af4c-75fbe926513e","branch":"?string"},{"icon":"BriefcaseIcon","primary_color":"#362429","index":["name","description","mission"],"workspace_id":"string","parent":"Thing","node_key":"hiveworkspace-workspace_id","secondary_color":"#D25353","shape":"sphere","type":"HiveWorkspace","updated_at":"?string","description_key":"description","title_key":"name","mission":"?string","description":"?string","name":"string","domain":"Hive","type_description":"A Hive workspace, mirrored from Postgres. The single anchor node for workspace-level knowledge: general Concepts (preferences, best practices, gotchas, processes) link here rather than to any repository.","ref_id":"d7f784a6-faa5-4721-99ef-76f1d628c13a","created_at":"?string","slug":"?string"},{"icon":"PersonIcon","primary_color":"#38243C","index":["name","description"],"parent":"Thing","node_key":"hiveworkspacemember-member_id","secondary_color":"#F468D4","shape":"sphere","type":"HiveWorkspaceMember","member_id":"string","description_key":"description","title_key":"name","description":"?string","name":"string","joined_at":"?string","domain":"Hive","type_description":"A member of a Hive workspace, mirrored from Postgres. Anchor node for per-person knowledge: a member's preference Concepts link here via PREFERENCE edges.","ref_id":"88e5a7c7-2b22-471e-a7d4-11cea2a57130","role":"?string","github_username":"?string","user_id":"?string"},{"index":["name","description"],"description_key":"description","title_key":"name","image_url":"?string","description":"?string","name":"string","domain":"Entity","ref_id":"b1c5f9b6-0f92-4613-9145-9a2798624fed","parent":"Person","node_key":"host-name","type":"Host","is_favorite":"?boolean"},{"registration_id":"string","use_in_commerce":"?boolean","owner_name":"?string","node_key":"ipasset-registration_id","secondary_color":"#D7CCC8","type":"IPAsset","docket_id":"?string","asset_type":"?string","name":"?string","type_description":"An intellectual property asset such as a patent, trademark, or copyright.","domain":"Legal","agent_managed":"?boolean","business_owner":"?string","classes":"?string","icon":"LightBulbIcon","primary_color":"#6D4C41","index":["registration_id","asset_type","name","status"],"priority_date":"?string","status":"?string","deployment_risk":"?string","local_agent":"?string","parent":"Thing","shape":"sphere","filing_date":"?string","description_key":"asset_type","title_key":"name","renewal_deadline":"?string","license_bucket":"?string","expiration_date":"?string","grant_date":"?string","ref_id":"911e578d-4dcf-4117-bf8d-e31162a451ac"},{"body":"?string","index":["name","body"],"parent":"CodeArtifact","node_key":"import-name-file","type":"Import","description_key":"body","title_key":"name","start":"?int","file":"string","name":"string","domain":"CodeArtifact","type_description":"A section at the top of a file that contains all imported modules, libraries, or dependencies used within the file.","ref_id":"370d619f-e4fb-42ca-8ed4-25034c178aab","end":"?int"},{"icon":"NodesIcon","body":"?string","index":["name","body"],"parent":"CodeArtifact","node_key":"instance-name-file","shape":"sphere","type":"Instance","description_key":"body","title_key":"name","start":"?int","file":"string","name":"string","domain":"CodeArtifact","type_description":"An instantiation of a class in source code, representing a specific object created from a class definition.","ref_id":"7aa1521f-4804-476f-9aca-066976165a5d","end":"?int"},{"icon":"NodesIcon","body":"?string","index":["name","body"],"parent":"Test","node_key":"integrationtest-name-file","shape":"sphere","type":"IntegrationTest","description_key":"body","title_key":"name","start":"?int","file":"string","name":"string","domain":"CodeArtifact","type_description":"An integration test verifying multiple components or an API boundary working together.","ref_id":"d29c7643-41e0-4d28-b334-d234e96be5d2","end":"?int"},{"icon":"SearchIcon","primary_color":"#6D4C41","index":["matter_slug","status","investigation_type"],"status":"string","parent":"Legal","node_key":"investigationlog-allegation","secondary_color":"#D7CCC8","shape":"sphere","type":"InvestigationLog","conduct_timeframe":"?string","attorney_directed":"boolean","investigation_type":"?string","allegation":"string","description_key":"investigation_type","title_key":"allegation","domain":"Legal","type_description":"An attorney-directed or HR investigation log for a workplace or regulatory matter.","ref_id":"40876b28-17da-4fbd-aef0-305af9809be9","last_updated":"?datetime"},{"icon":"NodesIcon","index":"name","count":"?int","parent":"Repository","node_key":"issues-name","shape":"sphere","type":"Issues","namespace":"?string","description_key":"name","title_key":"name","name":"string","domain":"CodeArtifact","type_description":"A collection of individual issue nodes belonging to a repository.","ref_id":"57061e5d-760d-4765-87da-e91cf6420b66"},{"icon":"NodesIcon","index":["name","description"],"parent":"KnowledgeArtifact","node_key":"jargon-name","shape":"sphere","type":"Jargon","description_key":"description","title_key":"name","description":"?string","name":"string","domain":"KnowledgeArtifact","type_description":"An internally-used term and its meaning, optionally linked to the graph node it names.","ref_id":"9bde9004-f412-48c2-ad52-3809ce2fbdf6"},{"forum":"?string","state":"?string","node_key":"jurisdiction-name","secondary_color":"#D7CCC8","type":"Jurisdiction","court_system":"?string","level":"?string","name":"string","type_description":"A legal jurisdiction, such as a country, state, or regulatory body forum.","domain":"Legal","icon":"GlobeIcon","primary_color":"#6D4C41","index":["name","forum"],"sali_locale":"?string","parent":"Thing","shape":"sphere","country":"?string","sali_court_code":"?string","description_key":"forum","parent_ref_id":"?string","appeal_path_ref_id":"?string","title_key":"name","ref_id":"f08db6ef-c471-400f-b418-41a5b7a7ad2e","circuit":"?string","jurisdiction_kind":"?string"},{"icon":"BookIcon","index":"name","domain":"KnowledgeArtifact","type_description":"An abstract parent for AI-generated and user-facing knowledge nodes.","ref_id":"715266b4-4e95-47c1-800c-5591608fdd69","parent":"Thing","type":"KnowledgeArtifact"},{"icon":"NodesIcon","index":"name","description_key":"name","title_key":"name","name":"string","domain":"CodeArtifact","type_description":"A programming language used in the repository.","ref_id":"aef66983-e555-4fbd-8d18-bf1675656503","parent":"CodeArtifact","node_key":"language-name","shape":"sphere","type":"Language"},{"icon":"BookIcon","index":["name","description"],"parent":"CodeArtifact","node_key":"learning-name","shape":"sphere","type":"Learning","description_key":"description","title_key":"name","description":"?string","name":"string","domain":"CodeArtifact","type_description":"A learning resource or educational content item associated with a codebase.","ref_id":"2942e22b-8c6c-4189-bfc6-a2f769a69f51"},{"icon":"HomeIcon","lessee":"?string","primary_color":"#6D4C41","index":["name","lessor","lessee","property_address","lease_term"],"lessor":"?string","parent":"Agreement","node_key":"leaseagreement-id","property_address":"?string","secondary_color":"#D7CCC8","shape":"sphere","type":"LeaseAgreement","security_deposit":"?float","id":"string","description_key":"property_address","title_key":"name","monthly_rent":"?float","name":"?string","domain":"Legal","type_description":"A lease agreement specifying terms between a lessor and lessee for a property.","ref_id":"151c0569-88b7-4780-a822-e67832506dd4","lease_term":"?string"},{"icon":"ScalesIcon","primary_color":"#6D4C41","index":["name"],"parent":"Thing","secondary_color":"#D7CCC8","shape":"sphere","type":"Legal","description_key":"description","title_key":"name","description":"?string","name":"?string","domain":"Legal","type_description":"Domain anchor for all Legal entity types in the knowledge graph.","ref_id":"a08a10c6-d169-4924-8565-28533ffa9985"},{"node_key":"legalargument-matter_slug-argument_id","secondary_color":"#D7CCC8","resolution":"?string","type":"LegalArgument","source_document":"?string","priority":"?string","type_description":"A legal argument, statutory position, citation, or evidentiary issue identified in a litigation document.","domain":"Legal","raised_by":"?string","argument_id":"string","icon":"ScaleIcon","primary_color":"#6D4C41","statute_or_case":"?string","index":["matter_slug","argument_kind","statute_or_case"],"parent":"Legal","weakness_flag":"?boolean","severity":"?string","shape":"sphere","assertion":"string","description_key":"argument_kind","title_key":"assertion","ref_id":"081b2c0d-4f76-44f4-ba9b-51b2b8ab336a","notes":"?string","argument_kind":"string","matter_slug":"string"},{"icon":"LockClosedIcon","primary_color":"#6D4C41","next_refresh":"?string","index":["matter_slug","status","issued_date"],"last_refresh":"?datetime","scope":"?string","status":"?string","parent":"Thing","node_key":"legalhold-matter_slug","secondary_color":"#D7CCC8","shape":"sphere","type":"LegalHold","issued_by":"?string","released":"?boolean","description_key":"scope","title_key":"matter_slug","issued_date":"?string","release_date":"?datetime","domain":"Legal","type_description":"A legal hold (litigation hold) preserving documents and data relevant to anticipated or ongoing litigation.","ref_id":"af04c6fd-58fd-416c-815c-c66fa7de8eb4","matter_slug":"string"},{"player_role":"string","node_key":"legalparty-matter_slug-entity_id-player_role","secondary_color":"#D7CCC8","type":"LegalParty","entity_id":"string","end_date":"?datetime","side":"?string","type_description":"A matter-scoped player (person or organization) with a specific role in a legal matter. Implements the SALI LMSS Player model with player_role and representation_role separation.","domain":"Legal","firm_name":"?string","icon":"UserCircleIcon","representation_role":"?string","primary_color":"#6D4C41","index":["player_role","representation_role","matter_slug"],"entity_kind":"string","parent":"Legal","shape":"sphere","entity_name":"string","description_key":"player_role","bar_number":"?string","title_key":"entity_name","ref_id":"ad1cd3b9-6230-42bb-9dc2-2b38cbac7022","is_primary":"?boolean","notes":"?string","start_date":"?datetime","matter_slug":"string"},{"body":"?string","index":["name","body"],"parent":"CodeArtifact","node_key":"library-name-file","type_descrioption":"A reusable collection of code or modules providing functionality that can be imported and used in other projects.","type":"Library","description_key":"body","title_key":"name","start":"?int","file":"string","name":"string","domain":"CodeArtifact","ref_id":"5714a98a-d44b-4b09-b3c4-841963535f10","end":"?int"},{"icon":"ClockIcon","primary_color":"#6D4C41","index":["jurisdiction","matter_type"],"parent":"Legal","node_key":"limitationstatute-jurisdiction-matter_type","limitation_years":"float","secondary_color":"#D7CCC8","shape":"sphere","jurisdiction":"string","type":"LimitationStatute","description_key":"jurisdiction","title_key":"matter_type","matter_type":"string","domain":"Legal","type_description":"A statute of limitations applicable to a given matter type within a jurisdiction.","ref_id":"8f8e1d3d-ddbe-484a-9998-0bdf4a4e5b6c","notes":"?string","discovery_rule":"boolean"},{"icon":"BookTextIcon","primary_color":"#1D3140","index":["name","definition"],"definition":"?string","parent":"Thing","node_key":"lingo-name","secondary_color":"#4FA7D9","shape":"sphere","type":"Lingo","lingo_type":"?string","description_key":"definition","title_key":"name","name":"string","domain":"Entity","type_description":"A domain-specific term or vocabulary entry","ref_id":"425b3de0-fb58-4144-a334-32e6c86497bb"},{"icon":"PlaceIcon","primary_color":"#2A2545","index":["name","description"],"parent":"Thing","node_key":"location-name","secondary_color":"#9368FB","shape":"sphere","type":"Location","description_key":"description","title_key":"name","description":"?string","name":"string","domain":"Entity","type_description":"A physical or virtual location","ref_id":"7420f347-3b7a-4b06-b024-a0a5630eeb75"},{"next_action":"?string","closed_date":"?datetime","limitation_deadline":"?datetime","risk_likelihood":"?string","node_key":"matter-slug","secondary_color":"#D7CCC8","jurisdiction":"?string","type":"Matter","instruction_ledger":"?string","damages_calculation":"?string","stage":"?string","initial_posture":"?string","termination_kind":"?string","our_role":"?string","file_no":"?string","name":"?string","next_action_date":"?datetime","type_description":"A legal matter or case, including litigation, regulatory investigation, or transactional matter.","domain":"Legal","outside_counsel":"?string","last_touched":"?datetime","conflict_check_done":"?boolean","client_name":"?string","opened_date":"?datetime","icon":"BriefcaseIcon","statutory_exceptions":"?string","primary_color":"#6D4C41","index":["slug","name","matter_type","status"],"status":"?string","parent":"Thing","shape":"sphere","outcome":"?string","exposure_range":"?string","description_key":"matter_type","title_key":"name","matter_type":"?string","confidentiality":"?string","risk_severity":"?string","ref_id":"c327a21e-6b39-4139-a361-cb3ead2eb56c","slug":"string","materiality":"?string","final_cost":"?string"},{"icon":"GeneratedStepIcon","primary_color":"#38243C","index":"content","parent":"Workflow","memory_id":"string","node_key":"memory-memory_id","secondary_color":"#F468D4","shape":"sphere","type":"Memory","content":"string","description_key":"content","title_key":"memory_id","domain":"Workflow","type_description":"A memory unit for storing information and context learned by an Agent.","ref_id":"35e2971d-468d-44b7-8c0d-085e5c3239ca"},{"media_type":"?string","chat_pubkey":"?string","node_key":"message-uuid","secondary_color":"#54AC52","media_token":"?string","date":"int","type":"Message","kind":"?int","amount":"?int","sender":"string","media_key":"?string","type_description":" A communication conveyed through text, speech, or signals","domain":"Content","reply":"?string","thread_uuid":"?string","icon":"MessageIcon","primary_color":"#22362A","index":"content","parent":"Content","shape":"sphere","content":"string","description_key":"content","title_key":"content","ref_id":"7df3f6c6-afc0-4e30-97f7-494fcab47632","uuid":"string"},{"body":"?string","index":["name","body"],"parent":"CodeArtifact","node_key":"mock-name","mocked":"boolean","type":"Mock","description_key":"body","title_key":"name","start":"?int","file":"?string","name":"string","domain":"CodeArtifact","type_description":"A mock object or function used for testing purposes, simulating the behavior of real components.","ref_id":"0fefd66a-92c5-4a82-b90b-31c36db85fa2","end":"?int"},{"icon":"DocumentIcon","primary_color":"#2A2545","index":"source_link","parent":"Content","node_key":"multimedia-source_link","secondary_color":"#9368FB","shape":"sphere","type":"Multimedia","description_key":"source_link","title_key":"source_link","domain":"Content","type_description":"A generic type of content","ref_id":"3a74c3eb-73ff-46a1-86e7-d3de66775eed","source_link":"string"},{"firm_size":"?string","node_key":"organization-name","secondary_color":"#C25AF3","type":"Organization","practice_areas":"?string","court_system":"?string","image_url":"?string","description":"?string","name":"string","type_description":"A structured group of people with a collective purpose","domain":"Entity","org_kind":"?string","enabling_statute":"?string","court_level":"?string","icon":"OrganizationIcon","sali_govt_code":"?string","primary_color":"#302342","index":["name","description"],"sali_industry_code":"?string","acronym":"?string","parent":"Thing","primary_jurisdiction":"?string","shape":"sphere","sali_court_code":"?string","description_key":"description","title_key":"name","ref_id":"f9cae1c9-aab6-4d7a-bcdd-4d867e1ebc6f","circuit":"?string"},{"icon":"NodesIcon","body":"?string","index":["name","body"],"parent":"CodeArtifact","node_key":"package-name-file","shape":"sphere","type":"Package","description_key":"body","title_key":"name","start":"?int","file":"string","name":"string","domain":"CodeArtifact","type_description":"A package or module grouping related source files and dependencies within a repository.","ref_id":"b58ce83c-582c-45c2-a3c7-3ee4b61a7a31","end":"?int"},{"body":"?string","index":["name","body"],"parent":"CodeArtifact","node_key":"page-name-file","type":"Page","description_key":"body","title_key":"name","start":"?int","file":"string","name":"string","domain":"CodeArtifact","type_description":"A webpage or route within an application, representing a specific view or section of the system. It can serve as the starting point for a codemap.","ref_id":"45ed4c69-359f-4a24-8edf-3df33c09f9ee","end":"?int"},{"certification_number":"?string","icon":"PersonIcon","primary_color":"#362429","bar_state":"?string","index":["name","description"],"alias":"?string","bar_admitted_date":"?datetime","twitter_handle":"?string","parent":"Thing","node_key":"person-name","secondary_color":"#D25353","shape":"sphere","type":"Person","title":"?string","bar_number":"?string","description_key":"description","title_key":"name","image_url":"?string","expertise_domain":"?string","description":"?string","name":"string","domain":"Entity","type_description":"A human being regarded as an individual","ref_id":"3b7acdb2-3238-4ce9-b595-01f68d2aaee0"},{"icon":"PlaceIcon","primary_color":"#2A2545","index":["name","description"],"parent":"Thing","node_key":"place-name","secondary_color":"#9368FB","shape":"sphere","type":"Place","description_key":"description","title_key":"name","image_url":"?string","description":"?string","name":"string","domain":"Entity","type_description":"A particular position, point, or area in space","ref_id":"392aa4ca-b1d5-4c66-8e36-3f41f602165d"},{"icon":"BookmarkIcon","primary_color":"#6D4C41","index":["scope","clause_type","severity"],"scope":"string","parent":"Legal","node_key":"playbookentry-scope-clause_type","severity":"string","suggested_text":"?string","secondary_color":"#D7CCC8","shape":"sphere","fallback_position":"?string","type":"PlaybookEntry","clause_type":"string","red_line":"boolean","description_key":"firm_position","title_key":"clause_type","firm_position":"string","domain":"Legal","type_description":"A negotiation playbook entry specifying firm positions and fallback positions for a contract clause type.","ref_id":"1829e31d-421d-49fa-8078-6685e113519d","notes":"?string"},{"link":"?string","node_key":"podcast-episode_title-timestamp","secondary_color":"#4FA7D9","sentiment_score":"?float","date":"?datetime","type":"Podcast","timestamp":"string","image_url":"?string","description":"?string","type_description":"A digital audio program made up of episodic recordings","domain":"Content","source_link":"?string","pub_key":"?string","icon":"AudioIcon","primary_color":"#1D3140","text":"?string","index":["episode_title","text","description"],"episode_title":"string","media_url":"string","parent":"Episode","show_title":"?string","shape":"sphere","num_boost":"?int","description_key":"description","title_key":"episode_title","english_translation":"?string","ref_id":"3ed41af8-6d8e-4d0b-a799-8e74712e6f8a","boost":"?int","language":"?string"},{"icon":"DocumentTextIcon","primary_color":"#6D4C41","index":["name"],"parent":"Thing","node_key":"policy-name","secondary_color":"#D7CCC8","shape":"sphere","type":"Policy","description_key":"description","title_key":"name","description":"?string","name":"string","domain":"Legal","type_description":"An internal or external policy document governing organizational conduct.","ref_id":"87ab2b1b-db8c-4083-86d9-c1a4b70c53c2"},{"icon":"DatabaseIcon","primary_color":"#6D4C41","index":["name","legal_basis","regime"],"parent":"Thing","node_key":"processingactivity-name","secondary_color":"#D7CCC8","shape":"sphere","purpose":"?string","type":"ProcessingActivity","description_key":"purpose","title_key":"name","legal_basis":"?string","name":"string","domain":"Legal","type_description":"A data processing activity subject to privacy regulations such as GDPR or CCPA.","ref_id":"6b70e0dd-d633-49df-9bd5-5563a021bd8d","triage_result":"?string","regime":"?string"},{"primary_color":"#353124","index":"name","description_key":"name","title_key":"name","name":"string","domain":"Entity","type_description":"A product or item","ref_id":"9fe7badd-c23a-42ca-9638-a22c47d1e15a","parent":"Thing","node_key":"product-name","secondary_color":"#BA9D39","type":"Product"},{"icon":"NodesIcon","body":"?string","index":["name","description","body"],"parent":"Workflow","node_key":"prompt-id","shape":"sphere","type":"Prompt","id":"string","description_key":"description","title_key":"name","description":"?string","name":"?string","domain":"Workflow","type_description":"A prompt template used within workflow definitions.","ref_id":"915b2c28-4905-4dc6-a9cd-9ed43cecbdfa","customer_id":"?int"},{"summary":"?string","fix_type":"string","node_key":"proposedfix-fix_id","secondary_color":"#E09242","before_score":"?string","type":"ProposedFix","criterion_title":"?string","stakwork_run_id":"?string","new_prompt_version_id":"?string","fix_id":"string","prompt_name":"?string","rerun_run_id":"?string","prompt_id":"?string","resolved_by":"?string","type_description":"A fix-scoped, fix-type-polymorphic node representing any eval-driven improvement. One node per fix, identified by a caller-generated, globally-unique fix_id (NOT one node per criterion). fix_type is an open string; conventional values: prompt | workflow | architecture | schema | other — new fix kinds require no migration. Criterion and prompt fields are optional; populate them only when fix_type=prompt. rerun_run_id references the upstream evaluation run id (e.g. EvalTriggerOutput.id) that produced this fix proposal — it is NOT an EvalRun.id reference (EvalRun is deprecated from the canonical model as of migration 084). Anchored to the unified eval chain: EvalSet → EvalRequirement → EvalTrigger → EvalTriggerOutput → CriterionResult → ProposedFix. Duplicate fix_id values are silently merged (not rejected) by the node_key migration helper; callers must ensure global uniqueness. OUTCOME FIELD — eval_status (canonical): the accept/reject outcome of this fix. Lifecycle: pending → accepted | rejected. Exact allowed set only — downstream readers and writers MUST validate against this fixed set before acting on it; a malformed or unexpected value would silently mis-branch accept/reject logic in the recursion loop (accepted = trunk node, rejected = dead-end leaf). LEGACY FIELD — status: retained for compatibility; no longer the outcome signal. Do not use status for accept/reject branching in new code; use eval_status instead. FIX LINEAGE — DERIVED_FROM edge (child → parent, append-only, git-commit-parent style): accepted fixes form a linear trunk (latest accepted = the tip, i.e. the accepted node with no accepted child pointing to it); a rejected fix is a dead-end leaf pointing at the accepted parent it was tried against. Only the accepted trunk is linearly ordered by topology; rejected siblings off one accepted parent are an unordered set by design — no timestamp or sequence field is added. PARENT LOOKUP — parent_fix_id: a denormalized, edge-free mirror of the DERIVED_FROM parent (analogous to rerun_run_id). The DERIVED_FROM edge is the source of truth; keeping parent_fix_id consistent with the edge and rejecting cycles is the responsibility of the sibling writer feature, not enforced by this ontology. TRAVERSAL SAFETY CONTRACT: no acyclicity or depth guarantee exists at the ontology layer. Downstream chain-walkers (recursion cron, eval-runner) MUST bound traversal depth and reject cycles — e.g. validate parent_fix_id lineage before writing a new DERIVED_FROM edge — otherwise a cycle written later could loop a walker unbounded. TARGET SNAPSHOT (generic before/after for any fix kind) — five optional fields added by migration 105: target_type, target_name, target_version, old_value, new_value. old_value/new_value each hold ONE JSON object serialized to a JSON string via json.dumps — never a raw object (both are typed ?string, so validate_by_schema rejects non-string values). Conventional envelope shapes by target_type: prompt -> {\"text\": ...}; concept -> {\"name\": ..., \"documentation\": ...} — readers MUST accept either \"documentation\" or \"docs\" as the concept body key (Concept's body field may be renamed from documentation to docs in a separate in-flight change; this convention is forward-compatible with either); workflow -> the workflow's JSON definition. These shapes are a documented convention only, NOT runtime-validated at the schema layer — readers must tolerate a missing or unparseable envelope gracefully (render the raw text and flag it, never throw). DISCRIMINATOR PRECEDENCE: target_type is authoritative for interpreting the snapshot envelope; fix_type remains the existing fix-kind label. The two are not schema-enforced to agree. When target_type is absent (true for every pre-existing ProposedFix node — no backfill is performed), readers fall back to fix_type for labelling and render an empty-snapshot state. RELATION TO EXISTING BEFORE/AFTER FIELDS (none deprecated by 105): failing_value/passing_value/delta are criterion-level observed values; before_score/after_score/score_delta are numeric eval scores; old_value/new_value are the full target-artifact snapshot — a diff renderer should read only old_value/new_value. DENORMALIZED IDENTITY: target_ref remains the source of truth for target identity; target_name/target_version are edge-free display mirrors (same spirit as parent_fix_id) that may go stale — keeping them consistent is the writer's responsibility, not enforced here. For fix_type=prompt, prompt_name/prompt_version_id/new_prompt_version_id remain canonical; target_name/target_version merely mirror them. WRITE PATH: attach a snapshot to an existing ProposedFix via POST /v2/nodes with reprocess=true (in-place update, preserves DERIVED_FROM lineage); never force_delete (DETACH DELETE destroys lineage) and never allow_scratchpad=true (a rejected write would be durably parked as a ScratchpadEntry under a different access-control model — undesirable for large snapshot payloads). SECRET HYGIENE: workflow-target JSON snapshots can embed credentials/secrets; old_value/new_value are deliberately publicly readable (no paid_properties gating), so producers MUST redact credentials/secret values before writing a workflow-targeted snapshot.","domain":"CodeArtifact","target_version":"?string","criterion_id":"?string","parent_fix_id":"?string","after_score":"?string","icon":"PencilAltIcon","rerun_status":"?string","primary_color":"#392828","index":["fix_id","fix_type","summary","status","task_slug"],"new_value":"?string","target_name":"?string","status":"?string","delta":"?string","parent":"Thing","shape":"sphere","target_ref":"?string","resolved_at":"?string","eval_status":"?string","task_slug":"?string","passing_value":"?string","reasoning":"string","prompt_version_id":"?string","title_key":"summary","old_value":"?string","rubric_criterion_ref":"?string","score_delta":"?string","ref_id":"9f787d04-0aa0-4131-b284-548245517792","target_type":"?string","failing_value":"?string"},{"icon":"NodesIcon","index":["name","description"],"state":"?string","parent":"Repository","node_key":"pullrequest-name","number":"?int","shape":"sphere","type":"PullRequest","namespace":"?string","description_key":"description","title_key":"name","description":"?string","name":"string","domain":"CodeArtifact","type_description":"A pull request created by a developer to merge changes into the main branch.","ref_id":"e9eed9da-2487-4ab3-beca-702c04e6c4a6","created_at":"?string","source_link":"?string","user":"?string"},{"icon":"BookOpenIcon","primary_color":"#6D4C41","index":["name","agency","regime"],"status":"?string","parent":"Thing","agency":"?string","status_verified":"?boolean","node_key":"regulation-name","secondary_color":"#D7CCC8","shape":"sphere","type":"Regulation","relevance_hook":"?string","description_key":"regime","title_key":"name","name":"string","domain":"Legal","type_description":"A law, regulation, or regulatory framework applicable to the organization (e.g. GDPR, CCPA, SOX).","ref_id":"a5e50fb4-1b08-4679-bd56-6927d469c39e","effective_date":"?string","regime":"?string","item_type":"?string"},{"link":"?string","node_key":"regulatoryitem-id","secondary_color":"#D7CCC8","type":"RegulatoryItem","decision":"?string","id":"string","title":"?string","type_description":"A discrete regulatory requirement, rule, or guidance item issued under a Regulation.","domain":"Legal","filed_at":"?datetime","detected":"?datetime","item_type":"?string","icon":"ClipboardListIcon","citation":"?string","primary_color":"#6D4C41","index":["id","item_type","agency","materiality_tier"],"materiality_tier":"?string","parent":"Thing","agency":"?string","shape":"sphere","description_key":"item_type","title_key":"title","ref_id":"c80b1515-af2d-41ea-8dba-d19bebf857ba","effective_date":"?datetime","owner_slack":"?string","comment_deadline":"?string"},{"business_owner":"?string","icon":"RefreshIcon","primary_color":"#6D4C41","renewal_mechanism":"?string","index":["counterparty","signed_date","status"],"cancel_by":"?datetime","signed_date":"string","status":"string","notice_period_days":"?int","initial_term_end":"?datetime","parent":"Legal","node_key":"renewalentry-counterparty-signed_date","secondary_color":"#D7CCC8","shape":"sphere","price_on_renewal":"?string","type":"RenewalEntry","counterparty":"string","description_key":"status","title_key":"counterparty","domain":"Legal","type_description":"A contract renewal record tracking key renewal dates, terms, and owners.","ref_id":"dda88769-ae75-41df-9cce-accd9d5cb4de","annual_value":"?string","clm_id":"?string"},{"icon":"HomeIcon","body":"?string","index":["name","body"],"hash":"?string","parent":"Thing","node_key":"repository-name-file-start","shape":"sphere","type":"Repository","description_key":"body","title_key":"name","start":"int","file":"string","name":"string","domain":"CodeArtifact","type_description":"A code repository that contains source files, directories, and version history.","ref_id":"35d0b681-fa57-4289-bc73-cceed785fcae","source_link":"?string","end":"?int"},{"summary":"?string","body":"?string","node_key":"request-name-file-verb","type":"Request","namespace":"?string","verb":"string","description":"?string","file":"string","name":"string","type_description":"An HTTP request representation, defining interactions with an API or web service.","domain":"CodeArtifact","source_link":"?string","end":"?int","icon":"ConstructionIcon","text":"?string","index":["name","summary","description"],"hash":"?string","parent":"CodeArtifact","shape":"sphere","description_key":"summary","title_key":"name","start":"?int","ref_id":"c71ceadd-e1d6-43b4-a23e-167e3366d6b4","method":"?string","handler":"?string"},{"icon":"RunIcon","primary_color":"#36292D","index":["project_id","workflow_state"],"parent":"Workflow","node_key":"run-project_id","secondary_color":"#A96755","shape":"sphere","type":"Run","evaluation":"?boolean","description_key":"workflow_state","title_key":"project_id","workflow_state":"?string","project_id":"int","domain":"Workflow","type_description":"An execution instance of a workflow or process","ref_id":"0127e76b-39f5-4e7f-b12c-4b29ab2eddbe"},{"icon":"StepIcon","primary_color":"#362429","index":["description","step_unique_id"],"output_json":"?string","parent":"Workflow","node_key":"run_step-step_unique_id","secondary_color":"#D25353","shape":"sphere","input_json":"?string","type":"Run_step","step_unique_id":"string","id":"string","description_key":"description","title_key":"step_unique_id","description":"?string","domain":"Workflow","type_description":"An individual step within a workflow run execution","ref_id":"6a640450-9511-45e7-8d42-95c7b8eae72f"},{"icon":"NodesIcon","index":["name","description"],"parent":"KnowledgeArtifact","node_key":"scope-name","shape":"sphere","type":"Scope","description_key":"description","title_key":"name","description":"?string","name":"string","domain":"KnowledgeArtifact","type_description":"A scope label that groups related learnings, such as a technology, pattern, or area of the codebase.","ref_id":"806755c4-2080-419e-9cd5-bd904bc8e3bb"},{"icon":"PencilAltIcon","index":["intended_type","name"],"entry_hash":"string","intended_type":"string","parent":"Thing","node_key":"scratchpadentry-intended_type-entry_hash","shape":"sphere","rejection_reason":"?string","type":"ScratchpadEntry","payload_json":"?string","title_key":"name","name":"?string","rejection_detail":"?string","domain":"Scratchpad","type_description":"A write that did not match the strict ontology, preserved verbatim instead of being rejected. intended_type records the node type the caller tried to create; payload_json holds the original node_data as a JSON string (the ontology validators reject undeclared attributes, so the payload cannot be spread into real properties). entry_hash is a sha256 of that payload, so a writer retrying the same rejected request repeatedly produces one node, not one per try. The Scratchpad domain is system-hidden: these nodes are excluded from search and are never offered to the extraction agent as a target type. INVARIANT: a ScratchpadEntry may be the SOURCE of an edge (so an entry keeps context by pointing at canonical nodes) but never the TARGET, so nothing traversing the canonical graph can walk into ungoverned data. Promotion of entries into real node types is deliberately out of scope; this tier is a staging area and a record of which node types the ontology is missing.","ref_id":"9b433ec6-e502-4cab-aabe-6b7ae0eadee3"},{"icon":"TaskIcon","primary_color":"#1B3134","body":"?string","index":["name","description","body"],"parent":"Workflow","node_key":"script-id","secondary_color":"#21B38A","shape":"sphere","type":"Script","id":"int","description_key":"description","title_key":"name","description":"?string","name":"?string","domain":"Workflow","type_description":"A script or code block used within workflow execution","ref_id":"7d605ac2-d97f-4c44-85b1-d1fbb3910c28","customer_id":"?int"},{"icon":"TaskIcon","primary_color":"#1B3134","usage_count":"?int","index":["name","description"],"parent":"Thing","node_key":"secret-id","secondary_color":"#21B38A","shape":"sphere","type":"Secret","id":"int","description_key":"description","title_key":"name","description":"string","name":"string","domain":"Workflow","type_description":"A named credential or sensitive value optionally scoped to a skill and customer.","usage_count_30d":"?int","ref_id":"9dfc3e87-4d02-454f-8c41-35d9cfb549d0","skill_id":"?int","customer_id":"?int"},{"summary":"?string","icon":"DocumentIcon","primary_color":"#2A2545","index":["text","source_link"],"text":"string","parent":"Document","node_key":"section-text","secondary_color":"#9368FB","shape":"sphere","type":"Section","description_key":"text","title_key":"text","domain":"Content","type_description":"A distinct part or subdivision of a document","ref_id":"7099575b-ee14-4e40-82e9-31668c8933c8","source_link":"?string"},{"icon":"VideoIcon","primary_color":"#38243C","index":"show_title","parent":"Content","node_key":"show-show_title","show_title":"string","secondary_color":"#F468D4","shape":"sphere","type":"Show","description_key":"show_title","title_key":"show_title","image_url":"?string","domain":"Content","type_description":" A podcast is a digital medium consisting of audio (or video) episodes that relate to a specific theme","ref_id":"6e6cd66e-9c96-412a-a0db-6330a55e98f1"},{"icon":"TaskIcon","primary_color":"#1D3140","usage_count":"?int","index":["name","description","input_schema","output_schema"],"graph_description":"?string","input_schema":"?string","output_schema":"?string","parent":"Workflow","node_key":"skill-name","secondary_color":"#4FA7D9","shape":"sphere","type":"Skill","id":"?int","description_key":"description","title_key":"name","description":"?string","name":"string","domain":"Workflow","type_description":"A reusable capability or function that can be composed into workflows","usage_count_30d":"?int","ref_id":"2af571af-d21a-412d-8177-3ce792e46317","skill_id":"?int","mockable":"?boolean"},{"icon":"StrategyIcon","primary_color":"#353124","index":["name","steps_list"],"LLM_response_id":"?int","parent":"Workflow","node_key":"strategy-strategy_id","secondary_color":"#BA9D39","shape":"sphere","type":"Strategy","description_key":"steps_list","title_key":"name","steps_list":"?string","name":"?string","domain":"Workflow","type_description":"A plan or approach for accomplishing a specific goal or set of objectives","ref_id":"b5c26d54-ad93-4685-aa22-dbc59d281bc2","strategy_id":"int","success":"?boolean"},{"icon":"TableIcon","primary_color":"#6D4C41","index":["column_name","state","column_type"],"column_type":"string","location":"?string","state":"string","parent":"Legal","node_key":"tabularreviewcell-column_name-column_type-state","secondary_color":"#D7CCC8","shape":"sphere","type":"TabularReviewCell","column_name":"string","description_key":"value","title_key":"column_name","quote":"?string","domain":"Legal","value":"?string","type_description":"A single cell in a tabular contract or document review, capturing a named column value for a specific document.","ref_id":"1459218f-3d70-4b21-8533-0d0cee7c1266"},{"taskId":"?string","icon":"TaskIcon","primary_color":"#2A3229","index":"task","status":"?string","task":"?string","task_id":"int","parent":"Workflow","node_key":"task-task_id","secondary_color":"#96BD3F","shape":"sphere","type":"Task","description_key":"task","title_key":"task","project_id":"?int","domain":"Workflow","type_description":"A specific work item or unit of work that needs to be completed","ref_id":"ff186ad2-b21e-427f-850e-8a6b346575c2","success":"?boolean"},{"icon":"ConstructionIcon","index":"name","domain":"CodeArtifact","type_description":"An abstract parent for all test types (unit, integration, e2e).","ref_id":"058238a1-f4bb-430f-a682-1ce9d8911b95","parent":"CodeArtifact","type":"Test"},{"unique_source_id":"?string","icon":"NodesIcon","primary_color":"#36292D","index":["name","description"],"weight":"?float","node_key":"thing-name","secondary_color":"#A96755","shape":"sphere","type":"Thing","description_key":"description","title_key":"name","image_url":"?string","description":"?string","name":"string","is_muted":"?boolean","type_description":"The highest-level node in the ontology hierarchy, representing an abstract concept with no direct individual instances","ref_id":"2f8b346c-74e3-43c2-9700-ce22c397c2ce"},{"icon":"CalendarIcon","primary_color":"#6D4C41","index":["matter_slug","entry_date","entry_type"],"parent":"Legal","node_key":"timelineentry-matter_slug-entry_date","entry_type":"string","secondary_color":"#D7CCC8","shape":"sphere","type":"TimelineEntry","author":"string","description_key":"entry_type","title_key":"description","source":"string","email_thread_id":"?string","description":"string","domain":"Legal","type_description":"A dated event or milestone on a legal matter timeline.","ref_id":"d52c3dfe-14c0-46c8-b31e-93a9aad85617","entry_date":"datetime","matter_slug":"string"},{"icon":"BookIcon","primary_color":"#1D3140","index":["name","description"],"parent":"Thing","node_key":"topic-name","secondary_color":"#4FA7D9","shape":"sphere","type":"Topic","description_key":"description","title_key":"name","image_url":"?string","description":"?string","name":"string","is_muted":"?boolean","domain":"Content","relevancy_score":"?float","type_description":"A subject or theme of discussion, study, or interest","ref_id":"83819187-c84f-492d-a112-f64e8ea62adc"},{"body":"?string","index":["name","body"],"parent":"CodeArtifact","node_key":"trait-name-file","type":"Trait","description_key":"body","title_key":"name","start":"?int","file":"string","name":"string","domain":"CodeArtifact","type_description":"A reusable set of properties or behaviors in source code, often used in object-oriented or functional programming.","ref_id":"594ae6bb-c5ac-42d4-ab8f-e4b31a5eafb8","end":"?int"},{"icon":"StepIcon","primary_color":"#2A2545","index":["content","tool"],"tool":"?string","parent":"Workflow","node_key":"turn-turn_id","secondary_color":"#9368FB","shape":"sphere","type":"Turn","turn_id":"string","outcome":"?string","content":"?string","turn_type":"?string","description_key":"content","title_key":"tool","order":"?int","domain":"Workflow","type_description":"A single turn in an agent session — a tool call, thought, response, user input, or error.","ref_id":"6888e270-a3fd-4aa0-b3cf-c447b747b84f","tokens":"?int"},{"quote_count":"?string","tweet_id":"string","twitter_handle":"?string","node_key":"tweet-tweet_id","secondary_color":"#D25353","date":"?datetime","type":"Tweet","followers":"?string","impression_count":"?string","image_url":"?string","description":"?string","verified":"?boolean","name":"?string","type_description":"A short message posted on a social media platform","domain":"Content","source_link":"?string","icon":"TwitterIcon","primary_color":"#362429","text":"?string","index":["text","twitter_handle"],"reply_count":"?string","status":"?string","media_url":"?string","parent":"Content","shape":"sphere","pubkey":"?string","description_key":"text","title_key":"twitter_handle","like_count":"?string","project_id":"?string","ref_id":"d7103144-1c0a-4ec9-91ee-713a84335514","retweet_count":"?string","bookmark_count":"?string"},{"icon":"TwitterIcon","primary_color":"#362429","index":["twitter_handle","name"],"verified_type":"?string","twitter_handle":"string","parent":"Thing","node_key":"twitteraccount-twitter_handle","secondary_color":"#D25353","shape":"sphere","type":"TwitterAccount","is_identity_verified":"?boolean","description_key":"name","title_key":"twitter_handle","image_url":"?string","verified":"?boolean","name":"?string","domain":"Content","type_description":"A Twitter/X account associated with a person or organization","ref_id":"96f8744c-554e-4f9b-9e10-01965d83e544","author_id":"?string"},{"icon":"NodesIcon","body":"?string","index":["name","body"],"parent":"Test","node_key":"unittest-name-file","shape":"sphere","type":"UnitTest","description_key":"body","title_key":"name","start":"?int","file":"string","name":"string","domain":"CodeArtifact","type_description":"A unit test verifying a single function or module in isolation.","ref_id":"1af06b0b-d6f1-4944-b330-89d6524f1842","end":"?int"},{"icon":"TargetIcon","index":["name","description"],"parent":"KnowledgeArtifact","node_key":"userobjective-name","shape":"sphere","type":"UserObjective","description_key":"description","title_key":"name","description":"?string","name":"string","is_muted":"?boolean","domain":"KnowledgeArtifact","type_description":"A user-defined objective or goal to track","ref_id":"2c22ea3f-a917-4116-9e01-08453ad691fd"},{"body":"?string","index":["name","body"],"parent":"CodeArtifact","node_key":"var-name-file","type":"Var","description_key":"body","title_key":"name","start":"?int","file":"string","name":"string","domain":"CodeArtifact","type_description":"A variable declaration or usage in source code, representing data storage and manipulation within a program.","ref_id":"a7f02c51-eb83-41e2-8c2c-cf8289ed8471","end":"?int"},{"link":"?string","node_key":"video-episode_title-timestamp","secondary_color":"#21B38A","sentiment_score":"?float","date":"?datetime","type":"Video","timestamp":"string","image_url":"?string","description":"?string","type_description":"A recording of moving visual images","domain":"Content","source_link":"?string","pub_key":"?string","icon":"VideoIcon","primary_color":"#1B3134","text":"?string","index":["episode_title","text","description"],"episode_title":"string","media_url":"string","parent":"Episode","show_title":"?string","shape":"sphere","num_boost":"?int","description_key":"description","title_key":"episode_title","english_translation":"?string","ref_id":"36dcd4bc-25c5-4c71-9dc8-243ca3dc7185","boost":"?int","language":"?string"},{"body":"?string","workflow_version":"?int","node_key":"workflow-workflow_id","secondary_color":"#54AC52","type":"Workflow","description":"?string","name":"?string","workflow_id":"?int","type_description":"An abstract parent for all workflow automation execution types.","domain":"Workflow","usage_count_30d":"?int","published_workflow_version_id":"?int","icon":"TaskIcon","usage_count":"?int","primary_color":"#22362A","index":["name","description","body","input_schema","output_schema"],"input_schema":"?string","output_schema":"?string","parent":"Thing","workflow_json":"?string","shape":"sphere","description_key":"description","title_key":"name","parent_version_id":"?int","ref_id":"82793c01-c13a-4175-a2fc-86df96dd421b","branch":"?string","customer_id":"?int"},{"body":"?string","node_key":"workflow_version-workflow_id-workflow_version_id","secondary_color":"#E09242","type":"Workflow_version","description":"?string","name":"?string","workflow_id":"int","type_description":"A specific version of a workflow configuration with defined steps and parameters","domain":"Workflow","published":"?boolean","icon":"WorkflowIcon","primary_color":"#392828","index":["name","description","body","input_schema","output_schema"],"workflow_version_id":"int","input_schema":"?string","output_schema":"?string","parent":"Workflow","workflow_json":"?string","shape":"sphere","published_at":"?string","description_key":"description","title_key":"name","ref_id":"cb32dd65-19cb-4e15-8af1-f2d9a9c7d013","branch":"?string","success":"?boolean","customer_id":"?int"}],"edge_schemas":[{"source":"AISystem","edge":"HAS_DEADLINE","target":"Deadline","props":{"ref_id":"bfc2d84d-c01c-4f70-92f3-1d195719a5c9"}},{"source":"AISystem","edge":"IMPACT_ASSESSED_BY","target":"ProcessingActivity","props":{"ref_id":"209ca84b-7233-4753-b756-340ceea66311"}},{"source":"AISystem","edge":"SUBJECT_TO","target":"Regulation","props":{"ref_id":"f357bdaf-2807-49ea-99b8-3752d3421bf0"}},{"source":"AISystem","edge":"VENDOR_COVERED_BY","target":"Agreement","props":{"ref_id":"22f1cdea-87a0-48ab-881e-c8998d7cd857"}},{"source":"AgentRole","edge":"HAS_SESSION","target":"AgentSession","props":{"ref_id":"ce7e4dfb-cc16-4efd-86b9-69cf7627b186"}},{"source":"AgentSession","edge":"HAS_ABSTRACTION","target":"Abstraction","props":{"ref_id":"3ba0f08b-ce81-482a-9632-af9989b0e219"}},{"source":"AgentSession","edge":"HAS_TURN","target":"Turn","props":{"ref_id":"43eca24e-e4c7-4875-bf12-cbb8667ae5b9"}},{"source":"AgentSession","edge":"NEXT","target":"AgentSession","props":{"ref_id":"0dfd7a8d-54cf-4525-8de8-68264893dcad"}},{"source":"Agreement","edge":"AMENDS","target":"Agreement","props":{"ref_id":"bc8ec2a1-21eb-4f91-8030-9f2b3dc8d5f0"}},{"source":"Agreement","edge":"APPLIED_TO","target":"ComputedFigure","props":{"ref_id":"08863969-6fbe-4d41-8ebc-ca651614907f"}},{"source":"Agreement","edge":"CONTAINS_REQUEST","target":"DDRequestItem","props":{"ref_id":"ea3b3f26-0a0c-497f-bb78-69a7225b006a"}},{"source":"Agreement","edge":"DEFINES","target":"DefinedTerm","props":{"ref_id":"d729e3cd-4e5c-41c4-a9f0-d3fe478e6e25"}},{"source":"Agreement","edge":"GOVERNED_BY_LAW","target":"Country","props":{"state":"?string","ref_id":"6a415e72-e7de-4c18-8298-aaaf310f43f6"}},{"source":"Agreement","edge":"GOVERNED_BY_LAW","target":"Location","props":{"state":"?string","ref_id":"dcc0e542-b28b-4feb-b101-35398f746170"}},{"source":"Agreement","edge":"GOVERNS","target":"IPAsset","props":{"ref_id":"22c960f6-ad5f-44b0-b778-3f012288ccaf"}},{"source":"Agreement","edge":"HAS_CLAUSE","target":"ContractClause","props":{"ref_id":"223dec2d-5c5f-4621-a4d5-344aa03cbbe5"}},{"source":"Agreement","edge":"HAS_DEADLINE","target":"Deadline","props":{"ref_id":"a55e76a6-308b-4095-8f7a-995beadc0d66"}},{"source":"Agreement","edge":"HAS_RENEWAL_ENTRY","target":"RenewalEntry","props":{"ref_id":"dec5188d-b689-499a-be2f-6cd18b3e44fc"}},{"source":"Agreement","edge":"REFERENCES","target":"Agreement","props":{"ref_id":"c936009f-4f5f-413c-859e-184ee1581b03"}},{"source":"Agreement","edge":"REVIEWED_IN","target":"TabularReviewCell","props":{"ref_id":"0f5b82a7-2e31-47a2-9a82-d175f7d45b98"}},{"source":"Belief","edge":"REFERS_TO","target":"Thing","props":{"ref_id":"4da1dfd6-4733-4944-8925-736623c1087e"}},{"source":"BenchmarkFailureCause","edge":"AFFECTS","target":"EvalRequirement","props":{"ref_id":"aef65a04-d96f-4259-b6ba-9376a4817e68"}},{"source":"Cause","edge":"CAUSE_CHILD_OF","target":"Cause","props":{"ref_id":"67466570-1d4a-4259-9785-95bab2e5ace2","cardinality":"many"}},{"source":"Check","edge":"SUPERSEDES","target":"Check","props":{"ref_id":"0a79f10f-ee33-4646-b9ed-33be78d14a67"}},{"source":"Check","edge":"TESTS","target":"Claim","props":{"ref_id":"7963757b-3491-4ce4-b068-931b047b6010"}},{"source":"Claim","edge":"ABOUT","target":"Thing","props":{"ref_id":"fc24db78-a30a-488f-aa5c-7817c0f81468"}},{"source":"Claim","edge":"CONTRADICTS","target":"Claim","props":{"ref_id":"d5881f57-b95d-4212-b8c1-612fb6c576fa"}},{"source":"Claim","edge":"DERIVED_FROM","target":"Claim","props":{"ref_id":"14ec537e-7714-4174-99eb-b258b7e6b157"}},{"source":"Claim","edge":"EVIDENCED_BY","target":"Evidence","props":{"strength":"?float","ref_id":"dc4c6f37-71dc-47f4-b6b2-0124a5b58d7b"}},{"source":"Claim","edge":"PARENT_OF","target":"Claim","props":{"ref_id":"ec7818b9-e379-4691-adf3-ab8b8407841a"}},{"source":"Claim","edge":"SOURCE","target":"Chapter","props":{"ref_id":"1824e0af-b190-4548-bf91-97615077b26c"}},{"source":"Claim","edge":"SOURCE","target":"Section","props":{"ref_id":"83315901-2e1f-427d-9c31-d93900f855e8"}},{"source":"Claim","edge":"SUPERSEDES","target":"Claim","props":{"ref_id":"30914867-6ade-4d7e-8129-990b276700c9"}},{"source":"Claim","edge":"SUPPORTS","target":"Claim","props":{"ref_id":"1b7576ee-1e9f-4f01-a035-72b239133f30"}},{"source":"Class","edge":"CALLS","target":"Class","props":{"ref_id":"162d5620-fbe6-4eee-a989-28c6fe925c11","call_start":"?int","call_end":"?int","operand":"?string"}},{"source":"Class","edge":"CONTAINS","target":"Datamodel","props":{"ref_id":"674805f9-8f7c-4cea-a949-e93fdc340d4a"}},{"source":"Class","edge":"IMPORTS","target":"Class","props":{"ref_id":"d2c979b6-259d-4231-99e7-46376c6f887e"}},{"source":"Class","edge":"OPERAND","target":"Function","props":{"ref_id":"c488fbdc-ad8f-4a3c-8662-a6a0ad69ffbf"}},{"source":"Class","edge":"PARENT_OF","target":"Class","props":{"ref_id":"710af56b-8f2f-4181-bb37-4c1dcf0708e7"}},{"source":"Clip","edge":"RELATED_TO","target":"Topic","props":{"ref_id":"6d1b3221-514e-469a-92ba-7f314f6e45de"}},{"source":"Commit","edge":"TOUCHES","target":"Concept","props":{"ref_id":"9b01949b-74c4-4422-99ef-1e7ad9f175c9"}},{"source":"Commit","edge":"TOUCHES","target":"Feature","props":{"ref_id":"bacb4e3d-aab0-4bba-a98d-622f997718ea"}},{"source":"ComputedFigure","edge":"APPLIED_TO","target":"Matter","props":{"ref_id":"db0159b0-5552-4c64-a25c-3b8063555e28"}},{"source":"ComputedFigure","edge":"CONTRADICTS","target":"Deadline","props":{"contradiction_type":"?string","ref_id":"ce7fe9ef-641a-4dde-9896-90452cd97728","contradiction_reason":"?string"}},{"source":"ComputedFigure","edge":"DERIVED_FROM","target":"Excerpt","props":{"ref_id":"e2bac065-b2f1-460d-8334-d55563d91752"}},{"source":"ComputedFigure","edge":"DERIVED_FROM","target":"Figure","props":{"ref_id":"6f83d676-a339-4a59-b880-3f5de370e76f"}},{"source":"ComputedFigure","edge":"GOVERNED_BY","target":"RegulatoryItem","props":{"ref_id":"0c0464b5-43d4-4d2a-a291-124c8519a96b"}},{"source":"ComputedFigure","edge":"HAS_COMPONENT","target":"FormulaComponent","props":{"ref_id":"4b84cc0a-f72b-4cc9-9cba-4538d8a3cee3"}},{"source":"ComputedFigure","edge":"QUANTIFIES","target":"DefinedTerm","props":{"field_name":"?string","value_as_stated":"?string","ref_id":"65dcc3b9-9a38-4e3d-b687-afe6c4d5417d","notes":"?string"}},{"source":"ComputedFigure","edge":"QUANTIFIES","target":"PlaybookEntry","props":{"field_name":"?string","value_as_stated":"?string","ref_id":"6cce34d1-2608-4a66-81eb-0e79177fe332","notes":"?string"}},{"source":"ComputedFigure","edge":"VALIDATES","target":"Figure","props":{"ref_id":"3e97ceb0-36d6-4e5c-8480-6c2a8a800a61"}},{"source":"ComputedFigure","edge":"VALIDATES","target":"TabularReviewCell","props":{"ref_id":"f3499d0f-ca47-44e3-ab77-ffb0bcf9e8f6"}},{"source":"Concept","edge":"IN_REPO","target":"Repository","props":{"ref_id":"49bbf792-f9aa-434b-b2b2-fdf2bfa6f1d6"}},{"source":"Concept","edge":"MODIFIES","target":"File","props":{"importance":"?float","ref_id":"c70e1a56-381a-4a1a-b36e-6838c286bdf1"}},{"source":"Concept","edge":"PARENT_OF","target":"Concept","props":{"ref_id":"cb56c71e-190d-40a1-a553-7abfdb89ddb6","cardinality":"many"}},{"source":"ContractClause","edge":"CONFLICTS_WITH","target":"Regulation","props":{"ref_id":"a743e310-cdc7-400e-a5a2-1b156d46d2ae"}},{"source":"ContractClause","edge":"CONTRADICTS","target":"ContractClause","props":{"ref_id":"d7d565c8-f190-4be7-b95c-0a006495e9a7"}},{"source":"ContractClause","edge":"DEFINES","target":"DefinedTerm","props":{"ref_id":"1b439211-627c-4eac-aacc-87af66663d63"}},{"source":"ContractClause","edge":"DEVIATES_FROM","target":"PlaybookEntry","props":{"ref_id":"278df46c-8d46-450e-8f93-bf15ca760e69"}},{"source":"ContractClause","edge":"HAS_EXCERPT","target":"Excerpt","props":{"ref_id":"1cf871f9-9664-4e1c-80b4-a2c246f550f1"}},{"source":"ContractClause","edge":"HAS_GAP","target":"GapItem","props":{"ref_id":"07ffd9af-7fb0-49af-a160-fa9af03ca290"}},{"source":"ContractClause","edge":"HAS_TYPE","target":"ClauseType","props":{"ref_id":"7bb7e3ae-c7a4-4517-88b0-d900f4f500c5"}},{"source":"ContractClause","edge":"SUPERSEDES","target":"ContractClause","props":{"ref_id":"d93d2267-12a8-4895-8320-62d8eb3427f0"}},{"source":"Corporation","edge":"EVIDENCED_BY","target":"Excerpt","props":{"ref_id":"237c39b6-c8f4-4219-97e8-e47026abe771"}},{"source":"Corporation","edge":"GOVERNED_BY","target":"Regulation","props":{"ref_id":"75cd81c8-064a-4489-9e95-ac8f07302834"}},{"source":"Corporation","edge":"INVOLVED_IN","target":"TimelineEntry","props":{"ref_id":"d21fe49c-cbfd-4107-8beb-2a00e1a6e37e"}},{"source":"Corporation","edge":"OUTSIDE_COUNSEL","target":"Corporation","props":{"ref_id":"181e0874-7ac6-4629-9729-72e35f61830d"}},{"source":"Corporation","edge":"REFERENCED_IN","target":"Excerpt","props":{"ref_id":"0250cbf4-d420-4e63-8d84-5b4db937f5f5"}},{"source":"Corporation","edge":"TRUSTEE_OF","target":"Entity","props":{"ref_id":"7f31b1db-2cb3-4ee0-8dd0-b5a8b43ad32b"}},{"source":"Country","edge":"HAS_CAPITAL","target":"Location","props":{"volatility":"STABLE","confidence_score":"?float","fluent":true,"invalid_at":"?datetime","temporal":true,"valid_at":"?datetime","ref_id":"57cae04d-0a5d-4cd5-a7fb-8b24ba98e15a","last_confirmed_at":"?datetime","invalidated_by":"?string","expired_at":"?datetime","cardinality":"single"}},{"source":"CriterionResult","edge":"HAS","target":"Cause","props":{"ref_id":"91f207a0-1c99-4336-a71c-dccb616b05b4","cardinality":"many"}},{"source":"CriterionResult","edge":"HAS_PROPOSED_FIX","target":"ProposedFix","props":{"volatility":"EVOLVING","ref_id":"e722f757-07cf-4827-9b94-76a936ba01e5"}},{"source":"DSARRequest","edge":"SUBMITTED_BY","target":"Person","props":{"ref_id":"0f92bb3f-c906-46cf-ae34-7c3007f1c82c"}},{"source":"DSARRequest","edge":"SUBMITTED_TO","target":"Organization","props":{"ref_id":"0705993b-a2a4-4c04-859a-acb1a99554a6"}},{"source":"DataAnomalyRecord","edge":"FLAGS","target":"Concept","props":{"anomaly_reason":"?string","ref_id":"9cd73dd2-1383-4584-b164-660ef3e34c0b","severity":"?string","flag_category":"?string"}},{"source":"DataAnomalyRecord","edge":"FLAGS","target":"ContractClause","props":{"anomaly_reason":"?string","ref_id":"fd147673-4055-4cc2-9188-d2f6c0539cb0","severity":"?string","flag_category":"?string"}},{"source":"DataAnomalyRecord","edge":"FLAGS","target":"Document","props":{"anomaly_reason":"?string","ref_id":"3bf34751-cb6a-4cc8-a6e4-fb9f40507df2","severity":"?string","flag_category":"?string"}},{"source":"DataAnomalyRecord","edge":"FLAGS","target":"Excerpt","props":{"anomaly_reason":"?string","ref_id":"b547d12c-fe1e-4ff9-a769-8815b1244e32","severity":"?string","flag_category":"?string"}},{"source":"DataAnomalyRecord","edge":"FLAGS","target":"Figure","props":{"anomaly_reason":"?string","ref_id":"7eb2aaa0-387b-4795-a05e-a0e6bd8b10ff","severity":"?string","flag_category":"?string"}},{"source":"DataAnomalyRecord","edge":"FLAGS","target":"TimelineEntry","props":{"anomaly_reason":"?string","ref_id":"f4558b0d-6273-4174-8399-a123e75b5c4c","severity":"?string","flag_category":"?string"}},{"source":"Deadline","edge":"COINCIDES_WITH","target":"Deadline","props":{"ref_id":"837b3681-0064-423a-9455-959bd7a138f2","coincidence_date":"?string","note":"?string"}},{"source":"Deadline","edge":"CONTRADICTS","target":"Deadline","props":{"contradiction_type":"?string","ref_id":"0367da1f-512d-4193-89aa-c2dc71eb6f58","contradiction_reason":"?string"}},{"source":"DefinedTerm","edge":"CONFLICTS_WITH","target":"DefinedTerm","props":{"field_name":"?string","delta":"?string","ref_id":"020f1597-fe49-4cd6-a063-11b744beed25","doc_a_value":"?string","doc_b_value":"?string"}},{"source":"DefinedTerm","edge":"LOCATED_IN","target":"Place","props":{"ref_id":"a366664d-f122-419b-b7e6-9ea56041d78a"}},{"source":"DefinedTerm","edge":"RELATED_TO","target":"Lingo","props":{"ref_id":"aa96b836-7db6-42ec-8479-f5ca14e9e1e0"}},{"source":"DefinedTerm","edge":"USED_IN","target":"Agreement","props":{"ref_id":"4c86eaaa-3b80-44c4-86d2-d6767233fd6e"}},{"source":"DefinedTerm","edge":"USED_IN","target":"Document","props":{"ref_id":"5361a962-ef96-4f58-acae-3a1055008c33"}},{"source":"DeliverableSchema","edge":"APPLIES_TO","target":"Matter","props":{"ref_id":"34b5ccbb-e0d5-41e2-8258-ed10f291403b"}},{"source":"DiligenceIssue","edge":"BLOCKS","target":"Deadline","props":{"ref_id":"ffb0007a-2e65-408d-8ee5-fedd7e67b848"}},{"source":"DiligenceIssue","edge":"EVIDENCED_BY","target":"Figure","props":{"ref_id":"a7cd9801-c826-459c-bb91-a195a2a26ed6"}},{"source":"DiligenceIssue","edge":"TRIGGERED_BY","target":"RegulatoryItem","props":{"ref_id":"a717795f-22c6-42bc-8930-d7e7a4f211cf"}},{"source":"Directory","edge":"CONTAINS","target":"File","props":{"ref_id":"2e39bb19-4cb3-4097-805c-53cd4c4149d4"}},{"source":"Doctrine","edge":"APPLIES_IN","target":"Jurisdiction","props":{"ref_id":"30fff9b4-5b30-4a82-b912-5d37fbe75bd5"}},{"source":"Doctrine","edge":"GOVERNS","target":"ClauseType","props":{"ref_id":"254fc04a-5f6d-41ff-a805-d67fa14ecf86"}},{"source":"Document","edge":"AMENDS","target":"Document","props":{"ref_id":"2acbbd4b-99d3-4eee-bd1c-1e61f890bd31"}},{"source":"Document","edge":"DEFINES","target":"DefinedTerm","props":{"ref_id":"dd5a9ba9-3cf7-459c-938a-4be6f1f1b9b8"}},{"source":"Document","edge":"HAS","target":"Section","props":{"ref_id":"36c4ba60-2141-40bf-9b4c-525bb347342e"}},{"source":"Document","edge":"HAS_COMPONENT","target":"FormulaComponent","props":{"ref_id":"47adeda8-5fc9-4b8e-9fd8-8111741de995"}},{"source":"Document","edge":"SUPPLEMENTS","target":"Document","props":{"ref_id":"8f4ad736-5252-451d-8a39-d7b5b9549f61"}},{"source":"E2etest","edge":"CALLS","target":"Function","props":{"ref_id":"ba574e17-d3a6-45fe-8fd4-6661d96733e5","call_start":"?int","call_end":"?int","operand":"?string"}},{"source":"Email","edge":"HAS","target":"Section","props":{"ref_id":"1decf156-eae4-4388-bdc4-346305208676"}},{"source":"Email","edge":"HAS_ATTACHMENT","target":"Attachment","props":{"ref_id":"62b2d6ff-a953-4cbc-845a-3d6ca0acae03"}},{"source":"Email","edge":"HAS_INVITE","target":"EmailInvite","props":{"ref_id":"ff8dddb5-eeae-448b-ac6c-f6b685f0cba6"}},{"source":"Email","edge":"PART_OF_THREAD","target":"Email","props":{"ref_id":"2b17d074-3ef8-4c8c-8183-fe0e1079fd96"}},{"source":"Email","edge":"REPLY_TO","target":"Email","props":{"ref_id":"2a3cfba7-271d-4d2c-9abf-d1543f82735d"}},{"source":"EmailInvite","edge":"LOCATED_AT","target":"Location","props":{"ref_id":"57473a78-fe24-46e0-bba4-076f650d56cf"}},{"source":"EmailInvite","edge":"RELATED_TO","target":"Event","props":{"ref_id":"bee56d0e-7682-4123-bc8a-6854b0960f57"}},{"source":"Endpoint","edge":"CALLS","target":"Function","props":{"ref_id":"15e1e05e-0651-4555-b1ab-ea5818b134f9"}},{"source":"Endpoint","edge":"HANDLER","target":"Function","props":{"ref_id":"36cc8137-09cf-4d2e-a08c-37e9767c8528"}},{"source":"Entity","edge":"INVOLVED_IN","target":"TimelineEntry","props":{"ref_id":"500aa8a8-e962-45b1-a9cc-31cba87b0b38"}},{"source":"Entity","edge":"REFERENCED_IN","target":"Excerpt","props":{"ref_id":"4cda2746-4f89-466f-8e55-87f9d8e5c31c"}},{"source":"Episode","edge":"HAS","target":"Chapter","props":{"ref_id":"23551de1-77ab-4c95-9423-221ef6089ae2"}},{"source":"Episode","edge":"HAS","target":"Clip","props":{"ref_id":"6bf30640-6a6c-42b4-9daf-a15ff1f699f1"}},{"source":"Episode","edge":"HAS","target":"Podcast","props":{"ref_id":"5143a0cc-5f02-4997-a545-31d90084a3c6"}},{"source":"Episode","edge":"HAS","target":"Video","props":{"ref_id":"5403cdc2-fcc6-4f64-90e5-1d483e98bda1"}},{"source":"Episode","edge":"MENTIONS","target":"Organization","props":{"ref_id":"963ee4c6-64e9-4280-a2a0-d3d788dfc44d"}},{"source":"Episode","edge":"MENTIONS","target":"Place","props":{"ref_id":"2f63340a-b40f-4531-a958-2faeb7f728d1"}},{"source":"Episode","edge":"MENTIONS","target":"Product","props":{"ref_id":"afb13bed-4415-48e1-908f-374fa3b2c36a"}},{"source":"Episode","edge":"MENTIONS","target":"Topic","props":{"ref_id":"58d4d5dd-c492-488f-9917-2fbada672f7f"}},{"source":"ErrorIssue","edge":"REFERENCES","target":"File","props":{"ref_id":"52eec5f9-8d1b-498b-aaf9-f1f9f81b7f37"}},{"source":"ErrorIssue","edge":"REFERENCES","target":"Function","props":{"ref_id":"05f550a4-f31b-4b9b-bfa1-8e6161b64cbc"}},{"source":"EscalationRecord","edge":"GOVERNED_BY","target":"Doctrine","props":{"ref_id":"87e22c36-e8b8-4e72-bf10-7195c7048e65"}},{"source":"EscalationRecord","edge":"TRIGGERED_BY","target":"LegalArgument","props":{"ref_id":"1b3f5dbd-648b-4d37-a16d-b6bae7c93887"}},{"source":"EvalRequirement","edge":"HAS_CRITERION_RESULT","target":"CriterionResult","props":{"ref_id":"d4606913-b5d1-4720-997e-90fa6079db85"}},{"source":"EvalRequirement","edge":"HAS_TRIGGER","target":"EvalTrigger","props":{"ref_id":"8cb0ac92-848e-4ae4-8105-28c637825619"}},{"source":"EvalSet","edge":"HAS_BASELINE_TRIGGER","target":"EvalTrigger","props":{"ref_id":"11a40913-f560-4c34-8137-049e0f7f19a4"}},{"source":"EvalSet","edge":"HAS_REQUIREMENT","target":"EvalRequirement","props":{"order":"?int","ref_id":"42fec7d0-4767-4868-81ca-dd09f634ebd7"}},{"source":"EvalSet","edge":"HAS_SUBSET","target":"EvalSet","props":{"ref_id":"d75d1988-b70a-4886-84ea-0caa440e80ac"}},{"source":"EvalSet","edge":"HAS_TRIGGER","target":"EvalTrigger","props":{"ref_id":"5d596d4a-d950-4486-be23-1e15997c4602"}},{"source":"EvalTrigger","edge":"ATTRIBUTED_TO","target":"HiveAgent","props":{"ref_id":"d6dea5d2-195e-4e93-9e30-a9ede0b18a4a"}},{"source":"EvalTrigger","edge":"EVALUATED","target":"AgentSession","props":{"ref_id":"536274c5-116b-45c4-bb6b-0a1b56a0308e"}},{"source":"EvalTrigger","edge":"HAS_OUTPUT","target":"EvalTriggerOutput","props":{"ref_id":"4f0bca60-7cdc-474e-b019-a71bc17723a8"}},{"source":"EvalTrigger","edge":"HAS_PROPOSED_FIX","target":"ProposedFix","props":{"volatility":"EVOLVING","ref_id":"bfc07a6e-9ced-4464-8dca-c6c6fbe1b7a6"}},{"source":"EvalTriggerOutput","edge":"ATTRIBUTED_TO","target":"BenchmarkFailureCause","props":{"ref_id":"865b439f-7a77-4bd3-a166-05e3e3953e2c"}},{"source":"EvalTriggerOutput","edge":"HAS_CRITERION_RESULT","target":"CriterionResult","props":{"ref_id":"03a5ea7c-ee89-4f7c-b355-3cc63965fdfb"}},{"source":"Evidence","edge":"ABOUT","target":"Thing","props":{"ref_id":"b19e33bc-a342-4b34-afb0-e697a5838ecb"}},{"source":"Evidence","edge":"HAS_SOURCE","target":"Thing","props":{"end_time":"?float","post_url":"?string","context":"?string","ref_id":"e71e06da-d9a2-4553-8204-393336eadcb8","start_time":"?float","created_at":"?datetime","message_id":"?string","page_reference":"?string","authority_level":"?string"}},{"source":"Evidence","edge":"PRODUCED_BY","target":"Check","props":{"ref_id":"52a15d77-15d6-46d6-967d-7e39102e7bd9"}},{"source":"Excerpt","edge":"CONFLICTS_WITH","target":"Excerpt","props":{"ref_id":"45cdf025-e5d9-4697-8916-80f9467d03c5"}},{"source":"Excerpt","edge":"DESCRIBES","target":"Agreement","props":{"ref_id":"2b64e4e8-4cc9-4873-862f-0e448671fc7f"}},{"source":"Excerpt","edge":"DESCRIBES","target":"Corporation","props":{"ref_id":"070b5aa9-4f49-4072-8922-87b61f6e63a3"}},{"source":"Excerpt","edge":"DESCRIBES","target":"Organization","props":{"ref_id":"e39bddf1-29fb-4865-b1ce-599c142b8da6"}},{"source":"Excerpt","edge":"EVIDENCED_BY","target":"LegalArgument","props":{"ref_id":"67dd377d-1bb3-4020-9a12-bd7a4eccf5ce"}},{"source":"Excerpt","edge":"REFERENCED_IN","target":"Person","props":{"ref_id":"25b8f668-13a9-40b5-aceb-2ea30a6696df"}},{"source":"Feature","edge":"MODIFIES","target":"File","props":{"importance":"?float","ref_id":"c249176d-0d55-4623-9750-3742fa67c7bf"}},{"source":"Figure","edge":"APPLIED_TO","target":"Matter","props":{"ref_id":"69511a87-2d74-4b62-962f-b87911f8a839"}},{"source":"Figure","edge":"CONFLICTS_WITH","target":"Figure","props":{"field_name":"?string","delta":"?string","ref_id":"8bc3847c-a077-46f8-9e02-e3bb44cf204e","doc_a_value":"?string","doc_b_value":"?string"}},{"source":"Figure","edge":"DERIVED_FROM","target":"Figure","props":{"ref_id":"9fb43204-5e27-4d98-96dd-61cef31b1d74"}},{"source":"Figure","edge":"DESCRIBES","target":"Organization","props":{"ref_id":"8a2b54fb-1f75-4090-bc65-4e33e3d468fc"}},{"source":"Figure","edge":"EXTRACTED_FROM","target":"Document","props":{"ref_id":"ad6790ce-c807-4f87-a3ef-30d64de1050a"}},{"source":"Figure","edge":"EXTRACTED_FROM","target":"Excerpt","props":{"ref_id":"a164bdc3-73a1-414e-8f56-9171173097ed"}},{"source":"Figure","edge":"EXTRACTED_FROM","target":"Section","props":{"ref_id":"da9dd4a0-36a0-41a2-8452-0e111ac18858"}},{"source":"Figure","edge":"GOVERNED_BY","target":"RegulatoryItem","props":{"ref_id":"e87d8393-b9b4-4b7b-bb7e-ef55cb8c7650"}},{"source":"Figure","edge":"QUANTIFIES","target":"PlaybookEntry","props":{"field_name":"?string","value_as_stated":"?string","ref_id":"1aca7996-efdb-4e37-8249-9371a3ee9bbf","notes":"?string"}},{"source":"Figure","edge":"QUANTIFIES","target":"Product","props":{"field_name":"?string","value_as_stated":"?string","ref_id":"e64e4f2a-9517-4569-bbed-03d6738c0f2d","notes":"?string"}},{"source":"File","edge":"CONTAINS","target":"Function","props":{"ref_id":"ef261cb7-ed12-4a93-b3d5-8730928cc908"}},{"source":"File","edge":"CONTAINS","target":"Trait","props":{"ref_id":"1bbab2ab-d8a0-4578-acd3-5795adc5f56f"}},{"source":"File","edge":"CONTAINS","target":"Var","props":{"ref_id":"35c38374-467e-4bce-8615-cb7631e34301"}},{"source":"File","edge":"IMPORTS","target":"File","props":{"ref_id":"581d4393-f5be-4136-9fb8-f0f18acc283e"}},{"source":"File","edge":"IMPORTS","target":"Library","props":{"ref_id":"d861dad0-7e9e-4fbd-8804-12536f8c5f5e"}},{"source":"Fluent","edge":"CURRENT_VALUE","target":"Thing","props":{"volatility":"EVOLVING","ref_id":"f149065f-0bc3-418b-87b6-881a6b185e30","cardinality":"single"}},{"source":"Fluent","edge":"HAS_EVENT","target":"FluentEvent","props":{"volatility":"STATIC","ref_id":"f3b10977-276d-43b6-9c53-f6cb5e4894e0","cardinality":"many"}},{"source":"FormulaComponent","edge":"DERIVED_FROM","target":"Figure","props":{"ref_id":"822fa443-6f83-410b-9507-363fad811dc6"}},{"source":"Function","edge":"CALLS","target":"Function","props":{"ref_id":"f221be8f-3833-4585-813e-52be78b8553f","call_start":"?int","call_end":"?int","operand":"?string"}},{"source":"Function","edge":"CONTAINS","target":"Datamodel","props":{"ref_id":"63cf80fa-6b21-4815-b962-f88767084250"}},{"source":"Function","edge":"CONTAINS","target":"Var","props":{"ref_id":"88155f12-bda8-4fa2-bc14-07b337fcb014"}},{"source":"Function","edge":"USES","target":"Function","props":{"ref_id":"8ced93d6-608a-43d8-9553-1b45c290396a","call_start":"?int","call_end":"?int","operand":"?string"}},{"source":"GapItem","edge":"BLOCKS","target":"AISystem","props":{"ref_id":"cbe92d6a-6c29-4205-9743-3504b8b29878"}},{"source":"GapItem","edge":"FLAGS","target":"Excerpt","props":{"undefined_term":"?string","ref_id":"566ad0c2-e819-476b-88cb-5ce7680c5f86","flag_category":"?string","gap_reason":"?string"}},{"source":"GapItem","edge":"GOVERNED_BY","target":"Regulation","props":{"ref_id":"5318adde-4c7e-4ef5-9041-6b52ada1896a"}},{"source":"GapItem","edge":"PROMPTED","target":"CommentPeriod","props":{"ref_id":"f6e07928-da14-48ec-8f1f-413c0dfbb148"}},{"source":"Generated_step","edge":"NEXT","target":"Generated_step","props":{"ref_id":"032251fd-81a6-4dc0-941a-ce5f7ac49c8c"}},{"source":"GitHubRepo","edge":"HAS","target":"Commits","props":{"ref_id":"976f4f49-aca0-4000-85f4-0906dc7bb39d"}},{"source":"GitHubRepo","edge":"HAS","target":"Issues","props":{"ref_id":"d9962b0d-7863-4d80-8f1d-386c9c5e3d62"}},{"source":"HiveAgent","edge":"HAS_PROMPT","target":"Prompt","props":{"ref_id":"a32530af-3f0e-48ff-8b80-b263ab2ed83f"}},{"source":"HiveFeature","edge":"HAS_MESSAGE","target":"HiveChatMessage","props":{"ref_id":"894aa11c-2e9e-4f7b-a9a8-c4dc65582eb6"}},{"source":"HiveFeature","edge":"HAS_TASK","target":"HiveTask","props":{"ref_id":"7b2e883c-ab57-4239-9994-5976d413ed8d"}},{"source":"HiveInitiative","edge":"HAS_MILESTONE","target":"HiveMilestone","props":{"ref_id":"32ae8f02-5fae-4bfc-9faa-c93a83bb2f02"}},{"source":"HiveInitiative","edge":"HAS_RESEARCH","target":"HiveResearch","props":{"ref_id":"5f04cef4-9209-4ac7-af09-b22c0e8e7b67"}},{"source":"HiveMilestone","edge":"HAS_RESEARCH","target":"HiveResearch","props":{"ref_id":"81453783-6945-4407-8f66-8d97c00f2d48"}},{"source":"HiveTask","edge":"HAS_MESSAGE","target":"HiveChatMessage","props":{"ref_id":"5073c5ec-e2ec-4f45-8f2c-778e46edbf98"}},{"source":"HiveTask","edge":"RESULTED_IN","target":"PullRequest","props":{"ref_id":"b1602bd9-84ca-4789-b2e9-a29e8fa3adf0"}},{"source":"HiveWorkspace","edge":"BEST_PRACTICE","target":"Concept","props":{"ref_id":"cbdeefa9-896a-44d4-9d7d-277c832d9f25"}},{"source":"HiveWorkspace","edge":"GOTCHA","target":"Concept","props":{"ref_id":"39fbd7fc-75bf-4a16-b11a-907f0a4688c6"}},{"source":"HiveWorkspace","edge":"HAS_CONCEPT","target":"Concept","props":{"ref_id":"cac9c2ea-1aec-4745-9895-a28d4faf9246"}},{"source":"HiveWorkspace","edge":"HAS_MEMBER","target":"HiveWorkspaceMember","props":{"ref_id":"0d55155b-a081-4b67-b75b-c444278ad2b4"}},{"source":"HiveWorkspace","edge":"PREFERENCE","target":"Concept","props":{"ref_id":"53fd6375-0d2d-4b73-808f-6825c6c15b2e"}},{"source":"HiveWorkspace","edge":"PROCESS","target":"Concept","props":{"ref_id":"31e7b53b-aaf7-4aa7-b723-5df7b4eaa1ab"}},{"source":"HiveWorkspaceMember","edge":"APPROVED","target":"Concept","props":{"ref_id":"d741793f-f43b-4d3f-ab33-f37dfc899148"}},{"source":"HiveWorkspaceMember","edge":"PREFERENCE","target":"Concept","props":{"ref_id":"03714449-6c25-4410-aca7-eddb21ed6d4e"}},{"source":"IPAsset","edge":"HAS_DEADLINE","target":"Deadline","props":{"ref_id":"434d38a0-3208-4afa-90cb-dcd766158ed9"}},{"source":"IPAsset","edge":"LICENSED_UNDER","target":"ContractClause","props":{"ref_id":"785487da-5911-4dc7-b0cc-ec1da1b2f8cc"}},{"source":"IPAsset","edge":"REGISTERED_IN","target":"Jurisdiction","props":{"filing_status":"?string","ref_id":"46398383-d39b-428a-8995-1b4d0638227a","filing_date":"?string","application_number":"?string"}},{"source":"IPAsset","edge":"RENEWAL_TRACKED_BY","target":"RenewalEntry","props":{"ref_id":"054b4fef-773f-46e7-abec-be3391a6f2d0"}},{"source":"IPAsset","edge":"SUPPORTED_BY","target":"Excerpt","props":{"support_type":"?string","ref_id":"8dc2e601-e309-45b0-b4f6-7957ed2dbd4b","support_reason":"?string"}},{"source":"Import","edge":"IMPORTS","target":"Class","props":{"ref_id":"462dc055-f4a7-402a-9ab4-4fa304ad802c"}},{"source":"Import","edge":"IMPORTS","target":"Datamodel","props":{"ref_id":"de64d06b-9a17-47c0-8953-7c371e54df31"}},{"source":"Import","edge":"IMPORTS","target":"Function","props":{"ref_id":"4e3203d0-3c85-449a-9a43-321013103f15"}},{"source":"Instance","edge":"OF","target":"Class","props":{"ref_id":"745d6921-045e-4e55-a56b-35030f84cfb1","call_start":"?int","call_end":"?int","operand":"?string"}},{"source":"IntegrationTest","edge":"CALLS","target":"Endpoint","props":{"ref_id":"df5b3667-bb00-4ed3-bd8e-607243e8f89e","call_start":"?int","call_end":"?int","operand":"?string"}},{"source":"IntegrationTest","edge":"CALLS","target":"Function","props":{"ref_id":"8a2a316f-e425-489b-b981-8090204ba1c7","call_start":"?int","call_end":"?int","operand":"?string"}},{"source":"Jargon","edge":"DEFINES","target":"Organization","props":{"ref_id":"83728110-7775-45e5-b084-b4a6afa316d6"}},{"source":"Jargon","edge":"DEFINES","target":"Person","props":{"ref_id":"2b1b2e2a-7369-4e60-98bc-87a6d286e0db"}},{"source":"Jargon","edge":"DEFINES","target":"Thing","props":{"ref_id":"24d9b6ab-4346-4bae-9e7d-8f29f15534ae"}},{"source":"Jargon","edge":"DEFINES","target":"Topic","props":{"ref_id":"a8f2d745-11df-4a77-9842-5ad6348ac41d"}},{"source":"Jurisdiction","edge":"PART_OF","target":"Jurisdiction","props":{"ref_id":"4cd96c6b-674f-46f4-b4f7-d61a982226b7"}},{"source":"LeaseAgreement","edge":"HAS_CLAUSE","target":"ContractClause","props":{"ref_id":"6ebb738a-a825-47c9-9b37-ab053de9bfc2"}},{"source":"LegalArgument","edge":"APPLIES_IN","target":"Jurisdiction","props":{"ref_id":"b233c7a1-7a00-4972-a02c-80b90b9e508f"}},{"source":"LegalArgument","edge":"APPLIES_TO","target":"Matter","props":{"ref_id":"1aaf8e7e-0d48-4cf9-8ad0-caae96a0727c"}},{"source":"LegalArgument","edge":"BLOCKS","target":"Deadline","props":{"ref_id":"4309fdc8-da66-4f5b-9294-7f73d72e9929"}},{"source":"LegalArgument","edge":"CONTRADICTS","target":"LegalArgument","props":{"ref_id":"1cfb7e8a-37bb-4870-9149-6504b74a1dff"}},{"source":"LegalArgument","edge":"GROUNDED_IN","target":"Doctrine","props":{"ref_id":"3e79fd6c-f6fd-45f2-95fc-68e71c915829"}},{"source":"LegalArgument","edge":"REFERENCES_DATE","target":"Deadline","props":{"ref_id":"f459b3a8-67fc-4fe5-ac69-7c29ba45cef5"}},{"source":"LegalArgument","edge":"SUPPORTED_BY","target":"Excerpt","props":{"ref_id":"27fba9fc-78b6-467e-8071-189d38d514fc"}},{"source":"LegalArgument","edge":"SUPPORTED_BY","target":"FormulaComponent","props":{"support_type":"?string","ref_id":"4ceb522f-0934-49fb-bd4f-788ad7dce399","support_reason":"?string"}},{"source":"LegalArgument","edge":"SUPPORTED_BY","target":"LegalArgument","props":{"ref_id":"e885870c-a2ec-4f99-a4b3-b6ed12d27163"}},{"source":"LegalArgument","edge":"SUPPORTED_BY","target":"TimelineEntry","props":{"support_type":"?string","ref_id":"8d0e9511-1a0e-4091-840a-ca8e065d97bf","support_reason":"?string"}},{"source":"LegalHold","edge":"IS_CUSTODIAN","target":"Person","props":{"ref_id":"b50c7e74-71b5-4794-8b6c-1d98a9f720fa"}},{"source":"LegalParty","edge":"REPRESENTS_ORG","target":"Organization","props":{"ref_id":"55e3c758-ca01-4c40-a33e-2fcee51e5e2d"}},{"source":"LegalParty","edge":"REPRESENTS_PERSON","target":"Person","props":{"ref_id":"30d73f9b-2b77-4cdc-b65b-a7915d767bd0"}},{"source":"LimitationStatute","edge":"APPLIES_IN","target":"Jurisdiction","props":{"ref_id":"48bb5691-f214-4a5c-bf89-98b867d6f887"}},{"source":"Lingo","edge":"RELATED_TO","target":"Lingo","props":{"ref_id":"8b0603f3-5522-40f4-9376-7ed69569cc2a"}},{"source":"Location","edge":"HAS_WEATHER","target":"Thing","props":{"volatility":"VOLATILE","confidence_score":"?float","invalid_at":"?datetime","temporal":true,"valid_at":"?datetime","ref_id":"41f7b326-4862-4856-81ff-106586cbe0ec","last_confirmed_at":"?datetime","invalidated_by":"?string","expired_at":"?datetime","cardinality":"single"}},{"source":"Location","edge":"MENTIONED_IN","target":"Section","props":{"ref_id":"87bba499-48ff-4a11-8e00-f9cc4d321d9b"}},{"source":"Matter","edge":"ASSIGNED_TO","target":"Person","props":{"ref_id":"0dd0bbae-c1a1-482b-ae3c-395ebba2dc80"}},{"source":"Matter","edge":"CONCERNS","target":"IPAsset","props":{"ref_id":"f0261684-1775-4a9c-9bfc-3c3d422dcca8"}},{"source":"Matter","edge":"CONTAINS_REQUEST","target":"DDRequestItem","props":{"ref_id":"520aeb11-8824-4f1f-bd41-2ab222d3929f"}},{"source":"Matter","edge":"FILED_IN","target":"Jurisdiction","props":{"ref_id":"d5a4e919-3eab-4753-84b8-559d35118c99"}},{"source":"Matter","edge":"HAS_ARGUMENT","target":"LegalArgument","props":{"ref_id":"07736aea-a61d-448b-b6ac-5f4275fcddf6"}},{"source":"Matter","edge":"HAS_CONFLICT_CHECK","target":"ConflictCheck","props":{"ref_id":"cc7343c4-659c-4021-becf-ef0d84c709de"}},{"source":"Matter","edge":"HAS_DEADLINE","target":"Deadline","props":{"ref_id":"d9781ea8-2f36-4621-8c93-4625aa2db362"}},{"source":"Matter","edge":"HAS_DILIGENCE_ISSUE","target":"DiligenceIssue","props":{"ref_id":"f85ab362-b75a-48a9-9b1f-a98b190d418a"}},{"source":"Matter","edge":"HAS_ESCALATION","target":"EscalationRecord","props":{"ref_id":"21158a8c-59cb-4f05-9556-45b2efe11d4e"}},{"source":"Matter","edge":"HAS_INVESTIGATION","target":"InvestigationLog","props":{"ref_id":"9dfb693a-e7b3-433f-8535-1a207be3d09a"}},{"source":"Matter","edge":"HAS_LEGAL_HOLD","target":"LegalHold","props":{"ref_id":"c3174343-8f92-4dd7-9b96-0f4e7a8e1cac"}},{"source":"Matter","edge":"HAS_PARTY","target":"LegalParty","props":{"ref_id":"9ad28e08-adfd-4236-817a-fb42ebf93670"}},{"source":"Matter","edge":"HAS_TIMELINE_ENTRY","target":"TimelineEntry","props":{"volatility":"STABLE","confidence_score":"?float","invalid_at":"?datetime","temporal":true,"valid_at":"?datetime","ref_id":"1c0521db-37e5-430e-bb13-700bdca2ab84","last_confirmed_at":"?datetime","invalidated_by":"?string","expired_at":"?datetime"}},{"source":"Matter","edge":"INVOLVES_PARTY","target":"Organization","props":{"ref_id":"bef4c280-0d8a-49ef-96de-08218024d580"}},{"source":"Matter","edge":"OUTSIDE_COUNSEL","target":"Organization","props":{"ref_id":"2a7381bf-cb01-4b62-843a-a933f5b378f8"}},{"source":"Message","edge":"RELATED_TO","target":"Topic","props":{"ref_id":"c7271484-894a-4b91-8610-7211fb92f833"}},{"source":"Organization","edge":"BACKED_BY","target":"Organization","props":{"ref_id":"563e643a-8d43-4795-9e09-9ab6ea2a0a8c"}},{"source":"Organization","edge":"CONDUCTS","target":"ProcessingActivity","props":{"ref_id":"124a65f7-a774-484c-ba42-3efd839cfe4a"}},{"source":"Organization","edge":"CONFLICTS_WITH","target":"Organization","props":{"doc_b_name":"?string","entity_reference":"?string","doc_a_source":"?string","ref_id":"9d851420-5a01-451e-ad2e-0eea97c77e64","doc_b_source":"?string","conflict_type":"?string","doc_a_name":"?string"}},{"source":"Organization","edge":"FINANCES","target":"Organization","props":{"amount":"?string","financing_type":"?string","ref_id":"46681ac2-7e56-4756-804d-5d12ea37e4b3"}},{"source":"Organization","edge":"HAS","target":"Repository","props":{"ref_id":"a3c4cf30-a912-405b-9d3b-510dc958a64d"}},{"source":"Organization","edge":"HAS_JURISDICTION","target":"Jurisdiction","props":{"ref_id":"97e6147d-9ab7-4477-be9a-a64b8e99cfb2"}},{"source":"Organization","edge":"HAS_OFFICE_IN","target":"Place","props":{"ref_id":"7bb26425-ba31-444e-ad2d-8294b4618ef8"}},{"source":"Organization","edge":"HOLDS_SHARES_IN","target":"Corporation","props":{"ref_id":"6c723ae8-e641-4038-8daa-b716e2723d8d"}},{"source":"Organization","edge":"IDENTIFIED_AS","target":"TwitterAccount","props":{"ref_id":"ebc97663-4168-46b4-bf7d-e8052d168767"}},{"source":"Organization","edge":"INCORPORATED_IN","target":"Country","props":{"ref_id":"89052d86-ed5f-4a4c-8cf2-41ceba749bc2"}},{"source":"Organization","edge":"IS_PARTY_TO","target":"Agreement","props":{"ref_id":"ae9c5bbc-fbbc-4d26-9c23-e05a66e26941"}},{"source":"Organization","edge":"IS_PARTY_TO","target":"LeaseAgreement","props":{"ref_id":"838e5d51-5375-4ace-bd78-8dadc15f1a9c"}},{"source":"Organization","edge":"MENTIONED_IN","target":"Agreement","props":{"ref_id":"6368bed1-66bc-47ec-aa47-da060017e386"}},{"source":"Organization","edge":"MENTIONED_IN","target":"Section","props":{"ref_id":"ca372235-3bcd-43a4-98e2-e34c995a1ade"}},{"source":"Organization","edge":"NOMINEE_FOR","target":"Person","props":{"ref_id":"ad98ad97-4e3a-4db4-a7e9-441ad7aa2fde"}},{"source":"Organization","edge":"OPERATES","target":"AISystem","props":{"ref_id":"b614da8e-be3f-4d67-93d4-c6d215862709"}},{"source":"Organization","edge":"OWNS","target":"IPAsset","props":{"ref_id":"e4d52a6d-1bdd-43bf-a710-30311327129d"}},{"source":"Organization","edge":"REGISTERED_AGENT_OF","target":"Corporation","props":{"ref_id":"93a73a1d-81df-41b0-a808-b78c162e9a2f"}},{"source":"Page","edge":"RENDERS","target":"Function","props":{"ref_id":"86016133-64c8-47ba-9466-487edc177e8e"}},{"source":"Person","edge":"ACCEPTED","target":"EmailInvite","props":{"ref_id":"0cc03b61-a81b-47da-9352-7d0c5bb17751"}},{"source":"Person","edge":"AUTHORED_BY","target":"Document","props":{"ref_id":"1c7e5314-f352-4af2-a687-642e9ce1e7eb"}},{"source":"Person","edge":"BELIEVES","target":"Belief","props":{"ref_id":"0a675e4c-22b7-4f39-adcf-8083ac9f2eaf"}},{"source":"Person","edge":"BENEFICIAL_OWNER_OF","target":"Corporation","props":{"ref_id":"52e0beca-7782-4fdb-8249-8a8560e40a14"}},{"source":"Person","edge":"BORN_ON","target":"Thing","props":{"volatility":"STATIC","confidence_score":"?float","invalid_at":"?datetime","temporal":true,"valid_at":"?datetime","ref_id":"01146b8d-6fba-4568-b44f-fc00c7b50d85","last_confirmed_at":"?datetime","invalidated_by":"?string","expired_at":"?datetime","cardinality":"single"}},{"source":"Person","edge":"CC_ON","target":"Email","props":{"ref_id":"b6178c78-7f1e-45dd-8473-17cee3e78b9e"}},{"source":"Person","edge":"COMPLAINANT_IN","target":"InvestigationLog","props":{"ref_id":"74fd1460-060c-4336-89c9-c4588e56f0a3"}},{"source":"Person","edge":"CONFLICTS_WITH","target":"Person","props":{"doc_b_name":"?string","entity_reference":"?string","doc_a_source":"?string","ref_id":"7580ca16-6934-49d4-88ab-d3fdecca1e64","doc_b_source":"?string","conflict_type":"?string","doc_a_name":"?string"}},{"source":"Person","edge":"DECLINED","target":"EmailInvite","props":{"ref_id":"43fc6f77-fe05-43dc-9182-1d5ae205eca4"}},{"source":"Person","edge":"DIRECTOR_OF","target":"Corporation","props":{"ref_id":"7f35c801-ef6a-48ef-86e6-6e70dfb80094"}},{"source":"Person","edge":"EMPLOYED_BY","target":"Organization","props":{"volatility":"EVOLVING","confidence_score":"?float","invalid_at":"?datetime","temporal":true,"valid_at":"?datetime","ref_id":"808bcf4e-fbc9-412a-9581-9e7c835c7c22","last_confirmed_at":"?datetime","invalidated_by":"?string","expired_at":"?datetime"}},{"source":"Person","edge":"HAS_JURISDICTION","target":"Country","props":{"ref_id":"db515035-9bf3-416c-a1c7-2e21237b16d2"}},{"source":"Person","edge":"HOLDS_SHARES_IN","target":"Corporation","props":{"ref_id":"99827a3d-8207-4356-a959-f3eb1de30688"}},{"source":"Person","edge":"IDENTIFIED_AS","target":"TwitterAccount","props":{"ref_id":"decff953-2493-47aa-ba00-9ca9f38fc42e"}},{"source":"Person","edge":"INVENTED","target":"IPAsset","props":{"ref_id":"3b40b8ca-95ce-4e56-ab28-7ff303026f3a"}},{"source":"Person","edge":"INVITED_TO","target":"EmailInvite","props":{"ref_id":"444810bf-5a78-4d9b-8838-0d7c35fff09b"}},{"source":"Person","edge":"INVOLVED_IN","target":"TimelineEntry","props":{"ref_id":"b5ee66fc-cba4-4cf0-9622-01624f90166e"}},{"source":"Person","edge":"IS_GUEST","target":"Episode","props":{"ref_id":"fd4766a0-082e-4ca5-8a0b-c358a1335257"}},{"source":"Person","edge":"IS_HOST","target":"Episode","props":{"ref_id":"26e7be2d-18de-4cda-ba46-53d8a173de05"}},{"source":"Person","edge":"IS_PARTY_TO","target":"Agreement","props":{"ref_id":"edab5904-037a-4c65-97a8-cb5993c7fe54"}},{"source":"Person","edge":"IS_SPEAKER","target":"Episode","props":{"ref_id":"305b9541-0006-4075-9e88-fd711f4d1671"}},{"source":"Person","edge":"MADE_CLAIM","target":"Claim","props":{"ref_id":"e509bd4e-c33e-472e-a734-fcc42774869f"}},{"source":"Person","edge":"MENTIONED","target":"Episode","props":{"ref_id":"2040360d-78f9-405e-ae86-980042d3f7f9"}},{"source":"Person","edge":"MENTIONED_IN","target":"Agreement","props":{"ref_id":"5ab5df36-8151-403a-9829-08872d45df5d"}},{"source":"Person","edge":"MENTIONED_IN","target":"Section","props":{"ref_id":"5457a4f7-b2b5-45db-b785-60aadb693c74"}},{"source":"Person","edge":"OFFICER_OF","target":"Corporation","props":{"ref_id":"ff4fa570-ee51-456c-a508-66851e9d1b97"}},{"source":"Person","edge":"ORGANIZED","target":"EmailInvite","props":{"ref_id":"bb8820bc-9214-411c-b7b9-e2dfd0c73574"}},{"source":"Person","edge":"POSTED","target":"Tweet","props":{"ref_id":"9c86a75f-bf88-4aa6-bd7f-ba94111af71f"}},{"source":"Person","edge":"RECEIVED","target":"Email","props":{"ref_id":"24a6afbc-535e-4f75-94ee-77dc9c3d3884"}},{"source":"Person","edge":"REFERENCED_IN","target":"Excerpt","props":{"ref_id":"0798600b-1540-4324-8e26-626279598035"}},{"source":"Person","edge":"RESPONDENT_IN","target":"InvestigationLog","props":{"ref_id":"e7f7a0da-fdc7-4d8d-ba71-f48301659749"}},{"source":"Person","edge":"SAME_AS","target":"Person","props":{"basis":"?string","doc_b_name":"?string","ref_id":"9d91368d-1b03-49f0-85b1-00c8cc6676a4","doc_a_name":"?string"}},{"source":"Person","edge":"SENT","target":"Email","props":{"ref_id":"a9e89780-2acb-4e63-a9af-d0f898798fac"}},{"source":"Person","edge":"SENT","target":"Message","props":{"ref_id":"47592886-1f38-443a-b653-2b544a8e5a31"}},{"source":"Person","edge":"TENTATIVE","target":"EmailInvite","props":{"ref_id":"54c96cfa-24e3-4cd8-bc16-e990284220e9"}},{"source":"Person","edge":"WORKS_AT","target":"Organization","props":{"volatility":"EVOLVING","confidence_score":"?float","fluent":true,"invalid_at":"?datetime","temporal":true,"valid_at":"?datetime","ref_id":"e0963238-68fa-46a9-84ca-71a5ea3ea62a","last_confirmed_at":"?datetime","invalidated_by":"?string","expired_at":"?datetime","cardinality":"single"}},{"source":"PlaybookEntry","edge":"APPLIES_IN","target":"Jurisdiction","props":{"ref_id":"06eb7475-d515-4c11-8e15-3ce056c84614"}},{"source":"PlaybookEntry","edge":"CALIBRATED_FOR","target":"Matter","props":{"ref_id":"8c432863-f91b-400a-91c2-51b78fddc86e"}},{"source":"PlaybookEntry","edge":"EVIDENCED_BY","target":"Excerpt","props":{"ref_id":"06b032f8-4d88-409c-aedb-f6c7dc36b41a"}},{"source":"PlaybookEntry","edge":"GOVERNED_BY","target":"Regulation","props":{"ref_id":"1c0d688c-c041-428e-81cc-03904bd11b0a"}},{"source":"PlaybookEntry","edge":"HAS_COMPONENT","target":"FormulaComponent","props":{"ref_id":"edfdd5a8-68ba-4a3b-8090-2f2a89218d1d"}},{"source":"PlaybookEntry","edge":"HAS_DEADLINE","target":"Deadline","props":{"ref_id":"3883f8e3-f19f-48de-8e56-e8b13fcbd00a"}},{"source":"Podcast","edge":"RELATED_TO","target":"Topic","props":{"ref_id":"d7872ab6-abe8-4806-a354-3110c1bd99ea"}},{"source":"Policy","edge":"HAS_CLAUSE","target":"PlaybookEntry","props":{"ref_id":"e2f694a3-8bf8-4fed-99e4-401cdeb228e7"}},{"source":"Policy","edge":"HAS_GAP","target":"GapItem","props":{"ref_id":"22480af1-55d7-4207-b0e0-f66d727cf35e"}},{"source":"Policy","edge":"IMPLEMENTS","target":"Regulation","props":{"ref_id":"aca113aa-cbe4-4e47-a9dd-3698c6d2ff03"}},{"source":"ProcessingActivity","edge":"GOVERNED_BY","target":"Regulation","props":{"ref_id":"b3d4902c-00f5-44eb-bf9f-28fa2b993434"}},{"source":"Product","edge":"MENTIONED_IN","target":"Section","props":{"ref_id":"8d1a2321-9325-4d6b-a5df-b93dbaa65480"}},{"source":"ProposedFix","edge":"DERIVED_FROM","target":"ProposedFix","props":{"ref_id":"f0db92c8-58f8-45c6-ade8-0553cbd0c377"}},{"source":"ProposedFix","edge":"PRODUCED_BY","target":"EvalTriggerOutput","props":{"ref_id":"acbd6127-92c8-4555-a47d-24a402227668"}},{"source":"ProposedFix","edge":"TARGETS_CAUSE","target":"Cause","props":{"ref_id":"40edf25c-96cd-4db9-bc8a-6df92d21ad2b","cardinality":"many"}},{"source":"ProposedFix","edge":"TARGETS_CONCEPT","target":"Concept","props":{"ref_id":"c06ce15f-f067-493e-b733-46fff1c9b200","cardinality":"many"}},{"source":"PullRequest","edge":"CREATED_BY","target":"Contributor","props":{"ref_id":"63b9fc60-3074-4044-95d1-c74d5566732b"}},{"source":"PullRequest","edge":"TOUCHES","target":"Concept","props":{"ref_id":"0f148c19-132a-4a22-8246-34d53db137fc"}},{"source":"PullRequest","edge":"TOUCHES","target":"Feature","props":{"ref_id":"8df5e682-1c79-48fe-93e3-8fc7c251c1bf"}},{"source":"Regulation","edge":"EVIDENCED_BY","target":"Excerpt","props":{"ref_id":"e1302f97-a20b-40fe-a996-4256fa8d0544"}},{"source":"Regulation","edge":"HAS_COMMENT_PERIOD","target":"CommentPeriod","props":{"ref_id":"e4cd5f7e-1675-4ef2-ad49-a0d1af68ea47"}},{"source":"Regulation","edge":"HAS_GAP","target":"GapItem","props":{"ref_id":"db90c7e9-725b-4cf6-bfa6-2c424844380c"}},{"source":"Regulation","edge":"ISSUED_UNDER","target":"RegulatoryItem","props":{"ref_id":"6987d8fd-6040-415b-9a9b-cfeef7a66a2e"}},{"source":"RegulatoryItem","edge":"EVIDENCED_BY","target":"Excerpt","props":{"ref_id":"60e71f30-9d2b-4a01-8f69-765440ef82c8"}},{"source":"Repository","edge":"HAS","target":"PullRequest","props":{"ref_id":"63836bcc-e8ae-4c4d-8b5d-63667657ed69"}},{"source":"Request","edge":"CALLS","target":"Endpoint","props":{"ref_id":"ec466219-824b-48a6-ac77-0e15fe1a51a2"}},{"source":"Run","edge":"START","target":"Run_step","props":{"ref_id":"9ff4f755-8138-4e9b-bbe2-b0810e638ae6"}},{"source":"Run_step","edge":"START","target":"Run_step","props":{"accurate":"?boolean","ref_id":"a684b113-96f1-4eab-a01a-a7c58c1d9322"}},{"source":"Section","edge":"AUTHORED_BY","target":"Person","props":{"ref_id":"c0f4ac4d-0786-42ec-99d2-05b25e7d5a35"}},{"source":"Section","edge":"HAS_COMPONENT","target":"FormulaComponent","props":{"ref_id":"346399d1-6773-46a5-ab10-748acc76cc18"}},{"source":"Section","edge":"RELATED_TO","target":"Topic","props":{"ref_id":"08dbd412-02d3-4ce8-8c2a-472df7f78cd0"}},{"source":"Show","edge":"HAS","target":"Episode","props":{"ref_id":"23541d77-d7f0-4256-88a5-604ce3468a12"}},{"source":"Show","edge":"HAS_CLAIM","target":"Claim","props":{"ref_id":"be64a895-db5e-4ed4-9784-62cc8200004c"}},{"source":"TabularReviewCell","edge":"CELL_OF","target":"Document","props":{"ref_id":"8d8247dd-ebcd-46ac-9e48-eb357663ed74"}},{"source":"TabularReviewCell","edge":"CONFLICTS_WITH","target":"TabularReviewCell","props":{"field_name":"?string","delta":"?string","ref_id":"8cd10718-a111-4f9d-97e5-d3d36cdb15aa","doc_a_value":"?string","doc_b_value":"?string"}},{"source":"Task","edge":"GLOBAL_MEMORY","target":"Memory","props":{"ref_id":"52f96a78-baf6-4402-9d98-a072d282473a"}},{"source":"Thing","edge":"HAS_FLUENT","target":"Fluent","props":{"volatility":"STATIC","ref_id":"50efb113-9403-4af4-ab78-7b1c0d4377da","cardinality":"many"}},{"source":"Thing","edge":"HAS_PRICE","target":"Thing","props":{"volatility":"INSTANTANEOUS","confidence_score":"?float","invalid_at":"?datetime","temporal":true,"valid_at":"?datetime","ref_id":"900689aa-fbaf-4fac-9d4a-5f9f81492059","last_confirmed_at":"?datetime","invalidated_by":"?string","expired_at":"?datetime","cardinality":"single"}},{"source":"TimelineEntry","edge":"CONTRADICTS","target":"TimelineEntry","props":{"contradiction_type":"?string","ref_id":"596a983c-820c-4c99-86d7-203a4453f51f","contradiction_reason":"?string"}},{"source":"Topic","edge":"MENTIONED_IN","target":"Section","props":{"ref_id":"a49ce91c-1414-47a9-b21a-ad0a9bbcc068"}},{"source":"Trait","edge":"OPERAND","target":"Function","props":{"ref_id":"1220754e-8a14-46e2-958f-a72456c4c51b"}},{"source":"Turn","edge":"NEXT","target":"Turn","props":{"ref_id":"fcb0bd8b-47c5-4529-9c61-68b61e51031c"}},{"source":"Tweet","edge":"RELATED_TO","target":"Topic","props":{"ref_id":"360fc4f1-5850-42de-932d-3e70f2cc5ad2"}},{"source":"Tweet","edge":"THREAD_PART","target":"Tweet","props":{"ref_id":"10cac5be-f244-4a69-bc02-be160f5ce66a"}},{"source":"TwitterAccount","edge":"POSTED","target":"Tweet","props":{"ref_id":"46d8fb7a-cbca-43cf-b602-7579202b3303"}},{"source":"UnitTest","edge":"CALLS","target":"Class","props":{"ref_id":"fa7c23cd-c436-4cd3-b76f-4f50b50b731f","call_start":"?int","call_end":"?int","operand":"?string"}},{"source":"UnitTest","edge":"CALLS","target":"Endpoint","props":{"ref_id":"cf9bb952-bd78-4904-b909-8b82096e37e2","call_start":"?int","call_end":"?int","operand":"?string"}},{"source":"UnitTest","edge":"CALLS","target":"Function","props":{"ref_id":"2c966683-8994-4e52-a46d-83555bd87238","call_start":"?int","call_end":"?int","operand":"?string"}},{"source":"Var","edge":"CONTAINS","target":"Var","props":{"ref_id":"7419dc30-047a-460b-9c88-b244b86ff3b7"}},{"source":"Video","edge":"RELATED_TO","target":"Topic","props":{"ref_id":"30369268-5a01-4c90-9c52-b60e002ef609"}},{"source":"Workflow_version","edge":"START","target":"Generated_step","props":{"ref_id":"923240c0-8f03-4571-95cf-74bc58ecb5a8"}}],"hidden_domains":["Scratchpad"]}; diff --git a/src/graph/index-reconcile.test.ts b/src/graph/index-reconcile.test.ts new file mode 100644 index 0000000..a17372c --- /dev/null +++ b/src/graph/index-reconcile.test.ts @@ -0,0 +1,98 @@ +import { describe, it, before, after } from "node:test"; +import assert from "node:assert/strict"; +import { Bolt } from "./bolt.js"; +import { JARVIS_ONTOLOGY } from "./fixtures/jarvis-ontology.js"; +import { normalizeIndex, reconcileIndexLists, reconcileMigrationId, widenedIndex } from "./index-reconcile.js"; +import { seedJarvisOntology } from "./ontology-seed.js"; +import { graphSnapshot, testGraphConfig, wipeGraph } from "./test-util.js"; + +const cfg = testGraphConfig(); +const LIB = ["name", "summary", "description"]; + +describe("widenedIndex (pure)", () => { + it("the library's list for a non-empty strict subset, string or list", () => { + assert.deepEqual(widenedIndex("name", LIB), LIB); + assert.deepEqual(widenedIndex(["name"], LIB), LIB); + assert.deepEqual(widenedIndex(["description", "name"], LIB), LIB, "order is the library's"); + assert.deepEqual(widenedIndex(["name", "name"], LIB), LIB, "duplicates count once"); + }); + it("null for the same list, a wider or foreign one, an absent one, and a library without a list", () => { + assert.equal(widenedIndex(LIB, LIB), null); + assert.equal(widenedIndex(["description", "summary", "name"], LIB), null); + assert.equal(widenedIndex(["name", "extra"], LIB), null); + assert.equal(widenedIndex(["name", "summary", "description", "extra"], LIB), null); + assert.equal(widenedIndex(null, LIB), null); + assert.equal(widenedIndex(undefined, LIB), null); + assert.equal(widenedIndex([], LIB), null); + assert.equal(widenedIndex("", LIB), null); + assert.equal(widenedIndex("name", "name"), null); + assert.equal(widenedIndex("name", undefined), null); + }); + it("normalizes like jarvis's get_index_fields", () => { + assert.deepEqual(normalizeIndex(" name "), ["name"]); + assert.deepEqual(normalizeIndex(["a", "", " b "]), ["a", "b"]); + assert.deepEqual(normalizeIndex(7), []); + }); + it("the ledger id carries the fixture version", () => { + assert.equal(reconcileMigrationId("m125"), "strut_index_reconcile_m125"); + assert.match(JARVIS_ONTOLOGY.version, /^m\d+$/); + }); +}); + +describe("reconcileIndexLists (live Neo4j)", { skip: cfg ? false : "STRUT_TEST_NEO4J_URI not set" }, () => { + let bolt: Bolt; + const index = async (type: string) => (await bolt.run(`MATCH (s:Schema {type: $t}) RETURN s.index AS i`, { t: type }))[0]!["i"]; + before(async () => { + bolt = new Bolt(cfg!); + await bolt.verify(); + await wipeGraph(bolt); + await seedJarvisOntology(bolt); + }); + after(async () => { + await bolt?.close(); + }); + + it("widens strict subsets to the library's list, leaves the rest alone, stamps per fixture version, never re-runs under it", async () => { + // swarm38's shapes: the string `index` jarvis's early library declared, + // a list with a field the library lacks, an absent `index`, a type the + // library does not know, and a two-field subset. + await bolt.run(`MATCH (s:Schema {type: "Function"}) SET s.index = "name"`); + await bolt.run(`MATCH (s:Schema {type: "Commit"}) SET s.index = ["name", "message", "summary", "extra"]`); + await bolt.run(`MATCH (s:Schema {type: "Class"}) REMOVE s.index`); + await bolt.run(`CREATE (:Schema {type: "Alien", node_key: "alien-name", index: ["x"], name: "string", ref_id: "schema-alien"})`); + await bolt.run(`MATCH (s:Schema {type: "Endpoint"}) SET s.index = ["summary", "name"]`); + + const r1 = await reconcileIndexLists(bolt); + assert.equal(r1.status, "reconciled"); + assert.deepEqual(r1.widened, { + Function: { from: ["name"], to: LIB }, + Endpoint: { from: ["summary", "name"], to: LIB }, + }); + assert.deepEqual(await index("Function"), LIB); + assert.deepEqual(await index("Endpoint"), LIB); + assert.deepEqual(await index("Commit"), ["name", "message", "summary", "extra"]); + assert.equal(await index("Class"), null); + assert.deepEqual(await index("Alien"), ["x"]); + const stamped = await bolt.run(`MATCH (m:Migration {migration_id: $id}) RETURN count(m) AS c`, { id: reconcileMigrationId(JARVIS_ONTOLOGY.version) }); + assert.equal(stamped[0]!["c"], 1); + + // Idempotent: nothing read, nothing written. + const snap = await graphSnapshot(bolt); + const r2 = await reconcileIndexLists(bolt); + assert.deepEqual(r2, { status: "already_done", widened: {} }); + assert.deepEqual(await graphSnapshot(bolt), snap); + + // A list narrowed on purpose after the stamp stays narrow under the + // same snapshot — no fight with a jarvis that meant it. + await bolt.run(`MATCH (s:Schema {type: "Function"}) SET s.index = "name"`); + assert.equal((await reconcileIndexLists(bolt)).status, "already_done"); + assert.equal(await index("Function"), "name"); + + // The next snapshot widens once more. + const r4 = await reconcileIndexLists(bolt, { ...JARVIS_ONTOLOGY, version: "m999" }); + assert.equal(r4.status, "reconciled"); + assert.deepEqual(Object.keys(r4.widened), ["Function"]); + assert.deepEqual(await index("Function"), LIB); + assert.deepEqual(await reconcileIndexLists(bolt, { ...JARVIS_ONTOLOGY, version: "m999" }), { status: "already_done", widened: {} }); + }); +}); diff --git a/src/graph/index-reconcile.ts b/src/graph/index-reconcile.ts new file mode 100644 index 0000000..05b14f8 --- /dev/null +++ b/src/graph/index-reconcile.ts @@ -0,0 +1,98 @@ +/** + * The Schema `index` reconcile (plans/semantic-search.md §2) — strut brings + * a live `:Schema`'s `index` list up to the bundled jarvis library's by + * writing it directly, once per bundled snapshot. + * + * Why: a node's search text is composed from its Schema's `index` (strut's + * writer, the pass, jarvis's own writer — one rule), and schema seeding is + * add-only on both sides — jarvis's `_synchronize_schemas` never changes an + * existing `index` — so a graph seeded before jarvis widened a type's list + * (`Function`: `"name"` → `[name, summary, description]`, jarvis `e6b14dbc`) + * still embeds the name alone. The library is jarvis's own, so these are the + * values jarvis would set — but never through its Schema API, which + * re-embeds the whole type inside one request and rebuilds the shared + * keyword index once per type. + * + * Rule: a live `index` that is non-empty and a STRICT SUBSET of the + * library's for that type gets the library's list. Left alone: a type the + * library does not know, a live list holding a field the library lacks, and + * an absent `index` (the catch-all text — a different meaning). Written + * directly, the new list triggers nothing in jarvis (verified against its + * boot path): its next node write composes with the new list, as the pass + * does. + * + * Stamped per fixture version in the `Migration` ledger + * (`strut_index_reconcile_`): idempotent, and never a fight with a + * jarvis that narrows a list on purpose — a graph is widened once per + * library snapshot and left alone until the next. The pass + * (`embeddings.ts`) then sees every node of a widened type as stale; no + * vector migration of its own. + */ +import { Bolt } from "./bolt.js"; +import { JARVIS_ONTOLOGY, type OntologyFixture } from "./fixtures/jarvis-ontology.js"; +import { schemaStatement } from "./schema-seed.js"; + +export interface IndexReconcileReport { + /** `already_done` = the ledger row for this fixture version is present, + * nothing read; `nothing_to_do` = every live list is current (or wider, + * or absent), ledger stamped. */ + status: "reconciled" | "already_done" | "nothing_to_do"; + /** Per type, the live list and what replaced it. */ + widened: Record; +} + +export function reconcileMigrationId(version: string): string { + return `strut_index_reconcile_${version}`; +} + +/** jarvis `get_index_fields`: a string is a one-item list. */ +export function normalizeIndex(raw: unknown): string[] { + if (Array.isArray(raw)) return raw.map((x) => String(x).trim()).filter(Boolean); + if (typeof raw === "string" && raw.trim()) return [raw.trim()]; + return []; +} + +/** The library's list when `live` is a non-empty strict subset of it; + * null otherwise. Pure. */ +export function widenedIndex(live: unknown, library: unknown): string[] | null { + const a = normalizeIndex(live); + const b = normalizeIndex(library); + if (a.length === 0 || b.length === 0) return null; + const inLibrary = new Set(b); + if (!a.every((f) => inLibrary.has(f))) return null; + if (new Set(a).size >= b.length) return null; + return b; +} + +export async function reconcileIndexLists(bolt: Bolt, fixture: OntologyFixture = JARVIS_ONTOLOGY): Promise { + const report: IndexReconcileReport = { status: "nothing_to_do", widened: {} }; + const id = reconcileMigrationId(fixture.version); + const ledger = await bolt.run(`MATCH (m:Migration {migration_id: $id}) RETURN count(m) AS c`, { id }); + if (Number(ledger[0]?.["c"] ?? 0) > 0) { + report.status = "already_done"; + return report; + } + + for (const schema of fixture.schemas) { + const type = String(schema["type"]); + if (type === "*" || normalizeIndex(schema["index"]).length === 0) continue; + // Case-insensitive like the seeders; every live node of the type (a + // long-lived graph can hold duplicates), soft-deleted ones left alone. + const live = await bolt.run( + `MATCH (n:Schema) WHERE toLower(n.type) = toLower($t) AND (n.is_deleted IS NULL OR n.is_deleted = false) + RETURN elementId(n) AS eid, n.index AS index`, + { t: type }, + ); + for (const r of live) { + const to = widenedIndex(r["index"], schema["index"]); + if (!to) continue; + await bolt.run(`MATCH (n:Schema) WHERE elementId(n) = $eid SET n.index = $to`, { eid: r["eid"], to }); + report.widened[type] = { from: normalizeIndex(r["index"]), to }; + } + } + if (Object.keys(report.widened).length > 0) report.status = "reconciled"; + + await schemaStatement(bolt, `CREATE CONSTRAINT migration_id_unique IF NOT EXISTS FOR (m:Migration) REQUIRE m.migration_id IS UNIQUE`); + await bolt.run(`MERGE (m:Migration {migration_id: $id}) ON CREATE SET m.executed_at = timestamp()`, { id }); + return report; +} diff --git a/src/graph/node-writer.test.ts b/src/graph/node-writer.test.ts index 9ebec63..9a7f97e 100644 --- a/src/graph/node-writer.test.ts +++ b/src/graph/node-writer.test.ts @@ -411,6 +411,31 @@ describe("NodeWriter (live Neo4j)", { skip: cfg ? false : "STRUT_TEST_NEO4J_URI assert.ok(!("text_embeddings" in ((await node(a.ref_id))["props"] as Record))); }); + it("the no-embed mark: an execution record gets Data_Bank and no vector, with an embedder, on write and on update", async () => { + const seen: string[] = []; + const fake: Embedder = { async embed(texts) { seen.push(...texts); return texts.map((t) => Array.from({ length: 384 }, (_, i) => (i === 0 ? t.length : 0))); } }; + const w = new NodeWriter(bolt, { embedder: fake }); + const tc = await w.write({ type: "StrutToolCall", data: { run_id: "r", path: "wf/agent", seq: 1, tool_name: "bash", input_preview: "ls" } }); + const turn = await w.write({ type: "StrutTurn", data: { chat_id: "c", turn: 1, user_text_preview: "hello" } }); + assert.deepEqual(seen, [], "nothing embedded"); + const p = (await node(tc.ref_id))["props"] as Record; + assert.equal(p["Data_Bank"], "bash\nls"); + assert.deepEqual(p["_search_fields_used"], ["tool_name", "input_preview"]); + assert.ok(!("text_embeddings" in p)); + assert.equal(((await node(turn.ref_id))["props"] as Record)["Data_Bank"], "hello"); + assert.ok(!("text_embeddings" in ((await node(turn.ref_id))["props"] as Record))); + // A vector an earlier strut left on one goes with the next update. + await bolt.run(`MATCH (n:Data_Bank {ref_id: $r}) SET n.text_embeddings = [1.0]`, { r: tc.ref_id }); + await w.update(tc.ref_id, { set: { input_preview: "pwd" } }); + const p2 = (await node(tc.ref_id))["props"] as Record; + assert.equal(p2["Data_Bank"], "bash\npwd"); + assert.ok(!("text_embeddings" in p2)); + assert.deepEqual(seen, []); + // An embedded type still is. + await w.write({ type: "StrutRun", data: RUN }); + assert.deepEqual(seen, ["harvey-deliver\nsuccess\nDelivered 60 of 60"]); + }); + it("per-write namespace overrides the backend default", async () => { const r = await writer.write({ type: "StrutRun", data: RUN }, "create", { namespace: "tenant-z" }); assert.equal(((await node(r.ref_id))["props"] as Record)["namespace"], "tenant-z"); diff --git a/src/graph/node-writer.ts b/src/graph/node-writer.ts index 54ef882..4328330 100644 --- a/src/graph/node-writer.ts +++ b/src/graph/node-writer.ts @@ -287,7 +287,7 @@ const nonBlank = (v: unknown) => v !== null && v !== undefined && String(v).trim * real index (`["node_key"]`) or none of its index fields are usable, fall * through to jarvis's priority list + every other non-excluded property. */ -export function searchFieldsFor(schema: NodeSchema, values: Record): string[] { +export function searchFieldsFor(schema: Pick, values: Record): string[] { if (!(schema.index.length === 1 && schema.index[0] === "node_key")) { const focused = schema.index.filter((f) => nonBlank(values[f])); if (focused.length) return focused; @@ -309,8 +309,11 @@ export function searchFieldsFor(schema: NodeSchema, values: Record): { text: string | null; fields: string[] } { + * "\n" — no field-name prefixes. Null when nothing qualifies. The ONE + * composition: the writer, the pass (`embeddings.ts`) and jarvis's + * `build_search_text` all produce this text, which is why "stored + * `Data_Bank` ≠ composed text" is the pass's stale test. */ +export function buildSearchText(schema: Pick, values: Record): { text: string | null; fields: string[] } { const fields = searchFieldsFor(schema, values); const parts = fields.map((f) => String(values[f]).trim()).filter(Boolean); return { text: parts.length ? parts.join("\n") : null, fields }; @@ -424,7 +427,8 @@ export class NodeWriter { if (text !== null) { props["Data_Bank"] = text; props["_search_fields_used"] = fields; - jobs.push({ idx, column: "text_embeddings", text }); + // The no-embed mark: keyword text, never a vector. + if (v.schema.embed) jobs.push({ idx, column: "text_embeddings", text }); } for (const vi of v.schema.vector_index) { const raw = v.values[vi]; @@ -535,6 +539,7 @@ export class NodeWriter { const setMap: Record = { ...p!.onMatch, node_key }; const drop = new Set(remove); if (!("Data_Bank" in setMap)) for (const k of ["Data_Bank", "_search_fields_used", "text_embeddings"]) drop.add(k); + else if (!schema.embed) drop.add("text_embeddings"); // a vector an earlier writer left on a no-embed node goes with the update else if (!this.opts.embedder && setMap["Data_Bank"] !== props["Data_Bank"]) drop.add("text_embeddings"); for (const vi of schema.vector_index) { const col = embeddingColumn(vi); diff --git a/src/graph/schema-resolver.test.ts b/src/graph/schema-resolver.test.ts index bcbba8a..7069f64 100644 --- a/src/graph/schema-resolver.test.ts +++ b/src/graph/schema-resolver.test.ts @@ -109,6 +109,27 @@ describe("jarvis ontology + resolver + jarvis-typed writes (live Neo4j)", { skip assert.ok(!(written[0]!["l"] as string[]).includes("Evalset")); }); + it("reads the no-embed mark: a Schema's `embed: false` is a mark, not an attribute; strut's two execution records carry it in code only", async () => { + assert.equal((await resolver.schema("Turn"))!.embed, true, "the bundled fixture predates the jarvis PR"); + await bolt.run(`MATCH (s:Schema {type: "Turn"}) SET s.embed = false`); + resolver.invalidate(); + try { + const turn = (await resolver.schema("Turn"))!; + assert.equal(turn.embed, false); + assert.ok(!("embed" in turn.attributes)); + assert.deepEqual(turn.index, ["content", "tool"], "keyword text unchanged"); + assert.equal((await resolver.schema("StrutToolCall"))!.embed, false); + assert.equal((await resolver.schema("StrutTurn"))!.embed, false); + assert.equal((await resolver.schema("StrutRun"))!.embed, true); + assert.equal((await resolver.schema("Document"))!.embed, true); + const seeded = await bolt.run(`MATCH (s:Schema) WHERE s.type IN ["StrutToolCall", "StrutTurn"] RETURN collect(s.embed) AS e`); + assert.deepEqual(seeded[0]!["e"], [], "never flattened onto the Schema node (an older jarvis would read a required attribute)"); + } finally { + await bolt.run(`MATCH (s:Schema {type: "Turn"}) REMOVE s.embed`); + resolver.invalidate(); + } + }); + it("merges CHILD_OF ancestors, exposes index/domain, forces name optional", async () => { const doc = (await resolver.schema("document"))!; assert.equal(doc.type, "Document"); diff --git a/src/graph/schema-resolver.ts b/src/graph/schema-resolver.ts index 8df3a8b..80a9184 100644 --- a/src/graph/schema-resolver.ts +++ b/src/graph/schema-resolver.ts @@ -65,6 +65,11 @@ export interface NodeSchema { * list); `["node_key"]` when unset. */ index: string[]; vector_index: string[]; + /** False when the schema carries the no-embed mark (`embed: false`, a + * core Schema key — `SCHEMA_CORE_PROPERTIES`): the writer composes + * `Data_Bank` but computes no `text_embeddings`, and the pass removes any + * vector such a node holds. */ + embed: boolean; /** Attribute name → type string (`?`-prefixed = optional). Includes * everything inherited via CHILD_OF. */ attributes: Record; @@ -210,6 +215,7 @@ export class SchemaResolver { node_key: String(merged["node_key"] ?? `${type.toLowerCase()}-name`), index: index.length ? index : ["node_key"], vector_index: Array.isArray(rawVi) ? rawVi.map(String) : [], + embed: merged["embed"] !== false, attributes, title_key: typeof merged["title_key"] === "string" ? (merged["title_key"] as string) : undefined, description_key: typeof merged["description_key"] === "string" ? (merged["description_key"] as string) : undefined, @@ -357,6 +363,7 @@ export function fromStrut(strut: StrutSchema, hidden?: { domains: Set; t ...(strut.exact_key ? { exact_key: true } : {}), index: [...strut.index], vector_index: [...(strut.vector_index ?? [])], + embed: strut.embed !== false, attributes: { ...effectiveAttributes(strut) }, title_key: strut.title_key, description_key: strut.description_key, diff --git a/src/graph/schema-seed.ts b/src/graph/schema-seed.ts index e4714cc..38be01d 100644 --- a/src/graph/schema-seed.ts +++ b/src/graph/schema-seed.ts @@ -82,8 +82,12 @@ export function flattenSchema(schema: StrutSchema | typeof THING_SCHEMA): Record const { attributes, ...core } = schema; const flat: Record = { ...core, ...attributes }; // `exact_key` is strut's composition rule (strut-schemas.ts), not a - // jarvis schema key: on the node it would read as an attribute. + // jarvis schema key: on the node it would read as an attribute. `embed` + // IS a jarvis key, but only once jarvis knows it: on a Schema node an + // older jarvis reads it as a required attribute, so strut's own types + // keep their mark in code (plans/semantic-search.md ruling 2). delete flat["exact_key"]; + delete flat["embed"]; return flat; } diff --git a/src/graph/search.test.ts b/src/graph/search.test.ts index 2f863ed..3e93ba1 100644 --- a/src/graph/search.test.ts +++ b/src/graph/search.test.ts @@ -15,14 +15,17 @@ import { fetchLimit, fuseHits, inheritedAttributes, + overfetch, pyRound, rankHits, + routeIndexes, serializeNode, splitSchema, titleMatchMultiplier, type Hit, } from "./search.js"; import { EMBEDDING_DIM } from "./embeddings.js"; +import { SchemaResolver } from "./schema-resolver.js"; import { testGraphConfig, wipeGraph } from "./test-util.js"; const cfg = testGraphConfig(); @@ -325,3 +328,147 @@ describe("GraphReader (live Neo4j)", { skip: cfg ? false : "STRUT_TEST_NEO4J_URI assert.equal(await reader.getSchema("Nope"), null); }); }); + +describe("index routing + typed over-fetch (pure)", () => { + const existing = new Set(["data_bank_attribute_index_v2", "text_embeddings_vector_index", "domain_strut_vector_index", "domain_codeartifact_vector_index", "domain_strut_attribute_index_v2"]); + const vec = (r: Partial[0]>) => + routeIndexes({ domains: [], visibleDomains: ["strut", "codeartifact"], existing, suffix: "_vector_index", global: "text_embeddings_vector_index", ...r }); + + it("an explicit domains filter → those domains' indexes", () => { + assert.deepEqual(vec({ domains: ["strut"] }), ["domain_strut_vector_index"]); + assert.deepEqual(vec({ domains: ["strut", "nope"] }), ["domain_strut_vector_index"], "absent ones dropped"); + }); + it("a typed search → the union of the types' domain indexes; no domain, hidden, or no index → the global one", () => { + assert.deepEqual(vec({ typeDomains: new Map([["Function", "codeartifact"]]) }), ["domain_codeartifact_vector_index"]); + assert.deepEqual(vec({ typeDomains: new Map([["Function", "codeartifact"], ["Endpoint", "codeartifact"]]) }), ["domain_codeartifact_vector_index"]); + assert.deepEqual(vec({ typeDomains: new Map([["Context", null]]) }), ["text_embeddings_vector_index"]); + assert.deepEqual(vec({ typeDomains: new Map([["Document", "content"]]) }), ["text_embeddings_vector_index"], "a domain whose index is absent"); + assert.deepEqual(vec({ typeDomains: new Map([["Function", "codeartifact"], ["Context", null]]) }), ["domain_codeartifact_vector_index", "text_embeddings_vector_index"]); + }); + it("neither → the global index, or the visible domains' union where it is absent", () => { + assert.deepEqual(vec({}), ["text_embeddings_vector_index"]); + const noGlobal = new Set([...existing].filter((i) => i !== "text_embeddings_vector_index")); + assert.deepEqual(vec({ existing: noGlobal }), ["domain_strut_vector_index", "domain_codeartifact_vector_index"]); + assert.deepEqual(vec({ existing: noGlobal, typeDomains: new Map([["Context", null]]) }), ["domain_strut_vector_index", "domain_codeartifact_vector_index"]); + assert.deepEqual(routeIndexes({ domains: [], visibleDomains: ["strut"], existing, suffix: "_attribute_index_v2", global: "data_bank_attribute_index_v2" }), ["data_bank_attribute_index_v2"]); + }); + it("overfetch widens from cap × 10 by × 4 until cap survive or k reaches 2000; the query is run with each k", async () => { + const ks: number[] = []; + const survivors = (n: number) => Array.from({ length: n }, (_, i) => i); + assert.equal((await overfetch(120, async (k) => (ks.push(k), survivors(k >= 2000 ? 120 : 3)))).length, 120); + assert.deepEqual(ks, [1200, 2000]); + ks.length = 0; + assert.equal((await overfetch(120, async (k) => (ks.push(k), survivors(120)))).length, 120); + assert.deepEqual(ks, [1200], "stops as soon as cap survive"); + ks.length = 0; + assert.equal((await overfetch(5000, async (k) => (ks.push(k), survivors(1)))).length, 1); + assert.deepEqual(ks, [2000], "a cap past the ceiling is one query at the ceiling"); + ks.length = 0; + await overfetch(10, async (k) => (ks.push(k), []), { start: 2, growth: 3, maxK: 100 }); + assert.deepEqual(ks, [20, 60, 100]); + }); +}); + +describe("typed search routes through the type's domain index (live Neo4j)", { skip: cfg ? false : "STRUT_TEST_NEO4J_URI not set" }, () => { + let bolt: Bolt; + let resolver: SchemaResolver; + let reader: GraphReader; + /** Every vector query the reader ran: the index and its k. */ + const calls: Array<{ index: string; k: number }> = []; + const Q = "workspace access check"; + before(async () => { + bolt = new Bolt(cfg!); + await bolt.verify(); + await wipeGraph(bolt); + await seedStrutDomain(bolt); + // Two jarvis-typed Schemas by hand: a code type in CodeArtifact (with + // the domain's vector index, as jarvis's seed and strut's ontology seed + // create it) and a type with no domain at all. + await bolt.run( + `MATCH (t:Schema {type: "Thing"}) + CREATE (f:Schema {type: "Function", parent: "Thing", domain: "CodeArtifact", node_key: "function-name-file", index: ["name", "summary", "description"], name: "string", file: "string", summary: "?string", description: "?string", ref_id: "schema-function"})-[:CHILD_OF {ref_id: "e1"}]->(t) + CREATE (c:Schema {type: "Context", parent: "Thing", node_key: "context-name", index: ["name"], name: "string", ref_id: "schema-context"})-[:CHILD_OF {ref_id: "e2"}]->(t)`, + ); + await bolt.run( + `CREATE VECTOR INDEX domain_codeartifact_vector_index IF NOT EXISTS FOR (n:Domain_codeartifact) ON n.text_embeddings + OPTIONS { indexConfig: { \`vector.dimensions\`: 384, \`vector.similarity_function\`: 'cosine' } }`, + ); + resolver = new SchemaResolver(bolt); + const nodes = new NodeWriter(bolt, { embedder: bow, resolver }); + await nodes.writeMany([ + { type: "Function", data: { name: "resolveWorkspaceAccess", file: "src/access.ts", description: Q } }, + { type: "Context", data: { name: "unrelated gamma delta" } }, + ]); + // 1,300 decoys NEARER to the query than the function (their text IS the + // query), in another domain and on the global index — more than a + // typed search's first k (cap × 10 = 1,200). + const [v] = await bow.embed([Q]); + await bolt.run( + `UNWIND range(1, 1300) AS i + CREATE (n:StrutRun:Node:Data_Bank:Domain_strut) + SET n.node_key = 'strutrun-decoy-' + i, n.ref_id = 'decoy-' + i, n.namespace = 'default', n.run_id = 'decoy-' + i, + n.Data_Bank = $q, n.text_embeddings = $v, n.date_added_to_graph = 1`, + { q: Q, v }, + ); + await bolt.run(`CALL db.awaitIndexes(60)`); + const spy = new Proxy(bolt, { + get(t, k, r) { + if (k !== "run") return Reflect.get(t, k, r); + return (cypher: string, params?: Record) => { + if (params && typeof params["index"] === "string" && "k" in params) calls.push({ index: params["index"], k: Number(String(params["k"])) }); + return t.run(cypher, params); + }; + }, + }); + reader = new GraphReader(spy, { embedder: bow, resolver }); + }); + after(async () => { + await bolt?.close(); + }); + + it("a code type is found through its domain index among nearer decoys elsewhere", async () => { + calls.length = 0; + const r = await reader.search({ q: Q, types: ["Function"] }); + assert.deepEqual(r.nodes.map((n) => n.properties["name"]), ["resolveWorkspaceAccess"]); + assert.deepEqual(calls.map((c) => c.index), ["domain_codeartifact_vector_index", "domain_codeartifact_vector_index"]); + assert.deepEqual(calls.map((c) => c.k), [1200, 2000], "widened once: one node can never make cap"); + }); + + it("a type with no domain goes to the global index, and the over-fetch reaches past the decoys", async () => { + calls.length = 0; + const r = await reader.search({ q: Q, types: ["Context"] }); + assert.deepEqual(r.nodes.map((n) => n.properties["name"]), ["unrelated gamma delta"]); + assert.deepEqual(calls, [{ index: "text_embeddings_vector_index", k: 1200 }, { index: "text_embeddings_vector_index", k: 2000 }]); + calls.length = 0; + const both = await reader.search({ q: Q, types: ["Function", "Context"] }); + assert.deepEqual(both.nodes.map((n) => n.properties["name"]).sort(), ["resolveWorkspaceAccess", "unrelated gamma delta"]); + assert.deepEqual(new Set(calls.map((c) => c.index)), new Set(["domain_codeartifact_vector_index", "text_embeddings_vector_index"])); + }); + + it("an untyped search reads the global index with no over-fetch; a domains filter its domain's", async () => { + calls.length = 0; + const r = await reader.search({ q: Q, limit: 5 }); + assert.equal(r.nodes.length, 5); + assert.deepEqual(calls, [{ index: "text_embeddings_vector_index", k: 120 }]); + calls.length = 0; + const d = await reader.search({ q: Q, domains: ["codeartifact"] }); + assert.deepEqual(d.nodes.map((n) => n.properties["name"]), ["resolveWorkspaceAccess"]); + assert.deepEqual(calls.map((c) => c.index), ["domain_codeartifact_vector_index"]); + }); + + it("a hidden domain's types stay out of an untyped search, and a typed search for one falls back to the global index", async () => { + await bolt.run(`CREATE (:About {hidden_domains: ["CodeArtifact"]})`); + resolver.invalidate(); + try { + const r = await reader.search({ q: Q, limit: 2000 }); + assert.ok(!r.nodes.some((n) => n.node_type === "Function"), "hidden"); + calls.length = 0; + const typed = await reader.search({ q: Q, types: ["Function"] }); + assert.deepEqual(typed.nodes.map((n) => n.properties["name"]), ["resolveWorkspaceAccess"]); + assert.deepEqual(calls.map((c) => c.index), ["text_embeddings_vector_index", "text_embeddings_vector_index"]); + } finally { + await bolt.run(`MATCH (a:About) DELETE a`); + resolver.invalidate(); + } + }); +}); diff --git a/src/graph/search.ts b/src/graph/search.ts index 07c31ca..5feb959 100644 --- a/src/graph/search.ts +++ b/src/graph/search.ts @@ -21,6 +21,7 @@ import { EDGE_LIVE, NODE_LIVE } from "./deletion.js"; import { typeLabelOf } from "./edge-writer.js"; import { renderVectorField, type Embedder } from "./node-writer.js"; import type { SchemaResolver } from "./schema-resolver.js"; +import { GLOBAL_VECTOR_INDEX } from "./schema-seed.js"; import { SCHEMA_CORE_PROPERTIES, getStrutSchema, vectorIndexedPairs, vectorStem } from "./strut-schemas.js"; // ── Constants (jarvis) ────────────────────────────────────────────────────── @@ -56,9 +57,14 @@ export { SCHEMA_CORE_PROPERTIES }; const SCHEMA_PARENT_PROPERTIES_TO_IGNORE = new Set(["type_description"]); const DATA_BANK_FULLTEXT_INDEX_V2 = "data_bank_attribute_index_v2"; -const DOMAIN_ALL_VECTOR_INDEX = "domain_all_vector_index"; const LUCENE_SPECIAL = new Set('+-!(){}[]^"~*?:\\/'.split("")); +/** A typed search's semantic over-fetch (plans/semantic-search.md ruling + * 5): the database cannot filter a vector query, so `type` is applied + * after the nearest-k cut. Start at `cap × start`, multiply by `growth` + * until `cap` survive or `k` reaches `maxK`. Constants to tune on a swarm. */ +export const TYPED_OVERFETCH = { start: 10, growth: 4, maxK: 2000 } as const; + // ── Types ─────────────────────────────────────────────────────────────────── export interface NodeEnvelope { @@ -153,6 +159,54 @@ export class GraphReadError extends Error { // ── Pure helpers (exported for tests) ─────────────────────────────────────── +export interface RouteInput { + /** The explicit `domains` filter (lowercased suffixes). */ + domains: string[]; + /** For a typed search: each requested type → the lowercased domain its + * Schema's label names, or null (no domain, or hidden). */ + typeDomains?: Map; + visibleDomains: string[]; + /** Index names the database has (`SHOW INDEXES`, read once up front). */ + existing: Set; + suffix: "_attribute_index_v2" | "_vector_index"; + global: string; +} + +/** + * Which indexes one retriever reads (jarvis `_resolve_index_names`, with + * `type` as a reason to route): an explicit `domains` filter → those + * domains'; a typed search → the union of the requested types' domain + * indexes, a type with no domain (or a hidden one, or a domain whose index + * is absent) contributing the global index instead; neither → the global + * index. When the global index is absent (jarvis never mounted it, a strut + * DB seeded without it) the visible domains' union stands in, for fulltext + * and vectors alike. The domain route is what lets a typed search see a + * rare type: `Endpoint` is a few hundred of ~40k vectors in + * `Domain_codeartifact`, and a few hundred of ~330k globally. + */ +export function routeIndexes(r: RouteInput): string[] { + const domain = (d: string) => `domain_${d}${r.suffix}`; + const fallback = () => (r.existing.has(r.global) ? [r.global] : r.visibleDomains.map(domain)); + let out: string[]; + if (r.domains.length) out = r.domains.map(domain); + else if (r.typeDomains) { + out = []; + for (const d of r.typeDomains.values()) out.push(...(d && r.existing.has(domain(d)) ? [domain(d)] : fallback())); + } else out = fallback(); + return [...new Set(out)].filter((i) => r.existing.has(i)); +} + +/** Widen `k` until `cap` hits survive the caller's filter or the ceiling + * is reached; `run` queries the index with the given `k`. */ +export async function overfetch(cap: number, run: (k: number) => Promise, o: { start: number; growth: number; maxK: number } = TYPED_OVERFETCH): Promise { + let k = Math.min(cap * o.start, o.maxK); + for (;;) { + const hits = await run(k); + if (hits.length >= cap || k >= o.maxK) return hits; + k = Math.min(k * o.growth, o.maxK); + } +} + export function escapeLucene(value: string): string { let out = ""; for (const ch of value) out += LUCENE_SPECIAL.has(ch) ? `\\${ch}` : ch; @@ -612,17 +666,12 @@ export class GraphReader { const filter = clauses.join(" AND "); const cap = fetchLimit(limit, skip); - // Index routing (`_resolve_index_names`): none → global, one → domain, - // many → per-domain union. When the global index is absent (jarvis - // never mounted, or Neo4j too old for the multi-label vector index), - // fall back to the per-domain union over visible domains — jarvis does - // this for vectors; we do it for fulltext too so a strut-only DB needs - // no global index. Existence is read once, up front. + // Index routing — `routeIndexes` above. Existence is read once, up + // front; a typed search routes through the types' domain indexes. const existing = new Set((await this.rows(tx, `SHOW INDEXES YIELD name RETURN name`)).map((r) => String(r["name"]))); - const route = (suffix: string, global: string) => - domains.length ? domains.map((d) => `domain_${d}${suffix}`) : existing.has(global) ? [global] : visibleDomains.map((d) => `domain_${d}${suffix}`); - const ftIndexes = route("_attribute_index_v2", DATA_BANK_FULLTEXT_INDEX_V2).filter((i) => existing.has(i)); - const vecIndexes = route("_vector_index", DOMAIN_ALL_VECTOR_INDEX).filter((i) => existing.has(i)); + const typeDomains = types?.length ? await this.typeDomains(types) : undefined; + const ftIndexes = routeIndexes({ domains, typeDomains, visibleDomains, existing, suffix: "_attribute_index_v2", global: DATA_BANK_FULLTEXT_INDEX_V2 }); + const vecIndexes = routeIndexes({ domains, typeDomains, visibleDomains, existing, suffix: "_vector_index", global: GLOBAL_VECTOR_INDEX }); let fulltext: Hit[] = []; let semantic: Hit[] = []; @@ -680,7 +729,11 @@ export class GraphReader { if (q && this.opts.embedder && vecIndexes.length) { semantic = await layer("semantic", async () => { const [embedding] = await this.opts.embedder!.embed([q]); - return runVector(vecIndexes, cap, embedding!); + // `type` is a WHERE after the nearest-k cut (the database cannot + // filter a vector query), so a typed search asks for more and + // widens until `cap` survive — the query embedded once. + if (!types?.length) return runVector(vecIndexes, cap, embedding!); + return overfetch(cap, (k) => runVector(vecIndexes, k, embedding!)); }, []); if (semantic.length >= cap) semTruncated = true; } @@ -833,6 +886,18 @@ export class GraphReader { return split; } + /** Each canonical type → the lowercased domain its Schema's label names + * (the resolver's: null for a hidden type or domain, or no domain; null + * for every type without a resolver). */ + private async typeDomains(types: string[]): Promise> { + const out = new Map(); + for (const t of types) { + const label = this.opts.resolver ? (await this.opts.resolver.schema(t))?.domainLabels[0] : undefined; + out.set(t, label ? label.slice("Domain_".length) : null); + } + return out; + } + /** Resolve each type name to its canonical label; unresolved kept as-is. */ private async canonicalTypes(raw: string[]): Promise { if (!this.opts.resolver) return raw; diff --git a/src/graph/strut-schemas.ts b/src/graph/strut-schemas.ts index 5506d8b..c869c23 100644 --- a/src/graph/strut-schemas.ts +++ b/src/graph/strut-schemas.ts @@ -43,6 +43,15 @@ export interface StrutSchema { * index (jarvis `vector_index`). Only the `input_q`/`output_q` search * types declare this. */ vector_index?: string[]; + /** `false`: nodes of this type get `Data_Bank` (keyword search) but never + * a `text_embeddings` vector — the execution records (`StrutToolCall`, + * `StrutTurn`) are too fine-grained to search by meaning, and the pass + * (`embeddings.ts`) removes any vector they hold. Strut's own rule for + * its own types, never flattened onto the Schema node: an older jarvis + * reads an unknown Schema key as a REQUIRED attribute and refuses every + * node of the type. jarvis-typed nodes carry the same mark on their + * Schema node, which the resolver reads (plans/semantic-search.md §4). */ + embed?: false; icon: string; shape: string; primary_color: string; @@ -147,6 +156,11 @@ export const SCHEMA_CORE_PROPERTIES = new Set([ "shape", "index", "node_key", "conditional_formatting", "action", "type_description", "description", "display_name", "title_key", "description_key", "paid_properties", "domain", "vector_index", "volatility", "ref_id", + // The no-embed mark (plans/semantic-search.md ruling 2): `embed: false` + // on a Schema means its nodes keep their search text and never get a + // `text_embeddings` vector. In this list so the resolver reads it as a + // mark, not as an attribute named `embed` of type `false`. + "embed", ]); /** Attribute names a schema may not declare (jarvis reserved keys, plus the @@ -339,6 +353,7 @@ export const STRUT_SCHEMAS: readonly StrutSchema[] = [ type: "StrutToolCall", node_key: "struttoolcall-run_id-path-seq", index: ["tool_name", "input_preview"], + embed: false, title_key: "tool_name", description_key: "input_preview", type_description: "One tool call inside a strut agent session", @@ -381,6 +396,7 @@ export const STRUT_SCHEMAS: readonly StrutSchema[] = [ type: "StrutTurn", node_key: "strutturn-chat_id-turn", index: ["user_text_preview"], + embed: false, title_key: "user_text_preview", description_key: "assistant_text_preview", type_description: "One turn of a strut chat", diff --git a/src/index.ts b/src/index.ts index 711044d..9548246 100644 --- a/src/index.ts +++ b/src/index.ts @@ -518,7 +518,8 @@ export { EdgeWriter, type EdgeInput, type EdgeWriteResult } from "./graph/edge-w export { SchemaResolver, EDGE_TYPES_ALLOWLIST, type NodeSchema, type EdgeSchemaMatch } from "./graph/schema-resolver.js"; export { seedJarvisOntology, type OntologySeedReport } from "./graph/ontology-seed.js"; export { JARVIS_ONTOLOGY, type OntologyFixture } from "./graph/fixtures/jarvis-ontology.js"; -export { MiniLMEmbedder, backfillEmbeddings, EMBEDDING_DIM, type BackfillReport } from "./graph/embeddings.js"; +export { MiniLMEmbedder, EmbeddingPass, EMBEDDING_DIM, type EmbeddingPassOptions, type EmbeddingPassStatus } from "./graph/embeddings.js"; +export { reconcileIndexLists, widenedIndex, type IndexReconcileReport } from "./graph/index-reconcile.js"; export { GraphReader, GraphReadError,