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
2 changes: 1 addition & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ tracked in [`UPSTREAM_PROVENANCE.md`](UPSTREAM_PROVENANCE.md).
| **E11** Documentation, SDK Reference & Published Manual (#197) | **Closed/Accepted** (2026-07-25) | [DD-013](design/DD-013-documentation-sdk-reference-and-published-manual.md) **Accepted** (D1–D7 as recommended). Completed E7/DD-008's docs ambit. **All four phases shipped:** typedoc API reference over the ten packages (#198), GitHub Pages + Chestnut Labs theme (#199), SDK manual — getting-started/guides/concepts (#200), accuracy gate + `eslint-plugin-tsdoc` + version stamp (#201). **Live: [chestnutlabs.github.io/gcode-preview](https://chestnutlabs.github.io/gcode-preview/)** (manual at `/`, API at `/api/`), auto-redeployed on merge/release. No package/IR/renderer change. Deferred: flip the `notDocumented` doc-coverage check to error once the 55 TSDoc-syntax gaps are filled |
| **E8** Low-Resource Layer Mode (#9) | **Closed/Accepted** (2026-07-26) | [DD-014](design/DD-014-low-resource-layer-renderer.md) **Accepted** (D1–D5 as recommended; D6 build-now on the standing AnyBridge evidence). **All four §14 phases shipped** — #212 two new lockstep pkgs (`gcode-colors` shared ColorMode subsystem + `gcode-renderer-2d` Canvas 2D `LayerView2D`, no `three`/framework; renderer-three refactored onto the shared colorer) → **12 packages**; #213 adjacent "ghost" layers over a stable model frame; #214 **`renderer: '2d' \| '3d'` prop** through core + all 4 adapters (the 3D renderer is **loaded on demand** so a 2D-only bundle never ships Three.js) + 2D live-progress "cut"; #215 capability-honesty disclosures (non-planar/CNC via `renderer-unsupported`) + **§8 low-resource budget verified on a real device** (redraw ~0.2 ms median, ≤ 3.6 ms @ 6× CPU throttle vs the 16 ms budget; ~0 MB heap growth over 870 renders — no per-layer geometry) ([report](../tools/benchmark/results/e8-2d-lowresource-benchmark-2026-07-26.md)). §15 acceptance criteria met. Roadmap note (DD-008 §4.8): pure-Node GPU-less still rendering is a related deferred capability |
| **Binary G-code (`.bgcode`) decode** (#188) | **Closed/Accepted** (2026-07-28) | [DD-011](design/DD-011-binary-gcode-decode-adapter.md) **Accepted**, preceded by [RR-003](research/RR-003-bgcode-licensing-and-format-audit.md). New 13th lockstep pkg `@chestnutlabs/gcode-bgcode` decodes Prusa `.bgcode` → plain G-code (None / DEFLATE-zlib / heatshrink w11+w12 / MeatPack; MeatPack MIT + heatshrink ISC clean-room, no AGPL); validated against real Prusa files (21 MB XL 856/856 CRC; cube golden byte-identical); [§7 security review](design/SECURITY-REVIEW-DD-011-bgcode.md) **signed off**. **Shipped in `v0.3.0`.** |
| **Non-extrusion toolpath — CNC / laser / plotter** (#189) | **Phases 1–5 built + merged; documented; experimental tier** | [DD-012](design/DD-012-non-extrusion-toolpath-and-modal-tool-state.md) **Accepted** (D1–D8), preceded by [RR-004](research/RR-004-non-extrusion-toolpath-coverage.md). **Phases 1–5 (#248–#255):** `MoveKind.Cut` + opt-in `ModalChannel`/`toolPower`; modal-motion + canned cycles (`G81`/`G82`/`G83`); GRBL-laser/GRBL-mill/LinuxCNC dialects + **validation tiers** (experimental → claims `inferred`); color-by-power + cut-vs-rapid; [compatibility matrix](compatibility/dialects-and-containers.md#dialects-non-extrusion--cnc--laser--plotter-dd-012-189) + support docs. **Real-file work:** lexer handles multi-command lines / `N`-numbers / bare-`S` (#256 — real LinuxCNC/TinyG now parse); evidence-based detection (#258, 0/6→3/6 real samples); [STL export](../tools/demo) (#152, #257). All FDM-byte-identical. **Remaining:** phase 6 — hardware validation → promote tiers to `validated`; larger gaps (LinuxCNC O-word subroutines/params/expressions). Rides the next lockstep release (`v0.4.0`). |
| **Non-extrusion toolpath — CNC / laser / plotter** (#189) | **Phases 1–5 built + merged; documented; experimental tier** | [DD-012](design/DD-012-non-extrusion-toolpath-and-modal-tool-state.md) **Accepted** (D1–D8), preceded by [RR-004](research/RR-004-non-extrusion-toolpath-coverage.md). **Phases 1–5 (#248–#255):** `MoveKind.Cut` + opt-in `ModalChannel`/`toolPower`; modal-motion + canned cycles (`G81`/`G82`/`G83`); GRBL-laser/GRBL-mill/LinuxCNC dialects + **validation tiers** (experimental → claims `inferred`); color-by-power + cut-vs-rapid; [compatibility matrix](compatibility/dialects-and-containers.md#dialects-non-extrusion--cnc--laser--plotter-dd-012-189) + support docs. **Real-file work:** lexer handles multi-command lines / `N`-numbers / bare-`S` (#256 — real LinuxCNC/TinyG now parse); evidence-based detection (#258, 0/6→3/6 real samples); [STL export](../tools/demo) (#152, #257). All FDM-byte-identical. **Phase 7 (RS274NGC programming layer) shipped `v0.18.0`:** parameters + expressions + O-word control flow + in-file subroutines ([DD-017](design/DD-017-rs274ngc-parametric-programs.md); [coverage](compatibility/gcode-motion-coverage.md#rs274ngc-parametric-programs-dd-017), [guide](manual/concept-parametric-programs.md)). **Remaining:** phase 6 — hardware validation → promote grbl-mill/linuxcnc tiers to `validated` (laser already validated). |
| #152 STL export | Open, gated | Follows the **#118** chrome/showcase product decision, not an architecture DD (DD-009 §3) |

Shipped so far: `packages/toolpath-core` (SoA `ToolpathIR`, capability model), `packages/gcode-parser`
Expand Down
28 changes: 28 additions & 0 deletions docs/compatibility/gcode-motion-coverage.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,34 @@ other geometry (positions, kinds, layers, source bytes) stayed byte-identical.
`probe-position-runtime-dependent`; the native golden pins this, and the fixture is a documented,
intentional divergence from the inherited engine (which ignored both `G31` and `G92 Z`).

## RS274NGC parametric programs (DD-017)

Beyond the fixed motion codes above, the interpreter executes the **RS274NGC programming layer** — the
way LinuxCNC / CAM output *computes* geometry (parameters, expressions, control flow, subroutines). It
engages only when a line uses `#`, `[`, or a leading O-word; every other file takes the ordinary path
and is **byte-identical**. Shipped in v0.18.0 (DD-017 phases 1–3). See the
[parametric-programs guide](../manual/concept-parametric-programs.md) for a worked example.

| Construct | Support | Disclosure on trouble |
|---|---|---|
| Parameters `#1`–`#5399`, `#<local>`, `#<_global>`; assignment; indirect `##`; computed `#[expr]` | **honored** | read-before-write → `0` + `rs274-uninitialized-param` |
| System parameters | read-only allow-list (current position `#5420`–`#5422`) | others → `0` + `rs274-unsupported-sysparam` |
| Expressions `[ … ]` — full operator/function set, **degree** trig, LinuxCNC `MOD`/`EQ` | **honored** | malformed → word dropped + `rs274-bad-expression`; non-finite result → `rs274-non-finite-value` |
| `if` / `elseif` / `else` / `endif` | **honored** | — |
| `while` / `endwhile`, `do` / `while`, `repeat` / `endrepeat` | **honored** | total loop work capped → `rs274-iteration-limit` |
| `break` / `continue` | **honored** (innermost loop, frame-local) | outside a loop → `rs274-misplaced-control` |
| `sub` / `endsub`, `call [args]`, `return` — in-file, recursive, forward-referenceable | **honored** | recursion capped → `rs274-call-depth`; unknown sub → `rs274-unknown-sub`; redefined → `rs274-duplicate-sub` |
| External subprogram files (`M98 P…`, external `o<name> call`), persistent `.var` params, `return` values | **out of scope** | — |

**Bounds & honesty.** Two `ParseLimits` fields bound execution: `maxProgramIterations` (default
1,000,000) caps total loop work — charged per loop pass *and* per statement inside a loop or subroutine,
so a large body or an exponential recursive fan-out cannot exceed it — and `maxCallDepth` (default 50)
caps subroutine recursion. There is no `eval` and no I/O. Clean execution reports the
`parametricProgram` capability as `known`; any disclosure above drops it to `approximated`; a
non-parametric file reports `unavailable` — never a fabricated value. FDM / non-parametric input is
byte-identical (both golden suites unchanged). Design and the bounded-execution model:
[DD-017](../design/DD-017-rs274ngc-parametric-programs.md).

## Remaining gaps

The E10 motion-model gaps from the #154 audit are now all closed. Tracking issues: **#155** (G90/G91 +
Expand Down
11 changes: 7 additions & 4 deletions docs/design/DD-017-rs274ngc-parametric-programs.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
# DD-017 — RS274NGC parametric programs: parameters, expressions & O-word flow (#189 phase 7)

**Status:** **Accepted (Phases 1–2)** — Phase 1 (parameters + expressions, D2/D3, §5.1) and Phase 2
(O-word control flow — conditionals + bounded loops, D4/D5/D6 for `if`/`while`/`do`/`repeat`, §5.2) both
accepted & built 2026-08-27; **Phases 3–4 (subroutines, capability/docs polish) remain Proposed**, gated
on measured Phase 2 results. <!-- Draft | Proposed | Accepted | Superseded | Rejected -->
**Status:** **Accepted — all phases built & shipped in v0.18.0** (2026-08-27). Phase 1 (parameters +
expressions, D2/D3, §5.1), Phase 2 (O-word control flow, D4/D5/D6, §5.2), Phase 3 (in-file subroutines +
`maxCallDepth`, §5.3), and Phase 4 (capability/disclosure surface + docs, §5.4). Remaining, out of the
accepted scope: subroutine **return-value** propagation and external subprogram files (`M98` — an explicit
§3 non-goal). <!-- Draft | Proposed | Accepted | Superseded | Rejected -->
**Authors/Owners:** Nathaniel Chestnut
**Date:** 2026-07-29 · **Last revised:** 2026-08-27
**Owning Epic:** #189 (non-extrusion toolpath coverage), **phase 7** · **Milestone:** Future
Expand Down Expand Up @@ -207,3 +208,5 @@ the existing SoA). No renderer/adapter/color changes (they consume the same segm
| 2026-07-29 | DD-017 drafted as **Proposed** (D1–D8 open). Phase 7 of #189; the spec-derivable RS274NGC programming layer (params/expressions/O-words) flagged during real-file validation. Follows DD-012 §16 (spec-anchored CNC). | Chestnut Labs |
| 2026-08-27 | **Phase 1 accepted & built** (parameters + expressions only; D2/D3/§5.1). New `packages/gcode-parser/src/rs274.ts` — a pure recursive-descent evaluator (RS274NGC operator/function set, degree trig, LinuxCNC MOD/EQ semantics, `MAX_EXPR_DEPTH` guard, no `eval`) + parameter store (numbered/named/global, indirect `##`, computed `#[expr]`, read-only system-param allow-list `#5420–#5422`), gated on a per-line `#`/`[` scan (FDM byte-identical, native goldens regenerated for the additive `parametricProgram` capability only; ~2.7% parse overhead from the gate, measured on 3DBenchy). O-word control flow (D4, Phases 2–4) explicitly **not** authorized until Phase 1 results are reviewed. | Chestnut Labs (lead) |
| 2026-08-27 | **Phase 2 accepted & built** (O-word control flow — conditionals + bounded loops; D4/D5/D6, §5.2). New `packages/gcode-parser/src/rs274-flow.ts` — the program-buffered interpreter of D1 Option A: engaged only when `programUsesOWords(text)` (a cheap char-scan; FDM never enters it, byte-identical), it buffers the program, builds a **block tree**, and executes `if`/`elseif`/`else`/`endif`, `while`/`endwhile`, `do`/`while`, `repeat`/`endrepeat`, `break`/`continue` — re-feeding each plain line through the same `processLine` (one geometry path) and evaluating conditions/counts against the shared Phase-1 store (`Rs274Context.evalExpression`). **Bounded execution (D5):** new public `maxProgramIterations` limit (default 1M) charged per loop-body pass → `rs274-iteration-limit` + partial IR; internal `MAX_CONTROL_NESTING` cap; loops are iteration, not recursion, so only structural nesting (capped) uses JS stack — a hostile `o while [1]` wastes only bounded CPU, cannot hang/OOM/stack-overflow. **Honesty (D6):** clean flow → `parametricProgram: 'known'`; a degraded run (hit cap / unbalanced / unsupported / malformed condition) → `'approximated'` + a specific disclosure. `sub`/`call`/`return` disclosed unsupported and **not** executed (Phase 3). Streaming discloses + runs linearly (a partial stream can't re-run a line range, §4.1). Both golden suites unchanged; validated on a real LinuxCNC-idiom `while`-loop bolt circle (params + degree trig + flow). `maxCallDepth` (subroutine recursion) deferred to Phase 3. | Chestnut Labs (lead) |
| 2026-08-27 | **Phase 3 accepted & built** (in-file subroutines; §5.3). `sub`/`endsub`, `call [args]`, `return` in `rs274-flow.ts` + a scope stack in `rs274.ts`: recursion-safe LinuxCNC scoping (`#1`–`#30` and `#<local>` per call frame; `#31`+ and `#<_global>` shared), args → `#1`–`#30`, forward-referenceable, recursive. New public `maxCallDepth` limit (default 50) → `rs274-call-depth` disclose+skip; a runtime exec-depth backstop bounds combined nesting + call-depth JS recursion; `break`/`continue`/`return` are frame-local. Adversarial review caught + fixed a HIGH bounded-execution hole (a loop-free recursive fan-out was uncharged → exponential; now every statement inside a loop OR subroutine is charged, so total call-tree size is bounded by `maxProgramIterations`) + 2 honesty nits (id-mismatched `endsub`, malformed `call` arg now disclosed). Return VALUES not propagated (documented limitation); external sub files (`M98`) = §3 non-goal. Both golden suites unchanged. | Chestnut Labs (lead) |
| 2026-08-27 | **Phase 4 done** (capability/disclosure surface + docs; §5.4). No engine change. Documented the `parametricProgram` capability tiers + the full `rs274-…` warning-code set in the compatibility coverage matrix ([gcode-motion-coverage.md](../compatibility/gcode-motion-coverage.md#rs274ngc-parametric-programs-dd-017), construct-by-construct table) and a user-facing manual guide ([concept-parametric-programs.md](../manual/concept-parametric-programs.md), worked bolt-circle example + honesty/bounds); added `parametricProgram` to the capability-model concept page; refreshed the #189 epic row + this DD's status. Real-file validation folded into the phase work (the LinuxCNC-idiom bolt-circle integration test). **DD-017 complete; shipped in v0.18.0.** | Chestnut Labs (lead) |
2 changes: 1 addition & 1 deletion docs/design/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ boundary. Architecture-sensitive work is **blocked until its DD is Accepted** (g
| [DD-013](DD-013-documentation-sdk-reference-and-published-manual.md) | Documentation, SDK Reference & Published Manual | E11 | Future | **Accepted** 2026-07-25 (D1–D7 as recommended) (#197) |
| [DD-014](DD-014-low-resource-layer-renderer.md) | Low-Resource Layer Mode (2D/adjacent-layer renderer over IR) | E8 (#9) | Future | **Accepted** 2026-07-26 (D1–D5 as recommended; D6 build-now on the AnyBridge evidence artifact) |
| [DD-016](DD-016-annotation-derived-move-kinds.md) | Annotation-Derived Move Kinds (Wipe & Seam) | E9 (#182) | Future | **Accepted** 2026-07-27 (D1–D6 as recommended; D2 = narrow additive DD-005 sink amendment so a slicer-comment signal can set `Wipe`; seam a non-goal) |
| [DD-017](DD-017-rs274ngc-parametric-programs.md) | RS274NGC Parametric Programs (parameters, expressions & O-word flow) | #189 phase 7 | Future | **Proposed** 2026-07-29 (D1–D8 open) — spec-derivable RS274NGC programming layer: on-demand interpreter engaged only on `#`/`[`/O-words (FDM byte-identical), bounded iteration/recursion limits; per [RR-004](../research/RR-004-non-extrusion-toolpath-coverage.md) §9 |
| [DD-017](DD-017-rs274ngc-parametric-programs.md) | RS274NGC Parametric Programs (parameters, expressions & O-word flow) | #189 phase 7 | Shipped | **Accepted — phases 1–3 built & shipped v0.18.0** (2026-08-27): parameters + expressions (#410), O-word control flow (#413), in-file subroutines (#415). On-demand interpreter engaged only on `#`/`[`/O-words (FDM byte-identical); bounded by `maxProgramIterations`/`maxCallDepth`; honesty-tiered `parametricProgram`. Phase 4 (capability/docs) done. Only the optional docs-polish tail + return-value propagation remain. Per [RR-004](../research/RR-004-non-extrusion-toolpath-coverage.md) §9 |
| [DD-020](DD-020-interaction-aware-quality.md) | Interaction-aware render quality (progressive LOD) | #306 | M1 | **Accepted** 2026-08-24 — opt-in `interactionQuality:'auto'`: reduce render detail (pixel ratio, bounded frame-time step) while the camera moves, restore on settle; keeps the vertex-budget fallback; consumer maps High/Balanced/Performance. Additive, default off. |
| [DD-018](DD-018-model-renderer.md) | ModelRenderer — source-model presentation rendering (STL/3MF) | ModelRenderer (new epic) | M1 | **Accepted** 2026-08-23 (all sections as proposed; §14 v1 = both STL+3MF sequential; §12 shared stage stays in gcode-renderer-three short-term) — new sibling `@chestnutlabs/gcode-model-renderer` for presentation/thumbnail renders of source STL/3MF (distinct from toolpath inspection); shared "stage" extraction, headless/offscreen (SwiftShader) contract with transparent+themed bg, multi-object + material-capable scene model from day one, deterministic export + `(sourceHash, options, envId)` cache key; consumer: AnyBridge thumbnail sidecar |
| [DD-021](DD-021-interactive-model-viewer.md) | Interactive source-model viewer (`ModelViewer`) | ModelRenderer (DD-018 line) | M2 | **Accepted** 2026-08-24 (maintainer; AnyBridge boundary-reviewed, no blockers) — a distinct interactive `createModelViewer(canvas)` handle (orbit/zoom/pan of source STL/3MF, the live analogue of `renderModelStill`); reuses the shared stage + `ModelRenderer` scene core + the toolpath camera/controls + DD-020 quality; **generic open-`kind` model-source loader registry** (STL/3MF first, OBJ/STEP/PLY later w/o API change); distinct from ToolpathRenderer / `<GcodePreview>`; handle in `gcode-model-renderer`, shared-control extraction into `gcode-renderer-three`; components a later phase; consumer: AnyBridge "View in 3D" |
Expand Down
13 changes: 10 additions & 3 deletions docs/manual/concept-ir-capabilities.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,16 @@ Every derived claim is tagged with a confidence level:
| `unavailable` | Cannot be determined from this input. |

These live in the IR header's `capabilities` map — for example `extrusionMode`, `positioningMode`,
`layers`, `sourcePositions`. A consumer reads them to decide what UI to show: feature coloring only
when the feature was disclosed, a layer slider only when layers are `known`, an uncertainty band
when a position is `approximated`.
`layers`, `sourcePositions`, `parametricProgram`. A consumer reads them to decide what UI to show:
feature coloring only when the feature was disclosed, a layer slider only when layers are `known`, an
uncertainty band when a position is `approximated`.

The same rule governs computed geometry. When a file uses the RS274NGC programming layer (parameters,
expressions, loops, subroutines — see [Parametric programs](concept-parametric-programs.md)), the
interpreter *computes* the coordinates rather than inferring them, so a clean run reports
`parametricProgram: 'known'`. If a resource limit was hit or a construct couldn't be executed, it
reports `approximated` and emits a specific warning (each `rs274-…` warning names what was lost) — the
geometry it did produce is still real, and what it couldn't do is stated, not faked.

This is why the preview never silently lies: if a dialect didn't emit feature annotations, the
stack says so rather than inventing them; if the extruder mode wasn't stated, it defaults *and tells
Expand Down
Loading
Loading