v0.22.0 Phase 3 Shared Generator Review
Outcome
Phase 3 is complete. One non-recursive traversal, one string-escaping authority, and one byte-sink boundary implement all four public generation operations. No unresolved correctness or responsibility-boundary finding remains in the reviewed scope. Phase 4 practical integration is next.
Authority and Responsibility Review
The generator owns JSON traversal order, punctuation, exact Number emission, and member-name and string escaping. StringSink owns only validated String append; WriterSink owns only Writer forwarding. Adding another destination therefore cannot copy or override JSON spelling.
GenerationFrame is the sole suspended traversal representation. It stores a borrowed Value, or a borrowed Vec/Map plus the next semantic ordinal. The frame stack owns no JSON child and needs no cleanup bitmap, recursion limit, or recovery-side ownership table. Ordinary Vec destruction drops the stack on every exit.
Map and the private table own semantic ordinal projection. JSON consumes only MapEntryRef and cannot observe buckets, hash seeds, capacities, dense storage fields, or placement decisions. The projection has package visibility because it exists for suspended standard-library traversal, not as a new user-facing Map operation.
The generator reports a typed private result with complete, destination-failure, and traversal-allocation cases. Public wrappers apply policy once. They do not infer private classes from error codes, repeat traversal, or inspect an allocator representation.
Findings Resolved During Implementation
A movable iterator could not safely retain its own element loan
The first object and array frame design stored an iterator, called next, then attempted to move that iterator into a resumed frame while the returned child reference remained live. The checker correctly rejected the self-dependent state. The final design stores the source container and an ordinal separately. Child references now borrow the container, while the ordinal is freely copied.
Arbitrary byte batching could split a valid UTF-8 scalar
The first fixed buffer flushed at an arbitrary 16-byte boundary. Writer output remained valid as a complete stream, but String append validates every supplied chunk and could reject a multibyte scalar split between chunks. The escaping authority now determines UTF-8 scalar width and flushes before the complete scalar when capacity is insufficient. Native coverage fixes a multibyte scalar at that exact boundary.
Emission carried an impossible allocation branch
The initial token helper returned the complete generator result, forcing every punctuation site to handle traversal allocation even though emission cannot allocate the frame stack. It now returns only void!; the traversal boundary classifies sink failure, and stack operations classify allocation failure. This removes repeated impossible cases without weakening failure policy.
Execution and Tooling Evidence
Standard-module native tests cover scalar tokens, exact Number spelling, every control-escape class, quotation and reverse-solidus escaping, unescaped solidus, direct Unicode, the multibyte buffer boundary, nested and deep arrays, all object entries, recoverable output allocation, and storage surviving a different current region.
An external package implements the public Writer contract and proves complete write, explicit allocator try_write, unchanged destination errors, and observable partial output. This avoids a test-only Writer implementation in the standard JSON contract.
Language-server qualification hovers the public stringify contract from ordinary user source and rejects leakage of GenerationFrame, GenerationAttempt, ByteSink, or StringSink. Discovery's reviewed standard dependency graph includes the new output boundary exactly.
Residual Scope
Object order remains intentionally unspecified. Generation does not provide pretty printing, canonical sorting, floating-point conversion, streaming input, or generic serialization. Phase 4 will add application and complete editor/documentation integration without changing this generator authority.