# Capability Spec Delta: bitpacker (bitpacker-canonical-spec) **Package**: `@suaveplan/bitpacker` **Status**: PROPOSED > Every requirement below carries a `**Verified by:**` line at authoring time. The requirements are ported from upstream `/mnt/s/web/suaveplan/openspec/specs/bitpacker/spec.md` (cited in the proposal source mapping); SHALL phrasing has been added to satisfy the genesis OpenSpec validator. Behavior described here is already implemented in genesis; this change documents the contract. ## Purpose (preamble) `@suaveplan/bitpacker` provides bit-level binary serialization driven by declarative schemas. It supports fixed-width primitives (`u8`, `i16`, etc.), variable-length strings/arrays with max-sized length prefixes, and — as of 2026-04-10 — an adaptive blob type (`"~"`) whose length-prefix width is self-describing via a 2-bit tag so payloads ranging from bytes to 1 TiB share a schema without wasting bits on small entries. ## ADDED Requirements ### Requirement: Adaptive blob schema type `"~"` The package SHALL treat schema value `"~"` as a binary blob whose length prefix is self-describing via a 2-bit width tag selecting 2, 3, 4, or 5 bytes of length. Pack input and unpack output SHALL be `Uint8Array` with no encoding. #### Scenario: tag selected for a small payload - **WHEN** packing 200 bytes with schema field `data: "~"` - **THEN** the written bits are `[tag=0][2-byte length=200][200 raw bytes]` #### Scenario: tag selected for a large payload - **WHEN** packing 500 MiB - **THEN** the tag is `2` and the length prefix is 4 bytes #### Scenario: payload over 1 TiB rejected - **WHEN** packing a buffer whose length exceeds `0xFFFFFFFFFF` - **THEN** the packer throws #### Scenario: round-trip preserves bytes - **WHEN** a `Uint8Array` is packed then unpacked - **THEN** the output is byte-identical to the input **Verified by:** `packages/bitpacker/bitpacker-strategies/src/strategies/blob/blob.test.ts::"selects 2-byte length tag for payloads under 64 KiB"` AND `packages/bitpacker/bitpacker-strategies/src/strategies/blob/blob.test.ts::"selects 4-byte length tag for payloads over 16 MiB"` AND `packages/bitpacker/bitpacker-strategies/src/strategies/blob/blob.test.ts::"throws on payloads exceeding 1 TiB"` AND `packages/bitpacker/bitpacker-strategies/src/strategies/blob/blob.test.ts::"round-trip preserves bytes byte-identical"` --- ### Requirement: Blob strategy runs before string strategy The strategy chain SHALL resolve `"~"` via `BlobPackingStrategy` before `StringPackingStrategy` sees it, so the reserved keyword MUST NOT be misinterpreted. #### Scenario: registerDefaultStrategies orders blob before string - **WHEN** `registerDefaultStrategies(manager)` runs and `findStrategy("~")` is called - **THEN** the returned strategy is `BlobPackingStrategy`, not `StringPackingStrategy` **Verified by:** `packages/bitpacker/bitpacker-strategies/src/register-default-strategies.test.ts::"BlobPackingStrategy resolves '~' before StringPackingStrategy"` --- ### Requirement: Safety-limit enforcement The package SHALL validate every variable-length type (`"-N"`, `"-N[M]"`, `"~"`) against `safetyLimits.maxBufferSize` before writing. #### Scenario: variable-length string above maxBufferSize rejected - **WHEN** a payload of `("-32")` exceeds `safetyLimits.maxBufferSize` - **THEN** the packer throws before allocating a write buffer #### Scenario: dynamic array above maxBufferSize rejected - **WHEN** an array `("-32[16]")` whose total bytes exceed `safetyLimits.maxBufferSize` is packed - **THEN** the packer throws before writing #### Scenario: adaptive blob above maxBufferSize rejected - **WHEN** a blob `"~"` whose length exceeds `safetyLimits.maxBufferSize` is packed - **THEN** the packer throws before writing **Verified by:** `packages/bitpacker/bitpacker-validation/src/safety/safety-checks.test.ts::"rejects variable-length string above maxBufferSize"` AND `packages/bitpacker/bitpacker-validation/src/safety/safety-checks.test.ts::"rejects dynamic array above maxBufferSize"` AND `packages/bitpacker/bitpacker-validation/src/safety/safety-checks.test.ts::"rejects adaptive blob above maxBufferSize"`