BUCKYVERSE

Date: 2025-05-23
Status: Accepted

Context

The Codexis build system previously operated with isolated, per-format builds where each output format (PDF, HTML, EPUB, DOCX, etc.) created its own temporary directory and independently processed LaTeX sources. This approach led to several inefficiencies:

  1. Redundant LaTeX Processing: Each format builder compiled LaTeX from scratch, generating duplicate auxiliary files (.aux, .toc, .bbl, .tdo, etc.)
  2. Resource Waste: Multiple temporary directories consuming disk space and I/O bandwidth
  3. Build Time Overhead: Sequential builds taking longer due to repeated LaTeX compilation
  4. Inconsistent Auxiliary Files: Different formats potentially using different versions of auxiliary files
  5. Complex Cleanup: Each builder managing its own cleanup logic independently

Decision

We will implement a Unified Build System with Shared Temporary Directory that centralizes temporary file management and eliminates redundant processing through the following architecture:

1. BuildOrchestrator Architecture

defmodule Codexis.BuildManager.BuildOrchestrator do
  @moduledoc """
  Manages a shared temporary directory for all format builds in a session.
  Eliminates redundant LaTeX processing by coordinating auxiliary file sharing.
  """
  
  # Directory structure:
  # temp_root/codexis_build_<timestamp>_<random>/
  # ├── source/           # Source files copied here
  # ├── aux/             # LaTeX auxiliary files (.aux, .toc, .bbl, etc.)
  # ├── output/          # Format-specific outputs
  # │   ├── pdf/
  # │   ├── html/
  # │   ├── epub/
  # │   └── ...
  # ├── assets/          # Images, fonts, etc.
  # ├── images/          # Processed images
  # ├── styles/          # Style files
  # └── logs/            # Build logs
end

2. Build Process Flow

graph TD
    A[BuildManager.build/2] --> B[BuildOrchestrator.create/2]
    B --> C[Copy source files to temp/source]
    C --> D[Build PDF first - generates aux files]
    D --> E[Other formats read from shared aux/]
    E --> F[All formats write to temp/output/format/]
    F --> G[Copy outputs to final destination]
    G --> H[Cleanup or preserve temp directory]

3. Key Components

a. BuildOrchestrator Module

defmodule Codexis.BuildManager.BuildOrchestrator do
  @type t :: %__MODULE__{
    base_dir: String.t(),
    source_dir: String.t(),
    aux_dir: String.t(),
    output_dir: String.t(),
    assets_dir: String.t(),
    images_dir: String.t(),
    styles_dir: String.t(),
    logs_dir: String.t(),
    cleanup_on_success: boolean(),
    preserve_on_error: boolean()
  }

  def create(source_dir, opts \\ []) do
    # Creates unique temp directory with secure permissions (0700)
    # Sets up standardized subdirectory structure
    # Copies source files to temp location
  end

  def cleanup(orchestrator) do
    # Handles cleanup based on policy (success/error/preserve)
  end

  # Directory accessors
  def source_dir(orchestrator), do: orchestrator.source_dir
  def aux_dir(orchestrator), do: orchestrator.aux_dir
  def output_dir(orchestrator), do: orchestrator.output_dir
  # ... additional accessors
end

b. Refactored Build Pipeline

defmodule Codexis.BuildManager do
  def build(source_dir, output_dir, options \\ %{}) do
    with {:ok, orchestrator} <- BuildOrchestrator.create(source_dir, options),
         {:ok, formats} <- determine_formats(options),
         {:ok, _results} <- build_formats_unified(orchestrator, formats, output_dir, options) do
      
      # Cleanup based on policy
      if options[:cleanup_temp_dir] != false do
        BuildOrchestrator.cleanup(orchestrator)
      end
      
      {:ok, "Build completed successfully"}
    end
  end

  defp build_formats_unified(orchestrator, formats, output_dir, options) do
    # 1. Build PDF first (generates all auxiliary files)
    with {:ok, _pdf} <- build_pdf_with_orchestrator(orchestrator, output_dir, options) do
      
      # 2. Build other formats concurrently using shared aux files  
      other_formats = List.delete(formats, :pdf)
      
      Task.async_stream(other_formats, fn format ->
        build_format_with_orchestrator(format, orchestrator, output_dir, options)
      end, timeout: 300_000)
      |> Enum.to_list()
    end
  end
end

c. Builder Refactoring

All format builders (PDF, HTML, EPUB, DOCX, Markdown, RTF, WikiJS) have been refactored to:

  1. Accept a BuildOrchestrator parameter
  2. Read source files from orchestrator.source_dir
  3. Read auxiliary files from orchestrator.aux_dir
  4. Write outputs to orchestrator.output_dir/<format>/
  5. Eliminate their own temporary directory creation
