sparkles:wired — Delivery plan
Companion to SPEC.md: the milestones that build the library to the specification. Each milestone is independently green (builds + tests + lints).
M1 — Specification
SPEC.md — the normative surface: the format concept (§3), the JSON backend and supported types (§4), the @Wire* policy and its resolution lattice (§5), case styles (§6), enum representation (§7), value transforms (§8), errors (§9), and the public API (§10). Every code block is a runnable example with a checked output; the implementation milestones make them pass under nix run .#ci -- --verify.
M2 — base text primitives (sparkles:base)
Format-agnostic, no policy:
sparkles.base.text.case_style—CaseStyle, the CTFE-compatibleconvertCase!style(ident)word-splitter, and its@nogcwriter formwriteConvertedCase!style(w, ident)(convertCaseis the allocating wrapper over it) (case-style spec; SPEC §6).sparkles.base.text.enums—enumMemberName!style(value)(value → cased member name, selecting a compile-time literal) andenumFromValue!E(v)(membership-checked value → enum, viaOriginalType).sparkles.base.text.readers/.writers—readEnumStringgains aCaseStyle;writeEnumMemberName/writeEnumValueoutput-range primitives.
Gate: dub test :base — convertCase runtime cases plus static assert CTFE coverage (incl. acronym/digit boundaries), writeConvertedCase into a SmallBuffer matching convertCase for every style (and a @nogc case), the enum primitives, and a non-integer-backed enum; plus nix run .#ci -- --verify --files docs/specs/base/text/case-style.md.
M3 — policy (sparkles.wired.policy)
AnyFormat, Repr, WireSkip, WireInvalid, WireMatch, the @Wire* UDA structs supporting the exact source forms from SPEC §5.1, and the per-axis resolvers implementing the precedence lattice (SPEC §5), plus the per-member / per-field name dispatchers and uniqueness checks.
M4 — JSON backend (sparkles.wired.json)
struct Json {}, toJSON / fromJSON / readJSONFile / writeJSONFile, the supported-type mapping (SPEC §4.2), and the enum / aggregate-field / AA-key wiring that consults the policy under the Json tag. Re-export the public surface from sparkles.wired (package.d). Optional!T support adds the optional package as a sparkles:wired dependency (with the matching dub.selections.json / nix/dub-lock.json entries).
Gate: dub test :wired — Expected-returning file helpers with final newlines, atomic writes (temp + rename) and recursive parent-directory creation, strict scalar kind/range checks, character-as-string mapping with fit/validity rejection (non-ASCII char, astral wchar, out-of-range dchar), static-array (T[N]) exact-length decode, UTC SysTime round-trips with offsetless-string rejection, per-axis and per-format resolution, explicit WireTarget.all defaults, field overrides reaching through composed wrapper chains (Nullable!(E[]), E[][], V[Mode][]) down to the first enum/aggregate on each branch, WireTarget.key / WireTarget.value branch selection (including aggregate and nullable/optional value-slot casing, and key-branch enums), directly-nested null-aware rejection, enum value/name collision rejection, aggregate field @WireName / @WireCase, required-field handling, @WireOptional decode-tolerance across WireInvalid.reject / useDefault plus WireSkip encode-omission (whenEmpty / whenDefault / never), aggregate key collision rejection, unsupported aggregate field/construction shapes, @WireConvert return-type inference and round-trips, SumType zero-match and ambiguity errors under WireMatch.exactlyOne plus WireMatch.first order-based selection, nothrow and Expected-returning converter failures, decode errors with nested path diagnostics including escaped object-key path segments, and nested-struct isolation.
M5 — docs & verification
The docs/libs/wired/ guide; the VitePress sidebar entry for this spec; and nix run .#ci -- --verify over SPEC.md and the guide.
Gate: every spec example runs and matches; npm run docs:build is clean.