Commit Graph
7 Commits
Author SHA1 Message Date
Tommaso BianchiandClaude Opus 5 afb17e8889 D3 was testing luck: the pair started 3 degrees from square, inside inference's snap
Port of snaporca b3221f8a12; this is the fork the fault surfaced on.

The perpendicular rung drew its two lines 93.5 degrees apart and then asserted they did
NOT start perpendicular. On this rig, whose camera maps the same click a pixel differently,
they arrived at exactly 90.000000 -- inference had already done the job the rung exists to
test, so the precondition failed while every later check passed. Held on the other fork and
failed here from identical source: the rung depended on where a click happened to land, not
on the app.

The second point now starts the pair 56 degrees off, well outside any snap tolerance, so
the button has real work to do.

That immediately exposed a second, milder fault in the same rung. From a 51 degree start
the LIVE solve converges to its own tolerance and lands at 89.999999991; the old 1e-9
assertion held only because the correction used to be tiny -- it was measuring how little
work the solver had to do, not whether the lines came out perpendicular. It is 1e-6 degrees
now, which is 1.7e-8 radians. The round-trip check still demands exactly 90 and gets it,
because the committed feature re-solves from scratch.

Full ladder 118/118 on BOTH rigs after this, each driving its own fork's binary. This fork
had never had a green gesture ladder before today (snaporca-eoj1).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MrMzTpAf78U4NG2M8jfvHY
2026-08-31 11:29:35 +02:00
Tommaso BianchiandClaude Opus 5 d35d33971a the feature-tree row needs CHROME_DY too — the last chrome constant that did not carry it
Four of this fork's five absolute chrome coordinates were shifted by CHROME_DY when the
ladder was first brought up here (DESIGN_TAB, CONSTRUCTION_CHECKBOX, CON_BTN_Y,
CONFIRM_BTN). TREE_ROW0 was not, because it is declared above the CHROME_DY block and was
simply never in view.

The unshifted click lands 26 px below the first tree row, just past its 23 px height, so
the row is never selected and Delete does nothing. reset_document then spends 40 rounds on
it and dies with "could not empty the feature tree" — a message that names the feature
tree, which is not the fault. The same 26 px is why confirm_and_reopen's double-click did
not reopen the sketch, which surfaced as "sketch_describe: no sketch is open" three frames
away from the cause.

Measured, not inferred: the Sketch1 row centre reads y=241 on the rig at 1920x1080 with
the window at (0,0), against the constant's 215. CONFIRM_BTN was checked in the same pass
from a screenshot taken in CONSTRAIN mode and is correct at (1751, 101).

With this, the four new constraint rungs hold 20/20 on this fork's rig, driving the binary
built from 648b930e75 (BuildID 56417445) — so the DistanceX/Y fix ported here is now
exercised, not merely parity-checked.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MrMzTpAf78U4NG2M8jfvHY
2026-08-31 10:52:34 +02:00
Tommaso BianchiandClaude Opus 5 648b930e75 gesture rungs for the six new constraint buttons, and the DistanceX/Y bug they found
Port of snaporca 2951e3c60b; parity holds (17 identical, DesignPanel.cpp still exactly 32
divergent lines, so the hunk landed on the right side of the DropDown divergence).

The sketch-constraint epic added six toolbar buttons and covered all six with kernel
tests. Not one of them was ever clicked. The gesture ladder only pressed 'perpendicular'
and 'equal' -- and CON_BTN, which locates buttons by index, was silently wrong for every
entry past index 5 for the whole epic. The untested half of the toolbar was exactly the
broken half (snaporca-rqsy).

Four rungs now drive them: D4 Equal on two circles (must mean equal RADIUS, not the
equal-length no-op the epic fixed), D5 Collinear on two oblique lines, D6 a horizontal
distance, D7 symmetric about the implicit vertical axis. Full ladder 118/118 on snaporca;
this fork's rig has not been rebuilt against the change yet, so here it is reviewed,
parity-checked and NOT exercised.

D6 found a shipped defect. apply_entity_constraint enumerated {P0,p0},{P1,p1} for BOTH
entities regardless of type, but a Point's p1 is unused and reads (0,0), as does a
Circle's. The closest-pair search then picked those two phantom origins, distance 0: the
field opened pre-filled 0.00 and the solver dropped the constraint, because ptOf(Point,P1)
resolves to no handle. Nothing errored -- the dimension simply did nothing. ends_of() now
enumerates only the roles an entity actually exposes, and the pair with no point at all is
refused with a message instead of a silent no-op.

Five kernel tests, a 7/7 ladder, a review and a fork port all passed over this, because
every one of them exercises the kernel, where the geometry was always right.

Two rig faults fixed in the same pass, both of which produce a green-looking session that
tests nothing: start-headless-gui.sh never exported SNAPORCA_MCP or SNAPORCA_KEYTRACE, so
a freshly launched rig comes up healthy and every ladder dies on "Connection refused"; and
it never dismissed the "Restore" dialog a killed session leaves behind, which grabs every
synthetic click afterwards.

