- overview.md, core.md, emit.md, targets.md: modular spec set for the generalized engine (contexts + templates + partials -> text), with the three targets (ssr-html, bast-rust-codecs, call-handlers, wgsl-jit) as template sets plus emit postures - ADRs 001-010: one core/template-set split, handlebars 6.4 strict substrate, sync/wasm/deterministic posture, typed contexts with builders, per-registry escaper, SSR library posture, typed direct codecs output contract, template-set ownership, feature gating, library-only v1 - open-questions.md: OQ-01..OQ-08 centralized tracker carrying phase-0 residue (GN-01/02/07/09) with three deferred(scope) entries plus a resolved disposition for phase-0 OQ-GN-04 - tasks/architecture/: external-trigger tracker tasks paired with the deferred OQs (taskgraph validate passes) - phase-0.md checklist dispositioned for OQ-GN-04; AGENTS.md lifecycle updated to phase 1 Verification: taskgraph validate (4 tasks OK), cargo fmt --check, cargo test, em-dash grep clean; architecture-reviewer pass returned zero critical issues
3.6 KiB
3.6 KiB
ADR-007: BAST codec template set: typed direct codecs, zero-dependency output
Status
Accepted
Context
The reader POC (2026-09-08, re-validated on alktype 0.4.0 on 2026-11-06) answered the branch-1 output questions with executable evidence:
- A
Value-materializing generated reader runs ~1.9x faster than the alktype interpreter at identical output shape, and the decomposition showed the celebrated ~20x interpreter-vs-handwritten gap isValueallocation cost, not dispatch: hand-rolled code at the same output shape is only ~10 to 20% faster. - A second render with typed output (plain structs, direct cursor-based codecs) runs 291 to 322 ns: roughly 10x the Value shape and 15 to 20x the interpreter, within ~4x of the no-allocation hand-rolled floor (the residual is inherent String/Vec allocation).
- The typed direction was set at the 2026-09-08 debrief (russh-sftp protocol-type shape), leaving the (a) serde-derive vs (b) direct codec fork open. The debrief resolved it for (b) on speed, size, and wasm grounds: direct codecs are zero-dependency (no serde, no serde_json, no alktype in generated code), while serde-derive would reintroduce a serde dep and wrapper-heavy handling of BAST's per-field endianness and TUnion byte-discriminators.
Decision
The bast-rust-codecs template set emits typed direct codecs:
- Generated output is plain structs and enums with direct
decode/encodefunctions over a generated cursor core (fn decode(buf) -> Result<T, GenError>shape). NoValuematerialization, no serde machinery. - Generated code has zero dependencies; alktype appears only in the generator. Serde bridges (or a serde feature) may be added later if a consumer requires interop; starting dependency-free is the irreversible-safe direction (adding serde is additive, removing it is breaking).
- Generated code is self-contained (no alktype runtime calls) and
error-returning end to end: bounds checks, UTF-8 validation,
and union dispatch limits return typed errors, never panic
(reader POC finding F-2; AGENTS.md convention 2; alkcall accepts
BAST from arbitrary peers). The generated error type is
generated-code-local; its exact shape (mirroring
AlkTypeError::Access's variants without the alktype dependency) is a branch-1 detailed-spec decision constrained by this ADR. - Addressing is the uniform cursor model; compile-time
fixed_sizeand dispatch tables from plans are emitted as data, and constant cursor chains rely on LLVM folding rather than source offset algebra (finding F-1).
Consequences
- Positive: the success metric (recovering most of the ~20x gap at equal output contract) is achieved at the typed contract, with parity discipline proving semantic agreement byte-for-byte.
- Positive: zero-dep generated code keeps consumers light and the wasm story simple.
- Negative: no serde interop out of the box; consumers needing
serde-compatible output wait for a bridge feature (accepted trade recorded above). - Negative: generated-code error type duplicates alktype error semantics without alktype; parity and drift tests (three-way benchmark discipline) are the standing mitigation.
References
- targets.md (bast-rust-codecs)
- ADR-004 (contexts: plans for semantics, document for names)
docs/research/reader-poc-summary.md(executive summary, typed output resolution, follow-ups 1-4; phase-0 OQ-GN-05/06 resolutions)/workspace/russh-sftp/src/protocol/(typed-structure precedent)