femic.rebuild_runner Module

The femic.rebuild_runner module owns FEMIC’s deterministic rebuild-step execution skeleton. It defines typed rebuild steps and outcomes, resolves a stable topological execution order, runs step actions with shared context, and can persist a machine-readable rebuild execution report through a pluggable sink.

If you are debugging why rebuild steps executed in a certain order, why a run stopped after a failure, or how step metadata/error payloads become the stored execution report, this is the first module to read. In practice it owns:

  • typed rebuild step/outcome/report payloads

  • deterministic topological ordering

  • stop-on-failure behavior

  • JSON report-sink persistence

Start Here If…

Use this page first if you are trying to:

  • understand the execution skeleton under femic instance rebuild

  • inspect dependency ordering or cycle detection behavior

  • debug report content independent of the higher-level CLI wrapper

Typical maintenance path:

  1. Start with RebuildRunner for execution-order and failure-flow questions.

  2. Read RebuildStep, StepOutcome, and RebuildExecutionReport for payload semantics.

  3. Inspect JsonRebuildReportSink if the issue is in report persistence.

Typical Usage

The common pattern is to construct a small ordered step graph and let the runner handle execution order and report generation:

from pathlib import Path
from femic.rebuild_runner import JsonRebuildReportSink, RebuildRunner, RebuildStep

runner = RebuildRunner(
    steps=[
        RebuildStep(step_id="validate_case", action=lambda ctx: {"validated": True}),
        RebuildStep(step_id="compile_upstream", action=lambda ctx: {}, depends_on=("validate_case",)),
    ],
    report_sink=JsonRebuildReportSink(path=Path("runtime/logs/rebuild_report.json")),
)
report = runner.run(run_id="docs_example")

How This Fits Into The Pipeline

This module sits beneath rebuild orchestration but above individual step actions:

  1. higher-level code converts a rebuild spec into concrete step actions

  2. this module resolves execution order and runs them deterministically

  3. downstream report consumers read the resulting execution report

That means this module owns the generic rebuild runner contract, not the meaning of specific rebuild steps or invariants.

Key Entry Surfaces

The highest-value entrypoints in this module are:

  • RebuildRunner

  • RebuildStep

  • StepOutcome

  • RebuildExecutionReport

  • JsonRebuildReportSink

Core Contracts

The most important runtime contracts in this module are:

  • step IDs must be unique and dependency edges must resolve

  • execution order is deterministic and topological

  • step metadata can augment shared runtime context for downstream steps

  • failures are captured as text payloads in outcomes and can optionally stop the run immediately

  • report sinks receive one normalized run-level report payload

Failure Seams To Watch

The common failure boundaries in this module are:

  • dependency graph mistakes duplicate IDs, unknown dependencies, or cycles fail before execution begins

  • context propagation surprises step metadata is merged into shared runtime context, so collisions can change downstream behavior

  • stop-on-failure expectations caller assumptions about continued execution after a failed step must match the configured runner mode

Cross-References

Guides and references that pair especially closely with this module:

Related API pages:

Reusable deterministic rebuild runner with JSON report sink support.

class femic.rebuild_runner.JsonRebuildReportSink(*, path)[source]

Bases: object

Write rebuild execution reports to JSON files.

Parameters:

path (Path)

write(report)[source]

Serialize a rebuild execution report to the configured JSON path.

Parameters:

report (RebuildExecutionReport)

Return type:

None

class femic.rebuild_runner.RebuildExecutionReport(run_id, started_at_utc, finished_at_utc, failed, planned_order, outcomes)[source]

Bases: object

Run-level report for a rebuild execution.

Parameters:
  • run_id (str)

  • started_at_utc (str)

  • finished_at_utc (str)

  • failed (bool)

  • planned_order (tuple[str, ...])

  • outcomes (tuple[StepOutcome, ...])

failed: bool
finished_at_utc: str
outcomes: tuple[StepOutcome, ...]
planned_order: tuple[str, ...]
run_id: str
started_at_utc: str
class femic.rebuild_runner.RebuildReportSink(*args, **kwargs)[source]

Bases: Protocol

Report sink protocol for rebuild execution artifacts.

write(report)[source]

Persist a rebuild report.

Parameters:

report (RebuildExecutionReport)

Return type:

None

class femic.rebuild_runner.RebuildRunner(*, steps, report_sink=None, now_fn=None, stop_on_failure=True)[source]

Bases: object

Execute rebuild steps in deterministic topological order.

Parameters:
  • steps (list[RebuildStep])

  • report_sink (RebuildReportSink | None)

  • now_fn (Callable[[], datetime] | None)

  • stop_on_failure (bool)

run(*, run_id, context=None)[source]

Execute configured steps, persist report if configured, and return it.

Parameters:
  • run_id (str)

  • context (dict[str, Any] | None)

Return type:

RebuildExecutionReport

class femic.rebuild_runner.RebuildStep(step_id, action, depends_on=())[source]

Bases: object

One step in a rebuild graph.

Parameters:
  • step_id (str)

  • action (Callable[[dict[str, Any]], Mapping[str, Any] | None])

  • depends_on (tuple[str, ...])

action: Callable[[dict[str, Any]], Mapping[str, Any] | None]
depends_on: tuple[str, ...] = ()
step_id: str
class femic.rebuild_runner.StepOutcome(step_id, status, started_at_utc, finished_at_utc, duration_seconds, metadata, error)[source]

Bases: object

Execution result for one rebuild step.

Parameters:
  • step_id (str)

  • status (str)

  • started_at_utc (str)

  • finished_at_utc (str)

  • duration_seconds (float)

  • metadata (dict[str, Any])

  • error (str | None)

duration_seconds: float
error: str | None
finished_at_utc: str
metadata: dict[str, Any]
started_at_utc: str
status: str
step_id: str