Skip to content

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:

  1. Docs-from-Code Philosophy — why AST-driven documentation outperforms manual authoring.
  2. CodeAnalyzer Module — extracting classes, functions, parameters, and docstrings.
  3. API Reference Generation — producing structured API docs from analysis results.
  4. Template System — Jinja2 templates for flexible output formatting.
  5. 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:

  1. Source of truth is code — documentation is generated from what the code actually declares, not from what a developer remembers.
  2. Incremental updates — only re-generate docs for modules that have changed since the last generation run.
  3. Template separation — content extraction (AST analysis) is completely separate from presentation (Jinja2 templates).
  4. 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

Source File → Python AST → Visitor → ModuleInfo → API Reference

The analysis pipeline performs these steps:

  1. Parseast.parse() converts source code to an AST.
  2. Visit — A custom ast.NodeVisitor walks the tree, collecting:
  3. Module-level docstrings
  4. Class definitions (name, bases, decorators, methods)
  5. Function definitions (name, parameters, return type, decorators)
  6. Type annotations on parameters and return values
  7. Constants and module-level assignments
  8. Resolve — Cross-references between classes (inheritance, usage) are resolved to produce a connected dependency graph.
  9. Emit — The collected metadata is returned as ModuleInfo, ClassInfo, and FunctionInfo dataclasses.

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:

PersonaRegistry → CodeAnalyzer → APIReferenceGenerator → Templates → Output
  1. Load personasPersonaRegistry.from_data_dir() loads all persona definitions.
  2. Analyze codeCodeAnalyzer extracts structural metadata from src/fcc/ modules.
  3. Generate referencesAPIReferenceGenerator produces API docs.
  4. Render templates — Jinja2 templates produce the final output.
  5. 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-docs to see the CLI in action