Module

debug.delta_analyzer

Build delta analyzer for comparing builds and explaining changes.

Provides tools for comparing build snapshots to understand what changed between builds, tracking build time trends, and identifying performance regressions over time.

Key Features:

  • BuildSnapshot: Captures build state for comparison
  • BuildDelta: Computes differences between two snapshots
  • BuildHistory: Tracks builds over time for trend analysis
  • BuildDeltaAnalyzer: Debug tool combining all capabilities

Use Cases:

  • Compare current build to previous build
  • Track build performance trends over time
  • Identify when builds started slowing down
  • Understand what content was added/removed

Example:

>>> from bengal.debug import BuildDeltaAnalyzer
>>> analyzer = BuildDeltaAnalyzer(cache=cache)
>>> delta = analyzer.compare_to_previous()
>>> if delta:
...     print(delta.format_summary())

+5 pages | +120ms (+8%) | ⚠️ config changed

Related Modules:

  • bengal.orchestration.stats: BuildStats from build runs
  • bengal.cache.build_cache: Cache with build state
  • bengal.debug.base: Debug tool infrastructure

See Also:

  • bengal/debug/incremental_debugger.py: Cache-specific debugging
  • bengal/cli/commands/debug.py: CLI integration

Classes

BuildSnapshot 13
Snapshot of a build state for comparison. Captures key metrics and file lists from a build for del…

Snapshot of a build state for comparison.

Captures key metrics and file lists from a build for delta analysis.

Attributes

Name Type Description
timestamp datetime

When the build occurred

build_time_ms float

Total build time

page_count int

Number of pages built

asset_count int

Number of assets processed

pages set[str]

Set of page paths in this build

output_files set[str]

Set of output file paths

phase_times dict[str, float]

Timing by phase (discovery, rendering, etc.)

config_hash str | None

Hash of configuration at build time

metadata dict[str, Any]

Additional build metadata

Methods

from_build_stats 2 BuildSnapshot
Create snapshot from BuildStats.
classmethod
def from_build_stats(cls, stats: BuildStats, pages: set[str]) -> BuildSnapshot
Parameters
Name Type Description
stats

BuildStats from a completed build

pages

Set of page paths that were built

Returns
BuildSnapshot BuildSnapshot capturing the build state
from_cache 1 BuildSnapshot
Create snapshot from BuildCache.
classmethod
def from_cache(cls, cache: BuildCache) -> BuildSnapshot
Parameters
Name Type Description
cache

BuildCache with build state

Returns
BuildSnapshot BuildSnapshot capturing cached state
to_dict 0 dict[str, Any]
Convert to dictionary for JSON serialization.
def to_dict(self) -> dict[str, Any]
Returns
dict[str, Any] Dictionary suitable for json.dumps(). Sets are converted to lists.
from_dict 1 BuildSnapshot
Create snapshot from dictionary.
classmethod
def from_dict(cls, data: dict[str, Any]) -> BuildSnapshot
Parameters
Name Type Description
data

Dictionary from to_dict() or JSON parsing.

Returns
BuildSnapshot Reconstructed BuildSnapshot instance.
BuildDelta 14
Difference between two builds. Captures what changed between builds including added/removed pages,…

Difference between two builds.

Captures what changed between builds including added/removed pages, timing changes, and configuration differences.

Attributes

Name Type Description
before BuildSnapshot

The earlier build snapshot

after BuildSnapshot

The later build snapshot

added_pages set[str]

Pages in 'after' but not in 'before'

removed_pages set[str]

Pages in 'before' but not in 'after'

time_change_ms float

Change in build time (positive = slower)

time_change_pct float

Percentage change in build time

phase_changes dict[str, float]

Changes in phase timings

config_changed bool

Whether configuration hash changed

Methods

page_change_count 0 int
Total pages added or removed.
property
def page_change_count(self) -> int
Returns
int Sum of added and removed page counts.
is_significant 0 bool
Check if delta represents significant changes. **A delta is significant if:** …
property
def is_significant(self) -> bool

Check if delta represents significant changes.

A delta is significant if:

  • Any pages were added or removed
  • Build time changed by more than 10%
  • Configuration changed
Returns
bool True if changes are significant enough to report.
compute 2 BuildDelta
Compute delta between two builds.
classmethod
def compute(cls, before: BuildSnapshot, after: BuildSnapshot) -> BuildDelta
Parameters
Name Type Description
before

Earlier build snapshot

after

Later build snapshot

Returns
BuildDelta BuildDelta with computed differences
format_summary 0 str
Format as brief one-line summary.
def format_summary(self) -> str
Returns
str String like "+5 pages | +120ms (+8%) 🐌 | ⚠️ config changed"
format_detailed 0 str
Format with full details for verbose output. Includes timestamps, page changes…
def format_detailed(self) -> str

Format with full details for verbose output.

Includes timestamps, page changes (with samples), timing breakdown by phase, and configuration change warnings.

Returns
str Multi-line formatted string.
Internal Methods 1
_format_time_change 2 str
Format time change with emoji indicators.
def _format_time_change(self, ms: float, pct: float) -> str
Parameters
Name Type Description
ms

