release: promote v0.4.0 to main - #264
Merged
Merged
Conversation
…lotter) (#246) Records the #189 scope decision (RESOLVED — IN SCOPE, maintainer 2026-07-28), de-risked by real-hardware validation (maintainer laser + partner CNC tables). Audits current mis-classification (cut/burn/draw → Travel; tool state dropped; geometry sound), and recommends DD-012: - additive MoveKind.Cut = 1<<7 (composes like Wipe/Seam/ArcSegment; FDM output byte-identical since it only sets when E is absent + a tool-state holds) - an opt-in ModalChannel mechanism (laser power / spindle / pen) that ALSO serves #180/RR-002's fan/temp/accel color channels — one mechanism, owned by DD-012 (build it once, don't drift the IR) - canned-cycle (G81-G89) geometry expansion, per-dialect - validation-TIERED dialect honesty: known only when machine-verified, inferred+experimental for synthetic/spec-only, unavailable when untested - synthetic redistributable fixtures (no private design files committed) Reconciles RR-002 / #180 as consumers of the DD-012 modal mechanism. Co-authored-by: Nathaniel Chestnut <sobechestnut-dev@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…epted] (#247) * docs(design): DD-012 — non-extrusion toolpath & modal tool-state [Proposed] The design for #189 (per RR-004's in-scope decision). Additive, FDM-safe: - MoveKind.Cut = 1<<7 — tool-engaged productive move when E is absent (composes like Wipe/Seam; FDM IR byte-identical) - one opt-in ModalChannel mechanism, OWNED here, serving CNC/laser tool-state (laser power / spindle / pen) AND #180/RR-002's fan/temp/accel color channels — DD-015 collapses into this - canned-cycle (G81-89 + G98/G99) geometry expansion, per-dialect - validation-TIERED dialect honesty (known only when machine-verified) - no new package (extends core/parser/dialects/colors); synthetic fixtures Decision menu D1-D8 open for maintainer acceptance. Updates the DD index and retires the DD-015 reservation. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * docs(design): DD-012 Accepted — D1–D8 as recommended Maintainer accepted D1–D8 as recommended (2026-07-28): no new package; MoveKind.Cut bit; one shared opt-in ModalChannel mechanism owned by DD-012 (#180/RR-002 consume it → DD-015 retired); tool-state-driven with machine-class an inferred hint; canned-cycle MVP (G81/G82/G83 + G80 + G98/G99); validation- tiered dialects; reuse renderer + ramped colorers; synthetic fixtures + FDM byte-identical gate + real-machine acceptance. Implementation unblocked. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Nathaniel Chestnut <sobechestnut-dev@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…se 1, #189) (#248) Non-extrusion toolpaths (CNC/laser/plotter) no longer collapse productive moves into Travel. The parser tracks a tool-engaged modal state (M3/M4 on — incl. the M03/M04 leading-zero form — M5 off) and classifies a no-E move while engaged as the new MoveKind.Cut bit (composes with ArcSegment like the other kinds). - toolpath-core: MoveKind.Cut = 1 << 7 - gcode-parser: tool-state modal (M3/M4/M5), tri-state path classification (extrusion | cut | travel), and the cutMoves capability (known once a tool-state modal is seen, else unavailable) - FDM byte-identical: FDM never issues M3/M4, so Cut is never set and kinds are unchanged — proven by the native-golden corpus (demo-3dbenchy et al. show only the additive cutMoves key; kind hashes unchanged). CNC fixtures demo-easel and demo-mach3 are documented intentional adapter-divergences (Travel → Cut). - tests: packages/gcode-parser/src/__tests__/non-extrusion.test.ts DD-012 phase 1 of 6. Modal value channels (laser power/spindle S), canned cycles, and dialect families follow. Co-authored-by: Nathaniel Chestnut <sobechestnut-dev@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…2 phase 1, #189) (#250) Adds the shared opt-in ModalChannel mechanism (DD-012 D3) and its first channel, toolPower (modal spindle/laser S while a tool is engaged). - toolpath-core: ToolpathSegments.modal?: Record<string, Float32Array> — opt-in Float32 columns, present only when requested; unset = NaN, never fabricated 0. - gcode-parser: budget-aware SoA writer grows opt-in modal columns in lockstep (bytes accounted per DD-003); ParseOptions.modalChannels requests them; the S register (M3/M4 + inline GRBL-laser S) feeds toolPower (NaN when off/M5); toolPower capability known-when-tool-state-seen, else unavailable; unknown ids warn (modal-channel-unsupported) and are ignored. - Default parse pays nothing (no modalChannels ⇒ no modal, FDM unchanged). - tests: 5 new (stamping incl. inline S, NaN-when-off, opt-out, FDM-unavailable, unknown-channel warning). DD-012 phase 1: move model (Cut) + this mechanism done. Presentation labels (Watts/RPM), canned cycles, dialects, and #180's channels follow. Co-authored-by: Nathaniel Chestnut <sobechestnut-dev@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…(DD-012 phase 2, #189) (#251) CNC/LinuxCNC output often omits the G word on repeated moves (G1 X0 Y0 then bare X10 Y0). The parser dropped those lines entirely (3 moves → 1 segment). It now tracks the active G0-G3 mode and rewrites a coordinate-only line (leading X/Y/Z, no G/M/T) into a synthetic copy of that command, so the dispatch switch handles it unchanged — full path emitted, classified (Cut/Travel) and colored (inline S → toolPower) consistently. FDM byte-identical: slicers always emit the G word, so the continuation never triggers; the native-golden corpus is unchanged (no regen). Prerequisite for canned-cycle modal repeat. - tests: 5 new (G1/G0 repeat, Cut under engagement, inline-S toolPower, inert before any motion mode). Co-authored-by: Nathaniel Chestnut <sobechestnut-dev@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…189) (#252) CNC canned cycles previously produced zero geometry (holes vanished). They now expand to explicit sub-moves: - G81/G82: rapid to XY, rapid to R plane, feed to depth (Cut), rapid retract. - G83 peck: feed down by Q, rapid-retract to R between pecks, until depth; each down-feed is a Cut. - G98/G99 retract plane (initial Z / R); G80 cancels; G0-G3 also cancel. - Modal repeat: bare X/Y drills another hole retaining Z/R/Q + initial plane. - Rapids=Travel, plunges=Cut; new capability cannedCycles. FDM byte-identical (no canned cycles in FDM); native goldens gain only the additive cannedCycles capability, no geometry change. - tests: 7 new (G81 plunge-to-depth, modal repeat, G98/G99 retract, G83 peck, G80 cancel, FDM regression). Co-authored-by: Nathaniel Chestnut <sobechestnut-dev@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
… 3, #189) (#253) Controller detection + the validation-tier honesty mechanism: - gcode-dialects: new grblLaser / grblMill / linuxCnc adapters (LightBurn/$32/M4 for laser; Grbl banner / % envelope + M3 for mills). Registered in the batteries worker. - Each sets provenance (cnc.controller/machineClass/toolPowerLabel) + a validation tier. 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 — only for claims the file actually made (never fabricates an unused feature). - All launch dialects ship experimental (synthetic fixtures); a one-line tier:'validated' flip promotes a controller's claims to `known` after a real hardware run (DD-012 §8/§15). Geometry untouched (annotate/label only); FDM detection unaffected. - tests: 5 new CNC dialect tests (detection, tier downgrade, no-fabrication, no FDM false-positive). Co-authored-by: Nathaniel Chestnut <sobechestnut-dev@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
#189) (#254) Two ColorModes consuming the #189 channels (DD-012 D7): - power: ramps modal.toolPower (laser power / spindle RPM) like color-by-speed; auto-ranged (toolPowerRange) or explicit; NaN / no-channel → fallback (never fabricated). Capability-gated on toolPower in the Three renderer's isColorModeAvailable. - moveKind: cut-vs-rapid — productive (Extrude|Cut) vs rapid (Travel); reads the always-present kind channel → always available. Both flow through createSegmentColorer, so Three + Canvas-2D get them free. FDM coloring unchanged. - tests: 5 new (power ramp + NaN fallback, no-channel fallback, toolPowerRange, moveKind classes, segmentColor one-off). Co-authored-by: Nathaniel Chestnut <sobechestnut-dev@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…(DD-012 phase 5, #189) (#255) - compatibility matrix: new "Dialects (non-extrusion — CNC/laser/plotter)" section (GRBL laser/mill, LinuxCNC — all EXPERIMENTAL tier, claims inferred until hardware-validated; reserved rows for Marlin-laser/Mach/plotters) + cross-cutting rows (Cut classification, toolPower channel, canned cycles, modal motion). - support-policy: "Non-extrusion (CNC/laser/plotter) — experimental" subsection (geometry full; semantics inferred until validated; DSP/galvo out of scope). - manual: "Non-extrusion — CNC/laser/plotter (experimental)" concept section. - README: capability bullet + non-extrusion coloring note. Docs-only. Phase 6 (exit) = real-hardware validation → flip tiers to validated. Co-authored-by: Nathaniel Chestnut <sobechestnut-dev@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…) (#256) The inherited first-word lexer was FDM-shaped and dropped most real CNC/laser G-code. The lexer now reads every G/M/T word on a line (G20 G17 G90, G91 G81, S3400 M3 — so M3 spindle + G81 canned cycles are no longer lost), strips N-word line numbers (Fanuc/Mach/TinyG), and latches bare S/F lines. A numeric guard keeps letters embedded in extended commands (POLYGON, M486 T<count>) from becoming spurious commands/tool-changes. FDM byte-identical (slicers emit one command per line → multi-command path never runs; goldens change only in reduced garbage warnings). demo-mach3 + one adversarial binary fixture are documented intentional divergences. Dialect extended-command observation (EXCLUDE_OBJECT_* via rawLine) preserved by firing onCommand for codeless-but-non-blank lines. Validated on real public samples: LinuxCNC arcspiral 16→5506 segments, TinyG 0→344. Tests: lexer-multicommand.test.ts (8). Co-authored-by: Nathaniel Chestnut <sobechestnut-dev@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
A showcase-app action (kept in tools/demo, not the reusable packages, per the #152/#118 scoping). An "Export STL" button downloads the productive toolpath (extrude/cut moves) as a binary STL — each move a square-section tube, decimated to a triangle budget with an honest "strided N of M" note (no silent truncation). Self-contained: reads only the public ToolpathIR via renderer.ir. Co-authored-by: Nathaniel Chestnut <sobechestnut-dev@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…real files (#189) (#258) The phase-3 detectors matched none of the real public samples (LaserGRBL, LinuxCNC, GRBL CAM) — real output has no header and writes commands mid-line / concatenated. Detection is now evidence-scored: a scoreEvidence extractor (comments stripped, commands matched anywhere via trailing-digit lookahead) plus process rules — laser = tool-on + S + no Z-plunge; mill = M3 + negative-Z plunge; LinuxCNC = header or RS274NGC O-words. Extrusion tightened to E-on-a-move so LinuxCNC M67 E0 analog laser power isn't mistaken for FDM. Real files: 0/6 → 3/6 detected with correct machine class; misses are honest (commented/absent spindle = no tool-state). Still experimental tier. Fixtures are MIT-clean re-creations of the real fingerprints (no third-party files committed — LinuxCNC samples are GPL). Tests: +5 in cnc.test.ts. Co-authored-by: Nathaniel Chestnut <sobechestnut-dev@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…rk (#259) Refresh the status table: v0.3.0 shipped / v0.4.0 in prep; #188 bgcode Closed/Accepted (signed off, shipped in v0.3.0); add the #189 CNC/laser row (DD-012 phases 1–5 built+merged+documented at experimental tier, plus the lexer fix, evidence-based detection, and #152 STL export). No package change. Co-authored-by: Nathaniel Chestnut <sobechestnut-dev@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
* fix: G0 rapids classify as Travel, not Cut (#189) The non-extrusion Cut/Travel classifier keyed only on tool-state (M3/M4 latched), so on a router — spindle on across rapids — every G0 reposition was counted as a cutting move. DD-012 D2 §4.2 already specifies rapids stay Travel; this aligns the implementation: 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). Also adds the CNC/laser validation harness (tools/demo/validate.html) that surfaced this — load a physically-cut file, check each claim (machine class, cut-vs-rapid split, tool power, envelope, skipped commands) against the real machine, export a markdown report. Local-only; no upload, no worker. Geometry unchanged (only the demo-easel kind column shifts: 742/0 → 737/5); FDM byte-identical. +1 regression test. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(demo): power-view legend + honest constant-vs-range power claim (#189) The validation harness's Power view drew colored lines with no key, and the power claim read "200–200" for a single-power job. Fixes from real-file use: - Power range now measured over CUTTING moves only (a rapid can carry a latched S with the beam off — counting it over-reported the engaged tally). - View legend is mode-aware: cut/rapid swatches, or a cold→hot power scale with the real min/max — or a "constant N (no variation)" note when the job never modulates power (with the swatch matching the flat tone drawn). - Power claim phrases constant power as constant, not a degenerate range. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Nathaniel Chestnut <sobechestnut-dev@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Folds the reference landscape into the research (RR-004 §9) and design (DD-012 §16) docs, making the spec-anchored-CNC vs. observed-only-laser split explicit — the distinction that governs the validation tier: - CNC milling is spec-anchored: RS274NGC (NIST IR 6556) + ISO 6983 + the LinuxCNC reference define motion, canned cycles, coordinate systems, #params, [expressions], O-words. Phase-7 gaps are documented features to build against the spec, with hardware as the check. - Lasers are not spec-anchored: GRBL (source/wiki) + LightBurn (observed output) only — the machine is the source of truth, so laser dialects stay hardware-gated. Vendor extensions (e.g. mach3 plasma S=torch-height) escape every spec and are inferred by construction. Provenance: cited as behavioral parity targets / where-defined pointers only. ISO 6983 is copyrighted and the LinuxCNC reference is GPL/GFDL while this project is MIT — no spec prose is copied. DD-012 decision log notes the editorial addition (no decision change). Co-authored-by: Nathaniel Chestnut <sobechestnut-dev@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…189) (#262) First DD-012 D8 hardware-validation pass. 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 verified via the tools/demo/validate.html harness. - Flip grbl-laser tier experimental -> validated (cnc.ts): laser files now report cutMoves/toolPower as `known`, and the cnc-dialect-experimental warning is suppressed. - grbl-mill and linuxcnc stay experimental (per-controller flip) until a real CNC run. - Record the run as acceptance evidence in the new docs/design/DD-012-hardware-validation-log.md. - Tests updated: grbl-laser asserts validated/known/no-warning; grbl-mill asserts it still downgrades to inferred (scope guard). Co-authored-by: Nathaniel Chestnut <sobechestnut-dev@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…7) (#263) Drafts the design for the largest remaining #189 gap: LinuxCNC/CAM parametric programs — numbered/named parameters (#100 = 5), expressions (X[#1 + sin[30]]), and O-word subroutines/loops/conditionals — which the forward-only line processor drops today. Key decisions for acceptance (D1–D8): - D1: on-demand program-buffered interpreter engaged ONLY when #/[ /O-words appear; FDM + simple CNC keep the untouched forward-only fast path (byte-identical). One motion/classification core; the interpreter only feeds it. - D5: two new DD-003 limits (maxProgramIterations, maxCallDepth) so a while[1] or infinite recursion can't hang/OOM the worker — bounded, no eval, no I/O. - Spec-derivable from RS274NGC (NIST IR 6556) / LinuxCNC — hardware only re-confirms; parity targets only, no spec text copied (RR-004 §6). Proposed only — architecture-sensitive, so blocked until Accepted per governance. Co-authored-by: Nathaniel Chestnut <sobechestnut-dev@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
* release: version packages (lockstep) * ci: trigger required checks on the v0.4.0 version PR (#249) --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Nathaniel Chestnut <sobechestnut-dev@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
v0.4.0 — non-extrusion toolpath (CNC / laser / plotter), #189
Promotes
dev→mainfor the v0.4.0 publish. All 13@chestnutlabs/*packages bump lockstep to0.4.0.Highlights
MoveKind.Cut+ opt-inModalChannelmechanism (toolPower) — tool-engaged productive moves are classified; laser power / spindle RPM live on an opt-in per-segment channel (FDM pays nothing, stays byte-identical). DD-012 phases 1–2.G81/G82/G83(+G80/G98/G99) expand to real geometry.experimental→ claimsinferred).grbl-laserhardware-VALIDATED — first real-machine pass; its laser claims now reportknown.Nline numbers, bareS/F— real CNC files now parse.FDM output is byte-identical throughout (golden-equivalence gate green).