From 9865223a2af1d25a690c86dea60b029695b6d1dd Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 31 Jul 2026 20:47:19 +0000 Subject: [PATCH 1/2] release: version packages (lockstep) --- .changeset/cnc-evidence-detection.md | 27 ---- .changeset/dd012-canned-cycles.md | 21 ---- .changeset/dd012-cnc-coloring.md | 19 --- .changeset/dd012-cnc-dialects.md | 21 ---- .changeset/dd012-cut-classification.md | 22 ---- .changeset/dd012-modal-motion.md | 15 --- .changeset/dd012-modal-toolpower.md | 24 ---- .changeset/g0-rapid-travel-classification.md | 15 --- .changeset/grbl-laser-validated.md | 14 --- .changeset/lexer-multicommand.md | 25 ---- package-lock.json | 92 +++++++------- packages/gcode-bgcode/CHANGELOG.md | 8 ++ packages/gcode-bgcode/package.json | 6 +- packages/gcode-colors/CHANGELOG.md | 23 ++++ packages/gcode-colors/package.json | 4 +- packages/gcode-containers/CHANGELOG.md | 7 ++ packages/gcode-containers/package.json | 4 +- packages/gcode-dialects/CHANGELOG.md | 59 +++++++++ packages/gcode-dialects/package.json | 4 +- packages/gcode-parser/CHANGELOG.md | 126 +++++++++++++++++++ packages/gcode-parser/package.json | 10 +- packages/gcode-preview-core/CHANGELOG.md | 10 ++ packages/gcode-preview-core/package.json | 10 +- packages/gcode-preview-element/CHANGELOG.md | 10 ++ packages/gcode-preview-element/package.json | 10 +- packages/gcode-preview-react/CHANGELOG.md | 10 ++ packages/gcode-preview-react/package.json | 10 +- packages/gcode-preview-svelte/CHANGELOG.md | 10 ++ packages/gcode-preview-svelte/package.json | 10 +- packages/gcode-preview-vue/CHANGELOG.md | 10 ++ packages/gcode-preview-vue/package.json | 10 +- packages/gcode-renderer-2d/CHANGELOG.md | 8 ++ packages/gcode-renderer-2d/package.json | 6 +- packages/gcode-renderer-three/CHANGELOG.md | 24 ++++ packages/gcode-renderer-three/package.json | 6 +- packages/toolpath-core/CHANGELOG.md | 40 ++++++ packages/toolpath-core/package.json | 2 +- 37 files changed, 437 insertions(+), 295 deletions(-) delete mode 100644 .changeset/cnc-evidence-detection.md delete mode 100644 .changeset/dd012-canned-cycles.md delete mode 100644 .changeset/dd012-cnc-coloring.md delete mode 100644 .changeset/dd012-cnc-dialects.md delete mode 100644 .changeset/dd012-cut-classification.md delete mode 100644 .changeset/dd012-modal-motion.md delete mode 100644 .changeset/dd012-modal-toolpower.md delete mode 100644 .changeset/g0-rapid-travel-classification.md delete mode 100644 .changeset/grbl-laser-validated.md delete mode 100644 .changeset/lexer-multicommand.md diff --git a/.changeset/cnc-evidence-detection.md b/.changeset/cnc-evidence-detection.md deleted file mode 100644 index 7d52f8ba..00000000 --- a/.changeset/cnc-evidence-detection.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -"@chestnutlabs/gcode-dialects": minor ---- - -feat: evidence-based non-extrusion detection — recognize header-less real CNC/laser files (#189) - -The phase-3 CNC/laser detectors were tuned on synthetic fixtures and matched **none** of the real -public samples (LaserGRBL, LinuxCNC, GRBL CAM output) — real controller output usually has **no -generator header** and writes commands **mid-line** and **concatenated** (`s3400 m3`, `g1z-.1`). - -Detection is now **evidence-scored**, not banner-only: - -- A shared `scoreEvidence` extractor strips comments (so `(M3)` / `; LinuxCNC` in a comment can't - create a false marker) and matches commands as words anywhere on a line. -- **GRBL laser** — LightBurn / `$32=1`, **or** the header-less form: a tool-on command (`M3`/`M4`) with - `S` power and **no Z-plunge** (lasers are planar). -- **GRBL / generic mill** — `M3` spindle that **plunges into negative Z** with no extrusion (a milling - fingerprint that separates it from a planar laser); banner optional. -- **LinuxCNC** — explicit header, **or** RS274NGC **O-word** subroutines/flow (`o100 sub`). -- Extrusion detection tightened to `E` on a **motion line**, so LinuxCNC `M67 E0 Q…` analog laser power - is no longer mistaken for FDM. - -Real-file result: **0/6 → 3/6 detected, each with the correct machine class** (laser→laser, mill→mill, -LinuxCNC→linuxcnc); the misses are honest — files with a commented-out or absent spindle carry no -tool-state to infer. Still **experimental tier** (claims reported `inferred`) — detection working on -real files is one input; semantic ground truth (does our `Cut` = actual cutting, `S` scale) still wants -a real machine or a trusted reference. diff --git a/.changeset/dd012-canned-cycles.md b/.changeset/dd012-canned-cycles.md deleted file mode 100644 index b5b1aade..00000000 --- a/.changeset/dd012-canned-cycles.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -"@chestnutlabs/gcode-parser": minor ---- - -feat: canned drilling cycle expansion — G81/G82/G83 (DD-012 phase 2, #189) - -CNC canned drilling cycles previously produced **zero geometry** — holes vanished. They now expand to -explicit sub-moves so the drilling is real, classified toolpath: - -- **G81/G82** (drill / drill-with-dwell): rapid to the hole XY, rapid down to the R plane, **feed to - depth (`Cut`)**, rapid retract. -- **G83** (peck): the plunge is a peck loop — feed down by `Q`, rapid-retract to R between pecks, until - reaching depth; each down-feed is a `Cut`. -- **G98/G99** set the retract plane (initial Z vs R); **G80** cancels; a `G0`–`G3` motion also cancels. -- **Modal repeat**: with a cycle active, a bare `X`/`Y` line drills another hole (retaining Z/R/Q and - the initial plane) — the common CNC hole-pattern form. -- Rapids are `Travel`, plunges are `Cut`; new capability **`cannedCycles`** (`known` once a cycle is - seen, else `unavailable`). - -FDM output is unchanged (no canned cycles in FDM); the native-golden corpus gains only the additive -`cannedCycles` capability, with no geometry change. diff --git a/.changeset/dd012-cnc-coloring.md b/.changeset/dd012-cnc-coloring.md deleted file mode 100644 index cffd2ecc..00000000 --- a/.changeset/dd012-cnc-coloring.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -"@chestnutlabs/gcode-colors": minor -"@chestnutlabs/gcode-renderer-three": minor ---- - -feat: non-extrusion color modes — color-by-power + cut-vs-rapid (DD-012 phase 4, #189) - -Two new `ColorMode`s consuming the #189 channels (DD-012 D7): - -- **`power`** — ramps each segment's modal `toolPower` (laser power / spindle RPM, the `S` value) onto - a color ramp, the CNC/laser counterpart to color-by-speed. Auto-ranged (`toolPowerRange`) or explicit; - `NaN` (tool off) or a file parsed without the `toolPower` channel → fallback, never a fabricated color. - Capability-gated on `toolPower` (the Three renderer's `isColorModeAvailable` gates it). -- **`moveKind`** — cut-vs-rapid: productive moves (`Extrude` or `Cut`) vs rapids (`Travel`) — the - "where the tool is actually working" view. Reads the always-present `kind` channel, so it is always - available. - -Both flow through `createSegmentColorer`, so the Three and Canvas-2D renderers get them for free. FDM -coloring is unchanged. diff --git a/.changeset/dd012-cnc-dialects.md b/.changeset/dd012-cnc-dialects.md deleted file mode 100644 index fd870ecd..00000000 --- a/.changeset/dd012-cnc-dialects.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -"@chestnutlabs/gcode-dialects": minor -"@chestnutlabs/gcode-parser": minor ---- - -feat: non-extrusion dialect families + validation tiers (DD-012 phase 3, #189) - -Adds controller detection and the **validation-tier honesty mechanism** for CNC/laser toolpaths: - -- New dialects (`@chestnutlabs/gcode-dialects`): **GRBL laser** (LightBurn / `$32` laser mode / `M4`+`S`), - **GRBL mill** and **LinuxCNC** (`M3` spindle, `%`/banner envelopes). Registered in the batteries worker. -- Each dialect adds provenance (`cnc.controller`, `cnc.machineClass`, `cnc.toolPowerLabel`) and a - **validation tier** (`cnc.validationTier`). Per DD-012 D6: an **experimental** dialect reports its - non-extrusion claims (`cutMoves` / `toolPower` / `cannedCycles`) as **`inferred`** (never `known`), - with a `cnc-dialect-experimental` disclosure — and only for claims the file actually made (an unused - feature is never fabricated). -- **All launch dialects ship `experimental`** (synthetic fixtures only). A single `tier: 'validated'` - flip per controller promotes its claims to `known` once confirmed on real hardware (DD-012 §8/§15). - -Geometry is untouched (dialects only annotate/label). FDM detection is unaffected — CNC dialects do -not match FDM output. diff --git a/.changeset/dd012-cut-classification.md b/.changeset/dd012-cut-classification.md deleted file mode 100644 index 6b1934e6..00000000 --- a/.changeset/dd012-cut-classification.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -"@chestnutlabs/toolpath-core": minor -"@chestnutlabs/gcode-parser": minor ---- - -feat: non-extrusion `Cut` move classification + tool-state modal (DD-012 phase 1, #189) - -Non-extrusion toolpaths (CNC / laser / plotter) no longer collapse their productive moves into -`Travel`. The parser now tracks a tool-engaged modal state — `M3`/`M4` (spindle/laser on, incl. the -`M03`/`M04` leading-zero form) engage it, `M5` disengages — and classifies a move with **no extrusion -`E`** while the tool is engaged as the new **`MoveKind.Cut`** bit (a CNC/laser/plotter counterpart to -`Extrude`, composing with `ArcSegment` like the other kinds). - -- New IR move kind `MoveKind.Cut = 1 << 7` (`@chestnutlabs/toolpath-core`). -- New capability **`cutMoves`**: `known` once a tool-state modal is seen (a CNC/laser/plotter file), - `unavailable` for FDM. -- **FDM is byte-identical**: FDM slices never issue `M3`/`M4`, so `Cut` is never set and every move - stays `Extrude`/`Travel` exactly as before (verified against the native-golden corpus; the CNC - fixtures `demo-easel`/`demo-mach3` are documented intentional adapter-divergences). - -Modal tool-state *value* channels (laser power / spindle RPM via `S`), canned-cycle expansion, and -dialect families follow in later DD-012 phases. diff --git a/.changeset/dd012-modal-motion.md b/.changeset/dd012-modal-motion.md deleted file mode 100644 index ee82ac06..00000000 --- a/.changeset/dd012-modal-motion.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -"@chestnutlabs/gcode-parser": minor ---- - -feat: modal motion continuation — bare coordinate lines repeat the last G0–G3 (DD-012 phase 2, #189) - -CNC/LinuxCNC-style G-code frequently omits the `G` word on repeated moves (`G1 X0 Y0` then bare -`X10 Y0` / `X20 Y0`). The parser previously **dropped** those lines entirely — a three-move path -produced a single segment. It now tracks the active `G0`–`G3` motion mode and treats a line whose -leading word is a coordinate axis (`X`/`Y`/`Z`, with no `G`/`M`/`T` command) as a continuation of -that mode, so the full toolpath is emitted and classified/colored consistently (incl. inline `S` -for `toolPower`). - -FDM output is **byte-identical** — slicers always emit the `G` word, so the continuation path never -triggers (the native-golden corpus is unchanged). This unblocks canned-cycle repeat (next phase). diff --git a/.changeset/dd012-modal-toolpower.md b/.changeset/dd012-modal-toolpower.md deleted file mode 100644 index 90d2674e..00000000 --- a/.changeset/dd012-modal-toolpower.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -"@chestnutlabs/toolpath-core": minor -"@chestnutlabs/gcode-parser": minor ---- - -feat: opt-in modal tool-power channel (DD-012 phase 1 — the `ModalChannel` mechanism, #189) - -Adds the shared, opt-in **`ModalChannel`** mechanism DD-012 D3 is built around, and its first channel: -**`toolPower`** — the modal spindle/laser `S` value while a tool is engaged. - -- `ParseOptions.modalChannels?: readonly string[]` — request per-segment modal channels by id. - Supported id: `'toolPower'`. Unknown ids are ignored with a `modal-channel-unsupported` warning. -- `ToolpathSegments.modal?: Readonly>` — one Float32 column per requested - channel, present **only** when requested. An unset value is `NaN` (an honest "no value here"), never - a fabricated `0`. `toolPower` is the modal `S` (set on `M3`/`M4` and inline on GRBL-laser motion - lines) while engaged, `NaN` when the tool is off (`M5`). -- New capability **`toolPower`**: surfaced only when the channel is requested — `known` once a - tool-state modal is seen, else `unavailable`. -- **Default parse pays nothing**: no `modalChannels` ⇒ no `modal` on the IR, no extra columns, FDM - output unchanged. The budget-aware SoA writer (DD-003) grows the opt-in columns in lockstep and - accounts their bytes. - -Presentation (Watts vs RPM) is a dialect label, not a separate channel (DD-012 D4); #180's -fan/temp/accel color channels reuse this same mechanism in a later phase. diff --git a/.changeset/g0-rapid-travel-classification.md b/.changeset/g0-rapid-travel-classification.md deleted file mode 100644 index c09f95a1..00000000 --- a/.changeset/g0-rapid-travel-classification.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -"@chestnutlabs/gcode-parser": patch ---- - -fix: G0 rapids classify as Travel, not Cut, even while the tool is engaged (#189) - -The non-extrusion `Cut`/`Travel` classifier keyed only on tool-state (`M3`/`M4` latched), so on a -router — where the spindle stays on across rapids — every `G0` reposition was counted as a cutting -move. DD-012 D2 §4.2 already specifies that rapids stay `Travel`; this brings the implementation in -line: only a **feed** move (`G1`/`G2`/`G3`) with the tool engaged and no `E` delta is `Cut`; a `G0` -rapid is `Travel` regardless of tool state (a GRBL-laser also gates the beam off during `G0`). - -Surfaced by the CNC/laser validation harness on real files — e.g. the `easel` router fixture went -from 742 cut / 0 rapids to a correct 737 cut / 5 rapids (its 5 `G0` moves). Geometry is unchanged -(only the `kind` column shifts); FDM output is byte-identical since `Cut` is never evaluated there. diff --git a/.changeset/grbl-laser-validated.md b/.changeset/grbl-laser-validated.md deleted file mode 100644 index f2f5b6d3..00000000 --- a/.changeset/grbl-laser-validated.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -"@chestnutlabs/gcode-dialects": minor ---- - -feat(dialects): promote grbl-laser experimental → validated on hardware evidence (#189) - -First hardware-validation pass (DD-012 D8): a real GRBL/LightBurn diode-laser run — 6161 moves incl. -fill + offset-fill, full 0–1000 `S` power ramp — confirmed machine-class detection, the Cut-vs-rapid -split, and the `toolPower` channel against the physical cut (all claims ✓). `grbl-laser` is flipped -`experimental → validated`: for laser files its `cutMoves`/`toolPower` claims now report **`known`** -instead of `inferred`, and the `cnc-dialect-experimental` warning is no longer emitted. - -Scope is per-controller: `grbl-mill` and `linuxcnc` remain `experimental` (claims stay `inferred`) -until a run on real CNC hardware. Evidence recorded in `docs/design/DD-012-hardware-validation-log.md`. diff --git a/.changeset/lexer-multicommand.md b/.changeset/lexer-multicommand.md deleted file mode 100644 index 10ac1ac2..00000000 --- a/.changeset/lexer-multicommand.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -"@chestnutlabs/gcode-parser": minor ---- - -feat: lexer handles multi-command lines, N-word line numbers, and bare S/F (#189) - -Real CNC/laser G-code (GRBL, LinuxCNC, TinyG, Mach3, Fanuc) is written very differently from FDM -slicer output, and the inherited first-word lexer silently dropped most of it. The lexer now: - -- **Reads every G/M/T command word on a line**, not just the first — `G20 G17 G90`, `G91 G81 …`, - `S3400 M3` now all apply. This was the biggest gap: `M3` spindle-on and `G81` canned cycles were - being dropped as params, so mills showed no `Cut` moves and drilled holes vanished. -- **Strips `N`-word line numbers** (`N10 G1 X…`) — Fanuc/Mach/TinyG number every line, which - previously reduced whole files to zero geometry. -- **Latches bare `S` / `F` lines** (standalone `S1000` / `F600`) into modal power/feed — common in - GRBL-laser output. -- Guards against **letters embedded in extended-command words** (`EXCLUDE_OBJECT … POLYGON=…`): a - command/param is only taken when a real number follows the letter, so `T` in `M486 T` / - `M104 T` stays a parameter (not a tool select), and the `G` in `POLYGON` never becomes a move. - -Validated against real public sample files: a LinuxCNC arc-spiral went from 16 → 5,506 parsed -segments, a TinyG program from 0 → 344. **FDM output is byte-identical** — slicers emit one clean -command per line, so the multi-command path never runs for them (the real-G-code native-golden corpus -is unchanged except for fewer spurious `unsupported-command` warnings; `demo-mach3` and one adversarial -binary fixture are documented intentional divergences). diff --git a/package-lock.json b/package-lock.json index 4cbfef55..8d984506 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7385,11 +7385,11 @@ }, "packages/gcode-bgcode": { "name": "@chestnutlabs/gcode-bgcode", - "version": "0.3.0", + "version": "0.4.0", "license": "MIT", "dependencies": { - "@chestnutlabs/gcode-containers": "0.3.0", - "@chestnutlabs/toolpath-core": "0.3.0" + "@chestnutlabs/gcode-containers": "0.4.0", + "@chestnutlabs/toolpath-core": "0.4.0" }, "engines": { "node": ">=22" @@ -7397,10 +7397,10 @@ }, "packages/gcode-colors": { "name": "@chestnutlabs/gcode-colors", - "version": "0.3.0", + "version": "0.4.0", "license": "MIT", "dependencies": { - "@chestnutlabs/toolpath-core": "0.3.0" + "@chestnutlabs/toolpath-core": "0.4.0" }, "engines": { "node": ">=22" @@ -7408,10 +7408,10 @@ }, "packages/gcode-containers": { "name": "@chestnutlabs/gcode-containers", - "version": "0.3.0", + "version": "0.4.0", "license": "MIT", "dependencies": { - "@chestnutlabs/toolpath-core": "0.3.0" + "@chestnutlabs/toolpath-core": "0.4.0" }, "engines": { "node": ">=22" @@ -7419,10 +7419,10 @@ }, "packages/gcode-dialects": { "name": "@chestnutlabs/gcode-dialects", - "version": "0.3.0", + "version": "0.4.0", "license": "MIT", "dependencies": { - "@chestnutlabs/toolpath-core": "0.3.0" + "@chestnutlabs/toolpath-core": "0.4.0" }, "engines": { "node": ">=22" @@ -7430,13 +7430,13 @@ }, "packages/gcode-parser": { "name": "@chestnutlabs/gcode-parser", - "version": "0.3.0", + "version": "0.4.0", "license": "MIT", "dependencies": { - "@chestnutlabs/gcode-bgcode": "0.3.0", - "@chestnutlabs/gcode-containers": "0.3.0", - "@chestnutlabs/gcode-dialects": "0.3.0", - "@chestnutlabs/toolpath-core": "0.3.0" + "@chestnutlabs/gcode-bgcode": "0.4.0", + "@chestnutlabs/gcode-containers": "0.4.0", + "@chestnutlabs/gcode-dialects": "0.4.0", + "@chestnutlabs/toolpath-core": "0.4.0" }, "engines": { "node": ">=22" @@ -7444,13 +7444,13 @@ }, "packages/gcode-preview-core": { "name": "@chestnutlabs/gcode-preview-core", - "version": "0.3.0", + "version": "0.4.0", "license": "MIT", "dependencies": { - "@chestnutlabs/gcode-parser": "0.3.0", - "@chestnutlabs/gcode-renderer-2d": "0.3.0", - "@chestnutlabs/gcode-renderer-three": "0.3.0", - "@chestnutlabs/toolpath-core": "0.3.0" + "@chestnutlabs/gcode-parser": "0.4.0", + "@chestnutlabs/gcode-renderer-2d": "0.4.0", + "@chestnutlabs/gcode-renderer-three": "0.4.0", + "@chestnutlabs/toolpath-core": "0.4.0" }, "engines": { "node": ">=22" @@ -7458,13 +7458,13 @@ }, "packages/gcode-preview-element": { "name": "@chestnutlabs/gcode-preview-element", - "version": "0.3.0", + "version": "0.4.0", "license": "MIT", "dependencies": { - "@chestnutlabs/gcode-parser": "0.3.0", - "@chestnutlabs/gcode-preview-core": "0.3.0", - "@chestnutlabs/gcode-renderer-three": "0.3.0", - "@chestnutlabs/toolpath-core": "0.3.0" + "@chestnutlabs/gcode-parser": "0.4.0", + "@chestnutlabs/gcode-preview-core": "0.4.0", + "@chestnutlabs/gcode-renderer-three": "0.4.0", + "@chestnutlabs/toolpath-core": "0.4.0" }, "engines": { "node": ">=22" @@ -7472,13 +7472,13 @@ }, "packages/gcode-preview-react": { "name": "@chestnutlabs/gcode-preview-react", - "version": "0.3.0", + "version": "0.4.0", "license": "MIT", "dependencies": { - "@chestnutlabs/gcode-parser": "0.3.0", - "@chestnutlabs/gcode-preview-core": "0.3.0", - "@chestnutlabs/gcode-renderer-three": "0.3.0", - "@chestnutlabs/toolpath-core": "0.3.0" + "@chestnutlabs/gcode-parser": "0.4.0", + "@chestnutlabs/gcode-preview-core": "0.4.0", + "@chestnutlabs/gcode-renderer-three": "0.4.0", + "@chestnutlabs/toolpath-core": "0.4.0" }, "devDependencies": { "@types/react": "^18.3.0", @@ -7494,13 +7494,13 @@ }, "packages/gcode-preview-svelte": { "name": "@chestnutlabs/gcode-preview-svelte", - "version": "0.3.0", + "version": "0.4.0", "license": "MIT", "dependencies": { - "@chestnutlabs/gcode-parser": "0.3.0", - "@chestnutlabs/gcode-preview-core": "0.3.0", - "@chestnutlabs/gcode-renderer-three": "0.3.0", - "@chestnutlabs/toolpath-core": "0.3.0" + "@chestnutlabs/gcode-parser": "0.4.0", + "@chestnutlabs/gcode-preview-core": "0.4.0", + "@chestnutlabs/gcode-renderer-three": "0.4.0", + "@chestnutlabs/toolpath-core": "0.4.0" }, "devDependencies": { "svelte": "^4.2.0" @@ -7514,13 +7514,13 @@ }, "packages/gcode-preview-vue": { "name": "@chestnutlabs/gcode-preview-vue", - "version": "0.3.0", + "version": "0.4.0", "license": "MIT", "dependencies": { - "@chestnutlabs/gcode-parser": "0.3.0", - "@chestnutlabs/gcode-preview-core": "0.3.0", - "@chestnutlabs/gcode-renderer-three": "0.3.0", - "@chestnutlabs/toolpath-core": "0.3.0" + "@chestnutlabs/gcode-parser": "0.4.0", + "@chestnutlabs/gcode-preview-core": "0.4.0", + "@chestnutlabs/gcode-renderer-three": "0.4.0", + "@chestnutlabs/toolpath-core": "0.4.0" }, "devDependencies": { "vue": "^3.4.0" @@ -7534,11 +7534,11 @@ }, "packages/gcode-renderer-2d": { "name": "@chestnutlabs/gcode-renderer-2d", - "version": "0.3.0", + "version": "0.4.0", "license": "MIT", "dependencies": { - "@chestnutlabs/gcode-colors": "0.3.0", - "@chestnutlabs/toolpath-core": "0.3.0" + "@chestnutlabs/gcode-colors": "0.4.0", + "@chestnutlabs/toolpath-core": "0.4.0" }, "engines": { "node": ">=22" @@ -7546,11 +7546,11 @@ }, "packages/gcode-renderer-three": { "name": "@chestnutlabs/gcode-renderer-three", - "version": "0.3.0", + "version": "0.4.0", "license": "MIT", "dependencies": { - "@chestnutlabs/gcode-colors": "0.3.0", - "@chestnutlabs/toolpath-core": "0.3.0" + "@chestnutlabs/gcode-colors": "0.4.0", + "@chestnutlabs/toolpath-core": "0.4.0" }, "devDependencies": { "@types/three": "0.178.0" @@ -7564,7 +7564,7 @@ }, "packages/toolpath-core": { "name": "@chestnutlabs/toolpath-core", - "version": "0.3.0", + "version": "0.4.0", "license": "MIT", "engines": { "node": ">=22" diff --git a/packages/gcode-bgcode/CHANGELOG.md b/packages/gcode-bgcode/CHANGELOG.md index c6070e88..98247a5d 100644 --- a/packages/gcode-bgcode/CHANGELOG.md +++ b/packages/gcode-bgcode/CHANGELOG.md @@ -1,5 +1,13 @@ # @chestnutlabs/gcode-bgcode +## 0.4.0 + +### Patch Changes + +- Updated dependencies [[`1029580`](https://github.com/ChestnutLabs/gcode-preview/commit/10295803839816adaed224c48eba1f74374c0c2a), [`8fec7c3`](https://github.com/ChestnutLabs/gcode-preview/commit/8fec7c3622cd2a6d6d57b43d7866cfea1cb71e09)]: + - @chestnutlabs/toolpath-core@0.4.0 + - @chestnutlabs/gcode-containers@0.4.0 + ## 0.3.0 ### Minor Changes diff --git a/packages/gcode-bgcode/package.json b/packages/gcode-bgcode/package.json index 0eea326e..124e0995 100644 --- a/packages/gcode-bgcode/package.json +++ b/packages/gcode-bgcode/package.json @@ -1,6 +1,6 @@ { "name": "@chestnutlabs/gcode-bgcode", - "version": "0.3.0", + "version": "0.4.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", @@ -47,7 +47,7 @@ "test": "vitest run" }, "dependencies": { - "@chestnutlabs/toolpath-core": "0.3.0", - "@chestnutlabs/gcode-containers": "0.3.0" + "@chestnutlabs/toolpath-core": "0.4.0", + "@chestnutlabs/gcode-containers": "0.4.0" } } diff --git a/packages/gcode-colors/CHANGELOG.md b/packages/gcode-colors/CHANGELOG.md index ebc28a41..8199bd0d 100644 --- a/packages/gcode-colors/CHANGELOG.md +++ b/packages/gcode-colors/CHANGELOG.md @@ -1,5 +1,28 @@ # @chestnutlabs/gcode-colors +## 0.4.0 + +### Minor Changes + +- [#254](https://github.com/ChestnutLabs/gcode-preview/pull/254) [`5f59b77`](https://github.com/ChestnutLabs/gcode-preview/commit/5f59b7788bbb14cacfe21aaf3d7134c6ba8dcd86) Thanks [@sobechestnut-dev](https://github.com/sobechestnut-dev)! - feat: non-extrusion color modes — color-by-power + cut-vs-rapid (DD-012 phase 4, [#189](https://github.com/ChestnutLabs/gcode-preview/issues/189)) + + Two new `ColorMode`s consuming the [#189](https://github.com/ChestnutLabs/gcode-preview/issues/189) channels (DD-012 D7): + - **`power`** — ramps each segment's modal `toolPower` (laser power / spindle RPM, the `S` value) onto + a color ramp, the CNC/laser counterpart to color-by-speed. Auto-ranged (`toolPowerRange`) or explicit; + `NaN` (tool off) or a file parsed without the `toolPower` channel → fallback, never a fabricated color. + Capability-gated on `toolPower` (the Three renderer's `isColorModeAvailable` gates it). + - **`moveKind`** — cut-vs-rapid: productive moves (`Extrude` or `Cut`) vs rapids (`Travel`) — the + "where the tool is actually working" view. Reads the always-present `kind` channel, so it is always + available. + + Both flow through `createSegmentColorer`, so the Three and Canvas-2D renderers get them for free. FDM + coloring is unchanged. + +### Patch Changes + +- Updated dependencies [[`1029580`](https://github.com/ChestnutLabs/gcode-preview/commit/10295803839816adaed224c48eba1f74374c0c2a), [`8fec7c3`](https://github.com/ChestnutLabs/gcode-preview/commit/8fec7c3622cd2a6d6d57b43d7866cfea1cb71e09)]: + - @chestnutlabs/toolpath-core@0.4.0 + ## 0.3.0 ### Minor Changes diff --git a/packages/gcode-colors/package.json b/packages/gcode-colors/package.json index 81fa014b..37a414d1 100644 --- a/packages/gcode-colors/package.json +++ b/packages/gcode-colors/package.json @@ -1,6 +1,6 @@ { "name": "@chestnutlabs/gcode-colors", - "version": "0.3.0", + "version": "0.4.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", @@ -47,6 +47,6 @@ "test": "vitest run" }, "dependencies": { - "@chestnutlabs/toolpath-core": "0.3.0" + "@chestnutlabs/toolpath-core": "0.4.0" } } diff --git a/packages/gcode-containers/CHANGELOG.md b/packages/gcode-containers/CHANGELOG.md index eee8e6c7..c619c592 100644 --- a/packages/gcode-containers/CHANGELOG.md +++ b/packages/gcode-containers/CHANGELOG.md @@ -1,5 +1,12 @@ # @chestnutlabs/gcode-containers +## 0.4.0 + +### Patch Changes + +- Updated dependencies [[`1029580`](https://github.com/ChestnutLabs/gcode-preview/commit/10295803839816adaed224c48eba1f74374c0c2a), [`8fec7c3`](https://github.com/ChestnutLabs/gcode-preview/commit/8fec7c3622cd2a6d6d57b43d7866cfea1cb71e09)]: + - @chestnutlabs/toolpath-core@0.4.0 + ## 0.3.0 ### Patch Changes diff --git a/packages/gcode-containers/package.json b/packages/gcode-containers/package.json index 6fa15324..b5cf4409 100644 --- a/packages/gcode-containers/package.json +++ b/packages/gcode-containers/package.json @@ -1,6 +1,6 @@ { "name": "@chestnutlabs/gcode-containers", - "version": "0.3.0", + "version": "0.4.0", "description": "Safe, bounded, in-memory container extraction for sliced G-code (.gcode.3mf) — DD-005 §4.4/§7. Never writes files, never fetches, zero dependencies.", "keywords": [ "gcode", @@ -42,6 +42,6 @@ "test": "vitest run" }, "dependencies": { - "@chestnutlabs/toolpath-core": "0.3.0" + "@chestnutlabs/toolpath-core": "0.4.0" } } diff --git a/packages/gcode-dialects/CHANGELOG.md b/packages/gcode-dialects/CHANGELOG.md index f5d5d18f..cacaa069 100644 --- a/packages/gcode-dialects/CHANGELOG.md +++ b/packages/gcode-dialects/CHANGELOG.md @@ -1,5 +1,64 @@ # @chestnutlabs/gcode-dialects +## 0.4.0 + +### Minor Changes + +- [#258](https://github.com/ChestnutLabs/gcode-preview/pull/258) [`3f06e5b`](https://github.com/ChestnutLabs/gcode-preview/commit/3f06e5b7b6926daaad4290b29c577a380c9e10df) Thanks [@sobechestnut-dev](https://github.com/sobechestnut-dev)! - feat: evidence-based non-extrusion detection — recognize header-less real CNC/laser files ([#189](https://github.com/ChestnutLabs/gcode-preview/issues/189)) + + The phase-3 CNC/laser detectors were tuned on synthetic fixtures and matched **none** of the real + public samples (LaserGRBL, LinuxCNC, GRBL CAM output) — real controller output usually has **no + generator header** and writes commands **mid-line** and **concatenated** (`s3400 m3`, `g1z-.1`). + + Detection is now **evidence-scored**, not banner-only: + - A shared `scoreEvidence` extractor strips comments (so `(M3)` / `; LinuxCNC` in a comment can't + create a false marker) and matches commands as words anywhere on a line. + - **GRBL laser** — LightBurn / `$32=1`, **or** the header-less form: a tool-on command (`M3`/`M4`) with + `S` power and **no Z-plunge** (lasers are planar). + - **GRBL / generic mill** — `M3` spindle that **plunges into negative Z** with no extrusion (a milling + fingerprint that separates it from a planar laser); banner optional. + - **LinuxCNC** — explicit header, **or** RS274NGC **O-word** subroutines/flow (`o100 sub`). + - Extrusion detection tightened to `E` on a **motion line**, so LinuxCNC `M67 E0 Q…` analog laser power + is no longer mistaken for FDM. + + Real-file result: **0/6 → 3/6 detected, each with the correct machine class** (laser→laser, mill→mill, + LinuxCNC→linuxcnc); the misses are honest — files with a commented-out or absent spindle carry no + tool-state to infer. Still **experimental tier** (claims reported `inferred`) — detection working on + real files is one input; semantic ground truth (does our `Cut` = actual cutting, `S` scale) still wants + a real machine or a trusted reference. + +- [#253](https://github.com/ChestnutLabs/gcode-preview/pull/253) [`13fd5c6`](https://github.com/ChestnutLabs/gcode-preview/commit/13fd5c61d730428a7f7e73c28cf3cc9c48e68c19) Thanks [@sobechestnut-dev](https://github.com/sobechestnut-dev)! - feat: non-extrusion dialect families + validation tiers (DD-012 phase 3, [#189](https://github.com/ChestnutLabs/gcode-preview/issues/189)) + + Adds controller detection and the **validation-tier honesty mechanism** for CNC/laser toolpaths: + - New dialects (`@chestnutlabs/gcode-dialects`): **GRBL laser** (LightBurn / `$32` laser mode / `M4`+`S`), + **GRBL mill** and **LinuxCNC** (`M3` spindle, `%`/banner envelopes). Registered in the batteries worker. + - Each dialect adds provenance (`cnc.controller`, `cnc.machineClass`, `cnc.toolPowerLabel`) and a + **validation tier** (`cnc.validationTier`). Per DD-012 D6: an **experimental** dialect reports its + non-extrusion claims (`cutMoves` / `toolPower` / `cannedCycles`) as **`inferred`** (never `known`), + with a `cnc-dialect-experimental` disclosure — and only for claims the file actually made (an unused + feature is never fabricated). + - **All launch dialects ship `experimental`** (synthetic fixtures only). A single `tier: 'validated'` + flip per controller promotes its claims to `known` once confirmed on real hardware (DD-012 §8/§15). + + Geometry is untouched (dialects only annotate/label). FDM detection is unaffected — CNC dialects do + not match FDM output. + +- [#262](https://github.com/ChestnutLabs/gcode-preview/pull/262) [`3e244ae`](https://github.com/ChestnutLabs/gcode-preview/commit/3e244aee86463f2a8c030b3793d3bb2dd462e3a9) Thanks [@sobechestnut-dev](https://github.com/sobechestnut-dev)! - feat(dialects): promote grbl-laser experimental → validated on hardware evidence ([#189](https://github.com/ChestnutLabs/gcode-preview/issues/189)) + + First hardware-validation pass (DD-012 D8): a real GRBL/LightBurn diode-laser run — 6161 moves incl. + fill + offset-fill, full 0–1000 `S` power ramp — confirmed machine-class detection, the Cut-vs-rapid + split, and the `toolPower` channel against the physical cut (all claims ✓). `grbl-laser` is flipped + `experimental → validated`: for laser files its `cutMoves`/`toolPower` claims now report **`known`** + instead of `inferred`, and the `cnc-dialect-experimental` warning is no longer emitted. + + Scope is per-controller: `grbl-mill` and `linuxcnc` remain `experimental` (claims stay `inferred`) + until a run on real CNC hardware. Evidence recorded in `docs/design/DD-012-hardware-validation-log.md`. + +### Patch Changes + +- Updated dependencies [[`1029580`](https://github.com/ChestnutLabs/gcode-preview/commit/10295803839816adaed224c48eba1f74374c0c2a), [`8fec7c3`](https://github.com/ChestnutLabs/gcode-preview/commit/8fec7c3622cd2a6d6d57b43d7866cfea1cb71e09)]: + - @chestnutlabs/toolpath-core@0.4.0 + ## 0.3.0 ### Minor Changes diff --git a/packages/gcode-dialects/package.json b/packages/gcode-dialects/package.json index 19c3df00..1955fda4 100644 --- a/packages/gcode-dialects/package.json +++ b/packages/gcode-dialects/package.json @@ -1,6 +1,6 @@ { "name": "@chestnutlabs/gcode-dialects", - "version": "0.3.0", + "version": "0.4.0", "description": "Slicer/firmware dialect adapters for ToolpathIR annotation (DD-005). Adapters annotate metadata and optional channels — they can never alter geometry.", "keywords": [ "gcode", @@ -45,6 +45,6 @@ "test": "vitest run" }, "dependencies": { - "@chestnutlabs/toolpath-core": "0.3.0" + "@chestnutlabs/toolpath-core": "0.4.0" } } diff --git a/packages/gcode-parser/CHANGELOG.md b/packages/gcode-parser/CHANGELOG.md index a2df3f5a..0880b56a 100644 --- a/packages/gcode-parser/CHANGELOG.md +++ b/packages/gcode-parser/CHANGELOG.md @@ -1,5 +1,131 @@ # @chestnutlabs/gcode-parser +## 0.4.0 + +### Minor Changes + +- [#252](https://github.com/ChestnutLabs/gcode-preview/pull/252) [`b2053be`](https://github.com/ChestnutLabs/gcode-preview/commit/b2053be4b8e71250bc6077f60ef996fe601b6f3e) Thanks [@sobechestnut-dev](https://github.com/sobechestnut-dev)! - feat: canned drilling cycle expansion — G81/G82/G83 (DD-012 phase 2, [#189](https://github.com/ChestnutLabs/gcode-preview/issues/189)) + + CNC canned drilling cycles previously produced **zero geometry** — holes vanished. They now expand to + explicit sub-moves so the drilling is real, classified toolpath: + - **G81/G82** (drill / drill-with-dwell): rapid to the hole XY, rapid down to the R plane, **feed to + depth (`Cut`)**, rapid retract. + - **G83** (peck): the plunge is a peck loop — feed down by `Q`, rapid-retract to R between pecks, until + reaching depth; each down-feed is a `Cut`. + - **G98/G99** set the retract plane (initial Z vs R); **G80** cancels; a `G0`–`G3` motion also cancels. + - **Modal repeat**: with a cycle active, a bare `X`/`Y` line drills another hole (retaining Z/R/Q and + the initial plane) — the common CNC hole-pattern form. + - Rapids are `Travel`, plunges are `Cut`; new capability **`cannedCycles`** (`known` once a cycle is + seen, else `unavailable`). + + FDM output is unchanged (no canned cycles in FDM); the native-golden corpus gains only the additive + `cannedCycles` capability, with no geometry change. + +- [#253](https://github.com/ChestnutLabs/gcode-preview/pull/253) [`13fd5c6`](https://github.com/ChestnutLabs/gcode-preview/commit/13fd5c61d730428a7f7e73c28cf3cc9c48e68c19) Thanks [@sobechestnut-dev](https://github.com/sobechestnut-dev)! - feat: non-extrusion dialect families + validation tiers (DD-012 phase 3, [#189](https://github.com/ChestnutLabs/gcode-preview/issues/189)) + + Adds controller detection and the **validation-tier honesty mechanism** for CNC/laser toolpaths: + - New dialects (`@chestnutlabs/gcode-dialects`): **GRBL laser** (LightBurn / `$32` laser mode / `M4`+`S`), + **GRBL mill** and **LinuxCNC** (`M3` spindle, `%`/banner envelopes). Registered in the batteries worker. + - Each dialect adds provenance (`cnc.controller`, `cnc.machineClass`, `cnc.toolPowerLabel`) and a + **validation tier** (`cnc.validationTier`). Per DD-012 D6: an **experimental** dialect reports its + non-extrusion claims (`cutMoves` / `toolPower` / `cannedCycles`) as **`inferred`** (never `known`), + with a `cnc-dialect-experimental` disclosure — and only for claims the file actually made (an unused + feature is never fabricated). + - **All launch dialects ship `experimental`** (synthetic fixtures only). A single `tier: 'validated'` + flip per controller promotes its claims to `known` once confirmed on real hardware (DD-012 §8/§15). + + Geometry is untouched (dialects only annotate/label). FDM detection is unaffected — CNC dialects do + not match FDM output. + +- [#248](https://github.com/ChestnutLabs/gcode-preview/pull/248) [`1029580`](https://github.com/ChestnutLabs/gcode-preview/commit/10295803839816adaed224c48eba1f74374c0c2a) Thanks [@sobechestnut-dev](https://github.com/sobechestnut-dev)! - feat: non-extrusion `Cut` move classification + tool-state modal (DD-012 phase 1, [#189](https://github.com/ChestnutLabs/gcode-preview/issues/189)) + + Non-extrusion toolpaths (CNC / laser / plotter) no longer collapse their productive moves into + `Travel`. The parser now tracks a tool-engaged modal state — `M3`/`M4` (spindle/laser on, incl. the + `M03`/`M04` leading-zero form) engage it, `M5` disengages — and classifies a move with **no extrusion + `E`** while the tool is engaged as the new **`MoveKind.Cut`** bit (a CNC/laser/plotter counterpart to + `Extrude`, composing with `ArcSegment` like the other kinds). + - New IR move kind `MoveKind.Cut = 1 << 7` (`@chestnutlabs/toolpath-core`). + - New capability **`cutMoves`**: `known` once a tool-state modal is seen (a CNC/laser/plotter file), + `unavailable` for FDM. + - **FDM is byte-identical**: FDM slices never issue `M3`/`M4`, so `Cut` is never set and every move + stays `Extrude`/`Travel` exactly as before (verified against the native-golden corpus; the CNC + fixtures `demo-easel`/`demo-mach3` are documented intentional adapter-divergences). + + Modal tool-state _value_ channels (laser power / spindle RPM via `S`), canned-cycle expansion, and + dialect families follow in later DD-012 phases. + +- [#251](https://github.com/ChestnutLabs/gcode-preview/pull/251) [`11f317d`](https://github.com/ChestnutLabs/gcode-preview/commit/11f317de2d6cb963d2a7fb0c894c89d3d5adc86d) Thanks [@sobechestnut-dev](https://github.com/sobechestnut-dev)! - feat: modal motion continuation — bare coordinate lines repeat the last G0–G3 (DD-012 phase 2, [#189](https://github.com/ChestnutLabs/gcode-preview/issues/189)) + + CNC/LinuxCNC-style G-code frequently omits the `G` word on repeated moves (`G1 X0 Y0` then bare + `X10 Y0` / `X20 Y0`). The parser previously **dropped** those lines entirely — a three-move path + produced a single segment. It now tracks the active `G0`–`G3` motion mode and treats a line whose + leading word is a coordinate axis (`X`/`Y`/`Z`, with no `G`/`M`/`T` command) as a continuation of + that mode, so the full toolpath is emitted and classified/colored consistently (incl. inline `S` + for `toolPower`). + + FDM output is **byte-identical** — slicers always emit the `G` word, so the continuation path never + triggers (the native-golden corpus is unchanged). This unblocks canned-cycle repeat (next phase). + +- [#250](https://github.com/ChestnutLabs/gcode-preview/pull/250) [`8fec7c3`](https://github.com/ChestnutLabs/gcode-preview/commit/8fec7c3622cd2a6d6d57b43d7866cfea1cb71e09) Thanks [@sobechestnut-dev](https://github.com/sobechestnut-dev)! - feat: opt-in modal tool-power channel (DD-012 phase 1 — the `ModalChannel` mechanism, [#189](https://github.com/ChestnutLabs/gcode-preview/issues/189)) + + Adds the shared, opt-in **`ModalChannel`** mechanism DD-012 D3 is built around, and its first channel: + **`toolPower`** — the modal spindle/laser `S` value while a tool is engaged. + - `ParseOptions.modalChannels?: readonly string[]` — request per-segment modal channels by id. + Supported id: `'toolPower'`. Unknown ids are ignored with a `modal-channel-unsupported` warning. + - `ToolpathSegments.modal?: Readonly>` — one Float32 column per requested + channel, present **only** when requested. An unset value is `NaN` (an honest "no value here"), never + a fabricated `0`. `toolPower` is the modal `S` (set on `M3`/`M4` and inline on GRBL-laser motion + lines) while engaged, `NaN` when the tool is off (`M5`). + - New capability **`toolPower`**: surfaced only when the channel is requested — `known` once a + tool-state modal is seen, else `unavailable`. + - **Default parse pays nothing**: no `modalChannels` ⇒ no `modal` on the IR, no extra columns, FDM + output unchanged. The budget-aware SoA writer (DD-003) grows the opt-in columns in lockstep and + accounts their bytes. + + Presentation (Watts vs RPM) is a dialect label, not a separate channel (DD-012 D4); [#180](https://github.com/ChestnutLabs/gcode-preview/issues/180)'s + fan/temp/accel color channels reuse this same mechanism in a later phase. + +- [#256](https://github.com/ChestnutLabs/gcode-preview/pull/256) [`b84bea9`](https://github.com/ChestnutLabs/gcode-preview/commit/b84bea959b7aae24d148e6bcc488a9ed254a54f0) Thanks [@sobechestnut-dev](https://github.com/sobechestnut-dev)! - feat: lexer handles multi-command lines, N-word line numbers, and bare S/F ([#189](https://github.com/ChestnutLabs/gcode-preview/issues/189)) + + Real CNC/laser G-code (GRBL, LinuxCNC, TinyG, Mach3, Fanuc) is written very differently from FDM + slicer output, and the inherited first-word lexer silently dropped most of it. The lexer now: + - **Reads every G/M/T command word on a line**, not just the first — `G20 G17 G90`, `G91 G81 …`, + `S3400 M3` now all apply. This was the biggest gap: `M3` spindle-on and `G81` canned cycles were + being dropped as params, so mills showed no `Cut` moves and drilled holes vanished. + - **Strips `N`-word line numbers** (`N10 G1 X…`) — Fanuc/Mach/TinyG number every line, which + previously reduced whole files to zero geometry. + - **Latches bare `S` / `F` lines** (standalone `S1000` / `F600`) into modal power/feed — common in + GRBL-laser output. + - Guards against **letters embedded in extended-command words** (`EXCLUDE_OBJECT … POLYGON=…`): a + command/param is only taken when a real number follows the letter, so `T` in `M486 T` / + `M104 T` stays a parameter (not a tool select), and the `G` in `POLYGON` never becomes a move. + + Validated against real public sample files: a LinuxCNC arc-spiral went from 16 → 5,506 parsed + segments, a TinyG program from 0 → 344. **FDM output is byte-identical** — slicers emit one clean + command per line, so the multi-command path never runs for them (the real-G-code native-golden corpus + is unchanged except for fewer spurious `unsupported-command` warnings; `demo-mach3` and one adversarial + binary fixture are documented intentional divergences). + +### Patch Changes + +- [#260](https://github.com/ChestnutLabs/gcode-preview/pull/260) [`879b60a`](https://github.com/ChestnutLabs/gcode-preview/commit/879b60ae0fca87ca8187791603a1bc7f54e61c4c) Thanks [@sobechestnut-dev](https://github.com/sobechestnut-dev)! - fix: G0 rapids classify as Travel, not Cut, even while the tool is engaged ([#189](https://github.com/ChestnutLabs/gcode-preview/issues/189)) + + The non-extrusion `Cut`/`Travel` classifier keyed only on tool-state (`M3`/`M4` latched), so on a + router — where the spindle stays on across rapids — every `G0` reposition was counted as a cutting + move. DD-012 D2 §4.2 already specifies that rapids stay `Travel`; this brings the implementation in + line: only a **feed** move (`G1`/`G2`/`G3`) with the tool engaged and no `E` delta is `Cut`; a `G0` + rapid is `Travel` regardless of tool state (a GRBL-laser also gates the beam off during `G0`). + + Surfaced by the CNC/laser validation harness on real files — e.g. the `easel` router fixture went + from 742 cut / 0 rapids to a correct 737 cut / 5 rapids (its 5 `G0` moves). Geometry is unchanged + (only the `kind` column shifts); FDM output is byte-identical since `Cut` is never evaluated there. + +- Updated dependencies [[`3f06e5b`](https://github.com/ChestnutLabs/gcode-preview/commit/3f06e5b7b6926daaad4290b29c577a380c9e10df), [`13fd5c6`](https://github.com/ChestnutLabs/gcode-preview/commit/13fd5c61d730428a7f7e73c28cf3cc9c48e68c19), [`1029580`](https://github.com/ChestnutLabs/gcode-preview/commit/10295803839816adaed224c48eba1f74374c0c2a), [`8fec7c3`](https://github.com/ChestnutLabs/gcode-preview/commit/8fec7c3622cd2a6d6d57b43d7866cfea1cb71e09), [`3e244ae`](https://github.com/ChestnutLabs/gcode-preview/commit/3e244aee86463f2a8c030b3793d3bb2dd462e3a9)]: + - @chestnutlabs/gcode-dialects@0.4.0 + - @chestnutlabs/toolpath-core@0.4.0 + - @chestnutlabs/gcode-bgcode@0.4.0 + - @chestnutlabs/gcode-containers@0.4.0 + ## 0.3.0 ### Minor Changes diff --git a/packages/gcode-parser/package.json b/packages/gcode-parser/package.json index f053c7c0..453c24ef 100644 --- a/packages/gcode-parser/package.json +++ b/packages/gcode-parser/package.json @@ -1,6 +1,6 @@ { "name": "@chestnutlabs/gcode-parser", - "version": "0.3.0", + "version": "0.4.0", "description": "Worker-safe G-code parse core producing ToolpathIR (DD-003).", "keywords": [ "gcode", @@ -49,9 +49,9 @@ "test": "vitest run" }, "dependencies": { - "@chestnutlabs/toolpath-core": "0.3.0", - "@chestnutlabs/gcode-dialects": "0.3.0", - "@chestnutlabs/gcode-containers": "0.3.0", - "@chestnutlabs/gcode-bgcode": "0.3.0" + "@chestnutlabs/toolpath-core": "0.4.0", + "@chestnutlabs/gcode-dialects": "0.4.0", + "@chestnutlabs/gcode-containers": "0.4.0", + "@chestnutlabs/gcode-bgcode": "0.4.0" } } diff --git a/packages/gcode-preview-core/CHANGELOG.md b/packages/gcode-preview-core/CHANGELOG.md index 4bd942fa..46a09aa8 100644 --- a/packages/gcode-preview-core/CHANGELOG.md +++ b/packages/gcode-preview-core/CHANGELOG.md @@ -1,5 +1,15 @@ # @chestnutlabs/gcode-preview-core +## 0.4.0 + +### Patch Changes + +- Updated dependencies [[`b2053be`](https://github.com/ChestnutLabs/gcode-preview/commit/b2053be4b8e71250bc6077f60ef996fe601b6f3e), [`5f59b77`](https://github.com/ChestnutLabs/gcode-preview/commit/5f59b7788bbb14cacfe21aaf3d7134c6ba8dcd86), [`13fd5c6`](https://github.com/ChestnutLabs/gcode-preview/commit/13fd5c61d730428a7f7e73c28cf3cc9c48e68c19), [`1029580`](https://github.com/ChestnutLabs/gcode-preview/commit/10295803839816adaed224c48eba1f74374c0c2a), [`11f317d`](https://github.com/ChestnutLabs/gcode-preview/commit/11f317de2d6cb963d2a7fb0c894c89d3d5adc86d), [`8fec7c3`](https://github.com/ChestnutLabs/gcode-preview/commit/8fec7c3622cd2a6d6d57b43d7866cfea1cb71e09), [`879b60a`](https://github.com/ChestnutLabs/gcode-preview/commit/879b60ae0fca87ca8187791603a1bc7f54e61c4c), [`b84bea9`](https://github.com/ChestnutLabs/gcode-preview/commit/b84bea959b7aae24d148e6bcc488a9ed254a54f0)]: + - @chestnutlabs/gcode-parser@0.4.0 + - @chestnutlabs/gcode-renderer-three@0.4.0 + - @chestnutlabs/toolpath-core@0.4.0 + - @chestnutlabs/gcode-renderer-2d@0.4.0 + ## 0.3.0 ### Minor Changes diff --git a/packages/gcode-preview-core/package.json b/packages/gcode-preview-core/package.json index 4af0892f..80b68ee8 100644 --- a/packages/gcode-preview-core/package.json +++ b/packages/gcode-preview-core/package.json @@ -1,6 +1,6 @@ { "name": "@chestnutlabs/gcode-preview-core", - "version": "0.3.0", + "version": "0.4.0", "description": "Framework-neutral preview controller for the Chestnut Labs G-code viewer (DD-007 §4.6): the shared engine glue, state model, and TypeScript contracts beneath the Vue/React/Svelte adapters.", "keywords": [ "gcode", @@ -52,9 +52,9 @@ "test": "vitest run" }, "dependencies": { - "@chestnutlabs/gcode-parser": "0.3.0", - "@chestnutlabs/gcode-renderer-2d": "0.3.0", - "@chestnutlabs/gcode-renderer-three": "0.3.0", - "@chestnutlabs/toolpath-core": "0.3.0" + "@chestnutlabs/gcode-parser": "0.4.0", + "@chestnutlabs/gcode-renderer-2d": "0.4.0", + "@chestnutlabs/gcode-renderer-three": "0.4.0", + "@chestnutlabs/toolpath-core": "0.4.0" } } diff --git a/packages/gcode-preview-element/CHANGELOG.md b/packages/gcode-preview-element/CHANGELOG.md index 31a42209..394ca749 100644 --- a/packages/gcode-preview-element/CHANGELOG.md +++ b/packages/gcode-preview-element/CHANGELOG.md @@ -1,5 +1,15 @@ # @chestnutlabs/gcode-preview-element +## 0.4.0 + +### Patch Changes + +- Updated dependencies [[`b2053be`](https://github.com/ChestnutLabs/gcode-preview/commit/b2053be4b8e71250bc6077f60ef996fe601b6f3e), [`5f59b77`](https://github.com/ChestnutLabs/gcode-preview/commit/5f59b7788bbb14cacfe21aaf3d7134c6ba8dcd86), [`13fd5c6`](https://github.com/ChestnutLabs/gcode-preview/commit/13fd5c61d730428a7f7e73c28cf3cc9c48e68c19), [`1029580`](https://github.com/ChestnutLabs/gcode-preview/commit/10295803839816adaed224c48eba1f74374c0c2a), [`11f317d`](https://github.com/ChestnutLabs/gcode-preview/commit/11f317de2d6cb963d2a7fb0c894c89d3d5adc86d), [`8fec7c3`](https://github.com/ChestnutLabs/gcode-preview/commit/8fec7c3622cd2a6d6d57b43d7866cfea1cb71e09), [`879b60a`](https://github.com/ChestnutLabs/gcode-preview/commit/879b60ae0fca87ca8187791603a1bc7f54e61c4c), [`b84bea9`](https://github.com/ChestnutLabs/gcode-preview/commit/b84bea959b7aae24d148e6bcc488a9ed254a54f0)]: + - @chestnutlabs/gcode-parser@0.4.0 + - @chestnutlabs/gcode-renderer-three@0.4.0 + - @chestnutlabs/toolpath-core@0.4.0 + - @chestnutlabs/gcode-preview-core@0.4.0 + ## 0.3.0 ### Minor Changes diff --git a/packages/gcode-preview-element/package.json b/packages/gcode-preview-element/package.json index 9f0efda2..f790bd6a 100644 --- a/packages/gcode-preview-element/package.json +++ b/packages/gcode-preview-element/package.json @@ -1,6 +1,6 @@ { "name": "@chestnutlabs/gcode-preview-element", - "version": "0.3.0", + "version": "0.4.0", "description": "Framework-free Web Component for the Chestnut Labs G-code viewer (DD-007 D1 / DD-009 D5): a custom element bridging @chestnutlabs/gcode-preview-core, no framework peer dependency.", "keywords": [ "gcode", @@ -52,9 +52,9 @@ "test": "vitest run" }, "dependencies": { - "@chestnutlabs/gcode-parser": "0.3.0", - "@chestnutlabs/gcode-preview-core": "0.3.0", - "@chestnutlabs/gcode-renderer-three": "0.3.0", - "@chestnutlabs/toolpath-core": "0.3.0" + "@chestnutlabs/gcode-parser": "0.4.0", + "@chestnutlabs/gcode-preview-core": "0.4.0", + "@chestnutlabs/gcode-renderer-three": "0.4.0", + "@chestnutlabs/toolpath-core": "0.4.0" } } diff --git a/packages/gcode-preview-react/CHANGELOG.md b/packages/gcode-preview-react/CHANGELOG.md index d08ac4c0..ea9071d1 100644 --- a/packages/gcode-preview-react/CHANGELOG.md +++ b/packages/gcode-preview-react/CHANGELOG.md @@ -1,5 +1,15 @@ # @chestnutlabs/gcode-preview-react +## 0.4.0 + +### Patch Changes + +- Updated dependencies [[`b2053be`](https://github.com/ChestnutLabs/gcode-preview/commit/b2053be4b8e71250bc6077f60ef996fe601b6f3e), [`5f59b77`](https://github.com/ChestnutLabs/gcode-preview/commit/5f59b7788bbb14cacfe21aaf3d7134c6ba8dcd86), [`13fd5c6`](https://github.com/ChestnutLabs/gcode-preview/commit/13fd5c61d730428a7f7e73c28cf3cc9c48e68c19), [`1029580`](https://github.com/ChestnutLabs/gcode-preview/commit/10295803839816adaed224c48eba1f74374c0c2a), [`11f317d`](https://github.com/ChestnutLabs/gcode-preview/commit/11f317de2d6cb963d2a7fb0c894c89d3d5adc86d), [`8fec7c3`](https://github.com/ChestnutLabs/gcode-preview/commit/8fec7c3622cd2a6d6d57b43d7866cfea1cb71e09), [`879b60a`](https://github.com/ChestnutLabs/gcode-preview/commit/879b60ae0fca87ca8187791603a1bc7f54e61c4c), [`b84bea9`](https://github.com/ChestnutLabs/gcode-preview/commit/b84bea959b7aae24d148e6bcc488a9ed254a54f0)]: + - @chestnutlabs/gcode-parser@0.4.0 + - @chestnutlabs/gcode-renderer-three@0.4.0 + - @chestnutlabs/toolpath-core@0.4.0 + - @chestnutlabs/gcode-preview-core@0.4.0 + ## 0.3.0 ### Minor Changes diff --git a/packages/gcode-preview-react/package.json b/packages/gcode-preview-react/package.json index 895267f7..b5694e3e 100644 --- a/packages/gcode-preview-react/package.json +++ b/packages/gcode-preview-react/package.json @@ -1,6 +1,6 @@ { "name": "@chestnutlabs/gcode-preview-react", - "version": "0.3.0", + "version": "0.4.0", "description": "Thin React integration for the Chestnut Labs G-code viewer (DD-007 D1 amendment): useGcodePreview hook + GcodePreview component as a reactivity bridge over @chestnutlabs/gcode-preview-core.", "keywords": [ "gcode", @@ -49,10 +49,10 @@ "test": "vitest run" }, "dependencies": { - "@chestnutlabs/gcode-parser": "0.3.0", - "@chestnutlabs/gcode-preview-core": "0.3.0", - "@chestnutlabs/gcode-renderer-three": "0.3.0", - "@chestnutlabs/toolpath-core": "0.3.0" + "@chestnutlabs/gcode-parser": "0.4.0", + "@chestnutlabs/gcode-preview-core": "0.4.0", + "@chestnutlabs/gcode-renderer-three": "0.4.0", + "@chestnutlabs/toolpath-core": "0.4.0" }, "peerDependencies": { "react": "^18.0.0 || ^19.0.0" diff --git a/packages/gcode-preview-svelte/CHANGELOG.md b/packages/gcode-preview-svelte/CHANGELOG.md index b9dc9277..da69cef6 100644 --- a/packages/gcode-preview-svelte/CHANGELOG.md +++ b/packages/gcode-preview-svelte/CHANGELOG.md @@ -1,5 +1,15 @@ # @chestnutlabs/gcode-preview-svelte +## 0.4.0 + +### Patch Changes + +- Updated dependencies [[`b2053be`](https://github.com/ChestnutLabs/gcode-preview/commit/b2053be4b8e71250bc6077f60ef996fe601b6f3e), [`5f59b77`](https://github.com/ChestnutLabs/gcode-preview/commit/5f59b7788bbb14cacfe21aaf3d7134c6ba8dcd86), [`13fd5c6`](https://github.com/ChestnutLabs/gcode-preview/commit/13fd5c61d730428a7f7e73c28cf3cc9c48e68c19), [`1029580`](https://github.com/ChestnutLabs/gcode-preview/commit/10295803839816adaed224c48eba1f74374c0c2a), [`11f317d`](https://github.com/ChestnutLabs/gcode-preview/commit/11f317de2d6cb963d2a7fb0c894c89d3d5adc86d), [`8fec7c3`](https://github.com/ChestnutLabs/gcode-preview/commit/8fec7c3622cd2a6d6d57b43d7866cfea1cb71e09), [`879b60a`](https://github.com/ChestnutLabs/gcode-preview/commit/879b60ae0fca87ca8187791603a1bc7f54e61c4c), [`b84bea9`](https://github.com/ChestnutLabs/gcode-preview/commit/b84bea959b7aae24d148e6bcc488a9ed254a54f0)]: + - @chestnutlabs/gcode-parser@0.4.0 + - @chestnutlabs/gcode-renderer-three@0.4.0 + - @chestnutlabs/toolpath-core@0.4.0 + - @chestnutlabs/gcode-preview-core@0.4.0 + ## 0.3.0 ### Minor Changes diff --git a/packages/gcode-preview-svelte/package.json b/packages/gcode-preview-svelte/package.json index f3777e31..e1b53813 100644 --- a/packages/gcode-preview-svelte/package.json +++ b/packages/gcode-preview-svelte/package.json @@ -1,6 +1,6 @@ { "name": "@chestnutlabs/gcode-preview-svelte", - "version": "0.3.0", + "version": "0.4.0", "description": "Thin Svelte integration for the Chestnut Labs G-code viewer (DD-007 D1 amendment): createGcodePreview store/action API + GcodePreview component as a reactivity bridge over @chestnutlabs/gcode-preview-core.", "keywords": [ "gcode", @@ -55,10 +55,10 @@ "test": "vitest run" }, "dependencies": { - "@chestnutlabs/gcode-parser": "0.3.0", - "@chestnutlabs/gcode-preview-core": "0.3.0", - "@chestnutlabs/gcode-renderer-three": "0.3.0", - "@chestnutlabs/toolpath-core": "0.3.0" + "@chestnutlabs/gcode-parser": "0.4.0", + "@chestnutlabs/gcode-preview-core": "0.4.0", + "@chestnutlabs/gcode-renderer-three": "0.4.0", + "@chestnutlabs/toolpath-core": "0.4.0" }, "peerDependencies": { "svelte": "^4.0.0 || ^5.0.0" diff --git a/packages/gcode-preview-vue/CHANGELOG.md b/packages/gcode-preview-vue/CHANGELOG.md index d6d28c5b..b5664a3f 100644 --- a/packages/gcode-preview-vue/CHANGELOG.md +++ b/packages/gcode-preview-vue/CHANGELOG.md @@ -1,5 +1,15 @@ # @chestnutlabs/gcode-preview-vue +## 0.4.0 + +### Patch Changes + +- Updated dependencies [[`b2053be`](https://github.com/ChestnutLabs/gcode-preview/commit/b2053be4b8e71250bc6077f60ef996fe601b6f3e), [`5f59b77`](https://github.com/ChestnutLabs/gcode-preview/commit/5f59b7788bbb14cacfe21aaf3d7134c6ba8dcd86), [`13fd5c6`](https://github.com/ChestnutLabs/gcode-preview/commit/13fd5c61d730428a7f7e73c28cf3cc9c48e68c19), [`1029580`](https://github.com/ChestnutLabs/gcode-preview/commit/10295803839816adaed224c48eba1f74374c0c2a), [`11f317d`](https://github.com/ChestnutLabs/gcode-preview/commit/11f317de2d6cb963d2a7fb0c894c89d3d5adc86d), [`8fec7c3`](https://github.com/ChestnutLabs/gcode-preview/commit/8fec7c3622cd2a6d6d57b43d7866cfea1cb71e09), [`879b60a`](https://github.com/ChestnutLabs/gcode-preview/commit/879b60ae0fca87ca8187791603a1bc7f54e61c4c), [`b84bea9`](https://github.com/ChestnutLabs/gcode-preview/commit/b84bea959b7aae24d148e6bcc488a9ed254a54f0)]: + - @chestnutlabs/gcode-parser@0.4.0 + - @chestnutlabs/gcode-renderer-three@0.4.0 + - @chestnutlabs/toolpath-core@0.4.0 + - @chestnutlabs/gcode-preview-core@0.4.0 + ## 0.3.0 ### Minor Changes diff --git a/packages/gcode-preview-vue/package.json b/packages/gcode-preview-vue/package.json index a82640a7..c2da5933 100644 --- a/packages/gcode-preview-vue/package.json +++ b/packages/gcode-preview-vue/package.json @@ -1,6 +1,6 @@ { "name": "@chestnutlabs/gcode-preview-vue", - "version": "0.3.0", + "version": "0.4.0", "description": "Thin Vue 3 integration for the Chestnut Labs G-code viewer (DD-007): useGcodePreview composable + GcodePreview component over the framework-neutral parser/renderer/progress packages.", "keywords": [ "gcode", @@ -50,10 +50,10 @@ "test": "vitest run" }, "dependencies": { - "@chestnutlabs/gcode-parser": "0.3.0", - "@chestnutlabs/gcode-renderer-three": "0.3.0", - "@chestnutlabs/toolpath-core": "0.3.0", - "@chestnutlabs/gcode-preview-core": "0.3.0" + "@chestnutlabs/gcode-parser": "0.4.0", + "@chestnutlabs/gcode-renderer-three": "0.4.0", + "@chestnutlabs/toolpath-core": "0.4.0", + "@chestnutlabs/gcode-preview-core": "0.4.0" }, "peerDependencies": { "vue": "^3.4.0" diff --git a/packages/gcode-renderer-2d/CHANGELOG.md b/packages/gcode-renderer-2d/CHANGELOG.md index 1d1ce1a1..b947e1f5 100644 --- a/packages/gcode-renderer-2d/CHANGELOG.md +++ b/packages/gcode-renderer-2d/CHANGELOG.md @@ -1,5 +1,13 @@ # @chestnutlabs/gcode-renderer-2d +## 0.4.0 + +### Patch Changes + +- Updated dependencies [[`5f59b77`](https://github.com/ChestnutLabs/gcode-preview/commit/5f59b7788bbb14cacfe21aaf3d7134c6ba8dcd86), [`1029580`](https://github.com/ChestnutLabs/gcode-preview/commit/10295803839816adaed224c48eba1f74374c0c2a), [`8fec7c3`](https://github.com/ChestnutLabs/gcode-preview/commit/8fec7c3622cd2a6d6d57b43d7866cfea1cb71e09)]: + - @chestnutlabs/gcode-colors@0.4.0 + - @chestnutlabs/toolpath-core@0.4.0 + ## 0.3.0 ### Minor Changes diff --git a/packages/gcode-renderer-2d/package.json b/packages/gcode-renderer-2d/package.json index 58735516..9aa60b83 100644 --- a/packages/gcode-renderer-2d/package.json +++ b/packages/gcode-renderer-2d/package.json @@ -1,6 +1,6 @@ { "name": "@chestnutlabs/gcode-renderer-2d", - "version": "0.3.0", + "version": "0.4.0", "description": "Low-resource Canvas 2D layer renderer for the Chestnut Labs G-code viewer (DD-014 / E8): an opt-in current/adjacent-layer 2D view over the existing ToolpathIR for low-GPU/low-memory/WebGL-blocked devices. No three, no framework.", "keywords": [ "gcode", @@ -49,7 +49,7 @@ "test": "vitest run" }, "dependencies": { - "@chestnutlabs/gcode-colors": "0.3.0", - "@chestnutlabs/toolpath-core": "0.3.0" + "@chestnutlabs/gcode-colors": "0.4.0", + "@chestnutlabs/toolpath-core": "0.4.0" } } diff --git a/packages/gcode-renderer-three/CHANGELOG.md b/packages/gcode-renderer-three/CHANGELOG.md index c0ad1d5f..10ff8a30 100644 --- a/packages/gcode-renderer-three/CHANGELOG.md +++ b/packages/gcode-renderer-three/CHANGELOG.md @@ -1,5 +1,29 @@ # @chestnutlabs/gcode-renderer-three +## 0.4.0 + +### Minor Changes + +- [#254](https://github.com/ChestnutLabs/gcode-preview/pull/254) [`5f59b77`](https://github.com/ChestnutLabs/gcode-preview/commit/5f59b7788bbb14cacfe21aaf3d7134c6ba8dcd86) Thanks [@sobechestnut-dev](https://github.com/sobechestnut-dev)! - feat: non-extrusion color modes — color-by-power + cut-vs-rapid (DD-012 phase 4, [#189](https://github.com/ChestnutLabs/gcode-preview/issues/189)) + + Two new `ColorMode`s consuming the [#189](https://github.com/ChestnutLabs/gcode-preview/issues/189) channels (DD-012 D7): + - **`power`** — ramps each segment's modal `toolPower` (laser power / spindle RPM, the `S` value) onto + a color ramp, the CNC/laser counterpart to color-by-speed. Auto-ranged (`toolPowerRange`) or explicit; + `NaN` (tool off) or a file parsed without the `toolPower` channel → fallback, never a fabricated color. + Capability-gated on `toolPower` (the Three renderer's `isColorModeAvailable` gates it). + - **`moveKind`** — cut-vs-rapid: productive moves (`Extrude` or `Cut`) vs rapids (`Travel`) — the + "where the tool is actually working" view. Reads the always-present `kind` channel, so it is always + available. + + Both flow through `createSegmentColorer`, so the Three and Canvas-2D renderers get them for free. FDM + coloring is unchanged. + +### Patch Changes + +- Updated dependencies [[`5f59b77`](https://github.com/ChestnutLabs/gcode-preview/commit/5f59b7788bbb14cacfe21aaf3d7134c6ba8dcd86), [`1029580`](https://github.com/ChestnutLabs/gcode-preview/commit/10295803839816adaed224c48eba1f74374c0c2a), [`8fec7c3`](https://github.com/ChestnutLabs/gcode-preview/commit/8fec7c3622cd2a6d6d57b43d7866cfea1cb71e09)]: + - @chestnutlabs/gcode-colors@0.4.0 + - @chestnutlabs/toolpath-core@0.4.0 + ## 0.3.0 ### Minor Changes diff --git a/packages/gcode-renderer-three/package.json b/packages/gcode-renderer-three/package.json index 4062988f..78ac75ac 100644 --- a/packages/gcode-renderer-three/package.json +++ b/packages/gcode-renderer-three/package.json @@ -1,6 +1,6 @@ { "name": "@chestnutlabs/gcode-renderer-three", - "version": "0.3.0", + "version": "0.4.0", "description": "Three.js toolpath renderer consuming ToolpathIR (DD-004). Phases 1-2: geometry builders + scene/lifecycle.", "keywords": [ "gcode", @@ -49,8 +49,8 @@ "test": "vitest run" }, "dependencies": { - "@chestnutlabs/gcode-colors": "0.3.0", - "@chestnutlabs/toolpath-core": "0.3.0" + "@chestnutlabs/gcode-colors": "0.4.0", + "@chestnutlabs/toolpath-core": "0.4.0" }, "devDependencies": { "@types/three": "0.178.0" diff --git a/packages/toolpath-core/CHANGELOG.md b/packages/toolpath-core/CHANGELOG.md index 5ed997b4..4c0cb7be 100644 --- a/packages/toolpath-core/CHANGELOG.md +++ b/packages/toolpath-core/CHANGELOG.md @@ -1,5 +1,45 @@ # @chestnutlabs/toolpath-core +## 0.4.0 + +### Minor Changes + +- [#248](https://github.com/ChestnutLabs/gcode-preview/pull/248) [`1029580`](https://github.com/ChestnutLabs/gcode-preview/commit/10295803839816adaed224c48eba1f74374c0c2a) Thanks [@sobechestnut-dev](https://github.com/sobechestnut-dev)! - feat: non-extrusion `Cut` move classification + tool-state modal (DD-012 phase 1, [#189](https://github.com/ChestnutLabs/gcode-preview/issues/189)) + + Non-extrusion toolpaths (CNC / laser / plotter) no longer collapse their productive moves into + `Travel`. The parser now tracks a tool-engaged modal state — `M3`/`M4` (spindle/laser on, incl. the + `M03`/`M04` leading-zero form) engage it, `M5` disengages — and classifies a move with **no extrusion + `E`** while the tool is engaged as the new **`MoveKind.Cut`** bit (a CNC/laser/plotter counterpart to + `Extrude`, composing with `ArcSegment` like the other kinds). + - New IR move kind `MoveKind.Cut = 1 << 7` (`@chestnutlabs/toolpath-core`). + - New capability **`cutMoves`**: `known` once a tool-state modal is seen (a CNC/laser/plotter file), + `unavailable` for FDM. + - **FDM is byte-identical**: FDM slices never issue `M3`/`M4`, so `Cut` is never set and every move + stays `Extrude`/`Travel` exactly as before (verified against the native-golden corpus; the CNC + fixtures `demo-easel`/`demo-mach3` are documented intentional adapter-divergences). + + Modal tool-state _value_ channels (laser power / spindle RPM via `S`), canned-cycle expansion, and + dialect families follow in later DD-012 phases. + +- [#250](https://github.com/ChestnutLabs/gcode-preview/pull/250) [`8fec7c3`](https://github.com/ChestnutLabs/gcode-preview/commit/8fec7c3622cd2a6d6d57b43d7866cfea1cb71e09) Thanks [@sobechestnut-dev](https://github.com/sobechestnut-dev)! - feat: opt-in modal tool-power channel (DD-012 phase 1 — the `ModalChannel` mechanism, [#189](https://github.com/ChestnutLabs/gcode-preview/issues/189)) + + Adds the shared, opt-in **`ModalChannel`** mechanism DD-012 D3 is built around, and its first channel: + **`toolPower`** — the modal spindle/laser `S` value while a tool is engaged. + - `ParseOptions.modalChannels?: readonly string[]` — request per-segment modal channels by id. + Supported id: `'toolPower'`. Unknown ids are ignored with a `modal-channel-unsupported` warning. + - `ToolpathSegments.modal?: Readonly>` — one Float32 column per requested + channel, present **only** when requested. An unset value is `NaN` (an honest "no value here"), never + a fabricated `0`. `toolPower` is the modal `S` (set on `M3`/`M4` and inline on GRBL-laser motion + lines) while engaged, `NaN` when the tool is off (`M5`). + - New capability **`toolPower`**: surfaced only when the channel is requested — `known` once a + tool-state modal is seen, else `unavailable`. + - **Default parse pays nothing**: no `modalChannels` ⇒ no `modal` on the IR, no extra columns, FDM + output unchanged. The budget-aware SoA writer (DD-003) grows the opt-in columns in lockstep and + accounts their bytes. + + Presentation (Watts vs RPM) is a dialect label, not a separate channel (DD-012 D4); [#180](https://github.com/ChestnutLabs/gcode-preview/issues/180)'s + fan/temp/accel color channels reuse this same mechanism in a later phase. + ## 0.3.0 ### Minor Changes diff --git a/packages/toolpath-core/package.json b/packages/toolpath-core/package.json index d6ca78a3..47d2a5c9 100644 --- a/packages/toolpath-core/package.json +++ b/packages/toolpath-core/package.json @@ -1,6 +1,6 @@ { "name": "@chestnutlabs/toolpath-core", - "version": "0.3.0", + "version": "0.4.0", "description": "Neutral ToolpathIR and capability model for the Chestnut Labs G-code Preview toolpath stack.", "keywords": [ "gcode", From 0a4f11389a534c8a65fcce3cbdd74dd85a2aa475 Mon Sep 17 00:00:00 2001 From: Nathaniel Chestnut Date: Fri, 31 Jul 2026 13:47:48 -0700 Subject: [PATCH 2/2] ci: trigger required checks on the v0.4.0 version PR (#249)