The graph domain¶
Status: preferred conceptual model; no graph engine, traversal vocabulary or renderer exists. The implementation is a bootstrap evaluator over Int, Float, Bool and same-type addition. Type syntax here is illustrative.
This document defines one of the two domains HQL reasons in. The other is the knowledge model. They are peers: neither is a layer of the other, and a type in one is not a supertype of a type in the other — the rule that type system states. The graph domain is the structural one. It knows nodes, edges and adjacency, and it knows nothing about meaning, truth or evidence.
Vocabulary¶
Node whatever a graph relates; never a type of its own
Edge<S,T> a directed connection: source, target, data
Graph<N,E> a set of nodes and a set of edges over them
Link<S,T> an edge in a document graph
Relation a knowledge relation, which is also an edge
There is no Node type. What a node is arrives as a type parameter, so a graph
over documents and a graph over concepts share one definition rather than a node
union or a kind field.
type Edge<S, T> {
source: S
target: T
data: Data
}
type Graph<N, E>
Edge<S, T> types the two ends separately. An edge whose ends differ in kind —
a card pointing at a concept, a concept supported by a document — needs no union
at the node position, which is what keeps a mixed graph expressible.
The payload is Data: a tree whose keys
belong to whoever wrote them. relation: parent is an entry, not grammar.
Nothing in the core knows what it means, and an edge annotated that way is not
thereby a Parent edge — an authored key never mints a type.
Two instantiations¶
type Link<S, T> : Edge<S, T>
type HmdGraph : Graph<Card, Link>
type Relation<S, T> : Edge<S, T>
type KnowledgeGraph : {Knowledge, Graph<Concept, Relation>}
The node parameters differ in a way worth reading carefully. The document graph
is over Card, because every card is a document and every document is a node in
it — a relation card included, since structurally it is a file with links like
any other. The knowledge graph is over Concept, so only a ConceptCard
qualifies: ConceptCard : {Card, Concept} supplies the node, while a
RelationCard supplies an edge and no node. The same file therefore sits at
different positions in the two graphs, which is exactly what it means for the
domains to be peers.
| Graph | Nodes | Edges | Where it comes from |
|---|---|---|---|
| Document graph | documents | authored links | the vault's own structure |
| Knowledge graph | concepts | relations | interpretation, performed and retained |
A document graph is discovered: the links are already written, and reading them asserts nothing. A knowledge graph is argued for, and the rule used to derive it must be kept with the result. That difference is why only the second declaration carries a knowledge parent: a graph of concepts and relations that had dropped its conflicting claims, provenance and evidence would be a picture of knowledge rather than knowledge, and the type says so.
Both render through the same machinery without being the same object, which is
the reason Graph is parameterized rather than declared once with a
discriminator.
Relation<S, T> : Edge<S, T> is an ordinary narrowing: an edge has source,
target and data; a relation has those and adds identity, evidence and
provenance. What is not true is Relation : Card. A relation may be
imported, derived or read from a store with no document anywhere; a
RelationCard merely represents one. See knowledge model.
Where edges come from¶
Authored links. The link operator writes one:
[[alice]] -> [[bob]] { relation: parent }
Inside alice, the short form [[bob]] { ... } means the same thing, because
the containing document supplies the source. Authoring it adds the edge to the
vault's graph; authoring it again updates the annotation rather than adding a
second edge.
Extensions. A database, a graph store or an indexer can supply edges the vault never wrote. The graph domain does not care which, and an extension supplying edges is the same kind of participant as one supplying documents.
Derivation. A rule can produce edges from existing ones. The rule is part of the result and must survive with it, which is a knowledge concern rather than a structural one.
Identity¶
The two graphs differ here, and the difference is not cosmetic.
A document edge is identified by its endpoints. One alice -> bob edge
exists; writing the link twice addresses it twice and merges the annotation. The
document graph is therefore a simple graph, which is right for it: two links to
bob in alice are one dependency stated twice, not two dependencies.
A knowledge edge is identified by itself. Distinct relations may make
conflicting claims about the same pair, and knowledge must retain both with
their provenance and evidence rather than merging them into one annotated edge.
The knowledge graph is a multigraph, and the identity is the relation's own —
which is exactly what Relation adds to Edge.
Collections already require that set membership must not equate distinct claims merely because they share endpoints. This is that requirement with a type behind it.
Node identity is open. Two documents, two concepts, or a document and the
concept it describes: when these are the same node has not been decided, and
Set<N> presumes an answer.
Direction and traversal¶
An edge is directed. uplinks are the outgoing direction and downlinks the
incoming one, and they traverse one edge set rather than two: a document cannot
know what points at it by reading itself, which is why the incoming direction
needs a vault. A node may be its own source and target.
Whether a graph exposes its parts as collections, and which ones, is open:
graph.nodes : Set<N>
graph.edges : Set<E>
Set follows the collections model, since discovering edges must not establish
an ordering guarantee. Less clear is whether a graph over a vault is
materialized at all. It may be a query a source executes — a store, a database
or the vault index — which is the execution freedom
pipes already reserves for collection steps.
A traversal, subgraph or path vocabulary has not been designed, and whether it
is ordinary functions or a separate query surface is undecided.
Projection and presentation¶
knowledge
| graph
graph is an ordinary function from a knowledge value to a graph, not a
presentation keyword and not a magical pipeline step. The value it returns happens to
have a renderer registered by the graph extension, which is what makes it appear
in a host as a picture.
Its result type is the open question. A KnowledgeGraph keeps both contracts,
so the projection loses nothing and the result can still be asked about claims,
provenance and evidence. A bare Graph<Concept, Relation> is the weaker,
genuinely lossy result, which is all a host that only draws pictures needs.
Whether these are two operations or one whose result type is stronger than it
used to be is undecided.
That separates the two readings that have been competing: the projection
produces a value, and rendering is a capability of that value, supplied by an
extension as render(Graph) -> Html rather than inherited through :. The
naming is still unsettled — whether the projection and the view may share the
name graph, and whether HmdGraph should be called that when it is a graph
over cards rather than a presentation.
A projection must not silently turn an assertion into a truth or collapse
distinct claims — which is exactly what a KnowledgeGraph is typed to prevent.
Graph is one projection of knowledge among several; tables, lists and diagrams
are others.
Where the domain lives¶
The layering is core → graph → knowledge, with document sources beside it.
- The core names no graph. It has values, bindings, functions and pipes.
- The graph extension owns
Edge,Graphand their operations. - The knowledge extension specializes them for meaning, and depends on the graph capabilities rather than the other way round.
- HMD is one source of documents and specializes them for the vault. Nothing depends on HMD.
An extension owns type knowledge and operations, not the data. This is the same boundary the architecture draws for documents.
Open questions¶
- Variance.
Card : Doc, so doesGraph<Card, Link> : Graph<Doc, Edge>? A function written overGraph<Doc, Edge>is useless if not. Covariance is defensible while graphs are immutable values and unsound once one can be extended in place, so the answer follows from whether construction is pure. - Endpoints as values or references. A forward link to a document that does not exist is permitted, which argues that an edge holds references the graph never resolves. What a reference yields when the target is missing is the open question the link operator records.
- Horizon.
cardsstops at the vault. A graph built from imported namespaces or an external store may not, and what bounds it is undecided. - Merge and conflict policy when two sources supply the same edge, and whether annotation merging is per key or deep.
- Whether
Graphis one type or a family with a shared surface. - Weights, hyperedges and ordered adjacency are not part of the model and have not been argued for or against.
See Graph for the type card,
link operator for the edge-writing
syntax, type system for :, generics and
refinement, knowledge model for the other domain,
semantic search for the first concrete demand on a
traversal vocabulary, and the
design conversation this model was
drawn from.