The value field also takes no keyboard focus from the WM -- typed digits go to the canvas
and Return commits the pre-filled number (typed 40, got 54.94). focus_field() finds it as
its own top-level window and clicks it first. The no-op tolerance is now 5e-3, the field's
own two-decimal display resolution, not 1e-6.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MrMzTpAf78U4NG2M8jfvHY
2026-08-31 10:40:38 +02:00
Tommaso Bianchi d0791c3b8a Make the ladder runnable on this fork's rig — 6 of 7 rungs now hold
This fork had never been gated end to end. Five separate things stopped it, none
of them a defect in the CAD code itself, and each failure named the wrong
subsystem — which is why they survived.

1. run-all-checks.sh invoked docs/ux/mockups/gen_offer_table.py. The design docs
   moved to docs/CAD/ (bbd1989e1e) and this path did not follow, so the rung
   failed on a missing file.
2. gen_offer_table.py then resolved REPO one dirname short, because it now sits a
   level deeper. OUT pointed at docs/src/.../DesignOffer.hpp, which does not
   exist, so --check diffed the generated table against an EMPTY file and
   reported all 189 lines as a difference.
3. DISPLAY was never passed into the container. The check scripts fall back to
   ":10", which is the other fork's rig; this one's Xvfb is :11. Symptom:
   "FATAL no app window on :10", which reads like a dead app.
4. Every absolute chrome coordinate was written in the Snapmaker fork's layout.
   This fork keeps mainline's top row (File / save / undo / redo / Calibration
   with the title), so the whole chrome sits 26 px lower. At the unshifted y the
   Design-tab click landed in the toolbar and the app stayed on the Home page,
   reported as "no sketch opened after plane click + Shift+S"; the unshifted
   Construction checkbox reported "0 construction axis". The three constants now
   derive from CHROME_DY. Canvas coordinates were never affected -- clickmm()
   computes them from live canvas geometry -- which is why dozens of geometric
   properties passed exactly on a GUI that had never been driven.
5. CON_BTN was stale for every index after 5, from the sketch epic's six new
   buttons. Fixed in both forks; see the companion commit on snaporca.

pdftocairo was also missing from the rig image (installed there, not a repo
change), without which every corpus sheet threw.

RESULT: offer-table, kernel, engine, corpus, corpus-scale and offer all hold.
The gesture ladder now reaches D2 and applies Equal length through the Constrain
toolbar, both sides landing at 99.928133658; it then fails re-entering the sketch
after commit, filed as snaporca-eoj1 with the evidence and the next measurement
to take. Kernel here is 7701 assertions / 270 cases.
2026-08-31 08:40:06 +02:00
Tommaso Bianchi fac3cf44df Infer parallel, perpendicular, equal radius and tangent while drawing
Port of snaporca 2d36d28770. Parity OK: 17 files identical, 8 diverging at their
expected counts.

infer_axis_constraint returned only Horizontal or Vertical. On the
CAD-1000-hours corpus the top two transitions are sketch_dim -> sketch_draw
(5896) and back (5756): the signature of geometry that does not self-constrain
as it is drawn.

Every rule requires the relation to be ALREADY TRUE within tolerance, so nothing
the user drew is moved; parallel/perpendicular and tangent additionally require a
shared endpoint.

TWO LIMITS THE CORPUS RUNG FORCED, neither visible to the unit tests:

1. At most ONE constraint per rule per new entity, not one per PAIR, and no
   one-at-a-time fallback for the relations batch. EqualRadius has no locality
   restriction, so 200 equal holes produced ~20000 candidates; the rejected batch
   then cost a solve per constraint and pinned the app at 95% of a core with the
   MCP socket unresponsive.

2. Relations only for gesture-sized batches. "A scripted add is not a drawn
   gesture" is already this file's rule at its bulk call site (snaporca-8xg1), and
   EqualRadius also couples geometrically distant entities, merging independent
   connected components and defeating the partitioning that makes large sketches
   solvable (snaporca-yww4). With the cap alone geometry stayed correct (32/32
   sheets clean) but seven of the largest timed out, including MPD681 -- the sheet
   that call site's own comment names.

Also fixes the tolerance leak behind 2: the bulk path asks for exact inference
with ang_tol_rad = 0 but len_tol_frac kept its 0.01 default.

ALSO independent of this feature: run-kernel-tests.sh defaulted to
TAGS=[CadDocument] while four CAD test files carry their own tags and nothing
selected them (2624 assertions / 206 cases reported, 7648 / 264 actual). All 58
dark cases were passing; the coverage was never exercised.

VERIFICATION LIMIT, as with the previous three commits: this fork's kernel suite
still cannot run (find_package(assimp) at configure time, snaporca-w80c). Shared
sources are byte-identical to snaporca's, where kernel is 7651 assertions / 265
cases and ALL LADDERS HELD 7/7.
2026-08-31 03:43:08 +02:00
Tommaso Bianchi a1f2a2687a Equal radius and Collinear, and one Equal button that knows what it picked
Port of snaporca 9ec6405e2d. Parity OK: 17 files identical, 8 diverging at their
expected counts (DesignPanel.cpp 32, test_slvs_constraints.cpp 3).

