v0.22.0 Phase 0 JSON Design Review
Result
Phase 0 is complete. The reviewed contract provides a strict owning RFC 8259 DOM, preserves JSON numbers without floating-point loss, rejects decoded duplicate names, and keeps parser and generator behavior in ordinary standard-library source. No compiler capability gap or unresolved public choice remains.
The review found one important implementation risk and closed it in the design before source was added: ordinary and recoverable APIs could otherwise grow separate parser/generator algorithms or distinguish failures by public error-code text. The implementation boundary now requires one recoverable core, private typed failure cases, and ordinary adapters that terminate only the allocation case.
RFC and Public Contract Review
The JSON specification chapter cites RFC 8259 and explicitly fixes areas in which conforming implementations vary:
- any JSON value may be the root;
- only the four RFC whitespace bytes are accepted;
- UTF-8 input is strict and a leading BOM is rejected;
- unpaired UTF-16 surrogates are rejected;
- object names are decoded before equality and duplicates are rejected;
- object order is not observable as a stable contract;
- exact number tokens have no implementation precision or range limit before requested conversion;
- generation uses one compact string spelling while retaining exact Number spelling.
These choices favor interoperable data and one observable behavior. No JSON5 extension, first/last-wins duplicate rule, host floating-point approximation, or private Map order leaks into the contract.
Authority Review
- JSON Values and Text solely owns public JSON semantics and API.
- Memory, Regions, and Allocators continues to own ordinary versus recoverable allocation and result provenance.
- Associative Collections continues to own Map equality, insertion, ownership, and unspecified iteration order.
- The JSON implementation boundary owns only responsibility direction and private authority constraints.
- The milestone owns work order; this review owns findings and evidence. Neither duplicates the public specification.
The compiler receives no JSON declaration registry, syntax kind, semantic query, MIR operation, runtime type, primitive, or target operation. Future tooling must consume the same ordinary declarations and checked bodies as every other standard module.
Representation and Ownership Review
Value recursion crosses Vec and Map owning storage. Those containers have finite source layouts containing pointers, buffers, lengths, and capacities rather than inline recursive Value fields. Existing specialized drop bodies destroy dynamic elements; JSON needs no recursive-layout escape hatch.
The parser design has one byte offset, one on-demand token decision, one explicit frame stack, and one completed-root slot. Frames own accepted children and pending object names. Closing transfers ownership forward; failure uses ordinary drop. This prevents the parser from needing a parallel token tree, initialized-slot bitmap, recovery count, or recursive call-stack ownership convention.
The generator design has one traversal and escaping engine. String and Writer adapters cannot select scalar spelling, container separators, Number output, or traversal order independently. The Writer path may publish a valid prefix before destination failure, as ordinary streaming I/O does, but no generator-owned partial value escapes.
Number and Unicode Review
Exact token storage avoids an unnecessary f64 prerequisite and makes round-trip generation lossless for every accepted magnitude and precision. Integer conversions operate on validated decimal components, return none on non-integral or out-of-range values, and never round.
JSON owns escape and surrogate syntax; the standard-internal UTF-8 owner encodes one validated Unicode scalar. This direction prevents an independent JSON UTF-8 implementation without forcing a public char type or changing String representation.
Allocation and Failure Review
Current and recoverable APIs share recoverable implementation cores. Private failure enums retain the distinction between input, allocation, and destination failure until the public wrapper applies its policy. No wrapper infers a class from error.code() text.
Nested recoverable results use the supplied allocator for Number, String, Vec, Map, parser-stack, and generator-stack storage. Existing buffer affinity owns later growth. Syntax errors remain recoverable for ordinary parsing, destination errors remain recoverable for ordinary writing, and ordinary allocation failure terminates.
Feasibility Evidence
The published v0.21.0 compiler accepted this representative owning shape and checked destruction of a nested array:
use std/map.Map
use std/string.String
use std/vec.Vec
enum Number { text(value: String) }
enum Value {
null
boolean(value: bool)
number(value: Number)
string(value: String)
array(value: Vec<Value>)
object(value: Map<String, Value>)
}
func main(): void {
var values: Vec<Value> = Vec.empty()
values.push(Value.null)
let nested = Value.array(move values)
drop nested
return
}
Command: dist/.nocter/nocter check --file <probe>.nct.
Source inspection confirmed the remaining requirements are expressible through current str, String, Vec, Map, TryAllocator, Writer, enum, pattern, move, and drop contracts. The review treated the specified u8.checked(u64) and u8.truncate(u64) surface as an existing numeric capability. Phase 1 implementation found that its standard body and target role were absent; the Phase 1 review records that correction. The two JSON-driven shared gaps remain the package-internal adapters assigned in the implementation boundary.
Phase 2 qualification found a second general gap outside JSON semantics. Recovery expressions did not pass an expected success-payload type into a direct generic call, although propagation expressions did. Consequently, result-only generic parameters could not be inferred under catch or otherwise. Phase 2 unified the recovery call-context path and added checker-level regression coverage. No JSON declaration or behavior entered the checker.
Evidence
- official RFC 8259 contract audit
- standalone recursive owning-model check with the published v0.21.0 compiler
node docs/build-docs.jscargo fmt --all --checkgit diff --check
All repository commands passed on 2026-08-31. No compiler source changed in Phase 0, so a workspace test was not required for this documentation and design checkpoint.