23301 Commits

Author SHA1 Message Date
Álvaro Tejero Cantero
73bc22f8fb
⬆️ Take Ladybug 0.19.1
`com.ladybugdb/lbug` moves from 0.18.0 to 0.19.1, the current release on
Maven Central. The engine fixes a SIGSEGV on an unwrapped parameter and
moves parameter coercion out of JNI, so shipping 0.18.0 would land a
native library into `develop` with a known crash already fixed upstream.

Nothing else changes. This branch has no `app.graph.arrow`, so the
top-level Arrow field-name backticking that 0.19.x retires does not
exist here and there is no workaround to remove alongside the bump.

AI-assisted-by: mixed models
2026-08-05 19:21:38 +02:00
Álvaro Tejero-Cantero
c18c44f575
Put the graph subsystem behind a flag, off by default (#11075)
`app.graph.ladybug` imports `com.ladybugdb.*` at namespace load. Two
namespaces reach the subsystem and both required it at the top level:
`app.http.debug`, which registers the `/dbg` routes, and
`app.srepl.main`, which loads with the REPL server. Every backend built
from this branch therefore linked the Ladybug native library into the
JVM at boot, whether or not a graph was ever used.

Add a `:graph` flag to `varia`, deliberately absent from `default` so
that a released Penpot ships with the subsystem off. Both require sites
now resolve `app.graph.*` at call time, so with the flag off no
`com.ladybugdb` class is loaded. The nine `/dbg` graph routes are
registered only when the flag is on, and 404 otherwise. The `/dbg` admin
gate is untouched: the flag decides which routes exist, not who may
reach them. When the flag is on, route init requires the subsystem
eagerly, so a missing or unusable native library fails the boot rather
than the first console request.

No tracked file turns the flag on. `backend/scripts/_env` leaves it out,
so a devenv boots with the subsystem off exactly as a released build
does, and `docker/images/docker-compose.yaml`, the self-hosting
distribution, is untouched. Whoever works on the graph turns it on for
one checkout through the gitignored `backend/scripts/_env.local`, which
every backend and exporter dev script sources right after `_env`.

Verified with `-verbose:class` over a boot's namespace load plus
`ig/init-key ::routes`: 9 `com.ladybugdb` classes before this change
with no flag set, 0 after it with the flag off, 9 with `enable-graph`.
2026-08-05 19:05:58 +02:00
Álvaro Tejero Cantero
df80aca9cd
🐛 Use app.system/system in the graph ingest helper
develop renamed app.main/system to app.system/system and dropped the
app.main require while this branch was away. Rebasing replays the old
call, so clj-kondo reports an unresolved namespace and the ns will not
load.
2026-08-05 19:05:58 +02:00
Álvaro Tejero Cantero
735b51ddc1
💄 One row per operation in the Live changes table
Columns revn | op | id: the revn repeats across a batch, the op wears the canvas diff colors (shape/attrs detail on hover), and the id column shows the uuid last group with the full uuid on hover, or N/A for ops without a subject id (e.g. mov-objects).

Signed-off-by: Álvaro Tejero Cantero <alvorithm@teje.ro>
2026-08-05 19:05:58 +02:00
Álvaro Tejero Cantero
c19a8b52a6
🔥 Remove the edge-bundling plugin
Bundled edges render unsmooth and ugly on this build; the gating constant goes with it.

Signed-off-by: Álvaro Tejero Cantero <alvorithm@teje.ro>
2026-08-05 19:05:58 +02:00
Álvaro Tejero Cantero
dd5c9b0cba
🐛 Guard renders against heavy graphs; add ?safe escape hatch
A heavy file could freeze the tab on load-and-render despite the animation gate: the render guard counted nodes only, and the edge-bundling plugin is iteration-heavy in edges. Guard now also trips on edges (8000), edge bundling only activates at <= 300 edges, and /dbg/graph?safe disables auto-render entirely (counts + "Render anyway"), so a page that hung can always be re-entered with the session intact.

Signed-off-by: Álvaro Tejero Cantero <alvorithm@teje.ro>
2026-08-05 19:05:58 +02:00
Álvaro Tejero Cantero
82746bbf06
💄 Session breadcrumb, changelog colors, spacing
File line becomes team › project › file (clickable) with the resident-memory figure beside it (moved up from the graph-size line; breadcrumb resolves from the files-tree payload, so files outside the profiles teams show plain). add-obj/del-obj in Live changes wear the canvas diff colors. Paragraph margins tightened above Feed; left column 330→350 px.

Signed-off-by: Álvaro Tejero Cantero <alvorithm@teje.ro>
2026-08-05 19:05:58 +02:00
Álvaro Tejero Cantero
f427c5a183
Enable the edge-bundling plugin
Signed-off-by: Álvaro Tejero Cantero <alvorithm@teje.ro>
2026-08-05 19:05:58 +02:00
Álvaro Tejero Cantero
398861932a
Legend entries toggle node-table visibility
Clicking a legend entry hides/shows that table across the view (struck-through while hidden, kept listed for re-enabling; pure client-side id filter through filteredGraphData, edges drop with their endpoints, ghosts respect it). Also: setting fold >= depth above 0 now switches foldable containers on — a positive depth was silently inert without combos.

Signed-off-by: Álvaro Tejero Cantero <alvorithm@teje.ro>
2026-08-05 19:05:58 +02:00
Álvaro Tejero Cantero
e4322390d3
💄 Console control-bar and session-panel rework
Left column narrowed 440->330 px (uuid input flexes). Control bar reordered: layout first, then animate and fade (narrow inputs), then the fold set; "fold containers" renamed "foldable containers" (on = foldable, not folded). Load becomes Reload once a session exists (same operation as the removed Full-reload button — load-session! on the current id; tooltip explains the fallback role) with Unload beside it. Session panel: revisions on one line ("ingested at N · graph now M", hover explains the difference), duplicate uuid after the file name dropped. Tried and rejected: fishbone (no positions on graph data) and compact-box (G6 tree layouts walk parent->child, IsChildOf points child->parent).

Signed-off-by: Álvaro Tejero Cantero <alvorithm@teje.ro>
2026-08-05 19:05:58 +02:00
Álvaro Tejero Cantero
9879bdf4da
Report actual graph memory from the buffer manager
graph-data gains bm-bytes (CALL bm_info() -> [mem_limit mem_usage], nil-safe, under the session lock); the session panel shows it as MiB behind the node/edge counts — real resident memory replacing the removed estimate.

Signed-off-by: Álvaro Tejero Cantero <alvorithm@teje.ro>
2026-08-05 19:05:58 +02:00
Álvaro Tejero Cantero
e011dedccf
💄 Console UI polish round
Merge the load form and files tree into one "Load graph from Penpot" box (tree first, uuid + Load/Unload in a row); Loaded session carries HH:MM in its legend; the Live changes box stays hidden until the first change arrives; query fieldset reads "Query graph (LadybugDB Cypher)" with the link covering both terms. Drop the hover tooltips (distracting, useless zoomed out) and the resident-size estimate (per-table counts stay on hover); every toggle gets a "When set/checked ..." title. Depth fold: 0 now expands every container (no more hunting for max depth). Node inspector: two-column flow, structured or long values folded behind the file-tree disclosure triangle.

Signed-off-by: Álvaro Tejero Cantero <alvorithm@teje.ro>
2026-08-05 19:05:58 +02:00
Álvaro Tejero Cantero
53420388d5
🐛 Restore fold-containers as the combo master gate
Since fold-unchanged and depth folding arrived, withCombos ORed them in, so unchecking "fold containers" could no longer remove the combo boxes. The checkbox is the gate again; the derived fold rules are dormant without it.

Signed-off-by: Álvaro Tejero Cantero <alvorithm@teje.ro>
2026-08-05 19:05:58 +02:00
Álvaro Tejero Cantero
bd712bb7fa
Add overview mode: fold containers at or beyond a depth
"fold >= depth" number input (root = 0, empty = off, localStorage): every combo whose container sits at that IsChildOf depth or deeper collapses, giving a top-of-file overview (e.g. 2 folds the containers hanging from a Page). Composes with fold-unchanged — depth folds first, changed ancestor paths are then drilled open. Derived fold state overrides manual folds while active.

Signed-off-by: Álvaro Tejero Cantero <alvorithm@teje.ro>
2026-08-05 19:05:58 +02:00
Álvaro Tejero Cantero
b882b97d21
Highlight clicked node neighborhood in graph console
click-select behavior with degree 1: the clicked element keeps a black ring, direct neighbors stay full-strength, everything else dims to 0.2 opacity (inactive state); clicking empty canvas clears. Works on edges too (selects both endpoints) and composes with the node inspector on the same click.

Signed-off-by: Álvaro Tejero Cantero <alvorithm@teje.ro>
2026-08-05 19:05:58 +02:00
Álvaro Tejero Cantero
f77b7ef7f9
💄 Prune graph console layout roster and tune overlap
Remove grid, random, force, fruchterman, force-atlas2 (nothing over the kept set) and mds (stress layout degenerates to spokes on tree distances, no collision term to tune). Parameterize the keepers against node overlap — concentric/radial get preventOverlap+nodeSize, d3-force a collide radius — and shrink node labels to 7 px on those layouts (DENSE_LABEL_LAYOUTS), verified against variants_simple (72 nodes).

Signed-off-by: Álvaro Tejero Cantero <alvorithm@teje.ro>
2026-08-05 19:05:58 +02:00
Álvaro Tejero Cantero
7747203c1a
Add PNG export and hover tooltips to graph console
Toolbar gains an export item: graph.toDataURL({mode: "overall"}) downloads the whole laid-out graph as graph-<revn>.png — page-chrome-free captures, also the fast path for agents debugging the console. A hover tooltip (table, label, id) backs the reduced/absent labels on dense layouts.

Signed-off-by: Álvaro Tejero Cantero <alvorithm@teje.ro>
2026-08-05 19:05:58 +02:00
Álvaro Tejero Cantero
9f0fde090a
💄 Polish graph console session panel and edge labels
Loaded-session fieldset: graph size gains a resident-memory estimate (fit to graph_sizes.md: ~1.1 MiB floor + ~5.4 KiB/node) with per-table counts on hover, replacing the load-time Projection stats; loaded-at compacts to local HH:MM with the full instant on hover. Edge rel labels drop to 7 px and lose the dashed stroke — the text label alone carries rel identity.

Signed-off-by: Álvaro Tejero Cantero <alvorithm@teje.ro>
2026-08-05 19:05:58 +02:00
Alejandro Alonso
bdad8d64e0
Sync Component library changes into the Ladybug graph 2026-08-05 19:05:58 +02:00
Álvaro Tejero Cantero
e08ac33700
💄 Graph console QoL round
"Show result in graph view" moves into an actions bar above the results table; results scroll inside a 45vh container (client and server render paths); the Loaded-session fieldset gains a live "Graph size" line that stays fresh through skipped repaints; IsInstanceOf mid-edge label becomes the spelled-out rel name (∈ read as membership, not derivation) with the legend falling back to the dash-arrow for long syms.

Signed-off-by: Álvaro Tejero Cantero <alvorithm@teje.ro>
2026-08-05 19:05:58 +02:00
Álvaro Tejero Cantero
6b10ed065a
Add node inspector panel to graph console
Clicking a node fetches its full attribute row (MATCH (n:`Table` {id: uuid(...)}) RETURN n.*) through the query endpoint and renders non-null attrs into a panel under the canvas (count of empty attrs noted). Panel over tooltip: projected tables carry ~80 columns, and the panel persists for reading without obstructing the graph. Table/id are validated before Cypher interpolation; the listener is re-attached on every instance recreation.

Signed-off-by: Álvaro Tejero Cantero <alvorithm@teje.ro>
2026-08-05 19:05:58 +02:00
Álvaro Tejero Cantero
dc6c97e446
Label edge rels with compact unicode symbols
Dash variants alone cannot carry the growing rel roster: EDGE_STYLES entries gain a sym rendered as a small mid-edge label with a white backing (IsInstanceOf = "∈"; IsChildOf stays unlabeled as the background structure), and the legend shows the symbol. Convention from the abacus viewer EDGE_SYM dict.

Signed-off-by: Álvaro Tejero Cantero <alvorithm@teje.ro>
2026-08-05 19:05:58 +02:00
Álvaro Tejero Cantero
661eeb7dfd
🐛 Expand folded combos that gain changed elements
setData merges datum props by id on a live G6 instance, so omitting style.collapsed retained a previous true: with "fold unchanged" on, a change inside a folded combo pulsed but never expanded it. Write the boolean explicitly both ways.

Signed-off-by: Álvaro Tejero Cantero <alvorithm@teje.ro>
2026-08-05 19:05:58 +02:00
Álvaro Tejero Cantero
b6d34a0a97
💄 Reserve chroma for changes in graph console diff mode
Monochrome entity scheme: all node tables share one slate hue, lightness separates within-glyph siblings (validated, worst pair dE 17.5), SVGRaw becomes the hollow hexagon, both rels go grey with dash as the only separator. Diff marks now own all color: thick green/crimson stroke ring (dashed for removals) plus a larger, subtler halo; the legend gains +/- entries while marks are live. Two additions to guide the eye: a brief DOM-overlay pulse on age-0 elements (independent of the G6 animation gate) and a "fold unchanged" toggle that collapses every combo not on an ancestor path of a changed element.

Signed-off-by: Álvaro Tejero Cantero <alvorithm@teje.ro>
2026-08-05 19:05:58 +02:00
Álvaro Tejero Cantero
0bc5d86c0e
Add graph diff marks with step fade to graph console
Each display-changing refetch is a step: added nodes/edges get a green halo, removed ones stay as ghosts with a dashed crimson halo (nodes, fading opacity) or thicker crimson stroke (edges), re-entering layout and combos through their ghost IsChildOf edges. Marks fade linearly and drop after N steps; N is the new "fade" number input (localStorage, 0 = off). Dash + fade carry the added/removed distinction under red-green CVD (#40c057/#c2255c, deutan dE 17.4); diff is vs the previous display step, not arbitrary revisions.

Signed-off-by: Álvaro Tejero Cantero <alvorithm@teje.ro>
2026-08-05 19:05:58 +02:00
Álvaro Tejero Cantero
0b46f5c582
Style Component nodes and IsInstanceOf edges in graph console
Slice-3 export sends edges with a rel field. Derive tree ranking, combo derivation and fold-ability from IsChildOf only; draw other rels as overlay edges with per-rel styles (EDGE_STYLES: IsInstanceOf violet dashed, matching the new Component diamond in NODE_STYLES). Legend now lists only displayed node tables and rels, re-rendered per redraw; help text trimmed to essentials.

Signed-off-by: Álvaro Tejero Cantero <alvorithm@teje.ro>
2026-08-05 19:05:58 +02:00
Alejandro Alonso
bc66645116
🐛 Fix memory leak 2026-08-05 19:05:58 +02:00
Alejandro Alonso
444d754c57
Add Component nodes and IsInstanceOf edges 2026-08-05 19:05:58 +02:00
Alejandro Alonso
5f0dc61caf
📎 Fix linter issues 2026-08-05 19:05:58 +02:00
Álvaro Tejero Cantero
35813ae908
Make the default query self-explanatory; link the Cypher docs
The default query is now multi-line with // comments that explain the filter_* column convention in place (Kuzu accepts comments and blank lines mid-statement; verified against an in-memory database through the console query path). The query fieldset is retitled 'LadybugDB Cypher' with the Cypher word linking to https://docs.ladybugdb.com/cypher/.

Signed-off-by: Álvaro Tejero Cantero <alvorithm@teje.ro>
2026-08-05 19:05:58 +02:00
Álvaro Tejero Cantero
331bd4e3e5
🐛 Fix runaway graph panel growth and blank canvas; drop Expand button
Root cause of 'graph flashes on load then disappears' plus unbounded horizontal growth of the graph panel: fieldsets default to min-inline-size: min-content, so #graph-view-panel sized to its content, and the new ResizeObserver->setSize path closed a feedback loop (setSize -> slightly wider G6 canvas -> wider fieldset -> wider .dashboard flex column -> observer fires) that grew the page ~10px per frame and wiped the painted canvas on every step. Fix severs the feedback path: #graph-view-panel gets min-inline-size: 0, #graph-canvas gets overflow: hidden, and the page section gets flex: 1 1 0 with min-width: 0 so column widths are viewport-driven, never content-driven. This also fixes the original narrow-window scrollbars defect for real. The observer stays (guarded by a current-size comparison) because G6's autoResize is inert on this UMD build (verified: window resizes left the canvas size untouched); the inert autoResize flag is dropped. Legend items now join with spaces so the nowrap spans can wrap between entries.

Also removes the header Expand button - the toolbar's expand/exit icons cover it, Esc still restores.

Verified against the running devenv with a logged-in profile and variants_simple loaded: graph renders and persists, widths stable over multiple seconds at 1400px and 1000px viewports with no horizontal overflow, canvas follows both window shrink and grow, toolbar expand gives a full-page canvas and Esc restores.

Signed-off-by: Álvaro Tejero Cantero <alvorithm@teje.ro>
2026-08-05 19:05:58 +02:00
Álvaro Tejero Cantero
6a26687ab6
Add graph toolbar, animate toggle, filter columns, repaint skip
Graph view gains an on-canvas G6 toolbar (auto-fit, expand, restore - the fullscreen icons drive the existing in-page expand), an 'animate' checkbox that disables animation unconditionally when off (persisted, adaptive <=100-node rule applies only when on), and a ResizeObserver on the canvas so the panel follows window/flex resizes without touching the user's viewport. Preset tree positions are now only injected for the built-in tree layout, removing the tree-then-layout flash on animated re-renders under G6 layouts. Refetches skip the repaint when the display projection (nodes, edges, truncated) is byte-identical, so attribute-only change bursts no longer repaint.

Console: default query returns s/t name+label over all edges plus filter_src_id/filter_tgt_id columns; filter_* columns are hidden from the results table (client and server render) but still feed the 'Show result in graph view' id harvest, keeping the table legible while the graph filter stays available. The query text persists in localStorage across page reloads (restored only over the default, never over a server-rendered query). Legend shows colored Unicode glyphs matching node shapes instead of squares with textual annotations. Load/Unload buttons share one row (HTML5 form attribute), and the loaded file name links to the Penpot workspace via the legacy /#/workspace/<project-id>/<file-id> route resolved client-side from the files-tree payload.

Signed-off-by: Álvaro Tejero Cantero <alvorithm@teje.ro>
2026-08-05 19:05:58 +02:00
Álvaro Tejero Cantero
a6dcd9bea3
Add query-result subgraph, ws auto-reconnect, adaptive animation
The Cypher result pane now offers 'Show result in graph view': any UUID found in any result cell selects the matching nodes in the cached export and the view renders the induced subgraph (edges kept when both endpoints match); 'Show full graph' resets. No graph reconstruction from the query result is needed.

The notifications websocket reconnects automatically (3 s retry) and resubscribes + refetches on reopen, so backend restarts no longer permanently kill the live feed; a lost session now reports 'no graph session (backend restarted?) - reload a file' instead of a bare 404.

Animation is size-adaptive: graphs (or filtered subgraphs) up to 100 nodes render animated for didactics, larger ones stay animation-free; crossing the threshold recreates the instance like a layout switch.

Signed-off-by: Álvaro Tejero Cantero <alvorithm@teje.ro>
2026-08-05 19:05:58 +02:00
Álvaro Tejero Cantero
85fd598815
Add layout dropdown to graph view
Adds a layout <select> next to the fold toggle, populated from the LAYOUTS map in the template: 'tree' (the O(n) preset layout, default) plus 13 G6 layouts (antv-dagre, dagre, circular, concentric, radial, grid, force, d3-force, force-atlas2, fruchterman, mds, combo-combined, random), all smoke-tested against combo data on this UMD build. Layout and fold toggle are independent; switching layouts recreates the graph instance (cheap with animation off); both choices persist in localStorage. antv-dagre stays available for when non-tree edges arrive.

Signed-off-by: Álvaro Tejero Cantero <alvorithm@teje.ro>
2026-08-05 19:05:58 +02:00
Álvaro Tejero Cantero
3c8e8da495
Fix graph view freeze on large files; add fold toggle and root rule
Root cause of the tab freeze on ~1700-node files was G6's default entrance animation: measured 1700 nodes at >2 min animated vs 1.5 s with animation: false. Secondary cost was antv-dagre (~7 s at that size); since IsChildOf is a tree, an O(n) tidy layout (depth = rank, post-order leaf slots, parents centered) computed client-side replaces it and renders the same file in ~1.4 s. A guard skips auto-render above 4000 nodes with an explicit Render-anyway button, so opening the console with a huge session loaded stays responsive.

Folding is now switchable ('fold containers' checkbox, persisted in localStorage) and generalized: any node with children folds except the IsChildOf root of the loaded graph, so Documents (and later Projects/Teams) fold automatically once they gain a parent node.

Signed-off-by: Álvaro Tejero Cantero <alvorithm@teje.ro>
2026-08-05 19:05:58 +02:00
Álvaro Tejero Cantero
186dfb72b0
Fold containers as collapsible combos in graph view
Non-empty containers (Page, Frame, Group, Boolean, SVGRaw) render as nested G6 rect combos holding their own node plus direct children; Document stays a plain node. Double-click folds/expands (collapse-expand behavior); collapsed combos show a member count and re-route child edges. Fold state is read back from getComboData and re-marked on every refetch, so it survives live redraws. Layout gains sortByCombo to keep same-rank nodes grouped by box.

Signed-off-by: Álvaro Tejero Cantero <alvorithm@teje.ro>
2026-08-05 19:05:58 +02:00
Álvaro Tejero Cantero
3f5469b6bd
♻️ Replace fullscreen with in-page expand for graph view
Fullscreen API took over the whole output and broke window-manager splits (and is denied in some environments). The Expand button now toggles a fixed-position overlay covering the page while keeping browser chrome; Esc restores. Column positioning moved from inline style to the stylesheet so the expanded class can override it.

Signed-off-by: Álvaro Tejero Cantero <alvorithm@teje.ro>
2026-08-05 19:05:58 +02:00
Álvaro Tejero Cantero
c056aa2cce
Split graph console in two columns; add file tree and fullscreen
Graph view moves to its own sticky right column (overrides .widget max-width). New /dbg/actions/graph-files endpoint lists teams -> projects -> files for the profile; the console renders it as a collapsible tree where clicking a file loads it. Maximize button fullscreens the graph panel and resizes G6 on fullscreenchange.

Signed-off-by: Álvaro Tejero Cantero <alvorithm@teje.ro>
2026-08-05 19:05:58 +02:00
Álvaro Tejero Cantero
8036f4a4c7
🐛 Fix list-column CSV ingest and serialize graph session access
COPY failed on any file with container shapes: list-typed DDL columns (shapes UUID[], points STRING[], strokes JSON[], ...) were JSON-encoded in staging CSVs, which Ladybug's list parser rejects. Write Kuzu list literals instead, typed per column. Also: value->clj no longer crashes on LIST/STRUCT values (binding lacks value_get_value support; fall back to string), and the debug session Connection is now guarded by a per-session lock — it was shared unsynchronized between the msgbus sync loop and HTTP query/export handlers, and one lost DETACH DELETE was observed under concurrent refetch load.

Signed-off-by: Álvaro Tejero Cantero <alvorithm@teje.ro>
2026-08-05 19:05:58 +02:00
Álvaro Tejero Cantero
7bb027e172
Add G6 graph view to debug graph console
POC per work/g6/plan.md. New /dbg/actions/graph-data exports the in-memory Ladybug session as plain JSON (per-table node queries + multi-table IsChildOf match, row cap 100k with truncation flag). Console page renders it with AntV G6 v5 (jsDelivr CDN, antv-dagre BT layout, color+glyph per node table, validated palette) and refetches debounced on live :file-change messages.

Signed-off-by: Álvaro Tejero Cantero <alvorithm@teje.ro>
2026-08-05 19:05:58 +02:00
Alejandro Alonso
2ab1d07366
♻️ Derive graph node schema from Malli registry 2026-08-05 19:05:58 +02:00
Alejandro Alonso
e51d66805f
🐛 Fix batch delete sync and keep graph console feed alive 2026-08-05 19:05:58 +02:00
Alejandro Alonso
cfac06f4be
Handle mov-objects in debug graph sync 2026-08-05 19:05:58 +02:00
Alejandro Alonso
1723077e85
Incrementally sync debug graph from Penpot file changes 2026-08-05 19:05:58 +02:00
Alejandro Alonso
f5f36d412d
Add live file-change feed to debug graph console 2026-08-05 19:05:58 +02:00
Alejandro Alonso
95d9bc668c
Add debug graph console for in-memory Cypher queries 2026-08-05 19:05:58 +02:00
Alejandro Alonso
41e5d5c340
Add Ladybug graph export to debug UI 2026-08-05 19:05:58 +02:00
Alejandro Alonso
ff60ce70bf
🐛 Fix graph COPY ingest for multiline text names 2026-08-05 19:05:58 +02:00
Alejandro Alonso
aeb3b7967a
Load graph ingest via Ladybug COPY bulk import 2026-08-05 19:05:58 +02:00
Alejandro Alonso
967b99c8d4
Project nested shapes recursively into the graph 2026-08-05 19:05:58 +02:00