Skip to content

release: promote v0.5.0 to main - #286

Merged
sobechestnut-dev merged 9 commits into
mainfrom
dev
Aug 14, 2026
Merged

release: promote v0.5.0 to main#286
sobechestnut-dev merged 9 commits into
mainfrom
dev

Conversation

@sobechestnut-dev

Copy link
Copy Markdown

v0.5.0 — pre-release hardening batch (epic #279)

Promotes devmain for the v0.5.0 publish. All 13 @chestnutlabs/* packages bump lockstep to 0.5.0.

Highlights

FDM output byte-identical; all suites green.

⚠️ Merge as a MERGE COMMIT, not squash — preserves the release lineage release-publish.yml verifies (tag ∈ main).

sobechestnut-dev and others added 9 commits August 13, 2026 22:46
…clamps (#267) (#269)

Turn on zoomToCursor (wheel zoom toward the pointer) and derive minDistance/
maxDistance from the framed model size, recomputed in frame() so they track
each file's bounds — the user can't dolly through or lose the model. Internal
to scene.ts; no dependency, no public-API/adapter change; headless still-render
path unaffected.

Co-authored-by: Nathaniel Chestnut <sobechestnut-dev@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…#268) (#270)

Adds three imperative camera methods threaded from the renderer through
PreviewRenderer and the controls handle into all four adapters:

- setView(view): snap to a preset orientation (top/bottom/front/back/left/
  right/iso), instant, preserving the active projection.
- getCameraState(): read the camera as a serializable CameraState
  { position, target, zoom, cameraMode } (scene coords) — a stable contract a
  dashboard can persist.
- setCameraState(state): restore a snapshot verbatim, no re-fit to the model.

New public types CameraView + CameraState (re-exported three-free from core).
No dependency, no IR/schema change, no animation. The 2D renderer honors the
methods as documented disclosures (getCameraState -> null; setView/
setCameraState -> renderer-unsupported) rather than fabricating a 3D pose.

Covered by the portable behavioral suite across all 4 adapters + focused
renderer-three unit tests (all 7 presets, distance/mode preservation, exact
round-trip). Verified live with real OrbitControls. Minor changeset (lockstep).

Co-authored-by: Nathaniel Chestnut <sobechestnut-dev@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Q1: docs/compatibility/dialects-and-containers.md now matches the code and the
sign-offs — grbl-laser is `validated` / claims `known` (hardware-validated
2026-07-29, DD-012 log), and the container security-review rows read "signed
off" (DD-005 containers 2026-07-23, DD-011 bgcode 2026-07-28) instead of
"awaiting sign-off".

Q4: README describes FOUR equal adapters — Vue, React, Svelte, and the
framework-neutral <gcode-preview> Web Component — in the lead, the adapters
bullet, and the shared-option-surface paragraph.

Docs only, no changeset.

Co-authored-by: Nathaniel Chestnut <sobechestnut-dev@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
#277) (#285)

Test-only; no code fix surfaced (the v0.4.0 non-extrusion paths are already
robust). Adds:

- M1/M2 CNC adversarial tier (cnc-adversarial.test.ts): malformed multi-command
  lines, overflow N-numbers, bare G/S garbage, and hostile canned cycles —
  through BOTH the in-memory and streaming drivers, all bounded. Proves G83
  pathological tiny-Q is stopped by the segment budget (no hang), Q=0 falls
  back to a single plunge, a first cycle missing Z/R collapses to the zero
  plane (never a fabricated deep plunge), and Z/R are correctly retained across
  a modal repeat (RS274NGC).
- M5 gaps: G82 (dwell drill) single-plunge expansion; GRBL $32=1 laser-mode
  detection branch. (toolPower NaN-off + its color-mapping fallback were
  already covered in the parser + gcode-colors suites.)

Fixtures are synthetic MIT-clean inline strings, never committed third-party
files.

Co-authored-by: Nathaniel Chestnut <sobechestnut-dev@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…time (#276) (#284)

The two most recent headline features shipped dark in the showcase. Add to
tools/demo:
- 7 preset-view buttons (top/bottom/front/back/left/right/iso) exercising
  renderer.setView, plus Save view / Restore view exercising
  getCameraState/setCameraState.
- A time-based scrub (kinematic time axis via computeToolpathTime +
  segmentsCompletedAtTime) and an estimated-print-time readout that shows the
  slicer|kinematic provenance honestly (slicer estimate when present; else
  kinematic constant-velocity, flagged as a lower bound when feedrates are
  unknown).

Verified live: calicat shows "37.3 min (slicer estimate)", time-scrub maps to
segments, presets + save/restore work. No changeset (tools/demo unpublished).

Co-authored-by: Nathaniel Chestnut <sobechestnut-dev@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
* fix(svelte): make buildVolume reactive after mount (#274)

The Svelte shell applied buildVolume once at init with no reactive statement,
so post-mount changes were a silent no-op — a parity break vs Vue (watch) and
React (useEffect). It was the only writable prop missing a $: wiring. Replace
the one-time call with a reactive statement matching the twelve siblings.

Guard: a zero-dependency source-invariant test asserts every writable prop is
reactively wired (or a documented init-only renderer option). The package has
no component-mount harness — its vitest runs in node with no Svelte compiler
plugin, and the portable behavioral suite drives the store, not the .svelte
component — so this static invariant is the enforceable guard; verified it
fails when the fix is removed.

Patch changeset (gcode-preview-svelte).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(svelte): read component source via ?raw, not node:fs (browser-only rule)

The prop-reactivity guard used node:fs, which the svelte package's
no-restricted-imports rule bans (browser-only, DD-007 §7) — caught in CI.
Switch to a Vite ?raw import of the .svelte source; same invariant, no Node
imports.

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>
…282)

Adapter canvases had aria-label but no tabindex (not focusable) and the
renderer never enabled OrbitControls key events, so only the standalone demo
was keyboard-usable. Add tabindex="0" to all four adapter canvases and enable
OrbitControls listenToKeyEvents scoped to the canvas (arrow-key pan when
focused; no page-level key hijack). Element a11y test asserts the focusable,
labelled canvas. DD-004 keyboard operability now holds for embedders.

Patch changesets: renderer-three + 4 adapters.

Co-authored-by: Nathaniel Chestnut <sobechestnut-dev@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…rops (#275 M3+M6) (#283)

M3: the parse-complete/ready event now carries capabilities (per-field
confidence map) + warnings, so adapter consumers can gate their own UI on
capability-honesty without the raw handle. Behavioral-suite case added ×4.

M6: setView/getCameraState/setCameraState (#268) get first-class declarative
props on all four adapters — a `view` prop (preset) and a `cameraState` prop
(restore) — paired with a new `camera-changed` event (renderer emits on
OrbitControls interaction end → controller → adapters) so cameraState
round-trips as a two-way binding. 2D keeps disclosing via renderer-unsupported.

Manual: camera two-way binding + capabilities-on-ready notes. Minor changesets
(renderer-three + core + 4 adapters, lockstep).

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.5.0 version PR (#272)

Changesets' GITHUB_TOKEN push doesn't trigger workflows (release gotcha #1),
so the version PR's required build check never ran → BLOCKED. This empty
commit kicks CI so #271 can merge.

---------

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>
@sobechestnut-dev
sobechestnut-dev merged commit ea9ba7d into main Aug 14, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant