Generating Lattice Generate and maintain knowledge graphs — structured, cross-referenced markdown anchored to source code symbols. The output is validated by the CLI, which catches documentation drift whenever code or docs change. The core mechanism is bidirectional linking: - Top-down (docs → code): wiki links in files point to specific symbols in source. When a symbol is renamed or deleted, catches the broken link. - Bottom-up (code → docs): comments in source point back to the concept they implement. When a section is renamed or removed, catches the dangling reference. Without both directi…

)\n\n# Existing annotation line (to detect and update)\nANNOTATION_RE = re.compile(r'^> Documented in: ')\n\n\ndef scan_lat_comments(project_root):\n \"\"\"Scan all source files for @lat: comments.\n\n Returns dict: {relative_file_path: [section_id, ...]}\n \"\"\"\n lat_refs = defaultdict(list)\n\n # Walk the project, skipping common non-source dirs\n skip_dirs = {'.git', 'node_modules', 'vendor', '__pycache__', '.venv',\n 'venv', 'dist', 'build', '.next', 'target', 'lat.md'}\n\n for dirpath, dirnames, filenames in os.walk(project_root):\n dirnames[:] = [d for d in dirnames if d not in skip_dirs and not d.startswith('.')]\n\n for fname in filenames:\n fpath = Path(dirpath) / fname\n # Only scan text files with known comment syntax\n if fpath.suffix not in {'.py', '.js', '.jsx', '.ts', '.tsx', '.go',\n '.rs', '.c', '.h', '.rb', '.sh'}:\n continue\n\n try:\n with open(fpath) as f:\n for line in f:\n match = LAT_COMMENT_RE.search(line)\n if match:\n section_id = match.group(1)\n rel_path = str(fpath.relative_to(project_root))\n if section_id not in lat_refs[rel_path]:\n lat_refs[rel_path].append(section_id)\n except (OSError, UnicodeDecodeError):\n pass\n\n return dict(lat_refs)\n\n\ndef annotate_map_file(map_path, project_root, lat_refs, dry_run=False):\n \"\"\"Add 'Documented in:' lines to a _MAP.md file.\n\n Returns number of annotations added/updated.\n \"\"\"\n map_dir = map_path.parent.relative_to(project_root)\n\n with open(map_path) as f:\n lines = f.readlines()\n\n new_lines = []\n changes = 0\n i = 0\n\n while i \u003c len(lines):\n line = lines[i]\n new_lines.append(line)\n\n # Check for file header\n fh = MAP_FILE_HEADER_RE.match(line.rstrip())\n if fh:\n filename = fh.group(1)\n rel_file = str(map_dir / filename)\n sections = lat_refs.get(rel_file, [])\n\n # Skip any existing annotation line(s) right after header\n while i + 1 \u003c len(lines) and ANNOTATION_RE.match(lines[i + 1].rstrip()):\n i += 1 # consume old annotation\n\n if sections:\n # Format section refs as [[lat.md/section]]\n refs = ', '.join(f'[[{s}]]' for s in sorted(sections))\n new_lines.append(f'> Documented in: {refs}\\n')\n changes += 1\n\n i += 1\n\n if changes > 0 and not dry_run:\n with open(map_path, 'w') as f:\n f.writelines(new_lines)\n\n return changes\n\n\ndef main():\n if len(sys.argv) \u003c 2:\n print(__doc__)\n sys.exit(1)\n\n project_root = Path(sys.argv[1]).resolve()\n dry_run = '--dry-run' in sys.argv\n\n lat_dir = project_root / 'lat.md'\n if not lat_dir.is_dir():\n print(f'Warning: {lat_dir} not found. No lat.md cross-references to add.')\n sys.exit(0)\n\n # Phase 1: Scan source for @lat: comments\n lat_refs = scan_lat_comments(project_root)\n total_refs = sum(len(v) for v in lat_refs.values())\n print(f'Found @lat: comments in {len(lat_refs)} files ({total_refs} section references).\\n')\n\n if not lat_refs:\n print('No @lat: comments found. Run suggest_backlinks.py --apply first.')\n sys.exit(0)\n\n # Phase 2: Annotate _MAP.md files\n total_changes = 0\n for map_path in sorted(project_root.rglob('_MAP.md')):\n changes = annotate_map_file(map_path, project_root, lat_refs, dry_run)\n if changes:\n action = 'Would annotate' if dry_run else 'Annotated'\n print(f' {action}: {map_path.relative_to(project_root)} ({changes} files)')\n total_changes += changes\n\n if total_changes:\n action = 'would annotate' if dry_run else 'annotated'\n print(f'\\n{total_changes} file entries {action} across _MAP.md files.')\n else:\n print('No _MAP.md entries needed annotation (files without @lat: comments).')\n\n\nif __name__ == '__main__':\n main()\n","content_type":"text/x-python; charset=utf-8","language":"python","size":5016,"content_sha256":"6db895aa3d2e06f72ef98cd09ad2a42c85a198889a5925cae0d03246278c3a6b"},{"filename":"scripts/suggest_backlinks.py","content":"#!/usr/bin/env python3\n\"\"\"\nsuggest_backlinks.py — Suggest @lat: back-link placements in source code.\n\nParses [[src/...]] wiki links from lat.md/ files, looks up referenced symbols\nin _MAP.md files (generated by mapping-codebases), checks for existing @lat:\ncomments, and suggests where to add missing back-links.\n\nRequires _MAP.md files to exist — run mapping-codebases first.\n\nUsage:\n python3 suggest_backlinks.py /path/to/repo [--apply] [--dry-run]\n\nOptions:\n --apply Write @lat: comments directly into source files\n --dry-run Show what --apply would do without writing (default)\n\"\"\"\n\nimport os\nimport re\nimport sys\nfrom pathlib import Path\nfrom collections import defaultdict\n\n# Wiki link pattern: [[src/path/to/file.ext#Symbol#Method]]\nWIKI_LINK_RE = re.compile(r'\\[\\[(src/[^\\]|]+)\\]\\]')\n\n# @lat: comment pattern\nLAT_COMMENT_RE = re.compile(r'(?://|#)\\s*@lat:\\s*\\[\\[([^\\]]+)\\]\\]')\n\n# Comment prefix by file extension\nCOMMENT_PREFIX = {\n '.js': '//', '.jsx': '//', '.ts': '//', '.tsx': '//',\n '.go': '//', '.rs': '//', '.c': '//', '.h': '//',\n '.py': '#', '.rb': '#', '.sh': '#',\n}\n\n# _MAP.md symbol entry pattern: - **name** (kind) `(sig)` :LINE\nMAP_SYMBOL_RE = re.compile(r'^(\\s*)- \\*\\*(\\w+)\\*\\*.*?:(\\d+)\\s*

