Skip to content

feat(bgcode): .bgcode decoder — walker + CRC + None/DEFLATE (DD-011 phase 1) (#188) - #233

Merged
sobechestnut-dev merged 1 commit into
devfrom
feat/188-bgcode-phase1
Jul 27, 2026
Merged

feat(bgcode): .bgcode decoder — walker + CRC + None/DEFLATE (DD-011 phase 1) (#188)#233
sobechestnut-dev merged 1 commit into
devfrom
feat/188-bgcode-phase1

Conversation

@sobechestnut-dev

Copy link
Copy Markdown

Phase 1 of the #188 bgcode epic, implementing accepted DD-011. Does not close #188 — phases 2–6 (MeatPack, heatshrink, container-adapter integration + golden-equivalence, adversarial corpus + §7.3 review, exit) remain.

What

New package @chestnutlabs/gcode-bgcode (14th lockstep) — a license-clean, in-memory decoder for Prusa binary G-code. .bgcode is a container of plain G-code, so openBgcode yields plain G-code the existing parser/dialect/IR/renderer pipeline consumes unchanged. Decode-only.

Phase 1 (DD-011 §14):

  • File header + block walker (spec v1), per-block CRC32 verification, sniffBgcode/openBgcode.
  • Compression None + DEFLATE, encoding None — decoded end-to-end.
  • MeatPack (phase 2) and heatshrink (phase 3) return honest structured E_BGCODE_UNSUPPORTED_* errors.
  • Every failure (bad magic/version, CRC mismatch, truncation, decompression bomb) is a bounded ContainerError; the DEFLATE path reuses the test(e7) phase 4: coverage-guided container fuzzing (Jazzer.js, E4 §7.3) #131-fuzzer's unhandled-rejection guard.

Licensing (the whole point)

Clean-room from the published spec (RR-003) — no AGPL libbgcode/MeatPack code. Deps: toolpath-core + gcode-containers (for crc32/ContainerError); no three/framework/fs/net (lint-enforced by a new boundary block). A TEST-ONLY clean-room .bgcode assembler generates fixtures without PrusaSlicer; real files land in phase 4 for golden-equivalence.

Verification

12 tests green — incl. the DEFLATE round-trip, multi-block concatenation + metadata/thumbnail walk-past, CRC-mismatch/truncation/bad-magic/bad-version rejection, phase-2/3 honest errors, the bomb cap, and the decoded-gcode → parseGcodeToIR bridge. typeCheck ✓, lint ✓ (0 errors), CI-like test:packages ✓ (bgcode included), pack:check ✓ (additive snapshot). Registration: pack-check + build-api PACKAGES, eslint block, changeset (auto fixed-group).

Note on DEFLATE flavor: phase 1 uses deflate-raw (self-consistent fixtures); the definitive Prusa flavor is confirmed against real files in phase 4.

🤖 Generated with Claude Code

…-011 phase 1) (#188)

New package @chestnutlabs/gcode-bgcode (14th lockstep): a license-clean, in-memory decoder for
Prusa binary G-code. .bgcode is a container of plain G-code, so decoding it feeds the existing
parser/dialect/IR/renderer pipeline unchanged. Decode-only.

Phase 1 (DD-011 §14): the file-header + block walker (spec v1), per-block CRC32 verification,
sniffBgcode/openBgcode, and None + DEFLATE compression with None encoding decoded end-to-end.
MeatPack (phase 2) and heatshrink (phase 3) return honest structured ContainerErrors. All failures
(bad magic/version, CRC mismatch, truncation, decompression bomb) are bounded structured errors —
the DEFLATE path reuses the #131-fuzzer's unhandled-rejection guard.

Clean-room from the published spec (RR-003) — NO AGPL libbgcode/MeatPack code. Deps: toolpath-core
+ gcode-containers (crc32/ContainerError); no three/framework/fs/net (lint-enforced). A TEST-ONLY
clean-room .bgcode assembler generates fixtures (no PrusaSlicer needed); real files land in phase 4
for golden-equivalence.

Registration: pack-check + build-api PACKAGES, eslint boundary block + test relaxation, pack
snapshot (additive), changeset (auto fixed-group). 12 tests green incl. the DEFLATE round-trip and
the decoded-gcode-→-parser bridge. typeCheck/lint/test:packages/pack:check all green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@sobechestnut-dev
sobechestnut-dev enabled auto-merge (squash) July 27, 2026 19:45
@sobechestnut-dev
sobechestnut-dev merged commit 83f0336 into dev Jul 27, 2026
4 checks passed
sobechestnut-dev added a commit that referenced this pull request Jul 27, 2026
Adds the MeatPack encoding (both variants) to the .bgcode decoder: a GCode block encoded with
MeatPack now decodes end-to-end (optionally after DEFLATE) to plain G-code.

The decoder is a faithful TS port of the MIT jamesgopsill/meatpack unpacker (© 2025 James Gopsill;
derived from the published Prusa spec), attribution preserved — NO AGPL libbgcode/OctoPrint-MeatPack
code (RR-003 §8). MeatPack packs the 15 most common g-code chars into 4-bit nibbles (first char =
low nibble); nibble 0xF escapes a full literal byte; FF FF <cmd> toggles packing/no-spaces; the
stream starts disabled (FF FF FB enables it).

Validated by HAND-COMPUTED vectors (the nibble table applied by hand as an oracle independent of the
decoder's own table): packable line, left/right/double full-width escapes, the (\n,\n)→single-newline
special case, no-spaces + disable-packing commands, invalid-command rejection — plus block-level
integration through openBgcode (None + DEFLATE × MeatPack/MeatPack-comments). Output is bounded
(bomb defense). Real PrusaSlicer meatpack files = phase-4 golden-equivalence.

Also fixes a docs-build regression: bgcode.ts's `{@link ContainerError}` (an unresolvable
cross-package typedoc link that landed in dev via #233's squash) → a code span, restoring the
API-docs warning budget to 3/3.

heatshrink compression remains phase 3.

Co-authored-by: Nathaniel Chestnut <sobechestnut-dev@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

epic: Binary G-code (.bgcode) decode support

1 participant