Doc-Symbol Linking
Version: 7.3
CKB can automatically detect symbol references in markdown documentation and link them to actual code symbols. This enables powerful queries like "What docs mention this symbol?" and "Which docs have stale references?".
Overview
Documentation often references code symbols in backticks like UserService.Authenticate or Engine.Start. CKB scans your markdown files, detects these references, and links them to SCIP symbol IDs. This creates a bidirectional mapping:
- Symbol → Docs: "What documentation references this symbol?"
- Doc → Symbols: "What symbols does this document reference?"
- Staleness: "Which references are broken because the symbol was renamed/deleted?"
Quick Start
# Index documentation (scans docs/, README.md, ARCHITECTURE.md, etc.)
ckb docs index
# Find docs that reference a symbol
ckb docs symbol Engine.Start
# Check a document for stale references
ckb docs stale README.md
# Check all docs for staleness
ckb docs stale --all
# Get documentation coverage stats
ckb docs coverage
Detection Methods
CKB uses three methods to detect symbol references:
1. Backtick Detection (DetectBacktick)
References in backticks are automatically detected:
Use `UserService.Authenticate` to validate credentials.
See `Session.Create` for session management.
Requirements:
- Must have at least 2 segments (e.g.,
Foo.Bar, not justFoo) - Supports multiple delimiter styles:
- Dots:
Foo.Bar - Double colons:
crate::module::Type(Rust) - Hash:
Class#method(JS/Ruby) - Slash + dot:
pkg/sub.Func(Go) - Arrow:
Class->method(PHP)
- Dots:
2. Directive Detection (DetectDirective)
For explicit symbol references, use HTML comments:
<!-- ckb:symbol internal.auth.UserService.Authenticate -->
This is useful when:
- The symbol name is ambiguous
- You need to reference a fully qualified name
- You want to force a specific resolution
3. Fence Detection (DetectFence) — v1.1
CKB can extract symbol references from fenced code blocks using tree-sitter:
func example() {
result := pkg.DoSomething()
obj.Method()
}
Supported languages: Go, Python, JavaScript, TypeScript, TSX, Rust, Java, Kotlin
Notes:
- Only qualified identifiers are extracted (e.g.,
pkg.Func, notx) - Lower confidence (0.7x multiplier) compared to backtick detection
- Requires CGO for tree-sitter parsing
Resolution Process
When CKB finds a potential symbol reference, it attempts to resolve it:
- Exact Match: Try to find a symbol with an exact canonical name match
- Suffix Match: Look for symbols ending with the reference text
- Classification:
exact— Fully qualified match (confidence: 1.0)suffix— Unique suffix match (confidence: 0.95)ambiguous— Multiple candidates matchmissing— No match foundineligible— Single-segment name (requires directive)
Directives
Module Linking
Link a document to a module explicitly:
<!-- ckb:module internal/auth -->
This enables queries like ckb docs module internal/auth to find all documentation for a module.
Known Symbols (v1.1)
Allow single-segment symbol detection for specific names:
<!-- ckb:known_symbols Engine, Start, UserService -->
This bypasses the 2-segment requirement for the listed symbols. Multiple directives are cumulative within a document.
Staleness Detection
Documentation can become stale when:
- Symbol Deleted (
missing_symbol) — The referenced symbol no longer exists - Symbol Ambiguous (
ambiguous_symbol) — The reference now matches multiple symbols - Index Gap (
index_incomplete) — The language isn't indexed at the current tier - Symbol Renamed (
symbol_renamed) — v1.1: The symbol was renamed or moved
Rename Detection (v1.1)
When a documented symbol is renamed, CKB can detect this via the alias chain:
$ ckb docs stale README.md
{
"reports": [{
"docPath": "README.md",
"stale": [{
"rawText": "`OldService.Method`",
"line": 42,
"reason": "symbol_renamed",
"message": "Symbol was renamed",
"suggestions": ["NewService.Method"],
"newSymbolId": "ckb:repo:sym:abc123"
}]
}]
}
MCP Tools
indexDocs
Scan and index documentation for symbol references.
{
"force": false // Re-index all docs even if unchanged
}
getDocsForSymbol
Find all documents that reference a symbol.
{
"symbol": "Engine.Start",
"limit": 10
}
getSymbolsInDoc
List all symbol references in a document.
{
"path": "README.md"
}
getDocsForModule
Find documents linked to a module via directives.
{
"moduleId": "internal/query"
}
checkDocStaleness
Check a document for stale symbol references.
{
"path": "README.md"
}
Or check all documents:
{
"all": true
}
getDocCoverage
Get documentation coverage statistics.
{
"exportedOnly": false, // Only count exported symbols
"topN": 10 // Number of top undocumented symbols
}
CI Integration
Coverage Threshold (v1.1)
Enforce minimum documentation coverage in CI:
# Fail if coverage drops below 80%
ckb docs coverage --fail-under=80
Exit codes:
0— Coverage meets or exceeds threshold1— Coverage below threshold
Staleness Checks
Check for stale documentation in CI:
# Check all docs, fail if any are stale
ckb docs stale --all --format json | jq '.totalStale'
Configuration
Documentation indexing is configured in .ckb/config.json:
{
"docs": {
"paths": ["docs", "README.md", "ARCHITECTURE.md", "DESIGN.md", "CONTRIBUTING.md"],
"include": ["*.md"],
"exclude": ["node_modules", "vendor", ".git"]
}
}
Best Practices
Writing Documentation
- Use qualified names: Write
UserService.Authenticateinstead of justAuthenticate - Use backticks consistently: Always wrap symbol references in backticks
- Add module directives: Link architectural docs to their modules
- Use known_symbols sparingly: Only for truly unique single-segment names
Maintaining Documentation
- Run staleness checks regularly: Add to CI pipeline
- Set coverage thresholds: Prevent documentation from falling behind
- Review rename suggestions: Update docs when symbols are renamed
- Check ambiguous references: Disambiguate with full paths or directives
Example Workflow
# 1. Index your codebase
ckb index
# 2. Index documentation
ckb docs index
# 3. Check for stale references
ckb docs stale --all
# 4. Find what docs mention a symbol you're changing
ckb docs symbol UserService.Authenticate
# 5. Update docs before merging
# ... fix stale references ...
# 6. Verify in CI
ckb docs coverage --fail-under=80
Limitations
- Single-segment names:
Enginealone won't be detected (useknown_symbolsdirective) - Dynamic references: Computed symbol names can't be detected
- Non-markdown: Only
.mdand.markdownfiles are scanned - Code blocks without language: Fence detection requires a language hint (
go,python, etc.) - Complex expressions: Fence detection only extracts simple qualified names, not method chains
Changelog
v1.1 (December 2024)
- CI Enforcement:
--fail-underflag for coverage threshold - Rename Detection: Detect when documented symbols are renamed via alias chain
- known_symbols Directive: Allow single-segment detection for listed symbols
- Fence Symbol Scanning: Extract identifiers from fenced code blocks (8 languages)
v1.0 (December 2024)
- Initial release with backtick and directive detection
- Suffix-based resolution with confidence scoring
- Staleness detection for missing/ambiguous references
- MCP tools:
indexDocs,getDocsForSymbol,checkDocStaleness,getDocCoverage
Related
- CI-CD-Integration - Documentation coverage enforcement in CI
- User Guide - CLI commands including
ckb docs - Configuration - Documentation path configuration