babylon.engine.headless_runner.run_summary

Build summary.json — terminal aggregates + audit log + performance.

Spec: 064-headless-sim-runner (T026).

The summary follows contracts/summary_json_schema.yaml. Top-level keys:

  • schema_version — locked literal “1.0”

  • run_metadata — session id, exit reason, ticks, year, seed, scope

  • terminal_state — aggregates at the final completed tick

  • external_node_flows — per-external-node summed flow magnitudes

  • county_terminal_snapshot — per-county terminal state (delta-vs-init)

  • conservation_audit — projection of conservation_audit_log rows

  • performance — wallclock breakdown

  • end_game_event (optional) — present when exit_reason == early_terminated

  • error (optional) — present when exit_reason == errored

The builder is decoupled from Postgres: callers feed it pre-shaped inputs. Postgres-backed runs query the relevant views/tables and pass the rows in; unit tests pass synthetic fixtures.

Functions

aggregate_external_node_flows(*, pool, ...)

Spec-065 T057: aggregate boundary_flow_register rows per external node.

build_summary(*, config, session_id, ...[, ...])

Construct the summary payload as a plain dict.

babylon.engine.headless_runner.run_summary.aggregate_external_node_flows(*, pool, session_id)[source]

Spec-065 T057: aggregate boundary_flow_register rows per external node.

Reads the per-tick rows produced by BoundaryFlowRegister.flush() that the bridge persists each tick, and computes per-external-node cumulative summaries:

  • total_phi_inflow: SUM(magnitude) for flow_type='drain_edge'

  • total_trade_inbound: SUM for flow_type='trade_edge'

  • total_commute_outbound: SUM for flow_type='commute_out'

  • tick_count_with_inflow: distinct ticks with at least one row

Spec-101 review fix #5: the external node plays a DIFFERENT structural role depending on flow_typeDRAIN_EDGE/TRADE_EDGE put it on source_node_id (babylon.engine.systems.phi_distribution, babylon.engine.systems.vol2_circulation), while COMMUTE_OUT puts it on dest_node_id. A single GROUP BY dest_node_id (as this function used before the fix) is therefore WRONG for the only currently- live flow type: for DRAIN_EDGE rows dest_node_id is the receiving county FIPS, not the bloc — node_id in the returned rows was silently a county view, contradicting this function’s own name and ADR055/proof.md’s “per external node” framing. The corrected query picks whichever side carries kind='external' per row, so the aggregation is genuinely per-bloc for every flow type (current and future).

Returns one entry per external node id present in the register. Empty list when the engine has not yet integrated boundary flows.

Return type:

list[dict[str, Any]]

Parameters:
babylon.engine.headless_runner.run_summary.build_summary(*, config, session_id, exit_reason, ticks_completed, wallclock_start, wallclock_end, terminal_state, external_node_flows, county_terminal_snapshot, conservation_audit, performance, end_game_event=None, error=None)[source]

Construct the summary payload as a plain dict.

Parameters:
  • config (SimulationRunConfig) – The driving SimulationRunConfig.

  • session_id (str) – UUID string for this run.

  • exit_reason (ExitReason) – How the run terminated.

  • ticks_completed (int) – Number of fully-persisted ticks (≤ config.ticks).

  • wallclock_start (datetime) – Run start time (UTC).

  • wallclock_end (datetime) – Run end time (UTC).

  • terminal_state (dict[str, Any]) – Aggregates at the final completed tick (counties_alive, total_population, total_v/c/s/k, mean ideology axes, etc.).

  • external_node_flows (list[dict[str, Any]]) – One entry per external node (canada, china, rest_of_usa) with summed inflows/outflows.

  • county_terminal_snapshot (list[dict[str, Any]]) – Per-county terminal row + delta-vs-initial.

  • conservation_audit (list[AuditEntry]) – Conservation-invariant violations from spec-062.

  • performance (PerformanceBreakdown) – Wallclock attribution model.

  • end_game_event (dict[str, Any] | None) – Present iff exit_reason == EARLY_TERMINATED.

  • error (dict[str, Any] | None) – Present iff exit_reason == ERRORED.

Return type:

dict[str, Any]

Returns:

Dict ready to be JSON-encoded as summary.json.