Rust Phase 5 plotter and text exit audit

Status: accepted after independent producer, contract, and gate review. Phase 5 is complete and its producer-specific strict a0 unions are frozen. This audit compares the established Python Plotter-IR producers with the native Rust producers and turns every remaining required family into a bounded slice. Phase 4 already closed the governed native netlist and compiled-schematic-graph work; this audit does not reopen those accepted boundaries. Native Windows kicad-cruncher remains Phase 6.

Audit boundary

The parity authority is the behavior actually emitted by footprint_to_ir, lib_symbol_to_ir, pcb_to_ir, and schematic_to_ir. Source-model carriers that those Python producers intentionally ignore do not become implicit Phase 5 requirements. Each promoted Rust producer must preserve Python category and operation order, generated-contract semantics, numeric rounding, resource failure before publication, and the package's transport-neutral core boundary. ADR-011 does not require a new WASM export for any of these native slices.

Current closure and gaps

ProducerNative stateRemaining exact Python surface
Text engine Shaping, hinted outlines, curve flattening, layout, markup, topology, typed cache I/O, and focused live KiCad save-oracle cases exist. No retained Phase 5 gap remains. Plotter carriers use bounded, caller-supplied font/cache resources; font discovery remains outside the transport-neutral core.
Standalone footprint Metadata, non-text graphics, patterned strokes, standard pads, drills, polygon custom pads, and chamfered pads exist. No retained standalone-footprint Plotter-IR gap remains in the Phase 5 bounded inventory.
Library symbol Header metadata, inherited body geometry, fill/deferred-outline order, pin shafts, and pin decorations exist. No retained library-symbol Plotter-IR gap remains in the Phase 5 bounded inventory.
Board Graphics, board text/text boxes and table cells with authored or caller-supplied native generated caches and outline wrapping, routing, vias, tables, all five dimension styles, authored zone fills, variables, net-class extras, and terminal embedded-footprint records with typed child and pad-block ownership exist. No retained board Plotter-IR gap remains in the Phase 5 bounded inventory.
Schematic Typed source bundles, hierarchy, connectivity, owned writeback, compiled graph, and netlist foundations exist. The native Plotter-IR producer now covers the sheet header, default or caller-supplied worksheet drawing, wires, buses, entries, junctions, no-connects, labels and decorations, netclass flags, text, text boxes, graphics, rule areas, PNG/JPEG/BMP images, tables, and placed symbol instances with pins, visible fields, DNP markers, transforms, and overlap overplots, and hierarchical sheets with typed pins, visible fields, DNP markers, and terminal ordering under a distinct strict schematic contract. No retained schematic Plotter-IR gap remains in the Phase 5 bounded inventory.

Schematic closure preserves this exact Python record order: sheet header; wires, buses, bus entries, junctions, and no-connects; local, global, and hierarchical labels; netclass flags; text and text boxes; polyline, arc, circle, rectangle, Bézier, rule area, image, and table records; all placed symbols followed by overlap records; then hierarchical sheets.

