/** * E3 graph observability + visualization — READ-ONLY over the entity/relation * graph (docs/plans/2026-06-02-graph-observability.md). * * This module only READS the graph (`loadEntities` / `loadRelations`) and renders * view-models; it issues no INSERT/UPDATE/DELETE, so `scripts/check-graph-writes.mjs` * stays green. Used by the CLI (`hippo graph show` / `hippo graph view`) and the * HTTP `GET /v1/graph` route, which all build the same `GraphModel`. */ import { type EntityType, type RelationType } from './graph.js'; export interface GraphNode { id: number; type: EntityType; name: string; } export interface GraphEdge { from: number; to: number; relType: RelationType; } export interface GraphModel { nodes: GraphNode[]; edges: GraphEdge[]; /** Conservative "maybe incomplete" flag: true when a loader returned exactly * its limit (the graph MAY be truncated). Can over-report, never under-report. */ truncated: boolean; } /** Default bound for the CLI viewer / show so an unbounded set is never laid out. */ export declare const DEFAULT_VIEW_LIMIT = 500; /** * Build the view-model from the graph (reads only). With `opts.entity`, returns a * focus subgraph: every entity whose name === entity, plus their 1-hop neighbours, * plus the edges among that union. Dangling edges (an endpoint outside the node * set) are always dropped. */ export declare function buildGraphModel(hippoRoot: string, tenantId: string, opts?: { entity?: string; limit?: number; }): GraphModel; /** * Deterministic Fruchterman-Reingold-style force layout. Seeded circular init + * fixed iterations, NO `Math.random`, so the same model always yields the same * positions (testable, stable output). Non-finite coordinates from a degenerate * step are clamped to the viewport centre; all positions are clamped in-bounds. */ export declare function layoutGraph(model: GraphModel, opts?: { width?: number; height?: number; iterations?: number; }): Map; /** HTML-escape for SVG text / title / markup content (XSS guard). */ export declare function escapeHtml(s: string): string; /** * Render the model as a SELF-CONTAINED, dependency-free, offline interactive HTML * node-link diagram. Positions are computed server-side (deterministic). User * strings are escaped per sink: SVG ``/`` via `escapeHtml`; the model * is inlined in a `<script type="application/json">` block with `<`/`>`/`&` * unicode-escaped so a `</script>` inside an entity name cannot break out (the * client `JSON.parse`s it back and never `innerHTML`s a user string). */ export declare function renderGraphHtml(model: GraphModel): string; /** * Render the model as a JSON Canvas (jsoncanvas.org) document — `nodes[]` of * type `text` positioned by the same deterministic layout, `edges[]` linking * them by id. Opens natively in Obsidian. Pure JSON; entity names live in the * `text` field (Obsidian renders/sanitizes them). */ export declare function renderGraphCanvas(model: GraphModel): string; //# sourceMappingURL=graph-view.d.ts.map