defmodule Codexis.Builders.HTMLBuilder do
  def build(orchestrator, output_path, options \\ %{}) do
    source_dir = BuildOrchestrator.source_dir(orchestrator)
    aux_dir = BuildOrchestrator.aux_dir(orchestrator)
    
    # Use shared auxiliary files - no LaTeX recompilation needed
    # Process using existing aux files from PDF build
  end
end

4. CLI Enhancements

New command-line flags support temp directory management:

# Display temp directory path for debugging
./codexis build --show-temp-dir --source manuscript --output output

# Preserve temp directory after build
./codexis build --preserve-temp-dir --source manuscript --output output  

# Specify custom temp directory root
./codexis build --temp-dir-root /custom/temp/path --source manuscript --output output

# All formats using unified system
./codexis build --all --source manuscript --output output

5. Configuration Options

The unified build system supports flexible configuration:

config :codexis, :build_orchestrator,
  temp_dir_root: System.tmp_dir!(),
  cleanup_on_success: true,
  preserve_on_error: true,
  secure_permissions: true,
  concurrent_builds: true

Implementation Details

Directory Structure

The BuildOrchestrator creates a standardized directory hierarchy:

/tmp/codexis_build_1748057072_abc123de/
├── source/manuscript_source/    # Source files copied here  
│   ├── manuscript.tex
│   ├── content/
│   ├── images/
│   └── meta.yaml
├── aux/                        # LaTeX auxiliary files
│   ├── manuscript.aux
│   ├── manuscript.toc  
│   ├── manuscript.bbl
│   ├── manuscript.tdo
│   └── ...
├── output/                     # Format-specific outputs
│   ├── pdf/
│   ├── html/
│   ├── epub/
│   ├── docx/
│   └── markdown/
├── assets/                     # Processed assets
├── images/                     # Image processing
├── styles/                     # Style files
└── logs/                       # Build logs

Security Model

Error Handling

Performance Optimizations

Testing Strategy

Comprehensive test coverage ensures system reliability:

Test Suites Implemented

  1. Unit Tests (test/codexis/build_manager/build_orchestrator_test.exs)

    • BuildOrchestrator creation and configuration
    • Directory structure and permissions
    • Source file copying and management
    • Cleanup and preservation policies
    • Error handling scenarios
  2. Integration Tests (test/codexis/build_manager_test.exs)

    • BuildManager with orchestrator integration
    • Multi-format builds through unified system
    • Error propagation and recovery
  3. End-to-End Tests (test/integration/unified_build_system_test.exs)

    • Complete build pipeline testing
    • Multi-format output validation
    • Auxiliary file reuse verification
  4. Performance Tests (test/performance/build_performance_test.exs)

    • Build time benchmarking
    • Memory usage monitoring
    • Unified vs sequential build comparison
  5. Validation Tests (test/validation/cross_format_consistency_test.exs)

    • Content consistency across formats
    • Mathematical content preservation
    • Cross-reference integrity

Test Results

Consequences

Positive

  1. Performance: Significant build time reduction through eliminated redundant LaTeX processing
  2. Efficiency: Reduced disk I/O and memory usage
  3. Consistency: All formats use identical auxiliary files ensuring consistency
  4. Maintainability: Centralized temp directory management simplifies cleanup and debugging
  5. Scalability: Better resource utilization for large documents and multiple format builds
  6. Reliability: Comprehensive error handling and recovery mechanisms

Negative

  1. Complexity: Increased coordination complexity between builders
  2. Dependencies: PDF build must complete before other formats can proceed
  3. Debugging: More complex debugging when issues span multiple formats

Migration Path

  1. Backward Compatibility: Existing CLI commands continue to work unchanged
  2. Gradual Adoption: New unified system used automatically for multi-format builds
  3. Fallback: Individual format builds still supported for specific use cases

Compliance

The unified build system maintains full compliance with:

  1. Output Quality: All formats produce identical quality to previous system
  2. Feature Parity: No reduction in functionality or supported features
  3. Configuration: All existing configuration options preserved
  4. CLI Compatibility: Existing command-line interfaces unchanged
  5. Performance: Measurable improvement in build times and resource usage

References

  1. ADR-0024: Build Pipeline Architecture
  2. Task #17: Design and Implement a Unified Build System
  3. "Elixir OTP Supervision Strategies" - Elixir Documentation
  4. "GenServer and Process Management" - Elixir in Action, Saša Jurić
  5. "File System Operations and Security" - Erlang/OTP Documentation