Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
A worker-based, cross-vendor **G-code toolpath stack** for the browser: parse `.gcode`,
`.gcode.3mf`, and Prusa binary `.bgcode` off the main thread, normalize them into a versioned
intermediate representation (`ToolpathIR`), and render an interactive Three.js (or low-resource
Canvas 2D) preview — with first-class **Vue, React, and Svelte** integrations that are thin adapters
over one shared, framework-neutral engine.
Canvas 2D) preview — with first-class **Vue, React, Svelte, and a framework-neutral Web Component**
integrations that are thin adapters over one shared engine.

> **Status: published.** Thirteen `@chestnutlabs/*` packages are on npm (latest **`v0.4.0`**,
> lockstep-versioned with npm provenance). E0–E11 of the
Expand Down Expand Up @@ -49,9 +49,10 @@ over one shared, framework-neutral engine.
mapped onto the toolpath with tiered confidence: a precise cut + marker when the source position
is known, an uncertainty band when it is approximated, stale-signal handling, and user scrub
always winning.
- **Three equal framework adapters** — each ships a ready-to-use `<GcodePreview>` component *and*
- **Four equal framework adapters** — Vue, React, Svelte, and a framework-neutral `<gcode-preview>`
Web Component (`@chestnutlabs/gcode-preview-element`) — each ships a ready-to-use component *and*
a lower-level surface, with the same capabilities, options, events, and TypeScript contracts,
enforced by a shared behavioral suite that runs against all three in CI.
enforced by a shared behavioral suite that runs against all four in CI.

