# PM-77 LDraw corpus testkit `polymodel-ldraw-testkit` is the dependency-light, target-safe contract for PM-86 parser and renderer work. It embeds authored fixture bytes and v1 expected records at compile time. It does not access the filesystem, network, process APIs, archives, or parser/renderer crates, so E can consume `CorpusGate` and `CorpusGateSet` in a wasm-compatible adapter. ## v1 contract `CanonicalRecord` contains syntax, semantic, and scene records, ordered diagnostics, raw tails/spans, normalized path identities, explicit numeric strings, and provenance links. Serialization uses serde's declaration order and is repeatable. Compatibility changes require a schema-version migration; upstream observations are never normative without a row in `compatibility-ledger.json`. The ten named gate families are exported in `GATE_NAMES`, and each gate is profile-scoped (`strict`, `compatibility`, `lossless`). `validate_inventory` checks unique IDs/paths, exact-byte SHA-256, complete attribution, and expected/provenance links. `CorpusGateSet` rejects duplicate names, missing profiles, missing required gates, and fixtures with no applicable gate. ## Authoring/review workflow 1. Add a minimized exact-byte fixture under `corpus/` with a behavior name. 2. Add an independently derived expected record and provenance (source URL/revision, SHA-256, license, original identity, modifications, and authority). 3. Add a matrix row and a gate tag; include happy, error, boundary, and adversarial cases where the profile permits it. 4. H/PM-81 owns the hand-computed `h-conditional-*` vectors and six classifier outcomes; D owns fixture schema/version and metadata only. 5. D owns semantic limits and limit+1 vectors; reservation arithmetic belongs to B/PM-88. 6. Run `just ldraw-corpus`, `just ldraw-wasm-check`, and `just ldraw-fuzz-smoke` before review. LDParse is isolated in `tools/ldraw-compat-harness` as an out-of-process observation adapter. Its exact PM-75 revisions, CPython 3.12.8 requirement, and offline lock/setup policy are documented there. The required minimum surface is fixed; unsupported features are named ledger rows rather than silently claimed coverage.