Measured on the CAD-1000-hours corpus: 51.5% of observed CAD time is 2D sketch
work, and dimensioning/constraining alone is 31.9% -- the largest single class.
Two constraints every industrial sketcher has were missing here.

EqualRadius fixes a dead end rather than adding a feature. Picking two circles
and pressing Equal emitted EqualLength, which maps to SLVS_C_EQUAL_LENGTH_LINES
and constrains nothing on a curve: a silent no-op with no error. Equal is now
one button with two meanings, as in Onshape and SolidWorks.

Collinear emits PARALLEL plus PT_LINE_DISTANCE=0 rather than PT_ON_LINE, whose
internal valP param this libslvs port leaves at 0, drifting an already-collinear
pair.

Both types are appended at the END of SketchConstraintType: cereal serializes it
positionally, so inserting elsewhere reinterprets every saved recipe.

VERIFICATION LIMIT, stated rather than implied: this fork's kernel suite could
NOT be run. scripts/CAD/run-kernel-tests.sh fails at CMake configure time on
find_package(assimp), before any source compiles -- a pre-existing deps gap
(snaporca-w80c), not this change. The shared sources are byte-identical to
snaporca's, where the full gate passed: kernel 2588/195 and ALL LADDERS HELD
across all seven rungs.

Also fixes two defects in this fork's scripts/CAD/run-all-checks.sh:
  - `cd $(dirname $0)/..` landed in scripts/ instead of the repo root, so every
    rung looked for itself under scripts/scripts/. Broken since the script moved
    into scripts/CAD/; the three sibling scripts were fixed then and this was
    missed, so the gate has not run since.
  - C defaulted to snaporca-gui, the OTHER fork's rig container, so this fork's
    gate would drive snaporca's app and report green about the wrong binary.
    run-kernel-tests.sh:31 documents the identical defect being fixed once
    already for the build volume; this is the third instance.
2026-08-31 01:09:43 +02:00
Tommaso Bianchi 13d5eac891 Move the Design-tab scripts into scripts/CAD/ and name them by role
Requested by SoftFever on PR #15238: ten of these had accumulated loose in
scripts/ next to ~20 unrelated upstream ones, with names that only meant
something to whoever wrote them. They now sit in scripts/CAD/, mirroring the
src/libslic3r/CAD/ and src/slic3r/GUI/CAD/ split, and the verb in the name is
the role: build- produces a binary, start- brings something up, run- runs a
suite, check- asserts one thing against a live app.

  kernel-test.sh        -> CAD/run-kernel-tests.sh
  ladder-all.sh         -> CAD/run-all-checks.sh
  sketch-ladder.py      -> CAD/check-sketch-engine.py
  ladder-corpus.py      -> CAD/check-sketch-engine-corpus.py
  gui-ladder.py         -> CAD/check-gui-sketching.py
  offer-ladder.py       -> CAD/check-gui-context-menu.py
  mcp-sketch-smoke.py   -> CAD/check-mcp-sketch.py
  rig-build.sh          -> CAD/build-gui.sh
  docker-iter-build.sh  -> CAD/build-gui-incremental.sh
  gui-session.sh        -> CAD/start-headless-gui.sh

"Ladder" was the worst of them: it named the shape of the test (rungs of
increasing difficulty) rather than what the test proves, so nothing in the
directory listing told you which one needed a GPU and which was pure kernel.

Every reference rewritten -- the docs, the cross-calls between the scripts,
Dockerfile.deps, and the container-side /OrcaSlicer/scripts paths. The three
shell scripts resolve REPO relative to themselves and now sit one level
deeper, so that walk went from /.. to /../.. . The copies these push into a
container's /tmp were renamed to match, or the container would have kept the
old names alive.

Two runtime paths deliberately NOT renamed. /tmp/orca-rig-build.lock is a
cross-fork contract -- both forks take the same lock so two concurrent builds
serialise instead of OOMing the box, and renaming it on one side silently
removes that guard. /tmp/gui-session.log is a runtime artefact, not a script.

Added scripts/CAD/README.md: what each script proves, what it needs, and the
two constraints that have each cost a session (never build inside the GUI
container; a window manager is required or synthetic keys are ignored).

On CI, which was the other half of the request: the kernel suite is already
there and always has been. The cases are registered in
tests/libslic3r/CMakeLists.txt under if (SLIC3R_CAD), which defaults ON and no
workflow turns off, so they build into libslic3r_tests and run under ctest on
every platform via unit_tests.yml -- like any other unit test, needing no new
job. They have simply never been seen to run, because the workflows on this PR
are still awaiting maintainer approval. run-kernel-tests.sh is the local loop
over the same cases, and it is the only script here CI could run: the other
six need an OpenGL canvas and synthetic input.

Verified: scripts/CAD/run-kernel-tests.sh from its new location, all tests
passed, 2562 assertions in 190 test cases.
2026-08-28 19:34:03 +02:00