recon_gen.common.spine.rail_firing
Rail firing (broad-mode) family — ViolationGenerator only.
AY.2.b promotion of common/l2/seed.py::RailFiringPlant (M.4.2 broad-mode plant kind). This is a SEED-COLOR generator: it plants ONE Posted firing of an L2-declared Rail to populate the L2 Flow Tracing dashboard’s Rails / Chains / Transfer Templates sheets with visible content. No SHOULD violation — the L1 surface stays clean.
The OLD _emit_rail_firing_rows carries a lot of picker-layer sophistication (chain-completion via _emit_plant_chain_completion, transfer-key metadata cascade from containing TransferTemplates, per-leg-origin resolution table). The spine generator deliberately stays minimal — emit a clean firing on a single resolved rail. The picker layer (post-AY.4) composes multiple generators + handles chain-completion via a dedicated generator. Convergence path: per AY.0 “the spine generator can start simpler than the OLD path and converge over time; AY.5 re-locks byte seeds after the rewrite.”
Per the AY.2.b evidence-currency layering:
intended returns a CoverageObservation keyed on (rail_name, transfer_id, firing_seq) — the seed claims “I planted a firing of rail X.” No matching Invariant (the L2 Flow Tracing surface reads rail firings directly off <prefix>_transactions; no matview surfaces “this rail did fire” as a violation, that would be backwards).
Rail kind branches internally (TwoLegRail → 2 legs summing to zero; SingleLegRail → 1 leg in the rail’s declared leg_direction); the factory’s scenario_for_*_rail smart constructors resolve the rail kind from the L2 instance and pre-populate the right fields. The single generator class avoids fragmenting the AY.2.b surface across 4 new modules (one per rail-kind × generator).
Classes
|
Smart constructor namespace for RailFiringGenerator. |
|
Emit one Posted firing of an L2-declared Rail. |
- class recon_gen.common.spine.rail_firing.RailFiringFactory(prefix='spec_example')[source]
Bases:
objectSmart constructor namespace for RailFiringGenerator.
Mirrors the Invariant.scenario_for(…) pattern from the rest of the spine for surface parity. Picks a rail by name from the L2 instance + resolves its kind, then builds a generator with the right field shape.
- Parameters:
prefix (str)
- name: ClassVar[str] = 'rail_firing'
- prefix: str = 'spec_example'
- scenario_for_rail(rail_name, *, account_id_a=None, account_id_b=None, amount=100.0, firing_seq=1, anchor_day=datetime.date(2030, 1, 1), instance=None)[source]
Resolve rail_name to a Rail + build a generator that plants one firing.
Account fields default to synthetic per-rail strings when not supplied — matches the AY.0 minimal-viable shape. The picker layer (post-AY.4) threads real TemplateInstance / Account identifiers when the firing needs to land on a materialized account.
Raises ValueError if the rail isn’t declared on the L2 OR if account_id_b is None for a TwoLegRail (second leg required for two-leg rails).
- Return type:
- Parameters:
rail_name (str)
account_id_a (str | None)
account_id_b (str | None)
amount (float)
firing_seq (int)
anchor_day (date)
instance (L2Instance | None)
- class recon_gen.common.spine.rail_firing.RailFiringGenerator(rail_name, is_two_leg, account_id_a, account_id_b, amount, single_leg_direction, firing_seq, anchor_day, prefix='spec_example', metadata_extras=())[source]
Bases:
objectEmit one Posted firing of an L2-declared Rail.
TwoLegRail: 2 legs (debit on account_id_a for -amount + credit on account_id_b for +amount) sharing one transfer_id; net = 0.
SingleLegRail: 1 leg on account_id_a in the resolved single_leg_direction; net = ±amount (the L1 SQL surfaces this as ‘Imbalanced’ against the rail’s expected_net = 0 — accurate representation of a bare single-leg cycle without its sibling legs in the broad-mode picker context).
intended returns a CoverageObservation keyed on (rail_name, transfer_id, firing_seq). No matching Invariant (rail firings aren’t violations).
Account fields are caller-supplied (the factory provides deterministic synthetic defaults). The picker layer (post-AY.4) threads real TemplateInstance.account_id / Account.id values when the firing needs to land on a materialized account.
- Parameters:
rail_name (str)
is_two_leg (bool)
account_id_a (str)
account_id_b (str | None)
amount (float)
single_leg_direction (Literal['Debit', 'Credit'])
firing_seq (int)
anchor_day (date)
prefix (str)
metadata_extras (tuple[tuple[str, str], ...])
- account_id_a: str
- account_id_b: str | None
- amount: float
- anchor_day: date
- property claimed_accounts: frozenset[str]
union of the rail’s leg account_ids. Two firings of the same rail with different firing_seq target the same account_id_a → ScenarioContext rejects parallel firings of the same rail unless the picker varies accounts.
- Type:
AV.5 contract
- emit(conn, *, scenario_id=None)[source]
- Return type:
None- Parameters:
conn (SyncConnection)
scenario_id (str | None)
- firing_seq: int
- property intended: CoverageObservation
rail X fired once on the anchor day. Identity carries the natural-key tuple a coverage detector would round-trip against if/when one lands.
- Type:
Presence evidence
- is_two_leg: bool
- metadata_extras: tuple[tuple[str, str], ...] = ()
- prefix: str = 'spec_example'
- rail_name: str
- single_leg_direction: Literal['Debit', 'Credit']
- property transfer_id: str