The markdown-graph engine — the surface that the oculus_* MCP tools, lantern rendering, and editor plugins drive — rebuilt as wanderland-core boundaries over an append-only overlay store. When you oculus_look / oculus_poke / oculus_link a node, loom boundaries are what run. Part of the pack catalog in wanderland-dev-ai-reference; this is its deep-dive.
Source: /Users/graemefawcett/working/wanderland-loom-pack. Verified 2026-07-30.
A slug is a stream of mdast tokens with holes. Sections, fences, and virtual-fences own token ranges within that stream. Reads are overlays (compose a baseline + its pokes at a level); writes are splices (append a typed record). Every record is typed at an address on core's append-only :store. Loom is policy over a dumb log — the store just appends; loom decides what "the current content at this address" means.
loom_create seeds content; loom_poke appends an operation; a read composes seed + pokes. loom_checkpoint materializes an overlay into a fresh baseline; loom_publish snapshots a whole node into fresh baselines.loom_undo appends a record that cancels the last poke; loom_archive tombstones; loom_resurrect anti-tombstones. Nothing is deleted — cancellation is another append.support/io.rb) is the ONE place all content/operation writes pass through, enforcing "one live content per address" as loom policy. Raw store.append stays only for test seeding.Loom registers no adapter kind. A site mounts these and loom's boundaries use them:
| Adapter | Role | Used by |
|---|---|---|
:store |
the append-only crossing store | 26 boundaries |
:remark |
markdown → mdast bridge | loom_ast, loom_peek |
:ruby_runtime |
Ruby fence bridge (JSON-RPC 2.0 over stdio, out-of-process) | loom_exec_ruby |
:python_runtime |
Python fence bridge | loom_exec_python |
The runtime bridges run fences out of process so a fence can't block the engine — a Ruby fence talks JSON-RPC 2.0 over stdio to a worker on the far side of :ruby_runtime (bridges/ruby/runtime.rb).
All prefixed loom_, under lib/wanderland_loom_pack/boundaries/.
Parse / ingest pipeline (the loom_ingest archetype chains these):
loom_ast — markdown → mdast via :remark.loom_section_markers — lift heading sections, leaving holes where they were.loom_fence_markers — lift code fences into canonical + meta + label records.loom_pattern_match — pattern engine: lift placeholders, extract structural blocks.loom_write_records — append the decomposed node / sections / fences / labels / vfences.loom_ingest — runs the full chain.loom_fence_attrs — parse a fence type[attrs] info string.Content CRUD (via the Io seam):
loom_create — seed content through Io (one-live-content-per-address).loom_poke — append an operation; reads compose seed + pokes.loom_meta / loom_metas — set / read metadata.loom_checkpoint — materialize an overlay → baseline.loom_publish — snapshot a node into fresh baselines.Graph / links:
loom_link / loom_unlink / loom_relink — edges at <from>:edge:<dir>:<target>.loom_edges — read edges grouped N/S/E/W.loom_backlinks — incoming edges.loom_move — move a ref's hole between parents.loom_tag / loom_tags / loom_tagged — tag / read / walk-and-collect.Read / render:
loom_peek — overlay-read at a level, recursively filling holes.loom_compose — fill a caller-supplied shape of includes.loom_page — assemble page data (content html + nav + trail); adapters: [:store].loom_nav — resolve a path → slug + breadcrumb.loom_load — read <root>/<slug>.md (file-bootstrap).Code execution:
loom_execute_fence — resolve a fence → dispatch to its language binding → write a linked :loom:output.loom_exec_ruby / loom_exec_python — the language bindings.Lifecycle:
loom_archive — tombstone.loom_resurrect — anti-tombstone.loom_undo — antiparticle cancels the last poke.loom_ingestlib/wanderland_loom_pack/archetypes/ingest.yml. Slots: ast → section_markers → fence_markers → pattern_match → write_records. Each slot reads its upstream via !Context for_boundary.<slot>.<field>. (The entry comment mentions a render chain too, but only ingest.yml ships.)
support/io.rb — the Io write seam (one-live-content-per-address policy over the dumb store).support/ast_util.rb — decomposition + read algorithms.support/node_file.rb — slug → path resolution with an escape guard, shared by loom_load / loom_page.bridges/ruby/runtime.rb — the JSON-RPC 2.0 Ruby fence worker (far side of :ruby_runtime).The oculus_* MCP surface is loom under the hood: oculus_look ≈ loom_peek / loom_page; oculus_poke ≈ loom_poke (or loom_poke path=content → a content-replacing compose); oculus_link / oculus_get_edges ≈ loom_link / loom_edges; oculus_add_tags / oculus_find_by_tag ≈ loom_tag / loom_tagged; oculus_execute_fence ≈ loom_execute_fence; oculus_undo / archive ≈ loom_undo / loom_archive.