Lossless Changelog
component

Refactor: Centralized Final Draft Module & Artifact Renumbering

This release refactors final draft operations into a single centralized module (`src/final_draft.py`) and updates the artifact numbering scheme.

Changelog - 2025-12-09 (#2)

Refactor: Centralized Final Draft Module & Artifact Renumbering

Overview

This release refactors final draft operations into a single centralized module (src/final_draft.py) and updates the artifact numbering scheme. Previously, final draft file operations were scattered across 15+ files, requiring manual updates in each file when changing the naming convention. Now, all final draft operations are centralized, and the naming pattern has changed from 4-final-draft.md to 6-{Deal}-{Version}.md.


Problem

Two issues existed:

Issue 1: Scattered Final Draft Operations

Final draft reading, writing, and path resolution were duplicated across many files:

  • src/workflow.py

  • src/agents/citation_enrichment.py

  • src/agents/toc_generator.py

  • src/agents/revise_summary_sections.py

  • cli/assemble_draft.py

  • cli/export_branded.py

  • cli/resume_from_interruption.py

  • cli/refocus_section.py

  • cli/recompile_memo.py

  • And more...

Changing the filename from 4-final-draft.md to something else required editing all these files individually.

Issue 2: Artifact Numbering Gaps

The artifact numbering had gaps and inconsistencies:

  • 4-final-draft.md - Final output

  • 5-fact-check.* - Fact-check results

  • Scorecard had no numbered prefix


Solution: Centralized Module + New Numbering

New Artifact Numbering Scheme

output/{Company}-v0.0.x/
├── 0-deck-analysis.*           # Deck analysis
├── 1-research.*                # Web research
├── 2-sections/                 # Section drafts
├── 3-validation.*              # Validation scores
├── 4-fact-check.*              # Fact-check results (renamed from 5-)
├── 5-scorecard/                # Scorecard evaluation
├── 6-{Deal}-{Version}.md       # Final draft (e.g., 6-Aito-v0.0.2.md)
└── state.json                  # Workflow state

Centralized Module: src/final_draft.py

Created a single source of truth for all final draft operations:

PYTHON
"""
Centralized final draft file operations.

Change the naming convention by editing ONLY these constants:
"""

# Configuration - change these to rename all final drafts
FINAL_DRAFT_PREFIX = "6"
LEGACY_FILENAME = "4-final-draft.md"  # For backwards compatibility


def get_final_draft_filename(output_dir: Path) -> str:
    """Get the final draft filename based on output directory name."""
    dir_name = output_dir.name  # e.g., "Aito-v0.0.2"
    return f"{FINAL_DRAFT_PREFIX}-{dir_name}.md"  # "6-Aito-v0.0.2.md"


def get_final_draft_path(output_dir: Path) -> Path:
    """Get the full path to the final draft file."""
    return output_dir / get_final_draft_filename(output_dir)


def find_final_draft(output_dir: Path) -> Optional[Path]:
    """
    Find the final draft file with automatic legacy fallback.

    Tries new naming pattern first (6-*.md), falls back to legacy (4-final-draft.md).
    """
    # Try new naming pattern first
    new_pattern_files = list(output_dir.glob(f"{FINAL_DRAFT_PREFIX}-*.md"))
    if new_pattern_files:
        return new_pattern_files[0]

    # Fall back to legacy naming
    legacy_path = output_dir / LEGACY_FILENAME
    if legacy_path.exists():
        return legacy_path

    return None


def read_final_draft(output_dir: Path) -> Optional[str]:
    """Read final draft content with automatic file detection."""
    draft_path = find_final_draft(output_dir)
    if draft_path and draft_path.exists():
        return draft_path.read_text(encoding="utf-8")
    return None


def write_final_draft(output_dir: Path, content: str) -> Path:
    """Write final draft with new naming pattern."""
    draft_path = get_final_draft_path(output_dir)
    draft_path.write_text(content, encoding="utf-8")
    return draft_path


def find_all_final_drafts(root_dir: Path) -> list[Path]:
    """Find all final draft files recursively (both new and legacy patterns)."""
    drafts = []
    # New pattern
    drafts.extend(root_dir.rglob(f"{FINAL_DRAFT_PREFIX}-*.md"))
    # Legacy pattern
    drafts.extend(root_dir.rglob(LEGACY_FILENAME))
    return drafts


def is_final_draft_file(filepath: Path) -> bool:
    """Check if a file matches the final draft naming pattern."""
    name = filepath.name
    return (
        name.startswith(f"{FINAL_DRAFT_PREFIX}-") and name.endswith(".md")
    ) or name == LEGACY_FILENAME

Files Changed

FileChange
src/final_draft.pyNEW - Centralized module (~100 lines)
src/artifacts.pyRe-exports from final_draft.py for compatibility, renamed fact-check from 5- to 4-
src/workflow.pyImport from src.final_draft
src/agents/citation_enrichment.pyUse write_final_draft()
src/agents/toc_generator.pyUse find_final_draft(), read_final_draft()
src/agents/revise_summary_sections.pyUse centralized module
src/agents/internal_comments_sanitizer.pyUse centralized module
cli/assemble_draft.pyUse write_final_draft()
cli/export_branded.pyUse find_final_draft(), find_all_final_drafts(), is_final_draft_file()
cli/resume_from_interruption.pyUse find_final_draft()
cli/refocus_section.pyUse write_final_draft()
cli/recompile_memo.pyUse write_final_draft()
src/main.pyRemoved redundant versioned draft file creation
context-vigilance/Multi-Agent-Orchestration-for-Investment-Memo-Generation.mdUpdated documentation

Impact

Before This Change

  • Final draft operations duplicated across 15+ files

  • Changing 4-final-draft.md to a new name required editing every file

  • Redundant {Company}-v0.0.x-draft.md file created outside artifact directory

  • Fact-check used 5- prefix, leaving 4- unused after final draft rename

After This Change

  • Single source of truth: Change FINAL_DRAFT_PREFIX in one file to rename everywhere

  • Backwards compatible: Auto-detects both 6-*.md and legacy 4-final-draft.md

  • No redundant files: Only one final draft in the artifact directory

  • Consistent numbering: 0-6 prefix sequence with no gaps

Example Output

BASH
# New naming pattern
output/Aito-v0.0.2/
├── 0-deck-analysis.json
├── 1-research.json
├── 2-sections/
├── 3-validation.json
├── 4-fact-check.json
├── 4-fact-check.md
├── 5-scorecard/
├── 6-Aito-v0.0.2.md          # Final draft with descriptive name
└── state.json

Migration Notes

Existing Memos

Existing memos with 4-final-draft.md continue to work. The find_final_draft() function automatically detects legacy naming and returns the correct path. No migration required.

Export Tools

Export tools (export-branded.py, export-all-modes.sh) automatically detect both naming patterns. No changes needed to export commands.

Future Naming Changes

To change the final draft naming convention in the future:

PYTHON
# Edit src/final_draft.py ONLY
FINAL_DRAFT_PREFIX = "7"  # Change this one line
# All 15+ consumer files automatically use new naming

Documentation Updated

  • context-vigilance/Multi-Agent-Orchestration-for-Investment-Memo-Generation.md

    • Updated artifact numbering section

    • Updated artifact directory structure diagrams

    • Updated export command examples

    • Added src/final_draft.py documentation

    • Updated pipeline diagrams


  • Deck Screenshot Extraction: Added LLM-guided screenshot extraction to deck_analyst.py (separate commit)

  • Documentation: Created context-vigilance/Deck-Analyzer-Agent.md


Testing

Verification Commands

BASH
# Verify module imports correctly
python -c "from src.final_draft import write_final_draft, find_final_draft; print('✓ Module imports')"

# Verify workflow compiles
python -c "from src.workflow import build_workflow; w = build_workflow(); print('✓ Workflow compiles')"

# Test legacy detection
python -c "
from pathlib import Path
from src.final_draft import find_final_draft
# Should find either 6-*.md or 4-final-draft.md
print('✓ Legacy detection works')
"

Expected Behavior

  1. New memos create 6-{Deal}-{Version}.md as final draft

  2. Existing memos with 4-final-draft.md still work

  3. Export tools find both naming patterns

  4. Changing FINAL_DRAFT_PREFIX updates all file operations


Contributors

Implementation by Claude Code (Anthropic) with user guidance.