Status: accepted native product slice.
SchematicDocument owns one exact UTF-8 schematic source and
its resource limits. It does not retain a generic S-expression tree or a
self-referential typed model. definition() rebuilds the
promoted typed schematic model on demand, while writes patch exact source
ranges and reparse the complete promoted model before committing.
The combined parse_named_with_definition and
from_named_reader_with_definition constructors additionally
return the owned typed definition validated during the same bounded source
admission. Existing constructors delegate to this path and discard the
snapshot. The snapshot cannot observe later document edits; callers use
definition() when they need a fresh post-mutation model.
This establishes native schematic writeback without claiming a
canonical pretty-printer. Unrecognized top-level and nested KiCad forms
remain byte-for-byte unchanged. The first promoted mutations address a
placed symbol by its nonempty UUID and create, update, or remove an
unambiguous property. Missing identities and duplicate UUID/property
matches fail closed. An absent removal and a repeated write are stable
no-ops. A newly created property includes KiCad's required three-value
(at 0 0 0) placement child; the zero placement is the
deterministic default until a caller-facing placement operation is
promoted.
Reader admission consumes at most max_source_bytes + 1 and
reports named UTF-8 and I/O failures. Every write checks
max_output_bytes before cloning or publishing source. Property
insertion respects the existing per-symbol property ceiling; scalar
decoding remains bounded by the schematic parser limit. Candidate output
is fully parsed before replacing the owned source, so failed edits leave
the document unchanged.
The mutation index performs one structural source scan and one source-ordered pass over selected placed-symbol, UUID, and property spans. Child ownership is assigned to the latest enclosing direct symbol, avoiding carrier-by-child rescans. Property/UUID lookup is linear in the selected source footprint. The crate continues to forbid unsafe code and adds no dependency.
Rack case L1_032 requires all eight package-local schematic references. The native gate performs two complete promoted semantic decodes per file, compares the typed definitions, and proves exact first and stable second owned writes across 4,206,216 source bytes. Focused Rust tests cover transactional create/update/remove behavior, unknown-form preservation, escaped values, CRLF and one-line insertion, ambiguity, source/property/ output limits, and named UTF-8/I/O diagnostics.
The mutation gate independently parses the emitted property structure
and reads it through the Python schematic model. That Python acceptance is
mandatory. When a schematic-capable kicad-cli is resolvable,
L1_032 also exports a netlist from the mutated schematic; this is optional
ongoing application coverage, while the accepted Phase 4 exit run recorded
KiCad 10 acceptance of the evidence file.
Broader schematic carrier mutation remains outside this focused property writer. Symbol-library, worksheet, project, compiler, and graph obligations are covered by the accepted Phase 4 exit under separate governed surfaces; native Cruncher and packaging behavior are governed by later accepted phases.