Assure Proper Integration of Table of Contents
The Table of Contents was consistently missing from final memo output despite the `toc_generator` agent running successfully mid-pipeline. Two separate ordering bugs caused the TOC to either never generate or get destroyed before finalization.
Changelog - 2026-03-23_01
Assure Proper Integration of Table of Contents
The Table of Contents was consistently missing from final memo output despite the toc_generator agent running successfully mid-pipeline. Two separate ordering bugs caused the TOC to either never generate or get destroyed before finalization.
Why
Investment memos require a navigable Table of Contents for both HTML/PDF exports and Obsidian viewing. Every run since the TOC agent was introduced has produced a final draft without a TOC — despite the agent logging "TOC generated" in the console. Users had to manually run cli/assemble_draft post-pipeline to get a TOC.
What Changed
Bug 1: TOC Agent Ran Before Final Draft Existed
The workflow graph placed the toc node BEFORE assemble_citations, which is the agent that actually creates the final draft file. The TOC agent looked for a final draft, found nothing, and skipped.
Before:
... → enrich_visualizations → toc → revise_summaries → ... → assemble_citations → ...
↑ ↑
No file exists yet Creates the file hereAfter:
... → enrich_visualizations → revise_summaries → ... → assemble_citations → toc → ...
↑ ↑
Creates the file Reads and inserts TOCCommit: d87fa36
Bug 2: integrate_scorecard Destroyed the TOC During Reassembly
Even after fixing Bug 1, the TOC was still missing. integrate_scorecard (the last agent that rewrites the final draft) attempted to import cli.assemble_draft.assemble_final_draft — which includes TOC generation. But cli/ had no __init__.py, making it unimportable. The import silently failed, falling through to a basic concatenation fallback with no TOC.
# This ALWAYS raised ImportError because cli/ wasn't a package
try:
from cli.assemble_draft import assemble_final_draft # includes TOC
...
except ImportError:
# Fallback: raw concatenation, NO TOC
for section_file in sorted(sections_dir.glob("*.md")):
content += section_file.read_text() + '\n\n'Fix: Created cli/__init__.py and rewrote the fallback to call assemble_citations() + toc_generator_agent().
Commit: cbd19c8
TOC Agent Made Context-Aware
Previously, the TOC agent blindly skipped if any ## Table of Contents heading existed. Now it validates accuracy and location:
Strips existing TOC from content
Generates correct TOC from current headers
Compares: if existing TOC matches and is correctly positioned → no changes
Otherwise: regenerates and reinserts in the correct location
Commit: d87fa36
Verification
| Metric | v0.2.3 (before) | v0.2.4 (after) |
| TOC in final draft | Missing | Present |
integrate_scorecard path | Always fallback (no TOC) | Primary path (with TOC) |
Files Changed
| File | Change |
src/workflow.py | Moved toc edge to after assemble_citations; rewrote integrate_scorecard fallback |
src/agents/toc_generator.py | Added remove_existing_toc(), extract_existing_toc(), context-aware validation |
src/agents/citation_assembly.py | Added docstring clarifying TOC is orchestrator's responsibility |
cli/__init__.py | Created — makes cli/ importable as a Python package |
context-v/reminders/Ideal-Orchestration-Agent-Workflow.md | Created — canonical agent sequence reference |