main
22
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
bb28ba3006 |
Resolve N3: maxLength is string/bytes-only (review #006)
- Parse gate in BastField::parse: maxLength on any kind other than
string/bytes is a clean Schema error (records, arrays, inline
structs, refs, union shared fields all covered; the choke point
needs no ref-following since $defs entries are struct/union/enum)
- Meta-schema FieldDef: if kind in {string, bytes} else maxLength
forbidden — the published alk.dev/bast/v1 contract matches the
parser (N2 dual-layer pattern)
- M5's compute-side record maxLength arm became unreachable and was
deleted (offset-indirect arm stays); the two superseded M5
maxLength tests rewritten as the n3_* parse-rejection family
- ADR-006 remedy message tailored per kind: for records both
annotated remedies are dead ends, so the error text points at the
last-position fix only
- Docs aligned: bast-format.md (FieldDef meta-schema + FieldDef/
Variable-Length Encoding prose), layout-engine.md (Strategy 2 +
ADR-006 paragraph), schema-layer.md, ADR-003 §2/§3a amended,
builder .max_length() doc
- Review #006: N3 resolved (all findings now closed), M5 update
note, test-count bookkeeping note (in-session probes vs static
counts), status lines flipped to fully resolved
Verified: 547 tests green + 2 ignored doctests in BOTH release and
default profiles (a stale debug artifact from an earlier session
masked one H3 roundtrip test in debug; clean rebuild passes both),
clippy -D warnings clean, cargo doc --no-deps zero warnings, wasm
build green.
|
||
|
|
5e74b991ac |
Fix H2: shared reference-graph guard for standalone walkers (review #006)
Cyclic or over-deep $ref graphs stack-overflowed the three standalone schema walkers (OffsetMap::compute, LayoutBuilder::new, materialize_aligned) — SIGABRT on probe, parity-preserved from 0.2.0. - New src/walk_guard.rs: check_ref_graph() — one bounded walk over the reachable reference graph (depth cap 128 matching the plan compilers, path-scoped cycle set; diamonds allowed, cycles and 201-def chains rejected with the plan compilers' error wording) - All three walkers run the guard at entry, before any recursion; materialize_aligned's is defense-in-depth (a cyclic doc can no longer produce an OffsetMap, but mismatched doc/map inputs must still fail cleanly) - Behavioral side effect, net-positive: the guard eagerly parses every reachable def, so an invalid non-root def now surfaces at LayoutBuilder::new instead of build() — four H3 tests updated to expect the same Schema error earlier - Test family: 12 new tests (walk_guard, offset_map, layout_builder, materialize) covering self/two-def/composite-carrier cycles, deep chains, and diamond non-rejection; no stack-overflow reproducers in-tree per the review's Methodology warning - Stale "walkers have no cycle guard" statements updated in validation.md, 030 plan, ADR-012, and the engine gate comment Verified: 501 tests green (423 + 17 + 34 + 15 + 12 + 2 ignored), clippy -D warnings clean, wasm32 build green, cargo doc zero warnings. |
||
|
|
05a2a42983 |
Fix H3: field-disc union wire convention — shared-then-variant (review #006)
Decision (recorded as an ADR-011 addendum): the packed-mode wire layout for a field-name-discriminator TUnion is shared-then-variant — the union's declared `fields` (disc + shared fields) first, then the variant's own fields. Reader and materializer already implemented this; LayoutBuilder was corrected from variant-only layout. Enforcement in BastUnion::parse (the choke point every consumer inherits — union roots at BastDoc::new, referenced unions at resolve_ref): - discriminator field must be declared in `fields` - `fields` must not contain duplicate names - variants must not re-declare shared fields (checked inline and through $ref resolution — parse chain now threads the doc root) - the discriminator field must be the FIRST entry in `fields` (the reader reads the disc at the union start; a later position made it dispatch on the wrong bytes — H3 item 2, probe-verified) Schemas relying on the old variant-only builder convention (variants re-declaring shared fields) are rejected with a clean Schema error naming the convention. Breaking for 0.2.0-era re-declaring schemas; announced with 0.3.x. - L5: FieldValue::Union::variant_start doc now states per-kind semantics (byte-disc: union_start + disc.offset + disc.size; field-disc: after the shared walk). - L6: roundtrip test added (poc_roundtrip.rs) — LayoutBuilder write → SequentialReader read → materialize_packed → validate_bytes over a field-disc union with a second shared field and non-redeclaring variant; pins event.type@0/seq@1/handle@5, total 10. - ADR-011: Status-block addendum recording the convention decision, the no-re-declare rule, and the breaking-constraint note. - Review #006 updated: H3/L5/L6 resolution blocks, resolution log, recommended order. Verified: 488 tests green (410+17+34+15+12, 2 pre-existing ignored), clippy -D warnings clean, wasm32 build green, cargo doc zero warnings. |
||
|
|
9949f914df |
Release v0.3.0: compiled forms — ReadPlan, owned BastDoc, LeafMeta, ValidationPlan, fingerprinting
Public API bump 0.2.0 -> 0.3.0 (the 030-compiled-forms plan is now fully implemented; all eight phases landed). - Cargo.toml: version 0.3.0. lib.rs re-exports complete (ReadPlan + sub-types, LeafMeta, OffsetEntry, ValidationPlan + sub-types). - ADR-007 "Cost" rewritten to the Arc<ReadPlan> cost (15.7 ns) with the 0.2.0 "re-parse on demand" framing as a historical note (review #004 L2, the last loose end from that review). - ADR-011/012 status blocks flipped to implemented; architecture README ADR table rows updated; layout-engine.md rewritten for the 0.3.0 surface (engine-factory reader construction, OffsetMap OffsetEntry/LeafMeta/fingerprint section, owned BastDoc compute signature); SequentialReader module doc points at the engine factory. Reviews #004 and #005 flipped to closed. - Bench re-run (alktty wire_vs_bast, 0.3.0 tree): read p64 98 ns/chunk (parity with phase 2; hand-rolled 5.7 us/stream), layout_build 180 ns (was ~1.2 us — the phase-4 owned-doc cache removed the per-build re-parse, ~7x), sequential_reader_new 15.7 ns, write p64 -3%, engine_compile unchanged (meta-schema validation dominates). No dedicated validate_bytes-stream bench: the phase-7 spot check (~0.2 us plan-validate vs ~0.6 us compile-per-call) stands; a dedicated bench is a follow-up if alkcall profiling motivates it. - Downstream: alktty compiles against the path dep unchanged; alkcall has no dependency yet. Verification (full block, all green): 474 tests; clippy -D warnings clean; cargo doc zero warnings; wasm32 release build green; cargo publish --dry-run clean at 0.3.0. |
||
|
|
e4636e6a44 |
Implement ValidationPlan (ADR-012 §3, plan phase 7)
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> |
||
|
|
e461f01c97 |
Resolve review #005: refine 0.3.0 plan + ADR-011/012
Resolve all 11 findings from the 0.3.0 plan review (#005) in one docs-only pass. No source changes; the crate still builds/tests at v0.2.0. The one substantive decision change is M3 (per user direction: ship ValidationPlan in 0.3.0, no more hedging); the rest are spec corrections or pre-implementation refinements to types that do not yet exist on main. - H1: refine ADR-011 CompositePlan::Union to carry shared: Option<Box<ReadPlan>> (field-disc shared fields) and variants: Vec<(String, CompositePlan)> (drop VariantPlan/ VariantKind). Plan phase 1 implements the refined shape. - H2: plan phase 2 specifies ReadPlan stores schema: Arc<Value> (not &Value), avoiding the self-referential struct ADR-011 rejects. Verified serde_json::Value: Hash + Eq holds with preserve_order, so phase 6 derives are not blocked. - M1: nested-union support falls out of the H1 shape refinement (a variant can be CompositePlan::Union) — option (a) from the review, no behavioral drop vs 0.2.0, no Semver regression row. - M2: plan phase 5 adds an explicit first sub-step to derive Hash on Endian and VariableEncoding in src/schema.rs (additive, semver-safe prerequisite the original plan omitted). - M3: reverse the ValidationPlan deferral. ADR-012's "Deferring ValidationPlan" becomes "ValidationPlan — in scope for 0.3.0"; new ADR-012 §3 commits the decision (compiled form, no per-buffer BastDoc walk, Hash + Eq + fingerprint()) and defers only the concrete shape to a follow-on design session + the plan's new phase 7. Plan gains phase 7 (ValidationPlan); old phase 7 (bump) renumbered to phase 8. ADR-011's Out-of-scope and Scope Boundaries bullets updated to point at ADR-012 §3. The deferral black hole this review's methodology flagged is closed: the work is committed with a concrete reactivation trigger, not hedged into an unplanned future. - L1: plan phase 2 corrects the dummy_field_for/ty_source removal claim — only packed-side call sites go away; the helpers stay for the aligned materialize_leaf_at path. - L2: plan phase 2 states the packed-vs-aligned materialize_typeref_packed split (packed gets a new plan-walking function; the existing function stays for aligned). - L3: plan phase 5 adds a Scope Boundary note — aligned materialize's BastDoc structure walk is the permanent 0.3.0 design; an AlignedPlan is out of scope, tracked as an OQ. - N1: fix "back-comat" -> "back-compat" typo. - N2: plan phase 1 verification adds the read_plan_is_send_sync static-bound assertion test ADR-011 requires. - N3: Semver Contract table notes the Result drop on SequentialReader::new (Result<Self, AlkTypeError> -> Self) alongside the argument-type change. Also: ADR-012 title -> "Plan Fingerprinting, ValidationPlan, and Closing the Deferred M1 Sites in 0.3.0"; §3 (Fingerprinting OffsetMap) renumbered to §4; README ADR table updated; review #005 gets a Resolution section recording how each finding was closed. Verification (docs-only change, v0.2.0 unchanged): cargo test --release ok (310 crate + 86 integration + 2 doctests) cargo clippy --all-targets -- -D warnings ok cargo doc --no-deps ok |
||
|
|
2310f6cbd8 |
Propose ADR-012 + 0.3.0 implementation plan
ADR-012 bundles two pieces of work into the 0.3.0 release so the
crate ships one round of breaking changes, not two:
- Fingerprinting: #[derive(Hash, Eq)] + fingerprint() -> u64 on
ReadPlan and OffsetMap. BTreeMap for ReadPlan.by_name (HashMap
blocks Hash derive). Fingerprint contract: equal hashes => identical
reads over identical bytes. Enables cross-run plan caching, alkcall
hub/spoke schema handshake, schema-version diagnostics.
- Closing the deferred M1 sites via owned BastDoc (lifetime removal,
scoped to LayoutBuilder/bast_validation/materialize_aligned/
OffsetMap::compute) + extending OffsetMap with LeafMeta
{kind, encoding, endian} for the aligned read_field/write_field paths.
Reframes the 'WritePlan' candidate from ADR-011's Future capabilities
section: the packed write-side compiled form is PackedLayout; the
aligned R/W compiled form is OffsetMap; the M1 fixes are 'cache the
parse' and 'extend the compiled form with leaf metadata', not 'add a
third compiled form.' Serves minimal-public-API-changes better than
a literal WritePlan type. ValidationPlan deferred (different shape,
not a hot loop).
The plan (docs/plans/030-compiled-forms.md) is the execution entry
point: seven phases ordered by dependency, each phase a session
boundary. Phase 1-2: ReadPlan (ADR-011). Phase 3: owned BastDoc.
Phase 4: LayoutBuilder M1 fix. Phase 5: OffsetMap LeafMeta. Phase 6:
fingerprinting. Phase 7: version bump + docs + verification. Includes
a semver contract table, deferred decisions, cross-phase invariants,
and the verification block.
ADR-011's Future capabilities section updated to point at ADR-012 for
the items moving into 0.3.0 and record the WritePlan reframe. README
ADR table gets ADR-012 as Proposed.
Verification: docs-only change; cargo test --release, cargo clippy
--all-targets -- -D warnings, cargo doc --no-deps unchanged (no source
touched).
|
||
|
|
1037e68091 |
Accept ADR-011: compiled read plan for packed mode
Tighten framing per pre-acceptance review (no decision changes): - Be precise about M1 coverage: closes the packed-side site (engine.rs:284 validate_bytes); the aligned-side M1 sites (engine.rs:334,467, layout_builder.rs:190) are a deliberate reversible bet, not a non-issue. - Replace the 'two type walkers is symmetric with OffsetMap/ PackedLayout' spin with an honest 'parallel typed tree, permanent maintenance tax, justified by ~20-50x composite-dispatch win on SFTP-shaped union-with-$ref-variants packets.' - Move the 'determinism enables fingerprinting/cache/handshake' future work out of the positives list into a dedicated 'Future capabilities' section — it is a forward reference, not a current win. - Clarify bast_doc: Value is retained unconditionally (unused in packed mode, still needed in aligned mode); add a Send+Sync test note for Arc<ReadPlan> shared from the Send+Sync engine. - Tighten the 'no format! allocations' claim to 'no resolve_typeref, no BastDef::parse, no JSON node access on the happy path' (error- path format! remains, and is not the cost being removed). - Add a 'POC coverage' section recording that the readplan-poc branch walked every BastType arm and confirmed ReadPlan covers all cases, including the union Byte/Field split and the array variable-stride (element_stride = 0) case. Status flipped Proposed -> Accepted. README ADR table updated. Verification: docs-only change; cargo test --release, cargo clippy --all-targets -- -D warnings, cargo doc --no-deps unchanged (no source touched). |
||
|
|
3184818c08 |
Propose ADR-011: compiled read plan for packed mode
Review #004 measured the packed read path at ~400x slower per chunk than a hand-rolled codec, root-caused to SequentialReader re-parsing BastDoc::new on every field read (the 're-parse on demand' framing from ADR-007). The write path is competitive because it has a compiled form (PackedLayout); the read path is the only mode/side pair without one. ADR-011 proposes ReadPlan — the packed read-side compiled form, symmetric to OffsetMap (aligned R/W) and PackedLayout (packed W). Packed positions are data-dependent (variable-length fields shift subsequent fields), so the compiled form is necessarily a read program (a pre-resolved tree of read instructions), not a flat lookup table like OffsetMap. ReadPlan::compile walks BastDoc once at engine construction, resolves all $ref\s eagerly, computes effective endianness at every node, and inlines union variants; the read loop then indexes into a Vec, matches on ReadKind, and calls data_access with a precomputed Endian — no BastDoc, no resolve_typeref, no JSON node access at read time. Scope: SequentialReader and materialize_packed consume the plan (one walker, not two); bast_validation, LayoutBuilder, and aligned one-shot paths stay on BastDoc (different concern, not hot loops). Includes a 7-step Recommended Order matching review #004's structure. Breaking public-API change (0.2.0 -> 0.3.0): SequentialReader::new and materialize_packed take ReadPlan; BastDoc and the Bast* types are unchanged (smaller breakage than review #004's Option A). Cross-links: ADR-007's 'Cost' section gets a Note pointing at review #004 and ADR-011, marking the 're-parse on demand' framing as the root cause slated for retirement (the factory decision itself is retained); the actual Cost/doc-comment rewrite happens in the implementation commit per ADR-011's recommended order. README ADR table updated. Verification: docs-only change, no source touched. Closes review #004 H1, M1 (packed side), L1, L2 (on implementation). |
||
|
|
82fec45bc6 |
Sync docs to 18 BAST kinds (Timestamp removal fallout)
- README: 19 -> 18 kinds, drop the timestamp row from the kinds table, drop 'timestamp shape' from the validate_bytes constraint list, remove the residual 'upcoming alkcall crate' sentence from the crate independence section (alkcall exists now), fix two '19 kinds' refs in the documentation pointer list and schema-layer link. - src/data_access.rs: module doc comment still said 'all 19 AlkType kinds' -> 18. - bast-format.md (normative): 19 -> 18 AlkTypeKind enum variants. - layout-engine.md: cross-reference to 'the 19 AlkType kinds' -> 18. - ADR-BAST (bast-bast-format.md): the Decision section claimed the post- pivot enum has '19 unchanged' variants; now 18, with the wording adjusted so it no longer says 'unchanged' across the pivot. - ADR-VAL-SPLIT: drop 'timestamp shape' from the value-domain constraint list and the validator-arm table row (validate_timestamp no longer exists). Left as historically accurate (describe the v0.1.0 pre-pivot state): ADR-003/004/006 Context mentions of AlkType:Timestamp, ADR-005 'engine now has 19', and the '19 jsonschema::Keyword factories' references in the What-is-removed sections of ADR-BAST and ADR-VAL-SPLIT. Verification: cargo test --release (407 pass), cargo clippy --all-targets -- -D warnings (clean), cargo doc --no-deps (clean), cargo build --target wasm32-unknown-unknown --release (clean). |
||
|
|
510553d800 |
Remove the Timestamp kind
The Timestamp kind was a residual from an early research reference. It was byte-identical to String everywhere (length-prefixed UTF-8) and its only distinguishing behavior was a hand-rolled non-strict RFC 3339 check that the docs admitted was incomplete (Feb 31 passes, seconds range unchecked, no leap seconds). JSON-level timestamp validation is jsonschema's job (format: date-time on the validate_json path), not alktype's. Removes the AlkTypeKind::Timestamp variant, its to_bast_str/from_bast_str mapping, the builder's Schema::timestamp() constructor, the validate_timestamp/is_rfc3339_timestamp validator arms, and the materializer/reader/engine timestamp arms. Updates the meta-schema primitive enum (14 -> 13), the spec docs (bast-format.md, schema-layer.md, builder.md, validation.md, overview.md, data-access.md, README.md), and the kind-count references (19 -> 18). Verification: cargo test --release (407 pass), cargo clippy --all-targets -- -D warnings (clean), cargo doc --no-deps (clean), cargo build --target wasm32-unknown-unknown --release (clean). |
||
|
|
62ed009281 |
Resolve review #003 nits N1, N3, N4
- N1: number_from_f64 now returns AlkTypeError::Access for non-finite floats instead of silently materializing Value::Null. A NaN/Inf in the buffer surfaces as a clear access error rather than a misleading 'expected a number' validation error. - N3: drop the dead Value::String arm from check_bytes; the materializer only ever emits bytes as an array of u8. Update the validation-model docs to match. - N4: fix stale ADR references in doc comments (ADR-096 -> ADR-002, ADR-097 -> ADR-003, ADR-098 -> ADR-004, ADR-101 -> ADR-007). N2 (BastType::alk_kind returning Struct for ) left as documented; every current caller resolves the ref first, so forcing Option through the call sites is churn without benefit. Verification: cargo test --release (411 pass), cargo clippy --all-targets -- -D warnings (clean), cargo doc --no-deps (clean). |
||
|
|
230345a867 |
Validate BAST documents against the meta-schema at compile time
Resolves review #003 finding M3. - Add bast_meta::validate_bast_doc and call it from AlkTypeEngine::compile before parsing. Malformed annotations (unknown endian/encoding strings, non-integer align/maxLength, missing required properties) now surface as AlkTypeError::Schema instead of being silently tolerated by the parser. - Align the meta-schema TypeRef with the parser: allow inline struct/union/ enum as TypeRefs (the parser and builder already accepted them; the meta-schema and spec did not). Update bast-format.md TypeRef table and the BastType doc comment to the seven-form vocabulary. Verification: cargo test --release (410 pass), cargo clippy --all-targets -- -D warnings (clean), cargo doc --no-deps (clean), cargo build --target wasm32-unknown-unknown --release (clean). |
||
|
|
62270b03ca |
Sync architecture docs and ADRs to BAST pivot (steps 9-10)
Step 9 (convert tests to BAST format) was a no-op: steps 4-8 converted
the tests as they went. The only remaining reference in
src/tests was the intentional rejection test at
src/schema.rs:462 (asserting the old keyword form is rejected). Full
suite passes: 389 tests (312 lib + 77 integration).
Step 10 (sync architecture docs and ADRs):
Descriptive docs rewritten/updated for BAST:
- schema-layer.md: rewritten for the BAST parser (BastDoc/BastDef/
BastType typed tree, AlkTypeKind enum with to_bast_str/from_bast_str,
what was removed). Points at bast-format.md for the normative format.
- validation.md: rewritten for the two-validator model
(bast_validation for validate_bytes, standard jsonschema for
validate_json). Documents the repurposed build_validator, the
AlkTypeError::Validation uniform payload (D-BAST-009), and what is
removed.
- builder.md: updated all output examples to BAST JSON
(struct_() -> { kind: struct, fields: [...] }; object() -> standard
JSON Schema). Documents build_doc, count(), and the field-name union
fields requirement (D-BAST-005).
- overview.md: updated for BAST (what/why, schema-is-the-format table,
dependencies, architecture pointers, design decisions table).
- README.md (architecture index): updated document table, ADR table
(new ADR-BAST + ADR-VAL-SPLIT, superseded ADR-001), OQ table
(OQ-007/OQ-008 resolutions updated for BAST-native validator), and
key design principles (#1, #2, #7, #10 reworded for BAST).
- data-access.md: updated tunion function signatures to BastUnion and
the variant resolution to return BastType (resolve_typeref for refs).
- layout-engine.md: updated construct signatures
(LayoutBuilder::new(bast_doc, root_name), OffsetMap::compute(&doc),
SequentialReader::new(bast_doc, root_name)), the recursive-walk
description (BAST typed tree), and composite-kind headings
(TStruct/TUnion/TArray -> struct/union/array). Added D-BAST-004
note on array count requirement.
New ADRs:
- ADR-BAST (bast-bast-format.md): the BAST format, meta-schema,
//kind vocabulary, design principles, what is removed, the
enum index bounds bug fix. Supersedes ADR-001's format-specific
content; records D-BAST-001..009.
- ADR-VAL-SPLIT (val-split-two-validator-model.md): the two-validator
model (BAST-native for validate_bytes, standard jsonschema for
validate_json), the repurposed build_validator, the uniform
AlkTypeError::Validation payload. Refines ADR-004's validation
strategy and ADR-010's validation step; records D-BAST-006/007/009.
Amended ADRs (supersession/amendment notes added; original decision
text preserved as historical record):
- ADR-001: format-specific content superseded by ADR-BAST;
purpose/scope and schema-is-the-format principle retained.
- ADR-002: unchanged under the pivot; one-line note that the input
format changed but the modes didn't.
- ADR-003: annotation semantics retained; annotation location moved
to BAST type-level properties (amended by ADR-BAST).
- ADR-004: AlkTypeError enum retained (D-BAST-009); validation
strategy section refined by ADR-VAL-SPLIT.
- ADR-009: builder API surface retained; build() output format
amended to BAST / standard JSON Schema by ADR-BAST (D-BAST-008).
- ADR-010: validate_bytes two-step concept retained; validation step
amended to the BAST-native validator by ADR-VAL-SPLIT.
Other:
- Cargo.toml description: JSON Schema with AlkType:* custom keywords
-> BAST document.
- bast-pivot.md research record: status draft -> implemented, with a
pointer to the ADRs that superseded its decisions.
- bast-implementation.md plan: status draft -> complete, with a note
that step 9 was a no-op and step 10 is this commit.
- open-questions.md: OQ-006/OQ-007/OQ-008 resolutions updated for the
BAST-native validator.
- questions/008-unionvalidator-variant-dispatch.md: added a
post-BAST-pivot note pointing to the current bast_validation
implementation; v0.1.0 resolution text preserved as historical
record.
Verification:
- cargo test --release: 389 pass (312 lib + 77 integration)
- cargo clippy --all-targets -- -D warnings: clean
- cargo doc --no-deps: clean
- cross-reference check: every relative link in the new/updated docs
resolves (verified by script).
|
||
|
|
f5f52c61e8 |
Decompose BAST pivot doc into normative spec + implementation plan
The bast-pivot.md research doc had grown to 1477 lines (~58KB) through iterative editing, pushing its most actionable content (D-BAST decisions, POC result, migration steps) past the 50KB Read tool cap. Agents peeking at the truncated file landed in duplicated/out-of-order sections. Decompose into three readable-sized files with distinct roles: - docs/architecture/bast-format.md (28KB, new): the normative BAST format spec -- meta-schema, TypeRef, examples, validation model. Grounded in the POC and D-BAST-001..009. Stable and safe to write now; schema-layer.md/validation.md stay describing current code and are rewritten post-implementation (per AGENTS.md ADR-grounding rule). - docs/plans/bast-implementation.md (31KB, new): the execution entry point -- ordered 10-step plan with per-step goal/files/spec-ref/ verification, the public-API semver contract table up front as a scope-creep guardrail, and the ADR-sync checklist at the end. Each step links to the specific bast-format.md section and D-BAST anchor. - docs/research/bast-pivot.md (28KB, trimmed): now the research record only -- Summary, Motivation, POC scope/result, Decisions, Risks, References. The normative format spec, what-changes tables, validator-split details, and migration steps moved to the two new docs; pointers added. 1155 lines removed, 216 added. - docs/architecture/README.md: index updated to list bast-format.md and the two in-progress pivot docs, with notes on schema-layer.md and validation.md being rewritten when the pivot lands. All three files are under the 50KB Read cap, so an implementing agent gets the whole document in one call. Cross-reference anchors verified to resolve. No code changes; cargo test --release (396 tests) green. Verification: cargo test --release (310 crate + 86 integration, all pass). |
||
|
|
c0217d91a8 |
Resolve v0.1.0 open questions and fix production-readiness issues
POC: /workspace/alktype-builder-poc/ (18/18 tests pass, findings in
docs/research/alktype-builder-poc/findings.md). Round 2 adds the SFTP
Packet validate_bytes tests (7 new: valid Init/Read/Write/Status,
short buffer, unknown discriminator, over-maxLength Bytes).
Open questions resolved (OQ-004 through OQ-008):
- OQ-004: Discriminator::Field name is String (already implemented;
docs updated to mark resolved)
- OQ-005: Both union discriminator kinds return the same shape:
{__discriminator, ...variant-fields}. Field-name path also had a
real offset bug (returned start, not end) - fixed.
- OQ-006: builder.md Example 3 now wraps the Union in a
Schema::struct_().field("payload", ...) and merges $defs via
Definitions::merge_into (matches the engine's AlkType:Struct-at-root
constraint and the SFTP wire shape)
- OQ-007: Bytes materialization is array-of-u8 (Value::Array of
Value::Number, one entry per byte 0..=255). BytesValidator accepts
both Value::String (validate_json) and Value::Array (validate_bytes).
maxLength = max byte count. Replaces the lossy from_utf8_lossy path
that corrupted non-UTF-8 bytes and broke maxLength semantics.
- OQ-008 (new): UnionValidator now dispatches to variant schemas via
sub-validators built at factory time. AlkTypeEngine::compile calls
schema::inline_union_variant_refs before build_validator to inline
$refs in union mapping entries (necessary because union_factory
receives the union node, but $defs live at the schema root).
Production-readiness fixes in src/ (no stubs/hedges in a published crate):
- materialize.rs: Record stub -> full count-prefixed key/value pair
implementation per schema-layer.md TRecord
- materialize.rs: root_of() was broken (returned the current node, not
the schema root) -> root schema threaded through every recursive call
so resolve_ref_or_inline can resolve $refs for nested composites
- builder.rs: LengthPrefixed encoding setter was a no-op when the
keyword was already in object form -> complete the branch (updates
the encoding entry in place for both LengthPrefixed and OffsetIndirect)
- builder.rs, engine.rs: POC-referencing comments cleaned up; the
round-trip test's or_else fallback (papering over write_field being
aligned-only) replaced with direct byte writes
Documentation:
- builder.md: Example 3 updated; Discriminator::Field spec shows String;
Open Questions section updated (OQ-004 resolved)
- validation.md: AlkType:Bytes and AlkType:Union validator descriptions
updated for array-of-u8 form and variant dispatch
- open-questions.md: OQ-004/005/006/007/008 marked resolved; new
Validation theme entries
- questions/004-008: individual OQ files updated with resolutions
- findings.md: round 2 results documented
Verification:
- cargo test: 369 -> 391 tests pass (22 new: 14 materialize, 5
inline_union_variant_refs, 3 validation/builder)
- cargo clippy --all-targets: clean
- POC: 11 -> 18 tests (7 new SFTP Packet tests); all pass
|
||
|
|
c6893eece8 |
Centralize scattered OQs into the tracker (OQ-004 through OQ-007)
Four open questions were scattered inline in builder.md and the POC findings doc. Moved them into the central OQ tracker under docs/architecture/questions/ and updated the index: - OQ-004: Discriminator::Field name type (&str vs String) — raised in builder.md during ADR-009 spec drafting - OQ-005: Union materialization shape (byte-offset vs field-name consistency) — raised in the POC findings - OQ-006: Builder spec Example 3 wrap Union in Struct — raised in the POC findings (doc fix; engine requires AlkType:Struct at top level) - OQ-007: Bytes materialization lossy UTF-8 — raised in the POC findings (blocks SFTP use case for validate_bytes) Index updates: - open-questions.md: new 'Schema Construction' and 'Validation' theme groups; new 'Open' section for active investigation targets (distinct from 'Deferred / Blocked' which holds scope-parked OQs) - README.md: OQ table extended with OQ-004 through OQ-007 - builder.md: inline OQ-004 replaced with a tracker reference - findings.md: inline OQ-005/006/007 replaced with tracker references Doc-only change; 369 tests pass. |
||
|
|
1a8a44ed0e |
Draft builder API (ADR-009) and generalized validation validate_bytes (ADR-010) for v0.1.0
- ADR-009: fluent Rust builder producing serde_json::Value, covers AlkType kinds + standard JSON Schema; resolves OQ-003 (alkcall is the unblocking consumer) - ADR-010: AlkTypeEngine::validate_bytes(&[u8]) as the single-call binary-buffer validation entry point; materialize Value from bytes, then validate; two methods on one struct, not a trait - builder.md: full builder API spec (Schema, Definitions, Discriminator) with four usage examples (channels chunk header, call input schema, SFTP Packet union, OperationSpec error schemas) - validation.md: new validate_bytes subsection + entry-point comparison table; AlkTypeEngine impl block updated; design decisions table updated - overview.md: builder.md added to component pointers; 'Not a schema builder' scope boundary retired; ADR-009/010 added to decisions table; OQ-003 marked resolved; Consumers table adds alkcall as first consumer - open-questions.md + questions/003: OQ-003 moved from deferred(scope) to resolved (ADR-009) - README.md: builder doc + ADR-009/010 added; OQ-003 marked resolved; two new Key Design Principles (9, 10) for v0.1.0 additions Doc-only change; 346 tests pass, clippy clean. |
||
|
|
6d6142978a |
Clean up rebranding drift in docs, agent configs, and source comments
Fix stale references left over from the alknet-typedef → alktype migration: - .opencode/agents/: replace @alkdev/alknet constraints (tokio, crypto, feature flags, anyhow/thiserror) with alktype-accurate ones (sync, AlkTypeError, WASM-clean); fix @alkimiadev → @alkdev org name; remove nonexistent AGENTS.md ref; replace alknet-http/alknet-agent spec examples - docs/sdd_process.md: fix wrong package name (@alkdev/storage → @alkdev/alktype) - docs/architecture/: rewrite dangling /workspace/ and docs/research/ paths as @alkdev/alknet: cross-repo references with explanatory notes; fix @alkimiadev → @alkdev; fix 'not yet used by any alknet crate' stale context - src/ + tests/: correct '17 AlkType kinds' → '19' in doc comments (enum has 19 variants; pre-existing count error); fix dangling /workspace/ path in poc_roundtrip.rs |
||
|
|
5e268e8f47 |
Rebrand TypeDef to AlkType in code, keyword strings, and docs
Rename all 19 JSON Schema custom keyword strings from "TypeDef:*"
to "AlkType:*" (e.g., "TypeDef:Struct" -> "AlkType:Struct")
across source, tests, and docs. This is a breaking change to the
schema format itself — existing schemas using the old keywords
must be updated.
Rename the Rust identifiers:
- TypedefEngine -> AlkTypeEngine
- TypedefError -> AlkTypeError
- TypeDefKind -> AlkTypeKind
- TYPEDEF_PREFIX -> ALKTYPE_PREFIX
- get_typedef_kind{,_loose,_loose_enum,_enum} ->
get_alktype_kind{,_loose,_loose_enum,_enum}
Update error message strings ("unknown TypeDef kind" ->
"unknown AlkType kind"), 11 test function names containing
typedef_kind/to_typedef_error, and doc-comment prose ("TypeDef
kind" -> "AlkType kind", "typedef engine" -> "alktype
engine", "typedef schema" -> "alktype schema"). Fix the broken
docs/architecture/crates/typedef/ path references in source doc
comments to point at docs/architecture/ directly. Rebrand the
typedef:annotation test fixture and the "not-a-typedef" test
string to their alktype equivalents.
Update ~20 generic "typedef" prose references in the architecture
docs ("typedef is the binary struct engine", "use typedef",
"typedef limitation", "replaced by typedef", etc.) to alktype.
Rename TypedefEngine in the ADR-007 code example to AlkTypeEngine.
Preserve as provenance per the prior prose-rebrand decision:
typedef.ts references (external TypeBox source file),
docs/research/alknet-typedef/findings.md research citations,
/workspace/alknet-typedef-poc/ POC path, and the
"alknet-typedef:" research section headers in findings.
Build, 295 tests, and clippy all pass clean.
|
||
|
|
1cfb3638d1 |
Rebrand alknet-typedef to alktype in docs, crate name, and lib name
Renumber ADRs 095-102 to 001-008 and OQs 069-071 to 001-003, and update all cross-references (titles, body prose, file-path links, tables) across the 5 spec docs, README, open-questions index, and all 11 ADR/OQ files. Inline the ADR-009 door-type definition from the parent alknet project (broken cross-project reference). Rebrand prose: alknet-typedef -> alktype in headings, body text, dependency diagrams, and "additions" notes. Disambiguate the prior failed attempt at /workspace/@alkimiadev/alktype/ as "the @alkimiadev/alktype prototype" to distinguish it from this crate. Historical research citations (docs/research/*, /workspace/alknet-typedef-poc/) are kept as-is for provenance. Rename the crate in Cargo.toml ([package].name, [lib].name) and update the 11 use alknet_typedef::* imports across the 4 test files. Rebrand the crate-level doc comment in src/lib.rs. The TypeDef:* keyword strings, TypedefError/TypedefEngine identifiers, and other code-level references are unchanged — those are a separate code rebrand pass. Build, 295 tests, and clippy all pass clean. |
||
|
|
2c4a4994dc |
Port alknet-typedef crate from alknet
Copy the binary struct engine (src/, tests/) verbatim from alknet/crates/alknet-typedef and create a standalone Cargo.toml (workspace-inherited fields inlined). Port the architecture docs (specs, ADRs 095-102, OQs 069-071) from alknet's nested multi-crate layout to a flat single-crate layout, fixing relative link paths. Build, 295 tests, and clippy all pass clean. |