Skip to content

Contour CAM: inside cuts inside, tabs hold, Run Job is not the default button - #905

Merged
ecto merged 2 commits into
mainfrom
claude/unruffled-villani-c08436
Sep 17, 2026
Merged

ecto merged 2 commits into
mainfrom
claude/unruffled-villani-c08436

Conversation

@ecto

@ecto ecto commented Sep 17, 2026

Copy link
Copy Markdown
Owner

Why

Getting the rana-60-cnc stator ready to cut on the Anolex 4030, I replayed the app's generated G-code against the outline it came from before letting it near the machine. That check — not the preview, and not the existing tests, which only asserted that moves came back — found that the job would have destroyed the part.

Kernel (vcad-kernel-cam)

  • Inside contours cut on the wrong side. Contour2D::inside() was byte-identical to outside(); both offset by +tool radius. The stator's bore-and-slots pass ran 3.2 mm into every post and the ring. inside is now a field and the compensation is signed.
  • Cutter that does not fit — an inward offset that falls into several pieces used to follow the first piece silently; it is now CamError::ContourSplit.
  • Tabs held nothing. Honoured on the final pass only (0.5 mm stepdown cut a 1 mm tab to 0.5 mm), width measured along the tool-centre path (4 mm → 0.8 mm of metal), a tab at position 0 clipped at the loop seam, entered along a ramp, and one landed inside the stator's 4 mm lead notch. Now: every pass below the tab top steps over it with vertical lift/plunge, width means metal left, the seam is handled, even spacing starts half a pitch in, and each tab settles on the nearest stretch that runs straight.
  • Always retract straight up after the last pass.

Tests check the side (both windings), the metal actually left under each tab on every pass, the seam case, tab placement on a notched outline, and the neck refusal. The side and placement tests were mutation-checked (fail on the old behaviour).

Native app

  • A contour imported as a through cut follows the stock thickness until its depth is edited by hand (importing before entering the thickness left the job blocked at 10 mm).
  • Run Job was the window's default button. Its shortcut was ⌥⌘Return; AppKit exposes any Return-keyed button as the default button, so an accessibility client pressing "return" pressed Run Job, and the confirmation that followed had "Start machining" as its Return default. Shortcut is now ⌥⌘J; run / home / move-to / set-zero / run-macro dialogs default to Cancel. Verified live on the Simulator.
  • CNCOutlineTests: VCAD_STATOR_GCODE_OUT dumps the job so it can be checked outside the app.

Result

First real cut with the fixed CAM: the stator profile in a 1 mm copper plate, Ø2 2-flute, sent from ncSender — clean profile, cutter survived. docs/native-app-friction-log.md items 32–54 record everything hit along the way, fixed and open.

Testing

  • cargo test -p vcad-kernel-cam (71 pass), cargo test -p vcad-ffi cam, cargo clippy -p vcad-kernel-cam -p vcad-ffi -- -D warnings, cargo fmt --check
  • swift test --filter "CNC|DesignShellTests|WorkspaceSwitchTests" (35 run, 0 failures)
  • Exported jobs verified against the outline: worst deviation 0.013–0.018 mm (polyline tolerance), no rapids below Z0.5 with XY motion

No generated WASM artifacts are touched.

🤖 Generated with Claude Code

…t button

Found by replaying the generated G-code against the outline before a first
cut on the Anolex, not by the preview or the existing tests (which asserted
only that moves came back).

Kernel (vcad-kernel-cam):
- Contour2D::inside() was identical to outside(): both offset by +tool
  radius, so an inside contour ran a tool diameter into the part. `inside`
  is now a field and the compensation is signed.
- An inward offset that falls into several pieces (cutter does not fit a
  neck) is CamError::ContourSplit instead of silently following the first.
- Tabs: honoured on every pass below the tab top (was final pass only),
  width is metal left (lifted run = width + tool diameter), vertical lift and
  plunge at the ends instead of a ramp from the previous vertex, a tab across
  the loop seam stays whole, even spacing starts half a pitch in, and each
  tab settles on the nearest straight stretch so it never lands in a notch.
- Always retract straight up after the last pass before the XY rapid.

Native app:
- A contour imported as a through cut follows the stock thickness until its
  depth is edited, so importing before entering the thickness no longer
  leaves the job blocked at the old depth.
- Run Job's shortcut was Option-Command-Return; AppKit exposes any
  Return-keyed button as the window's default button, so accessibility
  clients pressed it for "return". Now Option-Command-J, and every dialog
  that starts motion (run, home, move, zero, macro) defaults to Cancel.
- CNCOutlineTests: VCAD_STATOR_GCODE_OUT dumps the job for outside checks.

Friction log items 32-54 cover the session, including the first cut.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@vercel

vercel Bot commented Sep 17, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
vcad-mcp Building Building Preview Sep 17, 2026 7:39pm UTC
3 Skipped Deployments
Project Deployment Actions Updated
mecheval Ignored Ignored Sep 17, 2026 7:39pm UTC
vcad Ignored Ignored Sep 17, 2026 7:39pm UTC
vcad-docs Ignored Ignored Sep 17, 2026 7:39pm UTC

Request Review

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@ecto
ecto merged commit 415d78b into main Sep 17, 2026
14 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