Bounded implementation sequence

  1. P5_010 carrier text bridge. Define a caller-supplied, bounded font/cache sidecar over the accepted native render-cache engine. Close missing, stale, matching, multiline, markup, style, and font selection behavior without platform discovery in core, including the existing board text, text-box, and table carriers. Implemented, independently reviewed, and closed.
  2. P5_020 standalone footprint text. Add property, fp_text, and fp_text_box source selection and standalone decoding to FootprintView, then add their emission to the existing footprint record and generated contract. Board-nested footprint child models are not reused as standalone ownership types. Implemented, independently reviewed, and closed.
  3. P5_030 library-symbol text. Add body text and pin labels to the existing symbol record while preserving body-fill, text, pin, and deferred-outline ordering. Implemented, independently reviewed, and closed with exact Python vectors, bounded exact-case variables, strict generated contracts, native/host/real-WASM coverage, and L1_027 ownership.
  4. P5_040 board dimensions. Promote aligned, orthogonal, radial, leader, and center dimension geometry plus stroke and outline-font text records between tables and zones. Implemented, independently reviewed, and closed with exact Python vectors, bounded Newstroke markup and cache projection, strict generated contracts, and native/host/real-WASM coverage.
  5. P5_050 embedded board footprints. Reuse the promoted footprint operations under board-local record metadata and placement, preserving Python child metadata and board record order. Implemented, independently reviewed, and closed with exact Python vectors, bounded ownership and cache resources, strict block semantics, and native/host contract evidence.
  6. P5_060 schematic foundation. Establish the native schematic document/record contract and promote canvas metadata, the sheet header with default/project worksheet drawing, wires, buses, entries, junctions, and no-connects. Project variables and optional worksheet bytes are caller-supplied bounded sidecars; core performs no path discovery. Implemented, independently reviewed, and closed with exact Python vectors, strict generated contracts, aggregate resource ceilings, and a native-first Rack gate.
  7. P5_061 schematic annotations. Promote local, global, and hierarchical labels and decorations, netclass flags, ordinary text, and text boxes with project/built-in variables and drawing settings. Implemented, independently reviewed, and closed with exact hermetic Python vectors, deterministic caller-supplied font metrics, strict generated contracts, checked resource ceilings, and the native-first L1_036 gate.
  8. P5_062 schematic graphics. Promote polylines, arcs, circles, rectangles, Béziers, rule areas, decoded images, and tables. Implemented, independently reviewed, and closed with exact hermetic Python vectors, strict PNG/JPEG/BMP decoding, shared deterministic table metrics, generated contracts, resource ceilings, and the native-first L1_036 gate.
  9. P5_070 schematic symbols. Reuse symbol geometry and text for placed symbols, pins, fields, DNP behavior, transforms, and overlap overplots with occurrence-aware variables. Implemented, independently reviewed, and closed with exact hermetic Python vectors, typed pin ownership blocks, deterministic caller-supplied font metrics, strict generated contracts, checked symbol/library/overlap resource ceilings, and the native-first L1_036 gate.
  10. P5_071 hierarchical sheets. Promote sheet background and border passes, sheet pins and decorations, fields, DNP markers, and sheet metadata. Implemented, independently reviewed, and closed with exact hermetic Python vectors over all nine pin shapes, zero-width authored strokes, deterministic caller-supplied font metrics, strict generated contracts, checked sheet/property/pin and aggregate resource ceilings, and the native-first L1_036 gate.
  11. P5_080 Phase 5 exit. Rack L3_022 is the mandatory cross-producer gate over the final footprint, symbol, board, and schematic vectors; native resource and semantic mutation suites; package-local authoritative input/ footprint, symbol, board, and schematic corpus files; Cargo quality; and required live KiCad cache and plot acceptance. The gate fails rather than skips when the corpus, declared fonts, or required PCB/schematic KiCad CLI capabilities are absent. Implemented, independently reviewed, and closed with an immutable 12-schema/seven-union freeze ledger, exact cross-producer vectors, bounded native semantic/resource suites, live KiCad 10.0.5 acceptance, and the mandatory Windows L3_022 bot and publication gate.

Dependencies and exclusions

P5_010 precedes faced board dimensions, embedded footprint outline text, and schematic outline-font carriers. P5_020 and P5_030 can proceed from the existing source readers while the bridge is reviewed. P5_050 depends on both P5_010 and P5_020. P5_061 and P5_062 depend on the P5_060 document contract. P5_070 depends on P5_030 and P5_060; P5_071 depends on P5_060 and P5_061. P5_080 depends on every preceding slice.

The optional synthetic knockout fallback remains under the accepted geometry.planar_kernel_bridge deferral. Authored cached knockout behavior is already native. Zone refill, analytic polygon operations, ignored PCB groups/generated objects/images/barcodes, ignored standalone footprint constructs, downstream pcb_a0, application reports, and speculative WASM packaging remain outside this phase. Any future Python producer expansion must add a parity-ledger row before it can widen this exit gate.

Corpus evidence has two deliberately separate strengths. Exact producer parity is frozen by the checked-in vectors and four selected strict manifest cases. The complete 264-file footprint, symbol, board, and schematic corpus partition proves bounded S-expression source acceptance, not arbitrary producer-document parity. In particular, the Python authority for the official multi-subsymbol Device__R carrier restarts operation indexes per subsymbol record and therefore does not satisfy the strict document-global index contract; the governed exact symbol case is Connector_Generic__Conn_02x05_Odd_Even.

