Understanding the IR (Intermediate Representation) System in ReportEngine and Document Stitching
The IR (Intermediate Representation) system in ReportEngine is a canonical JSON contract that validates chapter structure before rendering, while document stitching merges multiple validated chapters into a single cohesive document using the DocumentComposer class.
The 666ghj/bettafish repository implements a robust reporting engine that bridges LLM-generated content with multiple output formats. The IR system ensures structural integrity through strict schema validation, while the stitching layer orchestrates multi-chapter documents with automatic anchor management and metadata injection.
What Is the IR (Intermediate Representation) System in ReportEngine?
The IR system serves as the canonical JSON contract that every report generated by the engine must obey. It acts as the bridge between raw LLM output and the final rendered documents (HTML, PDF, Markdown), ensuring that downstream renderers never encounter structural crashes.
Core Components of the IR Schema
The schema definition resides in ReportEngine/ir/schema.py and establishes several critical constraints:
- Versioning: Every IR payload carries a
versionfield defined byIR_VERSION = "1.0", ensuring backward compatibility as the schema evolves. - Allowed Inline Marks: The system restricts text formatting to a whitelist defined in
ALLOWED_INLINE_MARKS, includingbold,italic,link, and other semantic annotations. - Allowed Block Types: Content structure is constrained by
ALLOWED_BLOCK_TYPES, which enumerates valid building blocks such asheading,paragraph,list,table, andwidget. - Chapter Schema: The
CHAPTER_JSON_SCHEMAconstant defines the complete JSON-Schema for a chapter, specifying required fields likechapterId,title,anchor,order, andblocks, plus optional metadata extensions.
IR Validation with IRValidator
The IRValidator class in ReportEngine/ir/validator.py provides runtime enforcement of the schema. It walks a chapter (or whole document) and checks every field against CHAPTER_JSON_SCHEMA, returning a boolean validity flag and a list of human-readable error paths.
from ReportEngine.ir import IRValidator
validator = IRValidator()
is_ok, errors = validator.validate_chapter(chapter_json)
if not is_ok:
print("Chapter validation failed:", errors)
Source: ReportEngine/ir/validator.py
How Document Stitching Works in ReportEngine
Document stitching is the process of merging multiple validated chapter JSONs into a single cohesive Document IR. This logic lives in ReportEngine/core/stitcher.py and is encapsulated by the DocumentComposer class.
The DocumentComposer.build_document Method
The build_document method orchestrates the assembly process through several distinct phases:
- Collect TOC Anchors: Reads
metadata.toc.customEntriesto map any user-specifiedchapterId → anchoroverrides via_build_toc_anchor_map. - Sort Chapters: Orders the supplied chapters list by the
orderfield, defaulting to0for unspecified entries:ordered = sorted(chapters, key=lambda c: c.get("order", 0)). - Inject Defaults: Generates fallback values for missing required fields:
- Creates sequential
chapterIdvalues (S1,S2, …) if missing. - Ensures every chapter has a unique
anchorusing_ensure_unique_anchor. - Guarantees an
ordervalue (defaulting toidx * 10based on position).
- Creates sequential
- Add Placeholder Headings: If a chapter is marked as an error placeholder,
_ensure_heading_blockinserts a minimal heading block so the Table of Contents can still reference it. - Compose Final IR: Returns a dictionary containing
version,reportId, enrichedmetadata(addinggeneratedAttimestamp),themeTokens, the orderedchaptersarray, and any globalassets.
Handling Anchor Uniqueness and Defaults
The _ensure_unique_anchor method maintains an internal _seen_anchors set to detect collisions. When a duplicate anchor is detected, the system automatically appends suffixes (-2, -3, etc.) to ensure globally unique identifiers throughout the stitched document.
from ReportEngine.core.stitcher import DocumentComposer
composer = DocumentComposer()
# Example metadata (could include a custom TOC)
metadata = {
"title": "年度报告",
"toc": {
"customEntries": [
{"chapterId": "intro", "anchor": "overview"},
{"chapterId": "conclusion", "anchor": "end"},
]
},
"themeTokens": {"primary": "#123456"},
"assets": {"logo": "static/logo.png"},
}
# List of chapter payloads (already validated)
chapters = [chapter1, chapter2, chapter3]
document_ir = composer.build_document(
report_id="report-2025",
metadata=metadata,
chapters=chapters,
)
print(document_ir["version"]) # → "1.0"
print(document_ir["chapters"][0]["anchor"]) # unique, e.g. "overview"
Source: ReportEngine/core/stitcher.py
Complete Workflow: From Chapter Generation to Final Document
The typical pipeline for producing a report in the 666ghj/bettafish repository follows these stages:
- Generate each chapter using LLM or other engines → raw JSON payload.
- Validate each chapter with
IRValidatorto ensure schema compliance. - Collect all validated chapter JSONs into a sequential list.
- Instantiate
DocumentComposerand invokebuild_document(report_id, metadata, chapters). - Pass the resulting Document IR to the appropriate renderer (
ReportEngine/renderers/*.py) for HTML, PDF, or Markdown output.
from ReportEngine.ir import IRValidator
from ReportEngine.core.stitcher import DocumentComposer
validator = IRValidator()
composer = DocumentComposer()
validated_chapters = []
for raw in raw_chapter_jsons:
ok, errs = validator.validate_chapter(raw)
if ok:
validated_chapters.append(raw)
else:
raise ValueError(f"Invalid chapter: {errs}")
final_ir = composer.build_document(
report_id="my-report",
metadata=global_metadata,
chapters=validated_chapters,
)
# `final_ir` can now be rendered to HTML, PDF, etc.
Key Files in the IR and Stitching System
| File | Role |
|---|---|
ReportEngine/ir/schema.py |
Defines the IR version, allowed inline marks, block types, and the JSON-Schema for chapters. |
ReportEngine/ir/validator.py |
Implements IRValidator – the runtime checker that enforces the schema on each chapter. |
ReportEngine/core/stitcher.py |
Contains DocumentComposer, the component that merges chapter JSONs into a single Document IR, handling ordering, anchor uniqueness, and metadata injection. |
ReportEngine/utils/config.py |
Holds configuration defaults (output directories, template locations) often merged into the final IR’s metadata. |
ReportEngine/scripts/validate_ir.py |
CLI utility that invokes IRValidator on whole IR files – useful for debugging and CI checks. |
These files together form the backbone of the IR system and the document stitching process, guaranteeing that every generated report conforms to a strict, versioned contract before it reaches the rendering stage.
Summary
- The IR (Intermediate Representation) is a canonical JSON contract defined in
ReportEngine/ir/schema.pythat ensures all report chapters follow a strict, versioned structure before rendering. - IR validation is enforced by the
IRValidatorclass inReportEngine/ir/validator.py, which checks every chapter against theCHAPTER_JSON_SCHEMAand returns detailed error paths for debugging. - Document stitching is handled by
DocumentComposerinReportEngine/core/stitcher.py, which sorts chapters byorder, injects defaultchapterIdandanchorvalues, ensures global anchor uniqueness, and composes the final Document IR. - The complete workflow involves generating raw chapters, validating them with
IRValidator, collecting them into a list, and passing them toDocumentComposer.build_document()to produce a renderer-ready JSON payload.
Frequently Asked Questions
What is the current IR version in ReportEngine?
The current IR version is defined as IR_VERSION = "1.0" in ReportEngine/ir/schema.py. Every Document IR payload includes this version field to ensure backward compatibility and schema compliance across different versions of the rendering engine.
How does ReportEngine handle duplicate chapter anchors?
The DocumentComposer class maintains an internal _seen_anchors set during the stitching process. When _ensure_unique_anchor detects a collision, it automatically appends incremental suffixes such as -2, -3, etc., to create globally unique identifiers throughout the final document.
What happens if a chapter fails IR validation?
If IRValidator.validate_chapter() returns False, it provides a detailed list of human-readable error paths indicating which fields violate the CHAPTER_JSON_SCHEMA. The typical workflow raises a ValueError or logs the errors, preventing invalid chapters from reaching the stitching phase and ensuring renderers never receive malformed data.
Can I customize the table of contents entries during stitching?
Yes, the DocumentComposer.build_document method accepts a metadata dictionary that can include toc.customEntries. This array maps specific chapterId values to custom anchor strings, allowing you to override default anchor generation and ensure TOC links point to specific sections as defined in ReportEngine/core/stitcher.py.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →