recon_gen.common.handbook.l2ft_exceptions

L2FT Hygiene Exceptions parser — AA.C.4.

Reads src/recon_gen/docs/L2FT_Exceptions.md (the single source of truth for the six L2FT runtime checks) and returns a typed mapping of exception kind -> L2FTExceptionSection.

Mirrors common.handbook.invariants (which serves the L1 invariants doc + L1 dashboard panels). Two parser deltas from the L1 flavor:

  • L2FT exception headings are plain ### N. <Title> — no {{ l2_instance_name }}_<kind> Jinja prefix, because the kinds are check_type labels ("Chain Orphans" / "Unmatched Rail Name" / etc.) shipped in the L2FT dashboard’s unified-exceptions check_type column. Kind keys are slug-cased titles ("chain_orphans" / "unmatched_rail_name" / …).

  • No SHOULD-blockquote convention. L2FT exceptions are runtime checks against the L2 declaration, not L1 SHOULD-constraints — the leading prose paragraph is the “what this surfaces” description, no blockquote indirection.

The doc carries **Columns:** ... + **What to do:** ... lines in the same shape as L1_Invariants.md; the parser extracts them identically.

Functions

load_bundled_l2ft_exceptions()

Read the bundled L2FT_Exceptions.md from recon_gen.docs and return parsed sections.

panel_markdown(sections)

Compose the L2 Hygiene Exceptions sheet's bottom panel.

parse_l2ft_exceptions(md_text)

Walk the markdown source and yield one section per ``### N.

Classes

L2FTExceptionSection(kind, title, body, ...)

One parsed section from L2FT_Exceptions.md.

class recon_gen.common.handbook.l2ft_exceptions.L2FTExceptionSection(kind, title, body, columns, what_to_do)[source]

Bases: object

One parsed section from L2FT_Exceptions.md.

Same shape as common.handbook.invariants.InvariantSection minus short_statement — L2FT exceptions don’t use blockquote SHOULD-statements (they’re runtime checks against L2, not L1 invariants).

Parameters:
  • kind (str)

  • title (str)

  • body (str)

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

  • what_to_do (str)

body: str

Prose paragraphs after the heading. The **What to do:** ... line is extracted into what_to_do and dropped from body so the dashboard panel can render the remediation in its own styled block. The **Columns:** ... line stays inline.

columns: tuple[str, ...]

Parsed column names from the **Columns:** ... line. Empty tuple when the section doesn’t declare columns.

kind: str

Slug-cased section title — "chain_orphans" / "unmatched_rail_name" / etc. Joins to L2FT_EXCEPTION_KIND_TO_SHEET and to the L2FT unified dataset’s check_type literals (title-cased there: "Chain Orphans").

title: str

Human heading — "Chain Orphans" / "Unmatched Rail Name". Matches the unified L2 Exceptions dataset’s check_type literal exactly so a future renderer can cross-link a row to its panel description.

what_to_do: str

Remediation paragraph parsed from the **What to do:** ... line. One-paragraph guidance: what does a row in this check mean for the integrator, and what should they do about it. Empty string when the section omits the line.

recon_gen.common.handbook.l2ft_exceptions.load_bundled_l2ft_exceptions()[source]

Read the bundled L2FT_Exceptions.md from recon_gen.docs and return parsed sections.

Single call site for the dashboard-side consumer (AA.C.4 panel wiring) — it doesn’t need to know where the doc lives.

Return type:

dict[str, L2FTExceptionSection]

recon_gen.common.handbook.l2ft_exceptions.panel_markdown(sections)[source]

Compose the L2 Hygiene Exceptions sheet’s bottom panel.

L2FT’s six checks all roll up onto one sheet (the unified Hygiene Exceptions sheet), so unlike L1 — where each invariant kind has its own sheet + panel — L2FT gets one panel that lists all six kinds with their remediation guidance inline. Shape mirrors L1’s L1 Exceptions intro panel (AA.C.3.e).

Returns a markdown string suitable for rich_text.markdown(...).

Return type:

str

Parameters:

sections (dict[str, L2FTExceptionSection])

recon_gen.common.handbook.l2ft_exceptions.parse_l2ft_exceptions(md_text)[source]

Walk the markdown source and yield one section per ### N. <Title> heading. Returns {kind: L2FTExceptionSection}.

Return type:

dict[str, L2FTExceptionSection]

Parameters:

md_text (str)