open protocol · v0.1 draft · deterministic JSON · LLM-round-trippable

a graph-first document protocol with typed inline link facets.

BendScript is a JSON document format where every span can carry a typed edge to another document, span, or external URI. Documents are content-addressable, edges are span-addressable, and the parser round-trip holds for every document in the v0.1 corpus.

install — one package, no build step
// 1. install the reference framework
npm install @bendscript/core

// 2. parse, validate, hash a document
import { parseAndNormalize, computeDocumentId } from "@bendscript/core";

const doc = parseAndNormalize(readFileSync("note.bend.json", "utf8"));
const id  = await computeDocumentId(doc);
// → bagaaie...  (CIDv1, multicodec=json, sha2-256)
↓ live playground — paste any .bend.json, get id + edges + errors open in new tab ↑

this is the substrate — not a screenshot. paste a document, see live validation, watch link marks expand into edges, copy the canonical form. all client-side; no server sees your text.

a document protocol, not another markdown.

Most document formats in this neighborhood treat the graph as an afterthought — or skip it entirely. BendScript inverts the relationship: the graph is the document. Prose is one projection of it.

vs Markdown / MDX

prose-first; we're graph-first.

Markdown links are untyped strings inside a string. BendScript links carry a predicate (cites, supports, contradicts...) and resolve to spans, not just URLs. Round-trip a doc through an LLM and the graph survives.

vs JSON-LD / RDF

triples without losing the prose.

RDF can express any graph, but the document is metadata about a triple store. BendScript keeps the document as the unit; edges are attached to spans of text, not synthesized from out-of-band metadata.

vs ProseMirror / Slate

editor-format-agnostic; the protocol is JSON.

Editor schemas live in editor land. BendScript is host-coupling-free: an Elixir, Rust, or plain-HTML implementation must produce the same id for the same document. The reference is TypeScript; the spec is the contract.

six primitives. one round-trip claim.

The whole protocol is six things and one invariant. The invariant: parse(serialize(parse(d))) === parse(d) for every conforming document.

Document

the unit

a JSON object with blocks, edges, vocabulary, meta, and a content-addressable id. the id is a CIDv1 over JCS-canonical bytes — same blocks + edges, same id.

{
  "bendscript": "0.1",
  "id": "bagaaie...",
  "vocabulary": "core",
  "blocks": [...],
  "edges": [...]
}
Block

structure

paragraph, heading, list, list-item, quote, code, embed, divider — or any vocabulary-defined kind. blocks contain spans (or other blocks, for lists).

{
  "id": "blk-1",
  "kind": "paragraph",
  "spans": [...]
}
Span

addressable text

a chunk of text with an id. every edge target lands on a span: bend:<doc>#blk-1.spn-2. spans are why edges can attach to "this exact phrase" not just "this document."

{
  "id": "spn-2",
  "text": "the memory loop",
  "marks": [...]
}
Mark

inline annotation

bold, italic, code, link. only link carries data — a target URI and (optionally) a predicate. typed link marks expand deterministically into edges.

{
  "kind": "link",
  "target": "bend:bafy...",
  "predicate": "cites"
}
Edge

typed connection

subject → predicate → object, where either endpoint can be a span URI. nine core predicates plus any namespaced predicate from a vocabulary.

{
  "subject": "bend:<d>#blk-1",
  "predicate": "supports",
  "object": "bend:<e>#blk-3"
}
Vocabulary

typed extension

namespace your own block kinds, predicates, and meta fields without forking the protocol. five reserved vocabularies ship in v0.1; anyone can register more.

{
  "vocabulary": "bendscript.memory.v1",
  "meta": { /* vocab fields */ }
}

five reserved vocabularies. graphonomous adopts first.

Vocabularies are how BendScript stays small at the core and expressive at the edges. The protocol defines a tiny set; each portfolio product reserves a namespace and adds the fields it needs. v0.1 ships these five with bendscript.memory.v1 as the load-bearing adopter (§14.3.1).

core

blocks, marks, edges

the irreducible vocabulary. paragraph, heading, list, quote, code, embed, divider; nine edge predicates: cites, supports, contradicts, derives-from, supersedes, transcludes, responds-to, defines, exemplifies.

bendscript.memory.v1

graphonomous adoption

knowledge nodes, claims, evidence chains. four reserved predicates (derived-from, contradicts-belief, consolidated-into, routed-from) and four meta fields (confidence, topology, provenance, retrieval-context). the §14 gating commitment.

bendscript.argument.v1

deliberatic adoption

claims, warrants, rebuttals. structured argumentation graphs that compose with deliberatic's deliberation engine. round-trippable claim trees with provenance-preserving rewrites.

bendscript.spec.v1

specprompt adoption

requirements, MUST/SHOULD/MAY clauses, traceable spec sections. each clause is a span with edges to the implementations and tests that satisfy it.

bendscript.runefort.v1

runefort adoption

tile-bound prose: a paragraph anchored to a room on a runefort floor. the document is the reading surface; the floor is the spatial index.

Write your own at any time — namespace it freely (com.example.my-vocab.v1), declare it in vocabulary, ship. The protocol does not require registration; unknown vocabularies degrade gracefully.

the round-trip claim is verified.

BendScript v0.1 is a protocol that makes one falsifiable claim: the parser round-trip is deterministic across every document in a 20-doc corpus. That holds today. The other two gating items (LLM round-trip on real models; Graphonomous adoption) remain open.

96 tests passing across parser, hash, mark expansion, harness mechanics
verified
20 corpus documents covering Unicode, ZWJ emoji, nested lists, all five reserved vocabularies, adversarial inputs
verified
5 drift components weighted per §8.4: blocks, edges, spans, marks, vocabulary — mock models confirm harness mechanics
verified
3 gating items remaining: LLM round-trip on real models, Graphonomous adoption, Class A faithfulness judge
pending

an open protocol underneath.

BendScript is a small declarative protocol. The reference framework @bendscript/core is TypeScript on Node 20+. Documents are JSON; canonicalization is RFC 8785 (JCS); ids are CIDv1 with the json multicodec. Independent of the rest of the [&] stack — usable by them, never required.

bend the graph.

Open the playground. Paste a document. Watch link marks expand into edges. Copy the canonical form. Then reach for @bendscript/core and start round-tripping your own.

open the playground → read the spec github ↑