Pre-publish docs sweep: README, AGENTS.md, licenses, inline doc fixes
- Add README.md reflecting the v0.1.0 state: 19 AlkType kinds, two layout modes, builder + AlkTypeEngine usage example (verified to compile and run), validation entry points, crate independence, untrusted-schemas guarantee, docs pointers. Mirrors the alkvault README structure. - Add AGENTS.md with alktype-specific git workflow, project conventions (no comments, AlkTypeError, untrusted schemas, overflow safety, no async, no feature flags, wasm-clean, preserve_order load-bearing, no unsafe), verification commands, and ADR/OQ index. Blocks auto-commit on semver-relevant public API changes per the crates.io 0.1.0 contract. - Add LICENSE-MIT and LICENSE-APACHE (dual MIT/Apache-2.0, matching alkvault and the Cargo.toml license field). - Cargo.toml: add readme, keywords, categories, rust-version = "1.85". - Fix broken intra-doc link in builder.rs: DiscriminatorKind -> crate::schema::DiscriminatorKind (cargo doc now warning-free). - N1 (review #002): document is_rfc3339_timestamp as non-strict in the function doc comment. Lists the specific gaps (day-of-month per month, seconds range, leap seconds) and points consumers needing strict validation to chrono/time. - N2 (review #002): document the FieldValue::Bytes-for-Record API asymmetry in the FieldValue enum doc and on read_record_value. - .opencode/agents/implementation-specialist.md: point to AGENTS.md for full convention details (matches the alkvault pattern). - review #002: mark N1/N2 resolved; all 7 findings now closed. Verification: - cargo test --release: 396 tests pass (310 crate + 86 integration) - cargo clippy --all-targets -- -D warnings: clean - cargo doc --no-deps: clean (no broken intra-doc link warnings) - cargo build --target wasm32-unknown-unknown --release: clean - cargo publish --dry-run --allow-dirty: clean
This commit is contained in:
1 parent
5f88bca0d8
commit
fb3a27f974
10 files changed
+641
-13
No files matched your search
@@ -0,0 +1,176 @@
|
||||
# AGENTS.md
|
||||
|
||||
Operating instructions for opencode agents working in this repo. opencode
|
||||
auto-loads this file as instructions, overriding the built-in defaults for
|
||||
this project. Custom agents in `.opencode/agents/` inherit these rules
|
||||
unless their own prompts say otherwise.
|
||||
|
||||
## Git Workflow
|
||||
|
||||
**Commit and push when reasonable.** When a change is complete and
|
||||
verified (build + lint + tests pass), commit and push to `origin/main`
|
||||
without asking. This overrides the built-in default of "only commit when
|
||||
explicitly asked."
|
||||
|
||||
The workflow:
|
||||
|
||||
1. Make the change
|
||||
2. Verify: `cargo test --release`, `cargo clippy --all-targets --
|
||||
-D warnings`, `cargo doc --no-deps` if docs changed, `cargo build
|
||||
--target wasm32-unknown-unknown --release` if layout/wasm-relevant
|
||||
code changed
|
||||
3. Inspect `git status` and `git diff` before staging — stage only the
|
||||
intended files, never secrets
|
||||
4. Write a concise commit message matching the repo style (see `git log
|
||||
--oneline -10`). For multi-point changes, use a summary line plus a
|
||||
body with bullet points and a verification block.
|
||||
5. `git push origin main`
|
||||
6. Report the commit hash and the verification summary
|
||||
|
||||
Exceptions — **do not** commit or push without asking:
|
||||
|
||||
- The change is exploratory / speculative (you're not sure the user wants
|
||||
it kept)
|
||||
- The user is actively reviewing the diff and may ask for changes
|
||||
- The change touches semver-relevant public API (this repo is on
|
||||
crates.io; the public surface is the 0.1.0 contract — `AlkTypeEngine`,
|
||||
`Schema`/`Definitions`/`Discriminator` builder types, `FieldValue`,
|
||||
`AlkTypeKind`, `Endian`, `VariableEncoding`, `DiscriminatorKind`,
|
||||
`LayoutMode`, `OffsetMap`/`ByteRange`, `LayoutBuilder`/`PackedLayout`/
|
||||
`FieldPosition`, `SequentialReader`, `UnionDispatch`, `AlkTypeError`
|
||||
variants, and the `data_access`/`schema`/`tunion`/`materialize`/
|
||||
`validation` public function signatures). Additive, non-breaking
|
||||
changes (new methods, new error variants, new builder setters) are
|
||||
fine to commit; renames, removals, signature changes, or behavioral
|
||||
shifts on existing public items are not.
|
||||
- You'd be force-pushing, amending a published commit, creating an empty
|
||||
commit, or skipping hooks
|
||||
|
||||
Never commit secrets, keys, or credentials. If a commit fails or hooks
|
||||
reject it, fix the issue and create a new commit — do not amend the
|
||||
failed one.
|
||||
|
||||
Git identity is preconfigured (`glm-5.2 <glm-5.2@alk.dev>`). Do not
|
||||
change `git config`, skip hooks, or use `git commit -i`.
|
||||
|
||||
## Project Conventions (Rust / binary struct engine)
|
||||
|
||||
This is a binary struct engine crate. The conventions below apply to all
|
||||
work in `src/` and `tests/`. They mirror `.opencode/agents/
|
||||
implementation-specialist.md` §Project Conventions and are repeated here
|
||||
so they apply to every session, not just spawned implementation agents.
|
||||
|
||||
1. **No comments in code** unless the user explicitly asks. This is a
|
||||
project-wide convention. Doc comments (`///`, `//!`) are fine and
|
||||
expected on public API. Inline `//` comments only when the user asks
|
||||
or when a non-obvious safety/correctness constraint would otherwise be
|
||||
missed (e.g., "the `u32` at offset 1 is unaligned — correct for
|
||||
protocol wire formats, which pack fields tightly").
|
||||
|
||||
2. **Error handling** — `AlkTypeError` (the hand-rolled enum in
|
||||
`src/error.rs`) is the library error type. No `anyhow` or `thiserror`
|
||||
— this is a library crate with a single error enum covering the three
|
||||
engine phases (schema, offset, access) plus validation. Never panic
|
||||
in library code. No `unwrap()` or `expect()` outside tests — if you
|
||||
reach for `unwrap`, the error path wasn't specified, stop and decide
|
||||
what should actually happen.
|
||||
|
||||
3. **Schemas are untrusted input** — every engine path that walks a
|
||||
schema must return `Err` on a malformed schema, never `panic!`/
|
||||
`unreachable!`. The downstream `alkcall` consumer accepts schemas
|
||||
from arbitrary internet peers in its hub/spoke topology, so a
|
||||
malicious or unsupported schema definition must produce a handleable
|
||||
error, not a crash. If you add a new `AlkTypeKind` variant, the
|
||||
`k if k.is_fixed_size()` guard pattern in `offset_map` and
|
||||
`layout_builder` will catch it at runtime via the `_ => Err(...)`
|
||||
arm; listing all fixed-size kinds explicitly to restore compile-time
|
||||
exhaustiveness is a separate cleanup, not a blocker (review #002, L2).
|
||||
|
||||
4. **Overflow safety** — use `checked_add`/`try_from` for any offset
|
||||
arithmetic or cast that can overflow on adversarial input. The
|
||||
`data_access::write_bytes` u32 truncation guard (review #002, M2) is
|
||||
the canonical pattern: validate the cast, return
|
||||
`AlkTypeError::Access` on failure. Do not regress to bare `as u32`
|
||||
or `+` in production paths.
|
||||
|
||||
5. **No `async`** — the engine is fully synchronous. No `tokio`, no
|
||||
`async`/`.await`, no async-sync primitives. Schema compilation,
|
||||
layout walks, read/write, and validation are all blocking,
|
||||
CPU-bound operations.
|
||||
|
||||
6. **No feature flags** — the crate has no feature flags and no
|
||||
optional dependencies. `default = []` in `Cargo.toml`. If a future
|
||||
need surfaces (e.g. `no_std` per OQ-002, or an optional strict
|
||||
RFC 3339 validator), raise it as an OQ/ADR before adding one.
|
||||
|
||||
7. **WASM-clean** — the only dependencies are `jsonschema` (with
|
||||
`default-features = false`) and `serde_json` (with `preserve_order`).
|
||||
No platform deps, no `std::time`, no filesystem, no threads. Must
|
||||
compile to `wasm32-unknown-unknown`. If you reach for a new
|
||||
dependency, first verify it's wasm-compatible and confirm it's worth
|
||||
the dependency cost.
|
||||
|
||||
8. **`serde_json`'s `preserve_order` is load-bearing** — field order in
|
||||
the schema JSON determines byte order in packed mode, and the
|
||||
`OffsetMap`/`PackedLayout` iteration order in both modes. Do not
|
||||
disable the `preserve_order` feature, and do not sort schema object
|
||||
keys anywhere in the engine.
|
||||
|
||||
9. **Naming** — Rust standard: `snake_case` for functions/variables/
|
||||
modules, `PascalCase` for types/traits, `SCREAMING_SNAKE_CASE` for
|
||||
constants.
|
||||
|
||||
10. **Module structure** — one module per file under `src/`, re-exported
|
||||
from `src/lib.rs`. Public API surface is the `lib.rs` re-exports; if
|
||||
a new public type or function needs to be visible to consumers, add
|
||||
it to the `pub use` block in `lib.rs`.
|
||||
|
||||
11. **No `unsafe`** — the crate has zero `unsafe` blocks and zero `unsafe
|
||||
extern` declarations. Bounds-checked slice access via
|
||||
`data_access::check_bounds` and `get(..)` with `ok_or_else` is the
|
||||
pattern. Do not introduce `unsafe` for performance; the
|
||||
bounds-check-eliding optimization belongs in the `jsonschema`/serde
|
||||
layer, not here.
|
||||
|
||||
## Verification Commands
|
||||
|
||||
Run these before committing. All must pass.
|
||||
|
||||
```bash
|
||||
cargo test --release # full suite (~396 tests: 310 crate + 86 integration)
|
||||
cargo clippy --all-targets -- -D warnings
|
||||
cargo doc --no-deps # if docs changed
|
||||
cargo build --target wasm32-unknown-unknown --release # if layout/wasm-relevant code changed
|
||||
cargo publish --dry-run --allow-dirty # before a release
|
||||
```
|
||||
|
||||
## Architecture Context
|
||||
|
||||
- `docs/architecture/` — the authoritative spec. Read it before
|
||||
non-trivial changes. ADRs are numbered; OQs (open questions) track
|
||||
resolved/deferred decisions.
|
||||
- ADR-001 — purpose, scope, "schema is the format" principle,
|
||||
jsonschema as the validation engine
|
||||
- ADR-002 — two layout modes (packed sequential vs aligned static); the
|
||||
most important architectural decision
|
||||
- ADR-003 — schema annotations (endianness, alignment, encoding, TUnion
|
||||
discriminators)
|
||||
- ADR-004 — error handling and validation strategy; the `AlkTypeError`
|
||||
enum, load-time build, access-time check
|
||||
- ADR-005 — Int64/Uint64 as first-class kinds; JSON precision caveat
|
||||
- ADR-006 — reject non-final inline length-prefixed variable fields in
|
||||
aligned mode (prevents silent data corruption)
|
||||
- ADR-007 — packed-mode read factory; `engine.sequential_reader()`
|
||||
returns an owned fresh reader (the reader has mutable cursor state)
|
||||
- ADR-008 — reject TUnion in aligned mode for v1 (broken semantics)
|
||||
- ADR-009 — builder API producing `serde_json::Value`; resolves OQ-003
|
||||
- ADR-010 — `validate_bytes` on `AlkTypeEngine`; materialize `Value`
|
||||
from bytes, then validate
|
||||
- If a TODO references a design direction that an ADR has since decided
|
||||
against, the TODO is stale — remove it and align with the ADR. Do not
|
||||
implement the rejected design.
|
||||
- OQ-001 (deferred): arrays of variable-length-element structs — blocked
|
||||
on a concrete consumer that needs interleaved variable-stride arrays.
|
||||
- OQ-002 (deferred): `no_std` + `alloc` support — blocked on an embedded
|
||||
use case; the core engine is already allocation-free, `jsonschema` is
|
||||
the only `alloc` consumer.
|
||||
Reference in new issue
Block a user