Generating Lattice Generate and maintain knowledge graphs — structured, cross-referenced markdown anchored to source code symbols. The output is validated by the CLI, which catches documentation drift whenever code or docs change. The core mechanism is bidirectional linking: - Top-down (docs → code): wiki links in files point to specific symbols in source. When a symbol is renamed or deleted, catches the broken link. - Bottom-up (code → docs): comments in source point back to the concept they implement. When a section is renamed or removed, catches the dangling reference. Without both directi…

)\n# _MAP.md file header: ### filename.ext\nMAP_FILE_HEADER_RE = re.compile(r'^### (.+)

Generating Lattice Generate and maintain knowledge graphs — structured, cross-referenced markdown anchored to source code symbols. The output is validated by the CLI, which catches documentation drift whenever code or docs change. The core mechanism is bidirectional linking: - Top-down (docs → code): wiki links in files point to specific symbols in source. When a symbol is renamed or deleted, catches the broken link. - Bottom-up (code → docs): comments in source point back to the concept they implement. When a section is renamed or removed, catches the dangling reference. Without both directi…

)\n\n\ndef parse_source_refs(lat_dir):\n \"\"\"Extract all [[src/...]] wiki links from lat.md/ files with their section context.\"\"\"\n refs = [] # list of (source_path, symbol_path, section_id, lat_file)\n \n for md_file in sorted(lat_dir.glob('**/*.md')):\n rel_path = md_file.relative_to(lat_dir)\n current_sections = []\n \n with open(md_file) as f:\n for line in f:\n # Track section headings\n heading_match = re.match(r'^(#{1,6})\\s+(.+)', line)\n if heading_match:\n depth = len(heading_match.group(1))\n heading = heading_match.group(2).strip()\n # Trim to current depth\n current_sections = current_sections[:depth-1] + [heading]\n \n # Find wiki links to source\n for match in WIKI_LINK_RE.finditer(line):\n target = match.group(1)\n parts = target.split('#')\n source_file = parts[0]\n symbol_path = '#'.join(parts[1:]) if len(parts) > 1 else None\n \n # Build section id\n file_stem = str(rel_path).replace('.md', '')\n section_id = file_stem + ('#' + '#'.join(current_sections) if current_sections else '')\n \n refs.append({\n 'source_file': source_file,\n 'symbol': symbol_path,\n 'section_id': section_id,\n 'lat_file': str(rel_path),\n })\n \n return refs\n\n\ndef parse_map_files(project_root):\n \"\"\"Parse all _MAP.md files into a symbol → line lookup dict.\n\n Returns dict: {(relative_file_path, symbol_name): line_number}\n Handles nested symbols (class methods) by keying on leaf name and\n also on Parent#child path for disambiguation.\n \"\"\"\n symbol_map = {} # (rel_path, symbol) → line\n\n for map_path in project_root.rglob('_MAP.md'):\n map_dir = map_path.parent.relative_to(project_root)\n current_file = None\n parent_stack = [] # [(indent_level, name)] for hierarchy tracking\n\n try:\n with open(map_path) as f:\n for line in f:\n # File header\n fh = MAP_FILE_HEADER_RE.match(line)\n if fh:\n current_file = str(map_dir / fh.group(1))\n parent_stack = []\n continue\n\n if not current_file:\n continue\n\n # Symbol entry\n sm = MAP_SYMBOL_RE.match(line)\n if sm:\n indent = len(sm.group(1)) // 2 # 2 spaces per level\n name = sm.group(2)\n line_num = int(sm.group(3))\n\n # Maintain parent stack\n parent_stack = parent_stack[:indent]\n parent_stack.append(name)\n\n # Key by leaf name (most common lookup)\n symbol_map[(current_file, name)] = line_num\n\n # Also key by hierarchical path (Class#method)\n if len(parent_stack) > 1:\n hier_key = '#'.join(parent_stack)\n symbol_map[(current_file, hier_key)] = line_num\n except (OSError, UnicodeDecodeError):\n pass\n\n return symbol_map\n\n\ndef find_symbol_line(symbol_map, source_file, symbol_name):\n \"\"\"Look up a symbol's line number from the pre-parsed _MAP.md data.\n\n Tries hierarchical path first (e.g. 'App#listen'), then leaf name.\n \"\"\"\n if not symbol_name:\n return None\n\n # Direct lookup with full symbol path\n result = symbol_map.get((source_file, symbol_name))\n if result:\n return result\n\n # Try leaf symbol only (last segment after #)\n leaf = symbol_name.split('#')[-1]\n result = symbol_map.get((source_file, leaf))\n if result:\n return result\n\n return None\n\n\ndef find_existing_backlinks(file_path):\n \"\"\"Find all existing @lat: comments in a source file.\"\"\"\n backlinks = {} # line_number → section_id\n try:\n with open(file_path) as f:\n for i, line in enumerate(f, 1):\n match = LAT_COMMENT_RE.search(line)\n if match:\n backlinks[i] = match.group(1)\n except (OSError, UnicodeDecodeError):\n pass\n return backlinks\n\n\ndef suggest_backlinks(project_root, refs, symbol_map):\n \"\"\"Analyze refs and produce suggestions for missing @lat: back-links.\"\"\"\n suggestions = []\n already_linked = []\n not_found = []\n \n # Group refs by source file\n by_file = defaultdict(list)\n for ref in refs:\n by_file[ref['source_file']].append(ref)\n \n for source_file, file_refs in sorted(by_file.items()):\n full_path = project_root / source_file\n if not full_path.exists():\n for ref in file_refs:\n not_found.append(ref)\n continue\n \n ext = full_path.suffix\n prefix = COMMENT_PREFIX.get(ext)\n if not prefix:\n continue\n \n existing = find_existing_backlinks(full_path)\n existing_targets = set(existing.values())\n \n for ref in file_refs:\n if not ref['symbol']:\n # File-level link, no specific symbol to annotate\n continue\n \n # Check if this section is already back-linked anywhere in the file\n if ref['section_id'] in existing_targets:\n already_linked.append(ref)\n continue\n \n # Find where the symbol is defined via _MAP.md\n line_num = find_symbol_line(symbol_map, source_file, ref['symbol'])\n if line_num is None:\n not_found.append(ref)\n continue\n \n suggestions.append({\n **ref,\n 'line': line_num,\n 'comment': f'{prefix} @lat: [[{ref[\"section_id\"]}]]',\n 'full_path': str(full_path),\n })\n \n return suggestions, already_linked, not_found\n\n\ndef apply_backlinks(suggestions):\n \"\"\"Write @lat: comments into source files.\"\"\"\n # Group by file, sort by line descending (insert bottom-up to preserve line numbers)\n by_file = defaultdict(list)\n for s in suggestions:\n by_file[s['full_path']].append(s)\n \n for file_path, file_suggestions in by_file.items():\n with open(file_path) as f:\n lines = f.readlines()\n \n # Sort by line number descending so insertions don't shift earlier line numbers\n for s in sorted(file_suggestions, key=lambda x: x['line'], reverse=True):\n insert_at = s['line'] - 1 # 0-indexed\n indent = re.match(r'^(\\s*)', lines[insert_at]).group(1) if insert_at \u003c len(lines) else ''\n lines.insert(insert_at, f'{indent}{s[\"comment\"]}\\n')\n \n with open(file_path, 'w') as f:\n f.writelines(lines)\n \n print(f' Updated {file_path} ({len(file_suggestions)} back-links)')\n\n\ndef main():\n if len(sys.argv) \u003c 2:\n print(__doc__)\n sys.exit(1)\n \n project_root = Path(sys.argv[1]).resolve()\n apply = '--apply' in sys.argv\n \n lat_dir = project_root / 'lat.md'\n if not lat_dir.is_dir():\n print(f'Error: {lat_dir} not found. Generate lat.md/ files first.')\n sys.exit(1)\n \n # Parse _MAP.md files for symbol line lookup\n symbol_map = parse_map_files(project_root)\n if not symbol_map:\n print('Warning: No _MAP.md files found. Run mapping-codebases first.')\n print(' Symbol lookup will fail without _MAP.md data.\\n')\n else:\n print(f'Loaded {len(symbol_map)} symbol entries from _MAP.md files.\\n')\n \n print(f'Scanning {lat_dir} for [[src/...]] wiki links...\\n')\n \n refs = parse_source_refs(lat_dir)\n if not refs:\n print('No source code references found in lat.md/ files.')\n sys.exit(0)\n \n print(f'Found {len(refs)} source code references across lat.md/ files.\\n')\n \n suggestions, already_linked, not_found = suggest_backlinks(project_root, refs, symbol_map)\n \n # Report\n if already_linked:\n print(f'Already back-linked ({len(already_linked)}):')\n for ref in already_linked:\n print(f' ✓ {ref[\"source_file\"]}#{ref[\"symbol\"]} ← [[{ref[\"section_id\"]}]]')\n print()\n \n if suggestions:\n print(f'Missing back-links ({len(suggestions)}):')\n for s in suggestions:\n print(f' {s[\"source_file\"]}:{s[\"line\"]}')\n print(f' Symbol: {s[\"symbol\"]}')\n print(f' Add: {s[\"comment\"]}')\n print()\n \n if apply:\n print('Applying back-links...')\n apply_backlinks(suggestions)\n print(f'\\nDone. Run `lat check` to verify.')\n else:\n print(f'Run with --apply to write these {len(suggestions)} back-links into source files.')\n print('Review the suggestions first — placement is a judgment call.')\n else:\n print('All source code references have back-links. ✓')\n \n if not_found:\n print(f'\\nCould not locate ({len(not_found)}):')\n for ref in not_found:\n sym = f'#{ref[\"symbol\"]}' if ref['symbol'] else ''\n print(f' ? {ref[\"source_file\"]}{sym} (referenced in {ref[\"lat_file\"]})')\n\n\nif __name__ == '__main__':\n main()\n","content_type":"text/x-python; charset=utf-8","language":"python","size":11000,"content_sha256":"273188ef225e9ce9ba97eaf57d13db7e2b92cc4e54d11a5b060ce97b0d245dbc"}],"content_json":{"type":"doc","content":[{"type":"heading","attrs":{"level":1},"content":[{"text":"Generating Lattice","type":"text"}]},{"type":"paragraph","content":[{"text":"Generate and maintain ","type":"text"},{"text":"lat.md/","type":"text","marks":[{"type":"code_inline"}]},{"text":" knowledge graphs — structured, cross-referenced markdown anchored to source code symbols. The output is validated by the ","type":"text"},{"text":"lat","type":"text","marks":[{"type":"code_inline"}]},{"text":" CLI, which catches documentation drift whenever code or docs change.","type":"text"}]},{"type":"paragraph","content":[{"text":"The core mechanism is bidirectional linking:","type":"text","marks":[{"type":"strong"}]}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Top-down","type":"text","marks":[{"type":"strong"}]},{"text":" (docs → code): ","type":"text"},{"text":"[[src/auth.js#getValidToken]]","type":"text","marks":[{"type":"code_inline"}]},{"text":" wiki links in ","type":"text"},{"text":"lat.md/","type":"text","marks":[{"type":"code_inline"}]},{"text":" files point to specific symbols in source. When a symbol is renamed or deleted, ","type":"text"},{"text":"lat check","type":"text","marks":[{"type":"code_inline"}]},{"text":" catches the broken link.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Bottom-up","type":"text","marks":[{"type":"strong"}]},{"text":" (code → docs): ","type":"text"},{"text":"// @lat: [[auth#Token Refresh]]","type":"text","marks":[{"type":"code_inline"}]},{"text":" comments in source point back to the concept they implement. When a section is renamed or removed, ","type":"text"},{"text":"lat check","type":"text","marks":[{"type":"code_inline"}]},{"text":" catches the dangling reference.","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"Without both directions, the lattice is a static essay that drifts silently. With both, ","type":"text"},{"text":"lat check","type":"text","marks":[{"type":"code_inline"}]},{"text":" enforces consistency.","type":"text"}]},{"type":"paragraph","content":[{"text":"Dependency:","type":"text","marks":[{"type":"strong"}]},{"text":" Requires ","type":"text"},{"text":"mapping-codebases","type":"text","marks":[{"type":"strong"}]},{"text":" skill. The structural maps (","type":"text"},{"text":"_MAP.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" files) are the input that makes LLM-assisted authoring token-efficient — read maps to understand API surfaces, then selectively read source files only where design rationale lives.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Installation","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"npm install -g lat.md\nlat --version # verify (requires Node.js 22+)","type":"text"}]},{"type":"paragraph","content":[{"text":"The ","type":"text"},{"text":"lat","type":"text","marks":[{"type":"code_inline"}]},{"text":" CLI provides ","type":"text"},{"text":"lat check","type":"text","marks":[{"type":"code_inline"}]},{"text":" (validation), ","type":"text"},{"text":"lat search","type":"text","marks":[{"type":"code_inline"}]},{"text":" (semantic search), ","type":"text"},{"text":"lat section","type":"text","marks":[{"type":"code_inline"}]},{"text":" (browsing), ","type":"text"},{"text":"lat refs","type":"text","marks":[{"type":"code_inline"}]},{"text":" (reference lookup), and ","type":"text"},{"text":"lat mcp","type":"text","marks":[{"type":"code_inline"}]},{"text":" (agent integration).","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Generation Pipeline","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Phase 1: Structural Scan","type":"text"}]},{"type":"paragraph","content":[{"text":"Ensure ","type":"text"},{"text":"_MAP.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" files exist. Generate them if missing:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"# Install mapping-codebases dependencies\nuv venv /home/claude/.venv\nuv pip install tree-sitter-language-pack --python /home/claude/.venv/bin/python\n\n# Generate maps\n/home/claude/.venv/bin/python /mnt/skills/user/mapping-codebases/scripts/codemap.py /path/to/repo \\\n --skip tests,.github,node_modules,vendor","type":"text"}]},{"type":"paragraph","content":[{"text":"Read the root ","type":"text"},{"text":"_MAP.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" first for high-level orientation, then drill into subdirectory maps. The maps are the symbol inventory — they tell you what exists and where, so you can write source code links without reading every file.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Phase 2: Selective Source Reading","type":"text"}]},{"type":"paragraph","content":[{"text":"Maps reveal the API surface (exports, signatures, line numbers) without reading full files. Read source selectively to understand design rationale:","type":"text"}]},{"type":"paragraph","content":[{"text":"Read fully:","type":"text","marks":[{"type":"strong"}]},{"text":" Files with complex algorithms, business logic, configuration constants, data schemas. The maps identify these by export density and file size.","type":"text"}]},{"type":"paragraph","content":[{"text":"Read partially:","type":"text","marks":[{"type":"strong"}]},{"text":" Header comments and constant blocks in large files.","type":"text"}]},{"type":"paragraph","content":[{"text":"Skip:","type":"text","marks":[{"type":"strong"}]},{"text":" Files where the map signature tells the full story (thin wrappers, simple CRUD, format utilities).","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Phase 3: Generate Anchored Sections","type":"text"}]},{"type":"paragraph","content":[{"text":"Create ","type":"text"},{"text":"lat.md/","type":"text","marks":[{"type":"code_inline"}]},{"text":" directory and generate markdown files. ","type":"text"},{"text":"Every section must be anchored to source code symbols","type":"text","marks":[{"type":"strong"}]},{"text":" — this is what makes ","type":"text"},{"text":"lat check","type":"text","marks":[{"type":"code_inline"}]},{"text":" catch drift.","type":"text"}]},{"type":"heading","attrs":{"level":4},"content":[{"text":"Section Structure Rules","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Every section MUST have a leading paragraph ≤250 characters (excluding ","type":"text"},{"text":"[[wiki link]]","type":"text","marks":[{"type":"code_inline"}]},{"text":" content). This is the section's identity in search results.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"lat check","type":"text","marks":[{"type":"code_inline"}]},{"text":" validates this rule.","type":"text"}]}]}]},{"type":"code_block","attrs":{"wrap":false,"language":"markdown"},"content":[{"text":"# Good Section\n\nBrief overview anchored to [[src/auth.js#refreshToken]] and [[src/api.js#fetchWithRetry]].\n\nMore detail can follow in subsequent paragraphs.","type":"text"}]},{"type":"heading","attrs":{"level":4},"content":[{"text":"Source Code Links (the top-down anchors)","type":"text"}]},{"type":"paragraph","content":[{"text":"Use ","type":"text"},{"text":"[[src/path/file.ext#symbolName]]","type":"text","marks":[{"type":"code_inline"}]},{"text":" wiki links to anchor documentation to specific symbols. Supported extensions: ","type":"text"},{"text":".ts","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":".tsx","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":".js","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":".jsx","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":".py","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":".rs","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":".go","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":".c","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":".h","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"markdown"},"content":[{"text":"## Token Refresh\n\nOAuth token lifecycle managed by [[src/auth.js#getValidToken]] with automatic\nrefresh via [[src/auth.js#refreshToken]]. The refresh window\n([[src/auth.js#REFRESH_THRESHOLD_MS]]) triggers proactive renewal before expiry.","type":"text"}]},{"type":"paragraph","content":[{"text":"Symbol granularity matters.","type":"text","marks":[{"type":"strong"}]},{"text":" Link to the specific function, class, constant, or method — not just the file. ","type":"text"},{"text":"[[src/auth.js#refreshToken]]","type":"text","marks":[{"type":"code_inline"}]},{"text":" is useful; ","type":"text"},{"text":"[[src/auth.js]]","type":"text","marks":[{"type":"code_inline"}]},{"text":" tells you nothing that the filename didn't already say.","type":"text"}]},{"type":"paragraph","content":[{"text":"For class methods: ","type":"text"},{"text":"[[src/server.ts#App#listen]]","type":"text","marks":[{"type":"code_inline"}]},{"text":". For Rust impl methods: ","type":"text"},{"text":"[[src/lib.rs#Greeter#greet]]","type":"text","marks":[{"type":"code_inline"}]},{"text":". For Python: ","type":"text"},{"text":"[[lib/utils.py#parse_args]]","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]},{"type":"heading","attrs":{"level":4},"content":[{"text":"Section-to-Section Links","type":"text"}]},{"type":"paragraph","content":[{"text":"Use ","type":"text"},{"text":"[[file#Section#Subsection]]","type":"text","marks":[{"type":"code_inline"}]},{"text":" or short form ","type":"text"},{"text":"[[file#Section]]","type":"text","marks":[{"type":"code_inline"}]},{"text":" when the file stem is unique:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"markdown"},"content":[{"text":"The sync pipeline ([[data#Sync Pipeline]]) uses the same token refresh\nmechanism described in [[auth#Token Refresh]].","type":"text"}]},{"type":"heading","attrs":{"level":4},"content":[{"text":"Conceptual Grouping","type":"text"}]},{"type":"paragraph","content":[{"text":"Organize by domain concept, not file structure. A ","type":"text"},{"text":"data.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" file might reference ","type":"text"},{"text":"db.js","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"sync.js","type":"text","marks":[{"type":"code_inline"}]},{"text":", and ","type":"text"},{"text":"demo.js","type":"text","marks":[{"type":"code_inline"}]},{"text":" because they're all part of the data layer. The ","type":"text"},{"text":"_MAP.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" files already provide file-level structure; ","type":"text"},{"text":"lat.md/","type":"text","marks":[{"type":"code_inline"}]},{"text":" adds the semantic layer explaining WHY things connect.","type":"text"}]},{"type":"heading","attrs":{"level":4},"content":[{"text":"Index File","type":"text"}]},{"type":"paragraph","content":[{"text":"lat.md/lat.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" must contain a bullet list of all files with one-sentence descriptions using wiki links. ","type":"text"},{"text":"lat check --index","type":"text","marks":[{"type":"code_inline"}]},{"text":" validates completeness:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"markdown"},"content":[{"text":"- [[architecture]] — System design, OAuth flow, routing, signals\n- [[data]] — IndexedDB schema, sync pipeline, demo mode\n- [[awards]] — Award computation engine, data quality rules","type":"text"}]},{"type":"paragraph","content":[{"text":"Subdirectories need their own index: ","type":"text"},{"text":"lat.md/api/api.md","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Phase 4: Add Back-Links in Source Code","type":"text"}]},{"type":"paragraph","content":[{"text":"Add ","type":"text"},{"text":"// @lat:","type":"text","marks":[{"type":"code_inline"}]},{"text":" or ","type":"text"},{"text":"# @lat:","type":"text","marks":[{"type":"code_inline"}]},{"text":" comments in source code pointing back to ","type":"text"},{"text":"lat.md/","type":"text","marks":[{"type":"code_inline"}]},{"text":" sections. ","type":"text"},{"text":"This is not optional","type":"text","marks":[{"type":"strong"}]},{"text":" — back-links are what make ","type":"text"},{"text":"lat check","type":"text","marks":[{"type":"code_inline"}]},{"text":" detect when source code changes break documentation.","type":"text"}]},{"type":"paragraph","content":[{"text":"Run the back-link helper to identify where annotations are needed:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"python3 SKILL_DIR/scripts/suggest_backlinks.py /path/to/repo","type":"text"}]},{"type":"paragraph","content":[{"text":"This parses all ","type":"text"},{"text":"[[src/...]]","type":"text","marks":[{"type":"code_inline"}]},{"text":" wiki links from ","type":"text"},{"text":"lat.md/","type":"text","marks":[{"type":"code_inline"}]},{"text":" files, looks up referenced symbols in ","type":"text"},{"text":"_MAP.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" files for O(1) line number resolution, and suggests ","type":"text"},{"text":"@lat:","type":"text","marks":[{"type":"code_inline"}]},{"text":" comment placements. Requires ","type":"text"},{"text":"_MAP.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" files from Phase 1.","type":"text"}]},{"type":"paragraph","content":[{"text":"Comment syntax by language:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"JS/TS/Rust/Go/C: ","type":"text"},{"text":"// @lat: [[section#Subsection]]","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Python: ","type":"text"},{"text":"# @lat: [[section#Subsection]]","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"paragraph","content":[{"text":"Place one ","type":"text"},{"text":"@lat:","type":"text","marks":[{"type":"code_inline"}]},{"text":" comment per section reference, at the relevant code location — not at the top of the file:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"javascript"},"content":[{"text":"// @lat: [[auth#Token Refresh]]\nasync function refreshToken(token) { ... }","type":"text"}]},{"type":"paragraph","content":[{"text":"To auto-apply suggestions (review the output first):","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"python3 SKILL_DIR/scripts/suggest_backlinks.py /path/to/repo --apply","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Phase 4b: Annotate Maps with Lattice Cross-References","type":"text"}]},{"type":"paragraph","content":[{"text":"After backlinks exist in source, annotate ","type":"text"},{"text":"_MAP.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" files so someone browsing a code map can find the lat.md section that explains WHY a module is designed the way it is:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"python3 SKILL_DIR/scripts/annotate_maps.py /path/to/repo","type":"text"}]},{"type":"paragraph","content":[{"text":"This scans ","type":"text"},{"text":"@lat:","type":"text","marks":[{"type":"code_inline"}]},{"text":" comments in source and adds ","type":"text"},{"text":"> Documented in:","type":"text","marks":[{"type":"code_inline"}]},{"text":" lines to ","type":"text"},{"text":"_MAP.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" file headers. Idempotent — safe to re-run after regenerating maps.","type":"text"}]},{"type":"paragraph","content":[{"text":"Example output in ","type":"text"},{"text":"_MAP.md","type":"text","marks":[{"type":"code_inline"}]},{"text":":","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"markdown"},"content":[{"text":"### auth.js\n> Documented in: [[auth#Token Refresh]], [[auth#Server]]\n> Imports: `express`\n- **refreshToken** (f) `(token)` :15","type":"text"}]},{"type":"heading","attrs":{"level":4},"content":[{"text":"require-code-mention for Critical Sections","type":"text"}]},{"type":"paragraph","content":[{"text":"For sections where bidirectional traceability is essential (test specs, invariants, key business rules), add frontmatter:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"yaml"},"content":[{"text":"---\nlat:\n require-code-mention: true\n---","type":"text"}]},{"type":"paragraph","content":[{"text":"This makes ","type":"text"},{"text":"lat check","type":"text","marks":[{"type":"code_inline"}]},{"text":" fail if ANY leaf section in the file lacks a corresponding ","type":"text"},{"text":"@lat:","type":"text","marks":[{"type":"code_inline"}]},{"text":" comment in the codebase. Use for test spec files where every test must trace to its specification.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Phase 5: Validate","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"cd /path/to/repo\nlat check","type":"text"}]},{"type":"paragraph","content":[{"text":"This runs ALL checks:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"md","type":"text","marks":[{"type":"strong"}]},{"text":" — every ","type":"text"},{"text":"[[wiki link]]","type":"text","marks":[{"type":"code_inline"}]},{"text":" in ","type":"text"},{"text":"lat.md/","type":"text","marks":[{"type":"code_inline"}]},{"text":" resolves to a real section or source symbol","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"code-refs","type":"text","marks":[{"type":"strong"}]},{"text":" — every ","type":"text"},{"text":"@lat:","type":"text","marks":[{"type":"code_inline"}]},{"text":" comment in source points to a real section; and every leaf section in ","type":"text"},{"text":"require-code-mention","type":"text","marks":[{"type":"code_inline"}]},{"text":" files is referenced by code","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"sections","type":"text","marks":[{"type":"strong"}]},{"text":" — every section has a leading paragraph ≤250 chars","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"index","type":"text","marks":[{"type":"strong"}]},{"text":" — every directory in ","type":"text"},{"text":"lat.md/","type":"text","marks":[{"type":"code_inline"}]},{"text":" has a complete index file","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"All four must pass.","type":"text","marks":[{"type":"strong"}]},{"text":" Fix errors iteratively until ","type":"text"},{"text":"lat check","type":"text","marks":[{"type":"code_inline"}]},{"text":" is clean.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Phase 6: Agent Integration","type":"text"}]},{"type":"paragraph","content":[{"text":"Set up files that make coding agents maintain the lattice automatically.","type":"text"}]},{"type":"paragraph","content":[{"text":"Cache exclusion","type":"text","marks":[{"type":"strong"}]},{"text":" — create ","type":"text"},{"text":"lat.md/.gitignore","type":"text","marks":[{"type":"code_inline"}]},{"text":":","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":".cache/","type":"text"}]},{"type":"paragraph","content":[{"text":"Agent instructions","type":"text","marks":[{"type":"strong"}]},{"text":" — append to ","type":"text"},{"text":"CLAUDE.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" (or ","type":"text"},{"text":"AGENTS.md","type":"text","marks":[{"type":"code_inline"}]},{"text":") using markers:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"markdown"},"content":[{"text":"%% lat:begin %%\n# Before starting work\n\n- Run `lat search` to find sections relevant to your task.\n- Run `lat expand` on user prompts to expand any `[[refs]]`.\n\n# Post-task checklist (REQUIRED — do not skip)\n\nAfter EVERY task, before responding to the user:\n\n- [ ] Update `lat.md/` if you changed functionality, architecture, or behavior\n- [ ] Run `lat check` — all wiki links and code refs must pass\n%% lat:end %%","type":"text"}]},{"type":"paragraph","content":[{"text":"For full agent integration","type":"text","marks":[{"type":"strong"}]},{"text":" (hooks that auto-inject search results and block completion when ","type":"text"},{"text":"lat check","type":"text","marks":[{"type":"code_inline"}]},{"text":" fails), run ","type":"text"},{"text":"lat init","type":"text","marks":[{"type":"code_inline"}]},{"text":" interactively. This sets up agent hooks in ","type":"text"},{"text":".claude/settings.json","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":".cursor/hooks.json","type":"text","marks":[{"type":"code_inline"}]},{"text":", etc. The hooks require absolute paths to the ","type":"text"},{"text":"lat","type":"text","marks":[{"type":"code_inline"}]},{"text":" binary, which is machine-local.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Drift Prevention: How It Works","type":"text"}]},{"type":"paragraph","content":[{"text":"The lattice stays in sync because changes to either side break ","type":"text"},{"text":"lat check","type":"text","marks":[{"type":"code_inline"}]},{"text":":","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"What changed","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"What breaks","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"How lat check catches it","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Symbol renamed in source","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"[[src/file#oldName]]","type":"text","marks":[{"type":"code_inline"}]},{"text":" wiki links in lat.md/","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"lat check --md","type":"text","marks":[{"type":"code_inline"}]},{"text":" reports broken source ref","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Symbol deleted","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Same as above","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Same — dead source link","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Section renamed in lat.md/","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"@lat: [[old#Section]]","type":"text","marks":[{"type":"code_inline"}]},{"text":" comments in source","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"lat check --code-refs","type":"text","marks":[{"type":"code_inline"}]},{"text":" reports dangling ref","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Section deleted","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Same as above","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Same — orphaned code ref","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"New code added without docs","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"No back-link for new functions","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Manual review (or ","type":"text"},{"text":"require-code-mention","type":"text","marks":[{"type":"code_inline"}]},{"text":" enforcement)","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"New docs without code anchors","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Sections with no ","type":"text"},{"text":"[[src/...]]","type":"text","marks":[{"type":"code_inline"}]},{"text":" links","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Manual review — but this is the failure to prevent","type":"text"}]}]}]}]},{"type":"paragraph","content":[{"text":"The critical gap:","type":"text","marks":[{"type":"strong"}]},{"text":" new code without docs and new docs without anchors are NOT caught automatically unless ","type":"text"},{"text":"require-code-mention","type":"text","marks":[{"type":"code_inline"}]},{"text":" is set. The agent integration hooks (Phase 6) address this by reminding agents to update lat.md/ after every task and running ","type":"text"},{"text":"lat check","type":"text","marks":[{"type":"code_inline"}]},{"text":" before completion.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Quality Criteria","type":"text"}]},{"type":"paragraph","content":[{"text":"A good generated lattice:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Passes ","type":"text","marks":[{"type":"strong"}]},{"text":"lat check","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" on all four checks","type":"text","marks":[{"type":"strong"}]},{"text":" — md, code-refs, sections, index","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Has dense source code links","type":"text","marks":[{"type":"strong"}]},{"text":" — most sections reference specific symbols via ","type":"text"},{"text":"[[src/...#symbol]]","type":"text","marks":[{"type":"code_inline"}]},{"text":", not just file-level links","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Has back-links","type":"text","marks":[{"type":"strong"}]},{"text":" — source code has ","type":"text"},{"text":"@lat:","type":"text","marks":[{"type":"code_inline"}]},{"text":" comments pointing to the sections that describe them","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Captures WHY, not just WHAT","type":"text","marks":[{"type":"strong"}]},{"text":" — design rationale, invariants, constraints","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Groups by concept","type":"text","marks":[{"type":"strong"}]},{"text":" — not a 1:1 mirror of the file tree","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Concise leading paragraphs","type":"text","marks":[{"type":"strong"}]},{"text":" — ≤250 chars, the section's identity in search","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"Anti-patterns (what our v0.1 got wrong):","type":"text","marks":[{"type":"strong"}]}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Sections with only section-to-section links (","type":"text"},{"text":"[[clusters#Visual Pipeline]]","type":"text","marks":[{"type":"code_inline"}]},{"text":") and no source anchors — ","type":"text"},{"text":"lat check","type":"text","marks":[{"type":"code_inline"}]},{"text":" cannot catch code changes","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Architectural essays that describe the codebase without linking to it — a static document, not a knowledge graph","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Treating back-links as optional — without ","type":"text"},{"text":"@lat:","type":"text","marks":[{"type":"code_inline"}]},{"text":" comments, the bottom-up view doesn't exist and half the drift detection is missing","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Token Budget","type":"text"}]},{"type":"paragraph","content":[{"text":"The maps-first approach significantly reduces LLM token cost:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Mapping-codebases (Phase 1): zero LLM tokens — pure AST extraction","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Selective reading (Phase 2): ~30-50% of source bytes vs reading everything","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Generation (Phase 3): the actual LLM work — proportional to conceptual complexity, not codebase size","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Back-links (Phase 4): zero LLM tokens — the suggest_backlinks.py script is deterministic","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Validation (Phase 5): zero LLM tokens — deterministic ","type":"text"},{"text":"lat check","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"hr","attrs":{"markup":"---"}}]},"metadata":{"date":"2026-06-05","name":"generating-lattice","author":"@skillopedia","source":{"stars":124,"repo_name":"claude-skills","origin_url":"https://github.com/oaustegard/claude-skills/blob/HEAD/generating-lattice/SKILL.md","repo_owner":"oaustegard","body_sha256":"750bcb91ca8b6bbd723b00ee868948cfbb74dc38a4a4f02b99e3531f90b880ab","cluster_key":"92c1619052645af7c89a12db7c9a0ce8c41dd17c355b4fa5874873515eed4759","clean_bundle":{"format":"clean-skill-bundle-v1","source":"oaustegard/claude-skills/generating-lattice/SKILL.md","attachments":[{"id":"ae0780c7-0c03-56ec-b575-dc48d5cd00a7","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/ae0780c7-0c03-56ec-b575-dc48d5cd00a7/attachment.md","path":"CHANGELOG.md","size":1550,"sha256":"d7aa9c4b3ebf56b625ec9d135628499abdef72dddf9332b095c2c5f018316918","contentType":"text/markdown; charset=utf-8"},{"id":"b63357c5-d178-5541-ad42-e3efe713d2e9","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/b63357c5-d178-5541-ad42-e3efe713d2e9/attachment.md","path":"references/authoring-rules.md","size":3944,"sha256":"3127fe300460baf4b8fd2052ad0c2770efbc95839dfdb219f3db5b79715d5720","contentType":"text/markdown; charset=utf-8"},{"id":"e10a2f5f-c93a-5fec-be7e-4a8bc40c86b5","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/e10a2f5f-c93a-5fec-be7e-4a8bc40c86b5/attachment.py","path":"scripts/annotate_maps.py","size":5016,"sha256":"6db895aa3d2e06f72ef98cd09ad2a42c85a198889a5925cae0d03246278c3a6b","contentType":"text/x-python; charset=utf-8"},{"id":"0e30edaf-aeea-5d32-a58f-820ae3514d2a","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/0e30edaf-aeea-5d32-a58f-820ae3514d2a/attachment.py","path":"scripts/suggest_backlinks.py","size":11000,"sha256":"273188ef225e9ce9ba97eaf57d13db7e2b92cc4e54d11a5b060ce97b0d245dbc","contentType":"text/x-python; charset=utf-8"}],"bundle_sha256":"799d857bf4a91f45f2cb89babdda1008d29eb7a0330b2c6f5e78ba02340a5066","attachment_count":4,"text_attachments":4,"attachment_storage":"skillopedia-attachments-v1","binary_attachments":0,"excluded_attachments":[]},"cluster_size":1,"skill_md_path":"generating-lattice/SKILL.md","import_metadata":{"date":"2026-06-05","author":"@skillopedia","version":"v1","category":"documents-office","category_label":"Documents"},"exact_dupes_collapsed_into_this":0},"version":"v1","category":"documents-office","metadata":{"version":"0.3.0"},"import_tag":"clean-skills-v1","description":"Generate and maintain lat.md/ knowledge graphs with bidirectional source code anchoring. Docs link to code via [[src/file#symbol]] wiki links; code links back to docs via @lat: comments. lat check validates both directions, catching drift when either side changes. Use when user says \"lat.md\", \"lattice\", \"knowledge graph\", \"document this codebase\", \"add back-links\", or wants cross-referenced architecture docs anchored to source code symbols."}},"renderedAt":1782980429815}

Generating Lattice Generate and maintain knowledge graphs — structured, cross-referenced markdown anchored to source code symbols. The output is validated by the CLI, which catches documentation drift whenever code or docs change. The core mechanism is bidirectional linking: - Top-down (docs → code): wiki links in files point to specific symbols in source. When a symbol is renamed or deleted, catches the broken link. - Bottom-up (code → docs): comments in source point back to the concept they implement. When a section is renamed or removed, catches the dangling reference. Without both directi…