Chapter 18: Documentation Intelligence¶
Documentation intelligence automates the generation, validation, and maintenance of technical documentation by analyzing source code directly. Rather than relying on developers to manually write and update API references, the FCC documentation intelligence subsystem inspects Python AST (Abstract Syntax Trees), extracts structural metadata, and renders documentation through Jinja2 templates.
This chapter covers:
- Docs-from-Code Philosophy — why AST-driven documentation outperforms manual authoring.
- CodeAnalyzer Module — extracting classes, functions, parameters, and docstrings.
- API Reference Generation — producing structured API docs from analysis results.
- Template System — Jinja2 templates for flexible output formatting.
- Integration with FCC's DocGenerator — connecting analysis to the existing docs-as-code pipeline.
The flowchart below shows how source files flow through AST parsing, a node visitor, cross-reference resolution, and Jinja2 templates to emit Markdown or HTML documentation.
flowchart LR
SRC[Source .py Files] --> AST[ast.parse]
AST --> VIS[NodeVisitor]
VIS --> MI[ModuleInfo]
VIS --> CI[ClassInfo]
VIS --> FI[FunctionInfo]
MI --> XREF[Cross-Reference Resolution]
CI --> XREF
FI --> XREF
XREF --> API[APIReferenceGenerator]
API --> J2[Jinja2 Templates]
J2 --> MD[Markdown Output]
J2 --> HTML[HTML Output]
style SRC fill:#4CAF50,color:#fff
style API fill:#2196F3,color:#fff
style MD fill:#9C27B0,color:#fff
This means adopters can run the generator in CI against untrusted or partially installed codebases without importing them.
The Docs-from-Code Philosophy¶
Traditional documentation workflows suffer from drift: code changes but docs do not. The docs-from-code approach inverts this relationship. Documentation is derived from the source code, ensuring accuracy by construction.
Why AST Analysis?¶
| Approach | Pros | Cons |
|---|---|---|
| Manual authoring | Full creative control | Drifts from code |
| Docstring extraction (pydoc) | Easy setup | Misses structure, no cross-references |
| AST analysis | Full structural understanding | More complex to implement |
| Runtime introspection | Captures dynamic behavior | Requires import, may have side effects |
AST analysis provides the best balance: it understands the full structure of the code (classes, methods, parameters, return types, decorators, inheritance) without executing it. This means no side effects, no API keys, and no database connections required.
Core Principles¶
The FCC documentation intelligence system follows four principles:
- Source of truth is code — documentation is generated from what the code actually declares, not from what a developer remembers.
- Incremental updates — only re-generate docs for modules that have changed since the last generation run.
- Template separation — content extraction (AST analysis) is completely separate from presentation (Jinja2 templates).
- Cross-reference linking — generated docs automatically include links between related classes, functions, and modules.
The CodeAnalyzer Module¶
The CodeAnalyzer is the core engine that parses Python source files
and extracts structured metadata.
Analysis Pipeline¶
The analysis pipeline performs these steps:
- Parse —
ast.parse()converts source code to an AST. - Visit — A custom
ast.NodeVisitorwalks the tree, collecting: - Module-level docstrings
- Class definitions (name, bases, decorators, methods)
- Function definitions (name, parameters, return type, decorators)
- Type annotations on parameters and return values
- Constants and module-level assignments
- Resolve — Cross-references between classes (inheritance, usage) are resolved to produce a connected dependency graph.
- Emit — The collected metadata is returned as
ModuleInfo,ClassInfo, andFunctionInfodataclasses.
Using CodeAnalyzer¶
from fcc.docs import CodeAnalyzer
analyzer = CodeAnalyzer()
# Analyze a single module
module_info = analyzer.analyze_file("src/fcc/personas/registry.py")
print(f"Module: {module_info.name}")
print(f"Classes: {[c.name for c in module_info.classes]}")
print(f"Functions: {[f.name for f in module_info.functions]}")
print(f"Docstring: {module_info.docstring[:80]}...")
ClassInfo and FunctionInfo¶
Each extracted class and function carries rich metadata:
| Field | ClassInfo | FunctionInfo |
|---|---|---|
name |
Class name | Function name |
docstring |
Class docstring | Function docstring |
decorators |
List of decorator names | List of decorator names |
bases |
Base class names | N/A |
methods |
List of FunctionInfo |
N/A |
parameters |
N/A | List of ParameterInfo |
return_type |
N/A | Return type annotation |
line_number |
Start line in source | Start line in source |
ParameterInfo¶
Each function parameter is represented as:
@dataclass(frozen=True)
class ParameterInfo:
name: str
annotation: str | None # Type annotation string
default: str | None # Default value string
kind: str # "positional", "keyword", "var_positional", "var_keyword"
Analyzing Entire Packages¶
To analyze an entire package directory:
from fcc.docs import CodeAnalyzer
analyzer = CodeAnalyzer()
# Analyze all .py files in a package
package_info = analyzer.analyze_package("src/fcc/personas/")
for module in package_info.modules:
print(f"{module.name}: {len(module.classes)} classes, {len(module.functions)} functions")
API Reference Generation¶
Once the code is analyzed, the APIReferenceGenerator converts
ModuleInfo objects into structured API documentation:
from fcc.docs import CodeAnalyzer, APIReferenceGenerator
analyzer = CodeAnalyzer()
module_info = analyzer.analyze_file("src/fcc/personas/models.py")
generator = APIReferenceGenerator()
api_doc = generator.generate(module_info)
print(api_doc.title) # "fcc.personas.models"
print(api_doc.sections) # List of documentation sections
Generated Sections¶
The API reference generator produces:
| Section | Content |
|---|---|
| Module Overview | Module docstring and summary |
| Classes | Class signatures, bases, docstrings |
| Class Methods | Method signatures, parameters, return types |
| Functions | Module-level function signatures |
| Constants | Module-level constants and their values |
| Cross-References | Links to related modules |
| Source Location | File path and line numbers |
Cross-Reference Resolution¶
The generator automatically resolves cross-references:
- Inheritance — links base classes to their documentation.
- Parameter types — links type annotations to class documentation.
- Return types — links return type annotations to class documentation.
- Module imports — tracks which modules are referenced.
# Find all cross-references in generated docs
for xref in api_doc.cross_references:
print(f" {xref.source} -> {xref.target} ({xref.kind})")
Jinja2 Template System¶
The documentation intelligence system uses Jinja2 templates to separate content extraction from presentation. This allows the same analysis results to produce Markdown, HTML, reStructuredText, or any other format.
Template Directory Structure¶
src/fcc/templates/docs/
├── api_reference.md.j2 # Full API reference for a module
├── class_detail.md.j2 # Detailed class documentation
├── function_detail.md.j2 # Detailed function documentation
├── module_index.md.j2 # Index of all modules in a package
├── cross_reference.md.j2 # Cross-reference map
├── changelog.md.j2 # Auto-generated changelog from git
└── persona_api.md.j2 # Persona-specific API documentation
Template Variables¶
Each template receives a context dictionary with analysis results:
| Variable | Type | Description |
|---|---|---|
module |
ModuleInfo |
The analyzed module |
classes |
list[ClassInfo] |
All classes in the module |
functions |
list[FunctionInfo] |
All module-level functions |
cross_refs |
list[CrossRef] |
Cross-reference links |
package_name |
str |
Package name for breadcrumbs |
generation_date |
str |
ISO timestamp of generation |
Rendering Templates¶
from fcc.docs import TemplateRenderer
renderer = TemplateRenderer()
# Render API reference for a module
markdown = renderer.render("api_reference.md.j2", {
"module": module_info,
"classes": module_info.classes,
"functions": module_info.functions,
"cross_refs": api_doc.cross_references,
"package_name": "fcc.personas",
"generation_date": "2026-03-29",
})
print(markdown)
Custom Templates¶
Users can provide custom templates for project-specific documentation formats:
renderer = TemplateRenderer(template_dirs=[
"my_project/templates/", # Custom templates (checked first)
"src/fcc/templates/docs/", # FCC defaults (fallback)
])
output = renderer.render("my_custom_template.md.j2", context)
Integration with FCC's DocGenerator¶
The documentation intelligence system integrates with FCC's existing
DocGenerator (see Chapter 6) to produce
a complete documentation site.
DocGenerator Pipeline¶
The DocGenerator orchestrates the full documentation workflow:
- Load personas —
PersonaRegistry.from_data_dir()loads all persona definitions. - Analyze code —
CodeAnalyzerextracts structural metadata fromsrc/fcc/modules. - Generate references —
APIReferenceGeneratorproduces API docs. - Render templates — Jinja2 templates produce the final output.
- Write output — Generated files are written to the output directory.
CLI Integration¶
The documentation intelligence system is accessible through the FCC CLI:
# Generate API reference for the personas module
fcc generate-docs --module fcc.personas --output docs/api/
# Generate full package documentation
fcc generate-docs --package src/fcc/ --output docs/api/
# Validate generated docs against source
fcc validate-docs --docs docs/api/ --source src/fcc/
Incremental Generation¶
The DocGenerator supports incremental generation by tracking file
modification times:
from fcc.scaffold.doc_generator import DocGenerator
generator = DocGenerator(output_dir="docs/api/")
# Only regenerate docs for changed files
stats = generator.generate_incremental(source_dir="src/fcc/")
print(f"Regenerated: {stats.updated} files")
print(f"Unchanged: {stats.skipped} files")
Persona-Aware Documentation¶
A unique FCC capability is persona-aware documentation. Each persona's generated docs include:
- R.I.S.C.E.A.R. summary — the 10-component specification.
- Collaboration map — visual representation of upstream and downstream persona connections.
- Deliverable catalog — the named outputs this persona produces.
- Constitution reference — governance rules applicable to this persona.
- Evolution guide — how to adopt and grow into this persona role.
from fcc.scaffold.doc_generator import DocGenerator
generator = DocGenerator(output_dir="docs/personas/")
generator.generate_persona_docs(registry)
# Produces 56 files per persona (RISCEAR, collaboration, deliverables, etc.)
Practical Exercises¶
Exercise 1: Analyze a Module¶
Use the CodeAnalyzer to analyze src/fcc/personas/models.py. Count
the number of classes, methods, and parameters. Verify that all
dataclasses have frozen=True.
Exercise 2: Generate API Reference¶
Generate an API reference for src/fcc/workflow/actions.py. Check that
the WorkflowActionType enum members are all documented and that the
WorkflowAction dataclass fields are listed.
Exercise 3: Custom Template¶
Create a custom Jinja2 template that produces a one-page summary card for a module, showing: module name, class count, function count, and the first paragraph of the docstring.
Exercise 4: Incremental Generation¶
Modify a single file in src/fcc/personas/ and run incremental
generation. Verify that only the changed module's documentation is
regenerated.
Summary¶
Documentation intelligence closes the gap between code and documentation
by making documentation a derived artifact. The AST-based analysis
ensures structural accuracy, the Jinja2 template system provides
formatting flexibility, and the integration with FCC's DocGenerator
connects code analysis to the existing documentation pipeline.
| Component | Responsibility |
|---|---|
CodeAnalyzer |
Parse Python AST, extract classes/functions/parameters |
APIReferenceGenerator |
Convert analysis results to structured API docs |
TemplateRenderer |
Render Jinja2 templates with analysis context |
DocGenerator |
Orchestrate the full documentation workflow |
The key insight is that documentation should be computed, not written. When documentation is derived from source code, it is correct by construction and maintenance becomes a non-issue.
Next Steps
- Explore Wave 18 modules for hands-on documentation intelligence
- See Chapter 10 for cross-project documentation patterns
- Read the
src/fcc/templates/docs/directory for available Jinja2 templates- Try
fcc generate-docsto see the CLI in action