Every Bast* type drops <'a>: &'a str -> String, &'a Value -> Value
(deferred decision 1: plain String/Value — the tree is built once;
Arc<str> name-sharing needs a bench justification that doesn't exist).
BastDoc::new(&Value, &str) still takes references in and clones into
owned storage; the doc gains Clone. resolve_ref/resolve_typeref/
resolve_typeref_as_def return owned types.
- Engine ownership flip: AlkTypeEngine holds the owned BastDoc
(replacing bast_doc: Value + root_name: String; root_name()
delegates to the doc), killing its three per-call BastDoc::new
re-parses (aligned validate_bytes, read_field, write_field — the
review #004 M1 pattern removed by construction; phase 5 retires the
lookup_leaf_field walk itself). New public accessor root_name()
(additive). Engine Send + Sync with the owned doc, asserted in the
existing thread-share test.
- Bonus cleanup: materialize_typeref_packed's dead _field param
dropped (phase 2 left it dangling). Under ownership, keeping it
would force a deep Value clone per array element / record value /
union variant via dummy_field_for. The param, dummy_field_for, and
ty_source are gone; no behavior change (the arg was already
ignored). BastField::synthetic keeps an owned-signature
#[allow(dead_code)] definition (no remaining callers today).
- Consumers adapted: OffsetMap::compute(&BastDoc),
materialize_aligned(&BastDoc, ...) (no lifetime), BuildCtx/
ComputeCtx hold &'d BastDoc, tunion/discriminator name borrows,
lib.rs module doc. LayoutBuilder's doc_value re-parse cache is
unchanged pending phase 4.
Verification: 465 tests pass with zero test-logic changes (bast.rs
suites exercise every parser path through the public API); clippy
-D warnings clean; cargo doc zero warnings; wasm32 release build
green.
The compiled value-domain validation form: replaces the interpretive
BastDoc walk in validate_bytes with a compile-once-walk-many
constraint tree built at engine-compile time. This was the design
session + implementation ADR-012 §3 delegated; the shape decisions
are recorded in new ADR-012 §3a.
- New src/validation_plan.rs: ValidationPlan + ValidNode/ValidField/
ValidVariant (Debug+Clone+PartialEq+Eq+Hash+Send+Sync),
compile(&BastDoc) with eager $ref resolution, and a per-buffer walk
with deferred error-path rendering (zero happy-path allocation,
byte-identical error messages vs the 0.2.0 walker).
fingerprint() via DefaultHasher, same as the phase-6 pattern.
- Compile-time graph safety: definition-level cycle set + depth cap
(128) reject cyclic $ref graphs with AlkTypeError::Schema. The
interpretive walker resolved refs lazily with no guard (stack-
overflow hazard); diamond (shared) refs still compile.
- bast_validation.rs: interpretive walker retired (deleted);
validate_value survives as a one-shot wrapper (compile + validate)
for callers holding a doc without an engine.
- engine: Arc<ValidationPlan> built at compile in BOTH modes; the
plan compile runs before the layout build and doubles as the
engine's cyclic-ref gate (LayoutBuilder/OffsetMap struct recursion
has no cycle guard; a cyclic doc previously overflowed there).
validate_bytes walks the plan; new accessor validation_plan().
validate_bytes signature unchanged.
- lib.rs: pub mod validation_plan + re-exports (ValidationPlan,
ValidNode, ValidField, ValidVariant).
Verification: cargo test --release (355 pass, incl. parity suite,
fingerprint contract, cycle/depth rejection, Send+Sync + thread-share
assertions); clippy --all-targets -D warnings clean; cargo doc
zero warnings; wasm32-unknown-unknown release build green.
Co-authored-by: opencode <noreply@alk.dev>