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

ScriptPurposeUsage
validate_relationships.jsCheck consistency between JSON and .md filesnode validate_relationships.js [--module <folder>]
sync_relationships.jsBidirectional syncSee modes below
build_cross_module_index.jsRebuild global cross-module edge indexnode 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:

  1. Read _meta/relationships.json for existing edges
  2. Read _meta/technology_context.md for persona/tone rules
  3. Read _meta/*_terms_zero_to_hero.md for the term's level and description
  4. Generate the term .md file with ## Prerequisites and ## Related Terms sections
  5. Update _meta/relationships.json with the new term's edges
  6. Update _meta/missing_terms.md if any linked terms don't exist yet
  7. Run node validate_relationships.js to verify
  8. Run node build_cross_module_index.js if cross-module edges were added
  9. 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:

  • term key = snake_case filename without .md
  • module = 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
MessageMeaningFix
is in .md but missing from .jsonTerm file has a link JSON doesn't know aboutRun sync_relationships.js --from-files
does not reciprocateA lists B as related, but B doesn't list A backRun fix_relationships.js or add the back-link manually
Circular prerequisite chainA→B→A forms a cycle in the prereq graphContent issue — one of the edges should be related, not prerequisite
JSON references file … which does not existStale entry in JSONRemove the entry or create the missing term file
exists on disk but has no entry in relationships.jsonNew term file not yet registeredRun 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
Built with LogoFlowershow