A link takes a reader somewhere. A relationship also says why the connection matters. Keep that extra meaning clear enough to use, not elaborate enough to require a second framework.
Store the assertion at its source
Suppose a fictional project uses a fictional tool. The project stores:
relationships:
- predicate: uses
target: example-tool
The target is an ID, not a path. A renderer can later resolve it to a URL. Moving the tool’s file does not change the assertion.
This is an illustrative fragment. A real graph must register uses in its
ontology and contain a node with ID example-tool before accepting the edge.
Keep the vocabulary small
Prefer a precise, reusable predicate such as depends-on to a growing collection
of near synonyms. Write one sentence defining a new predicate before adopting it.
If two predicates mean the same thing, choose one.
Do not invent a relationship merely because two words occur in the same article. A connection is an assertion that needs justification, not a decorative line.
Derive the reverse view
If A depends on B, the system can show A in B’s incoming connections. It does not need a second manually maintained assertion. The incoming view retains the source and original predicate; it does not pretend to prove the converse.
Cycles are not inherently invalid. A cycle in depends-on might be a problem for
an execution order; a cycle of conceptual references might be entirely useful.
Define the rule for the meaning, not for the shape alone.
Use a simple review test
For each edge, ask: can I read “source — predicate → target” as a clear statement? Does the target exist? Is the assertion supported? Would it still mean the same thing after either page moves?
Try it: add just one justified relationship. Build an incoming view before adding more predicates. Seeing how the edge will be used often reveals whether it was worth storing.