Term Relationships — Contributor Guide
Term Relationships — Contributor Guide
Quick reference for working with the single source of truth for term relationships.
Overview
Every technology module has a _meta/relationships.json file that is the authoritative record of all term relationships. It captures:
- Prerequisites — directed edges: "understand term B before learning term A"
- Related terms — bidirectional edges: "A and B are conceptually connected"
- Cross-module links — edges that span technology boundaries (e.g. React → JavaScript)
A global index at _meta/cross_module_edges.json aggregates all cross-module edges for fast lookup.
Install the Pre-commit Hook
The hook auto-validates affected modules whenever you stage relationships.json or term .md files:
cp knowledge-base/.githooks/pre-commit .git/hooks/pre-commit
chmod +x .git/hooks/pre-commit
Scripts
| Script | Purpose | Usage |
|---|---|---|
validate_relationships.js | Check consistency between JSON and .md files | node validate_relationships.js [--module <folder>] |
sync_relationships.js | Bidirectional sync | See modes below |
build_cross_module_index.js | Rebuild global cross-module edge index | node build_cross_module_index.js |
extract_relationships.js | ⚠️ One-time migration only — already run | — |
sync_relationships.js modes
# After editing term .md files — update JSON to match
node knowledge-base/sync_relationships.js --from-files
# After editing relationships.json directly — rewrite .md §Prerequisites/§Related Terms
node knowledge-base/sync_relationships.js --from-json
# Preview what --from-files would change (no writes)
node knowledge-base/sync_relationships.js --diff
# Scope to a single module
node knowledge-base/sync_relationships.js --from-files --module 03-javascript
Workflows
Generating a New Term File (AI-assisted)
When you ask AI to generate a new term, it will:
- Read
_meta/relationships.jsonfor existing edges - Read
_meta/technology_context.mdfor persona/tone rules - Read
_meta/*_terms_zero_to_hero.mdfor the term's level and description - Generate the term
.mdfile with## Prerequisitesand## Related Termssections - Update
_meta/relationships.jsonwith the new term's edges - Update
_meta/missing_terms.mdif any linked terms don't exist yet - Run
node validate_relationships.jsto verify - Run
node build_cross_module_index.jsif cross-module edges were added - Commit all changes atomically
⚠️ Section numbers vary. "Prerequisites" may be §1 or §7 depending on the file. Scripts always match by heading text, never by number.
Editing an Existing Term's Relationships
Option A — Edit the .md file, then sync to JSON:
# Edit the term file manually
vim knowledge-base/03-javascript/terms/level_03/closure.md
# Sync changes to JSON
node knowledge-base/sync_relationships.js --from-files --module 03-javascript
# Rebuild the cross-module index if needed
node knowledge-base/build_cross_module_index.js
# Validate
node knowledge-base/validate_relationships.js --module 03-javascript
Option B — Edit relationships.json directly, then sync to .md files:
# Edit the JSON
vim knowledge-base/03-javascript/_meta/relationships.json
# Sync back to .md files (updates §Prerequisites and §Related Terms)
node knowledge-base/sync_relationships.js --from-json --module 03-javascript
# Validate
node knowledge-base/validate_relationships.js --module 03-javascript
Querying the Graph
// "What are all transitive prerequisites of closure?"
const graph = require('./knowledge-base/03-javascript/_meta/relationships.json');
function getPrereqChain(termKey, module, visited = new Set()) {
const key = `${module}::${termKey}`;
if (visited.has(key)) return [];
visited.add(key);
const term = graph.terms[termKey];
if (!term) return [];
const direct = term.prerequisites.map(p => p.term);
return [...direct, ...direct.flatMap(p => getPrereqChain(p, module, visited))];
}
console.log([...new Set(getPrereqChain('closure', '03-javascript'))]);
// → ['function', 'scope', 'variable', 'expression', ...]
// "Which modules reference a JavaScript term?"
const index = require('./knowledge-base/_meta/cross_module_edges.json');
const refs = index.edges.filter(e => e.target_module === '03-javascript' && e.target_term === 'promise');
console.log(refs.map(e => `${e.source_module}/${e.source_term}`));
JSON Schema
Each _meta/relationships.json validates against knowledge-base/_meta/relationships.schema.json.
Minimal entry:
{
"term_key": {
"level": 3,
"file": "terms/level_03/term_key.md",
"display_name": "Term Name",
"prerequisites": [
{ "term": "other_term", "module": "03-javascript", "description": "One-line reminder." }
],
"related": [
{ "term": "another_term", "module": "03-javascript", "description": "One-line reminder." }
]
}
}
Key rules:
termkey = snake_case filename without.mdmodule= technology folder name (e.g.03-javascript)description= the text after the—in markdown link syntax- Related terms are bidirectional — if A lists B as related, B should also list A
- Prerequisites are directed — A→B means "B must be understood before A"
Understanding Validation Output
Checking 03-javascript… ✗ 3 issue(s)
03-javascript (3):
! [closure] Prerequisite "scope" (03-javascript) is in .md but missing from .json
! [promise] Related term "async_await" does not reciprocate back to "promise"
! [closure] Circular prerequisite chain: closure → function → closure
| Message | Meaning | Fix |
|---|---|---|
is in .md but missing from .json | Term file has a link JSON doesn't know about | Run sync_relationships.js --from-files |
does not reciprocate | A lists B as related, but B doesn't list A back | Run fix_relationships.js or add the back-link manually |
Circular prerequisite chain | A→B→A forms a cycle in the prereq graph | Content issue — one of the edges should be related, not prerequisite |
JSON references file … which does not exist | Stale entry in JSON | Remove the entry or create the missing term file |
exists on disk but has no entry in relationships.json | New term file not yet registered | Run sync_relationships.js --from-files |
Atomic Commit Convention
When making relationship-related changes, always commit together:
docs(level_NN): add <Term Name> term doc
- Add terms/level_NN/term_key.md
- Update _meta/relationships.json (new term + any new edges)
- Update _meta/missing_terms.md if applicable
- Rebuild _meta/cross_module_edges.json if cross-module edges added