## ADDED Requirements ### Requirement: Core package exposes low-level bit I/O The `@suaveplan/bitpacker` package SHALL expose `BitWriter` and `BitReader` classes for bit-level read/write operations. #### Scenario: BitWriter packs bits sequentially - **WHEN** a caller invokes `writeUint(42, 8)` followed by `writeBool(true)` on a `BitWriter` - **THEN** the resulting byte array contains 42 in the first 8 bits and 1 in the 9th bit #### Scenario: BitReader unpacks bits sequentially - **WHEN** a caller constructs a `BitReader` from a packed byte array and invokes `readUint(8)` then `readBool()` - **THEN** the values match the original written values ### Requirement: Core package exposes strategy manager The `@suaveplan/bitpacker` package SHALL expose `PackingStrategyManager` that maintains an ordered chain of `PackingStrategy` instances. #### Scenario: Strategy manager resolves schema to strategy - **WHEN** `findStrategy(schema)` is called with a schema token - **THEN** the first strategy whose `canHandle(schema)` returns `true` is returned #### Scenario: Custom strategy registration - **WHEN** `registerStrategy(strategy)` is called - **THEN** the strategy is inserted before the catch-all `InvalidSchemaStrategy` ### Requirement: Core package exposes BitPacker orchestrator The `@suaveplan/bitpacker` package SHALL expose a `BitPacker` class that uses a `PackingStrategyManager` to pack/unpack values against schemas. #### Scenario: Round-trip pack and unpack - **WHEN** `pack(data, schema)` is invoked followed by `unpack(bytes, schema)` - **THEN** the unpacked value equals the original data #### Scenario: Schema registry resolves references - **WHEN** a schema contains `{ _ref: "namedSchema" }` and the name is registered via `registerSchema` - **THEN** the referenced schema is used for pack/unpack ### Requirement: Genesis additions are preserved in core The core package SHALL preserve `zigzagEncode`/`zigzagDecode`, `packBits`/`unpackBits`, `peek(bits)`, `seek(position)`, and `align()`. #### Scenario: Peek does not advance bit position - **WHEN** `peek(8)` is called on a `BitReader` - **THEN** the returned value matches the next 8 bits and `bitPosition` is unchanged #### Scenario: Zigzag encoding round-trips - **WHEN** `zigzagEncode(n)` is called followed by `zigzagDecode` on the result - **THEN** the original value is restored for both positive and negative integers ## MODIFIED Requirements None. ## REMOVED Requirements None.