6.6 KiB
Bitpacker canonical spec — port adaptive blob from upstream
Package: @suaveplan/bitpacker
Status: PROPOSED — decision required (genesis blob strategy diverged from upstream during the modular restructure; see §"Decision required" below)
Type: spec port + behavior decision
Decision required
During implementation of this change (2026-05-02), it surfaced that genesis's BlobPackingStrategy does NOT match the upstream contract. The two implementations are wire-incompatible.
| Aspect | Upstream | Genesis |
|---|---|---|
canHandle schema test |
schema === "~" |
schema === "blob" or { _blob: { maxLength: number } } |
| Wire format | [2-bit tag][2–5 byte length][raw bytes] |
[bitsRequired(maxLength)-bit length][raw bytes] (if maxLength set) or variable-length encoded differently for "blob" |
| Length range | up to 1 TiB via adaptive tag | up to caller-specified maxLength |
| Schema reservedness | "~" is a single-character reserved keyword |
"blob" is a regular keyword + an object form |
Three options. The user must pick before this change can fold:
- Re-align genesis to upstream: re-port
BlobPackingStrategyto use the"~"schema and 2-bit width tag exactly as upstream. This is a behavior change with potential wire-incompatibility for any current genesis consumer of"blob"schemas. The upstream canonical spec then folds verbatim intoopenspec/specs/bitpacker/spec.md. - Re-author canonical spec to describe genesis: keep the genesis
"blob"/_blobimplementation, and write a new canonical spec that documents what genesis actually does (max-length-bounded length-prefix). The upstream"~"spec is then NOT folded into genesis. - Coexist: re-port the
"~"adaptive strategy alongside the existing"blob"strategy, so consumers can pick. Both contracts get folded; the strategy chain ordering needs to put"~"before"blob"(and both before string), which is documented as a separate requirement.
Recommendation: Option 2 for now (genesis already diverged; the "blob" implementation is in active use; re-aligning would risk wire-compat breaks elsewhere in the monorepo). Confirm before continuing.
This proposal as currently authored assumes Option 1. The spec delta MUST be re-written if Option 2 or 3 is chosen.
Why
Why
Genesis has no openspec/specs/bitpacker/spec.md. Upstream has one at /mnt/s/web/suaveplan/openspec/specs/bitpacker/spec.md (32 L) defining three canonical requirements: the adaptive blob schema type "~", the strategy chain ordering that resolves "~" via BlobPackingStrategy before StringPackingStrategy, and safety-limit enforcement on every variable-length type. Those requirements describe behavior that is already implemented in genesis — bitpacker-strategies/strategies/blob/blob.ts exists and bitpacker-validation/safety/ exists — but no spec pins the contract, which means a future refactor can quietly break the wire format without any check failing.
This change folds the upstream canonical requirements into openspec/specs/bitpacker/spec.md. It is a port, not a redesign: every requirement is verbatim from upstream, with **Verified by:** lines added per genesis policy.
What changes
- ADDED:
openspec/specs/bitpacker/spec.md(created from this change's spec delta at archive time) with the three canonical requirements. - ADDED: per-requirement
**Verified by:**lines naming the existing test files that pin each scenario today (no new tests written). - ADDED: a
## Purposesection ported verbatim from upstream — gives the spec the same reading entry point as upstream so a port to a third codebase later remains 1:1 traceable.
Out of scope
- New behavior. This change only documents what is already true.
- Restructuring
bitpacker-modular-restructure's spec deltas. That change still has its ownspecs/bitpacker/spec.mdcovering the package-restructure-specific requirements (BitWriter / BitReader / strategy manager / BitPacker class). Both this change and the modular restructure fold into the same canonicalopenspec/specs/bitpacker/spec.md; OpenSpec folding is additive, so the requirements coexist. - Spec deltas for
bitpacker-strategies(whereBlobPackingStrategylives) orbitpacker-validation(whereSafetyCheckerlives). The upstream canonical spec puts all three requirements under thebitpackercapability and we keep that grouping for traceability; the per-strategy / per-safety-checker behaviors that aren't in upstream's canonical spec remain owned by their own caps.
Source mapping
The entire spec delta derives from upstream's canonical spec.
| Requirement | Source file | Source lines | Notes |
|---|---|---|---|
Adaptive blob schema type "~" |
/mnt/s/web/suaveplan/openspec/specs/bitpacker/spec.md |
L9-L26 | Verbatim |
| Blob strategy runs before string strategy | /mnt/s/web/suaveplan/openspec/specs/bitpacker/spec.md |
L28-L29 | Verbatim |
| Safety-limit enforcement | /mnt/s/web/suaveplan/openspec/specs/bitpacker/spec.md |
L31-L32 | Verbatim |
## Purpose preamble |
/mnt/s/web/suaveplan/openspec/specs/bitpacker/spec.md |
L1-L7 | Verbatim |
Requirements with no source line
| Requirement | Justification |
|---|---|
**Verified by:** lines on every requirement |
Genesis-wide AGENTS.md §13 policy — every requirement carries one at authoring time. Upstream did not enforce this. The lines name the existing tests that pin each scenario today. |
Verification approach
No new tests. Each canonical requirement is already pinned by an existing test in genesis — this change names those tests in the **Verified by:** lines.
| Requirement | Existing genesis test |
|---|---|
Adaptive blob "~" (4 scenarios) |
packages/bitpacker/bitpacker-strategies/src/strategies/blob/blob.test.ts |
| Blob-before-string strategy ordering | packages/bitpacker/bitpacker-strategies/src/register-default-strategies.test.ts |
| Safety-limit enforcement | packages/bitpacker/bitpacker-validation/src/safety/safety-checks.test.ts |
If any of those test files is missing the named it(...) titles at archive time, the change cannot fold; the missing it(...) must be added first. Adding it is in-scope for this change (it's part of "documenting what is already true").
Migration impact
None — additive only. No package surface changes; no consumer is affected.
This change does NOT block on bitpacker-modular-restructure or bitpacker-stub-completion or bitpacker-crypto-port. All four can archive independently into the same openspec/specs/bitpacker/spec.md (folding is additive). The recommended archive order is canonical-spec → modular-restructure → stub-completion → crypto-port, but it is not enforced.