Time change in milliseconds.

pct

Percentage change.

Returns
str Formatted string like "+150ms (+12%) 🐌" or "-50ms (-5%) 🚀"
BuildHistory 10
Tracks build history for trend analysis. Stores snapshots of builds over time to enable trend anal…

Tracks build history for trend analysis.

Stores snapshots of builds over time to enable trend analysis, baseline comparisons, and performance regression detection. History is persisted to disk and automatically pruned to max_snapshots.

Attributes

Name Type Description
storage_path

Path to JSON file storing history.

max_snapshots

Maximum number of snapshots to retain.

snapshots list[BuildSnapshot]

List of BuildSnapshot in chronological order.

Methods

add 1
Add a snapshot to history. Automatically prunes oldest snapshots if max_snapsh…
def add(self, snapshot: BuildSnapshot) -> None

Add a snapshot to history.

Automatically prunes oldest snapshots if max_snapshots is exceeded.

Parameters
Name Type Description
snapshot

BuildSnapshot to add.

get_latest 1 list[BuildSnapshot]
Get the N most recent snapshots.
def get_latest(self, n: int = 1) -> list[BuildSnapshot]
Parameters
Name Type Description
n

Number of snapshots to return.

Default:1
Returns
list[BuildSnapshot] List of most recent snapshots (may be fewer than n if history is short).
get_baseline 0 BuildSnapshot | None
Get the baseline (first) snapshot in history.
def get_baseline(self) -> BuildSnapshot | None
Returns
BuildSnapshot | None First recorded snapshot, or None if history is empty.
compute_trend 0 dict[str, Any]
Compute trend statistics over history.
def compute_trend(self) -> dict[str, Any]
Returns
dict[str, Any] Dictionary with keys: - build_count: Number of builds in history - avg_build_time_ms: Average build time - min_build_time_ms: Fastest build time - max_build_time_ms: Slowest build time - time_trend: Change in build time (first to last) - page_trend: Change in page count (first to last) Returns empty dict if fewer than 2 snapshots.
Internal Methods 3
__init__ 2
Initialize build history.
def __init__(self, storage_path: Path | None = None, max_snapshots: int = 50)
Parameters
Name Type Description
storage_path

Path to store history JSON file. Defaults to .bengal/build_history.json.

Default:None
max_snapshots

Maximum snapshots to retain. Older snapshots are pruned when limit is exceeded.

Default:50
_load 0
Load history from disk if storage file exists.
def _load(self) -> None
_save 0
Save history to disk, creating parent directories if needed.
def _save(self) -> None
BuildDeltaAnalyzer 8
Debug tool for comparing builds and explaining changes. Helps understand what changed between buil…

Debug tool for comparing builds and explaining changes.

Helps understand what changed between builds, why build times changed, and track build evolution over time.

Creation:

Direct instantiation or via DebugRegistry:

    analyzer = BuildDeltaAnalyzer(site=site, cache=cache)

Methods

analyze 0 DebugReport
Analyze build deltas and trends.
def analyze(self) -> DebugReport
Returns
DebugReport DebugReport with findings about build changes
compare_snapshots 2 BuildDelta
Compare two specific snapshots.
def compare_snapshots(self, before: BuildSnapshot, after: BuildSnapshot) -> BuildDelta
Parameters
Name Type Description
before

Earlier snapshot

after

Later snapshot

Returns
BuildDelta BuildDelta with comparison results
compare_to_previous 0 BuildDelta | None
Compare current state to most recent snapshot.
def compare_to_previous(self) -> BuildDelta | None
Returns
BuildDelta | None BuildDelta or None if no history available
compare_to_baseline 0 BuildDelta | None
Compare current state to baseline (first) snapshot.
def compare_to_baseline(self) -> BuildDelta | None
Returns
BuildDelta | None BuildDelta or None if no baseline available
save_baseline 0
Save current state as new baseline. Clears history and starts fresh with curre…
def save_baseline(self) -> None

Save current state as new baseline.

Clears history and starts fresh with current build as baseline. Useful after major changes or optimizations.

Internal Methods 3
__init__ 4
Initialize build delta analyzer.
def __init__(self, site: SiteLike | None = None, cache: BuildCache | None = None, root_path: Path | None = None, history: BuildHistory | None = None)
Parameters
Name Type Description
site

Site instance for current state

Default:None
cache

BuildCache for cache inspection

Default:None
root_path

Root path of the project

Default:None
history

Optional BuildHistory for trend analysis

Default:None
_get_current_snapshot 0 BuildSnapshot | None
Get snapshot of current build state. Creates snapshot from cache if available.
def _get_current_snapshot(self) -> BuildSnapshot | None

Get snapshot of current build state.

Creates snapshot from cache if available.

Returns
BuildSnapshot | None BuildSnapshot or None if no cache available.
_generate_recommendations 1 list[str]
Generate actionable recommendations based on analysis.
def _generate_recommendations(self, report: DebugReport) -> list[str]
Parameters
Name Type Description
report

Completed DebugReport with findings.

Returns
list[str] List of recommendation strings.