Contract compatibility during incubation

The generic kicad.plotter_ir.a0 schema remains the stable, forward-compatible consumer contract: it accepts unknown operation kinds and additional record fields. The strict generated footprint, symbol, and board schemas are producer-operation contracts in an unpublished incubation workspace. P5_020 through P5_071 may add record or operation union arms to those strict a0 schemas before the Phase 5 freeze only when all generated Rust, Python, and TypeScript clients regenerate atomically in the same slice. An older strict generated client is not compatible with a newer incubating document and must negotiate the operation contract or consume the generic schema instead.

P5_060 creates a distinct strict SchematicPlotDocumentA0 identity; it does not reuse the board document identity. P5_080 has frozen the producer-specific a0 unions through tests/parity/plotter_ir_phase5_freeze.json. A new record/operation union arm now requires a new producer-specific contract version or a separately reviewed tolerant envelope; regeneration alone is not a compatibility decision.

Evidence and runtime policy

Each slice owns a focused native suite and a shared Python-generated vector. P5_010 updates Rack L1_035 for carrier integration and L2_009 for live cache generation. P5_020 updates L1_026, P5_030 updates L1_027, and P5_040/P5_050 update L1_035. P5_060 creates L1_036, which P5_061, P5_062, P5_070, and P5_071 extend with their ordered schematic families. These Rack identifiers are the accepted slice owners. A row moves from planned to review_ready only after its Rack owner, executable vector, implementation evidence, and semantic/resource tests exist. Contract changes require TypeSpec regeneration checks and semantic mutation tests.

Carrier limits preserve every independent text-engine budget: font and decoded-text bytes, font slots/hashes, lines and runs, feature inspections and applications, cloned run metadata, glyphs, outline commands, Bézier work and scratch points, contours, topology work, cache polygons/points, operations, retained output points, and serialized output. Schematic inputs additionally bound worksheet items/repeats/bitmap bytes and image encoded bytes, decoded bytes, dimensions, pixels, and decode work. Placed-symbol inputs independently bound instances, overplots, properties, pins, embedded library symbols/subsymbols/pins, and pairwise overlap checks. Per-payload byte bounds precede decoding; aggregate counters and derived geometry are validated before retained operations are published.

Focused Rack owners must record warm runtime and keep their default slice gate under two minutes. L3_022 accepts producer and deterministic corpus-partition selectors for diagnostics, but the required Windows bot runs all producers and partitions serially so Cargo, live KiCad, and corpus setup are not duplicated. The cold bot job has a 120-minute ceiling. A run that exceeds that limit must reduce duplicate oracle work or record and review a new measured budget before promotion. Broad corpus and live KiCad work belongs in the final exit run unless a slice changes its authority boundary. Every slice is independently reviewed, logged through the development-standard plan, and committed before the next slice begins. The 2026-08-17 warm P5_040 L1_035 run completed four tests in 27.93 seconds after the native dimension suite was added to the focused Rack gate.

The 2026-08-17 warm P5_060 L1_036 run completed all four tests in 7.73 seconds (8.44 seconds including Rack signoff), below the two-minute slice policy.

The 2026-08-17 warm P5_061 L1_036 run completed all four tests in 1.81 seconds (2.54 seconds including Rack signoff), below the two-minute slice policy.

The 2026-08-17 warm P5_062 L1_036 run completed all four tests in 2.74 seconds (3.51 seconds including Rack signoff), below the two-minute slice policy.

The 2026-08-17 warm P5_070 L1_036 run completed all four tests in 4.32 seconds (5.06 seconds including Rack signoff), below the two-minute slice policy.

The 2026-08-17 warm P5_071 L1_036 run completed all four tests in 8.45 seconds (9.27 seconds including Rack signoff), below the two-minute slice policy.

The 2026-08-17 warm Phase 5 exit L3_022 run completed all seven mandatory tests in 120.26 seconds (121.75 seconds including Rack signoff). It covered 30 exact producer vectors with 771 operations, all selected native semantic/resource suites, the 12-schema/seven-union freeze, full Cargo quality and isolated WASM feature checks, 264 deterministically partitioned corpus inputs, live PCB and schematic SVG export, and native/live cache parity.