| Honest live progress | Layer clipping & scrub |
|---|---|
Expand Down Expand Up @@ -143,9 +144,10 @@ Ships as raw `.svelte` (your bundler's Svelte plugin compiles it). Lower level:
[`createGcodePreview()`](packages/gcode-preview-svelte/README.md) — store contract +
`use:` canvas action.

All three components share the same defaulted prop surface — `source`, `parseOptions`,
All four adapters share the same defaulted option surface — `source`, `parseOptions`,
`buildVolume`, `quality`, `colorMode`, `layerRange`, `scrub`, `showTravel`, `progress`,
`createWorker` — with matching events/callbacks. `<GcodePreview source={file} />` is the whole
`createWorker` — with matching events/callbacks (the Web Component exposes them as attributes /
properties). `<GcodePreview source={file} />` is the whole
thin path; the full viewer is reachable without switching APIs.

## Workers: batteries included, escape hatch provided
Expand Down
11 changes: 6 additions & 5 deletions docs/compatibility/dialects-and-containers.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,15 @@ annotation) · **unsupported** (generic parse only — geometry always works; me
## Dialects (non-extrusion — CNC / laser / plotter, DD-012 #189)

Non-extrusion controllers. Each declares a **validation tier** (DD-012 D6): until a controller is
confirmed on real hardware, its non-extrusion claims are reported **`inferred`** (experimental), never
`known` — the tier *is* the honesty mechanism. Geometry (positions, arcs, drilled holes) always parses
confirmed on real hardware, its non-extrusion claims are reported **`inferred`** (experimental); once
validated on a real machine they are promoted to **`known`** and the disclosure warning drops — the tier
*is* the honesty mechanism. Geometry (positions, arcs, drilled holes) always parses
regardless of tier; the tier governs only how much to trust the *semantic* classification. The
underlying capabilities are in [Cross-cutting coverage](#cross-cutting-coverage) below.

| Controller | Detection | Machine class | Validation tier | Non-extrusion claims | Fixtures | Evidence date |
|---|---|---|---|---|---|---|
| GRBL laser | LightBurn header / `$32=1` laser mode / `M4`+`S`, no extrusion | laser | **experimental** | `cutMoves` · `toolPower` (laser power) · `cannedCycles` — reported **`inferred`** until hardware-validated | synthetic | 2026-07-28 |
| GRBL laser | LightBurn header / `$32=1` laser mode / `M4`+`S`, no extrusion | laser | **validated** | `cutMoves` · `toolPower` (laser power) · `cannedCycles` — reported **`known`** (hardware-validated, [DD-012 log](../design/DD-012-hardware-validation-log.md)) | synthetic + real GRBL/LightBurn run | 2026-07-29 |
| GRBL mill | `Grbl` banner + `M3` spindle, no extrusion | mill | **experimental** | `cutMoves` · `toolPower` (spindle RPM) · `cannedCycles` — **`inferred`** | synthetic | 2026-07-28 |
| LinuxCNC / EMC | `LinuxCNC`/`EMC` header / `%`-program + `M3` | mill | **experimental** | as above — **`inferred`** | synthetic | 2026-07-28 |
| Marlin-laser / Mach / Smoothieware | _reserved_ | laser/mill | _pending_ | generic parse only until added | — | — |
Expand All @@ -54,8 +55,8 @@ are proprietary binary formats, not G-code.

| Container | Discovery | Plates | Machine metadata | Integrity checks | Security review | Fixtures | Evidence date |
|---|---|---|---|---|---|---|---|
| `.gcode.3mf` (Orca/Bambu) | **full** (magic sniff + CD walk) | **full** (multi-plate lifecycle, `{plate}` select, default-0 + warning) | **full** (`printable_area`/`printable_height`/printer/filaments → `MachineGeometry`, `known`) | **full** (CRC32, header agreement, encryption/zip64 rejection, duplicates, incremental caps) | [record prepared — awaiting sign-off](../design/SECURITY-REVIEW-DD-005-containers.md) | `container-mini-project` + 7 adversarial | 2026-07-23 |
| `.bgcode` (Prusa binary) | **full** (`GCDE` magic sniff) | single plate | **partial** (`bed_shape` INI → `MachineGeometry`, `inferred`) | **full** (per-block CRC32; bounded, capped decode; DEFLATE flavor-lock) | [record prepared — awaiting sign-off](../design/SECURITY-REVIEW-DD-011-bgcode.md) | `prim-cube` golden pair + adversarial fuzz corpus | 2026-07-27 |
| `.gcode.3mf` (Orca/Bambu) | **full** (magic sniff + CD walk) | **full** (multi-plate lifecycle, `{plate}` select, default-0 + warning) | **full** (`printable_area`/`printable_height`/printer/filaments → `MachineGeometry`, `known`) | **full** (CRC32, header agreement, encryption/zip64 rejection, duplicates, incremental caps) | [**signed off** 2026-07-23](../design/SECURITY-REVIEW-DD-005-containers.md) | `container-mini-project` + 7 adversarial | 2026-07-23 |
| `.bgcode` (Prusa binary) | **full** (`GCDE` magic sniff) | single plate | **partial** (`bed_shape` INI → `MachineGeometry`, `inferred`) | **full** (per-block CRC32; bounded, capped decode; DEFLATE flavor-lock) | [**signed off** 2026-07-28](../design/SECURITY-REVIEW-DD-011-bgcode.md) | `prim-cube` golden pair + adversarial fuzz corpus | 2026-07-27 |

## Cross-cutting coverage

Expand Down
39 changes: 39 additions & 0 deletions docs/manual/recipes.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,45 @@ Clip to a layer range and scrub within it — no geometry rebuilds, just draw-ra
`colorMode` is capability-gated — the stack colors by a feature only when the dialect actually
disclosed it (see [ToolpathIR & the capability model](concept-ir-capabilities.md)).

## Camera control: preset views & saved state

The imperative `controls` handle (the composable return / React ref / Svelte `bind:this` / element
instance) exposes preset orientations and a serializable camera snapshot:

```ts
const { controls } = preview; // or handleRef.current, etc.

controls.setView('iso'); // 'top' | 'bottom' | 'front' | 'back' | 'left' | 'right' | 'iso'
controls.frame(); // re-fit to the model bounds
controls.setCameraMode('orthographic'); // perspective ↔ ortho

// Persist "where the user was looking" and restore it later (e.g. a dashboard).
const view = controls.getCameraState(); // { position, target, zoom, cameraMode } | null
localStorage.setItem('view', JSON.stringify(view));
controls.setCameraState(view); // restores verbatim — no re-fit to the current model
```

`setView` snaps instantly (no animation) and preserves the active projection. `getCameraState`
returns `null` on the low-resource 2D renderer, which has no 3D pose — `setView`/`setCameraState`
there disclose via the `renderer-unsupported` event rather than fabricating one.

The same three are also **declarative props** on every adapter — a `view` prop (preset) and a
`cameraState` prop (restore) — paired with a **`camerachange`/`camera-change`** event that fires with
the new `CameraState` after a user orbits/pans/zooms. Together they form a two-way binding you can
persist:

```svelte
<GcodePreview {source} {view} bind:cameraState on:camerachange={(e) => save(e.detail)} />
```

## Capabilities & warnings on `ready`

The `ready` event (React `onReady`, Vue `@ready`, Svelte `on:ready`, element `ready`) carries
`capabilities` (the per-field `known | inferred | approximated | unavailable` map) and `warnings`
alongside `{ segments, layers, complete }` — so a consumer can gate its own UI (e.g. only offer a
color-by-power control when `capabilities.toolPower !== 'unavailable'`) without reaching for the raw
handle.

## `.gcode.3mf` multi-plate

`.gcode.3mf` containers can hold several sliced plates. Select one with `parseOptions.plate`:
Expand Down
92 changes: 46 additions & 46 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions packages/gcode-bgcode/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# @chestnutlabs/gcode-bgcode

## 0.5.0

### Patch Changes

- Updated dependencies []:
- @chestnutlabs/gcode-containers@0.5.0
- @chestnutlabs/toolpath-core@0.5.0

## 0.4.0

### Patch Changes
Expand Down
6 changes: 3 additions & 3 deletions packages/gcode-bgcode/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@chestnutlabs/gcode-bgcode",
"version": "0.4.0",
"version": "0.5.0",
"description": "Binary G-code (.bgcode) decode adapter for the Chestnut Labs G-code toolpath stack (DD-011): a license-clean, in-memory block walker that decodes Prusa .bgcode to plain G-code for the existing parser/dialect/renderer pipeline. Decode-only.",
"keywords": [
"gcode",
Expand Down Expand Up @@ -47,7 +47,7 @@
"test": "vitest run"
},
"dependencies": {
"@chestnutlabs/toolpath-core": "0.4.0",
"@chestnutlabs/gcode-containers": "0.4.0"
"@chestnutlabs/toolpath-core": "0.5.0",
"@chestnutlabs/gcode-containers": "0.5.0"
}
}
7 changes: 7 additions & 0 deletions packages/gcode-colors/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# @chestnutlabs/gcode-colors

## 0.5.0

### Patch Changes

- Updated dependencies []:
- @chestnutlabs/toolpath-core@0.5.0

## 0.4.0

### Minor Changes
Expand Down
4 changes: 2 additions & 2 deletions packages/gcode-colors/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@chestnutlabs/gcode-colors",
"version": "0.4.0",
"version": "0.5.0",
"description": "Renderer-agnostic per-segment color model for the Chestnut Labs G-code toolpath stack (DD-014 D3): the ColorMode union and honest, capability-gated segment coloring over ToolpathIR channels, shared by the 3D and 2D renderers.",
"keywords": [
"gcode",
Expand Down Expand Up @@ -47,6 +47,6 @@
"test": "vitest run"
},
"dependencies": {
"@chestnutlabs/toolpath-core": "0.4.0"
"@chestnutlabs/toolpath-core": "0.5.0"
}
}
7 changes: 7 additions & 0 deletions packages/gcode-containers/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# @chestnutlabs/gcode-containers

## 0.5.0

### Patch Changes

- Updated dependencies []:
- @chestnutlabs/toolpath-core@0.5.0

## 0.4.0

### Patch Changes
Expand Down
Loading
Loading