Keep cut outlines dark and etch strokes bright green. Assign drawing fills by a golden-angle hue walk with varied saturation/lightness tiers, preserving legacy schemes and rendering-only behavior. Include palette, visibility, persistence, and contrast regressions.
Build paths in the drawing-local frame and translate both ordinary and split cut/lead paths once, without changing CNC programs. Add native Windows regressions using the operator's synthetic G90 fixture and incremental controls. Four absolute-mode cases fail before the fix; all seven pass after.
PreferredContourEntries resolves one entry per hole by walking the
proposed hole route BACKWARD from the already-chosen perimeter entry.
Each hole ranks against the downstream contour's ACTUAL emitted pierce
(first non-rapid motion of the owned probe emission, native rounding
included), so the cut chain flows toward the outside start rather than
chaining on nominal points that rounding may move.
Catalogue is the S04 merged list (preferred kinds where present,
compass/arc fallbacks otherwise — pure circles included); ordering is
the S05 facing/tier/travel ranker; feasibility is one S08-bounded pick
per hole through caller-supplied S07 verdicts. A hole with no feasible
candidate yields an explicit no-preference proposal naming the contour
and reason — never a silent skip, never a partial chain. Arrival proxies
(part arrival for the first hole, previous hole centre otherwise) keep
the pass deterministic and circularity-free.
Deterministic (repeat runs identical), cancellation-aware, ownership-
checked, source program untouched, fresh owned probe programs only.
This is a recommended-v1 proposal: nothing is installed into the search
and no rapid is certified here — S12 wires it and must handle a blocked
preferred rapid.
Tests: circle pair flows hole->hole->outside via actual pierces (each
pierce strictly nearer downstream than the opposite compass pierce);
rectangular holes pick right-facing corners under all-clear evaluation;
blocked ideal candidate falls back to next-ranked on the same hole;
blocked hole yields honest no-preference finding; permutation integrity
in route order excluding the perimeter; determinism; foreign perimeter
refused; cancellation; fingerprint/ownership/fresh-program invariants.
Gate 9/0/0; full Core 3580/25skip/0; cross-build 0 errors; scoped
format verify 0; facing-drop and silent-skip mutants killed; nominal-
vs-actual-pierce mutant documented near-equivalent.
Browsing the saved-nest list was slow because arrowing to each row
downloaded that nest's archive from scratch. NestDetailsSession now
keeps a small LRU cache and exposes Prefetch(id); SavedNestsForm warms
the rows around the highlight once its own details are showing, so
arrowing through the page mostly resolves from cache instead of
re-downloading each nest.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
CuttingHoleOrder proposes the cut order of a part's remaining holes as
an OPEN path arrival -> every hole centre exactly once -> the fixed
perimeter entry, reusing CuttingPartOrder's bounded nearest-neighbour +
2-opt/Or-opt machinery (no exhaustive permutations, no new routing
invention). A proposal only: the search still certifies every rapid and
emitted lead; nothing is installed into the search yet.
CuttingPartOrder gains an optional endpoint: the terminal edge joins
EVERY improvement delta (2-opt tail edge on both sides; OrOpt gap to the
open end measures the endpoint distance), so heuristics see route moves
that re-point the path at the entry rather than only final scoring. No
endpoint keeps whole-part semantics byte-identical (control test);
precedence, prerequisites and tie policy unchanged.
Tests: empty/one hole; asymmetric fixture where the endpoint changes the
ORDER (open route ends at C, entry-facing route ends at B) with each
route asserted equal to its brute-force optimum computed from
coordinates; permutation integrity excluding the perimeter; random 7-set
within 1.05x brute force; deterministic tie order; cancellation; legacy
no-endpoint equality. Mutants dropping the terminal edge from OrOpt or
TwoOpt deltas are killed.
No-hole parts now choose the outside entry through the S03-S08 pipeline
at the part boundary: rank the native catalogue toward the NEXT cut's
placed-material centre, lazily certify each emitted lead with the shared
validator, cap at maxEntries with side coverage. The next cut is the
next unfinished part on the supplied order (re-read after every
learned-order replan) or, in sequence-free fallback, the nearest
dependency-ready remaining part with stable ordinal ties; the last part
has no target and ranks by tier then arrival distance — never the plate
origin. Target and arrival are converted to prepared LOCAL coordinates
exactly once; geometry is already rotated.
The look-ahead rank survives Follow's ordering: children sort by
nearest source first (the sequence-free tour stays nearest-first), then
contour, then the selection rank — plain OrderBy(Distance) can no longer
undo the facing. Measured fixture (three squares, 0.15 leads, origin
start): legacy cut every sheet at its arrival-nearest lower-left corner
with 10.5-unit cross-sheet rapids totalling 21.0; look-ahead cuts the
+X-facing corner with the same 21.0 total but each inter-part rapid now
starts at the facing edge instead of trailing across the whole sheet.
Uncertain validator answers are never precheck-refused: they skip the
selected slots but flow to the emitted-prefix Check and complete replay,
which stay the authority — a refused-looking incomplete is reported,
not hidden. A fully evaluated catalogue with no fitting lead surfaces
'No tested lead-in fits on part N, contour M'; budget exhaustion stays a
budget finding. Lead prechecks count separately from DFS expansions; the
pipeline itself is one counted expansion per contour. Full backtracking,
dependencies, locked/fixed programs, cutoff handling, emitted-prefix
Check and complete replay are unchanged; budgets and CuttingPartOrder
untouched. Hole parts keep the legacy path until S12.
ContourEntrySelection: lazy bounded selection over one contour's ranked
candidates. Greedy global rank order until the cap (default 16) fills or
the finite catalogue ends; blocked and incomplete candidates never
consume a slot, and once selection settles the untouched tail is never
evaluated (EvaluatedCount/EvaluatedKeys pin the counts, not timings).
At caps of 4+ a corrective scan represents every side of the candidate
bounding rectangle that HAS a feasible candidate — lazily chasing each
missing side and replacing the worst selected candidate only when every
other covered side survives; one corner may cover two sides. The cap is
never exceeded and points are never manufactured on infeasible sides;
caps 1-3 obey cap+ranking first, as promised. Verdicts memoize per
attempt; duplicate geometric points never take two slots.
Honest metadata: Choices/EvaluatedCount/Shortfall/Reason with None,
Exhausted and Incomplete kept distinct — 'no tested lead-in fits' is
producible only from a fully evaluated Exhausted catalogue; incomplete
checks and cancellation are never presented as geometric impossibility.
Sides are exactly the ranker's bounding-rectangle geometry. No search
changes and no larger search budget.
ContourEntryFeasibility: one adapter over the EXISTING LeadPathValidator
for one owned candidate — emit through the S06 diagnostic seam, read at
the placement position, certify emitted lead-in AND lead-out against ALL
placed material. Only complete+clear qualifies; blocked and incomplete
keep their reasons as distinct verdicts (an incomplete check never
reads as clear). Not a new collision implementation and not a plan
approval: NoLeadIn passes vacuously and the complete-plan missing-lead
check still runs later; rapids and pierce clearance stay with their
existing checkers.
One instance is one captured planning attempt: verdicts cache per exact
owned choice + node context (settings/placement are fixed per instance),
never static, never across instances. Lazy: only the checked candidate
is emitted; EvaluationCount counts validator executions for cost tests.
Foreign/malformed emissions are Incomplete verdicts with reasons, never
crashes; cancellation propagates without poisoning the cache. No search
changes and no broad-phase skips.
EmitCandidateForValidation emits exactly one owned contour with its
normal lead-in and lead-out and its ORIGINAL contour type — the
perimeter keeps External even with no holes before it — through a small
shared EmitChosenContours seam, so a perimeter candidate's emitted leads
can be validated before the hole choices exist. The probe is a throwaway
program: never installed on a Part, never a complete plan. Normal Emit
and EmitPrefix keep the perimeter-last gate untouched (still throwing
for Emit([perimeter]) on a holed part); foreign and re-stamped choices
still fail ownership/geometry validation and source shapes/settings are
never used directly. Differential tests pin per-contour block fidelity
(External-vs-hole lead geometry, five lead styles, two hole
choice/orders, scribes once, reversed winding, rotated capture, circle
rounding/clamping without cross-contour state) — contour lead geometry
is choice-independent, only absolute accumulated coordinates drift by
ulps with program head.
Pure deterministic ordering of the automatic catalogue: classify each
point by its nearest bounding-rectangle side(s) with the preparation
tolerance (a corner belongs to two sides), choose the facing side pair
from the look-ahead target against the centre (right/left and top/bottom
per the source plan), then order by matched facing sides descending,
rank tier ascending (corner, midpoint/tangent peer tier, fallbacks),
then arrival->entry + entry->target travel, then the stable geometric
key. Without a target (last part) the tier leads and distance to the
arrival breaks ties — never the plate origin. The input list is never
mutated, no candidates are added, no cap is applied and entity order is
never the tie-break; reversed and cyclically reindexed drawings rank to
the identical geometric order.
AutomaticEntryCandidatesWithFallbacks completes the uncapped catalogue
with tier-3 fallbacks after the preferred points: native arc midpoints,
the eight compass points of a whole circle (a pure-circle contour is now
usable instead of refusing), near-convex-corner points on each incident
straight edge back from the corner by 2 x the applicable lead-in length
using the emitter's own SelectLeadIn semantics (non-length lead-in styles
contribute 0 and the fallback is omitted, never approximated), and the
exact target-facing closest point toward the caller's look-ahead. Every
fallback runs through the same reflex/cusp exclusion — a raw closest
point or an inset landing on a forbidden inside corner is dropped — and
the same geometric duplicate merge; short edges omit an out-of-segment
inset by projection parameter instead of extrapolating. No ranking and
no lead-safety verdict yet.
Internal PreparedContours.AutomaticEntryCandidates builds the uncapped
preferred start catalogue per contour from the contour's own winding:
convex corners, then straight-edge midpoints, then line/arc tangent
joints, deduplicated geometrically with the preparation epsilon (the
most preferred metadata wins at equal points). Reflex and cusp vertices,
collinear splits and circles are never enumerated for automatic placement;
hole slugs classify from their own travel. Manual Entry/ClosestEntry and
the legacy Entries API are unchanged; emission wiring comes in S09.
Scoped dotnet format removed the unused entityIndex parameter from
TraversedBackwards_SquareCornersStayConvex, leaving MemberData supplying
two values to a one-parameter theory (8 xUnit failures at test discovery).
The parameter is now genuinely used: each geometric corner is classified
from both adjacent entities of the reversed contour.
Expose TryClassifyAutomaticStartCorner: an internal read-only query over
the emitter's existing TryGetCorner/ClassifyCorner with the same winding
derivation EmitContour uses, so start-point planning can prefer convex
corners without copying tangent math or touching lead generation. Corner-
kind characterization covers convex, reflex, tangent-smooth and cusp
vertices from either adjacent edge, both windings, under rotation, and
rejects midpoints and open contours.
The editor header and the Plan Cutting dialog counted the trailing empty
new-plate workspace PlateManager.EnsureSentinel maintains, so a one-plate
nest read 'Plate 1 of 2'. PlateDisplayNumbering now derives display-only
numbers that exclude only a trailing empty sentinel; interior empty plates
keep their slot and number, and navigation, storage indexes, exported
names and batch selection are untouched. The sentinel itself is labeled
'New plate (empty)' instead of being numbered beyond the shown total.
Fix DuplicateRows_CreateNestsButtonImportsOneDrawingWithCombinedQuantity timeout from Windows run 37526243901. Native trace on DesktopPC showed the sole OK button uses control ID 2, not IDOK 1. Preserve real dialog text and nest assertions; find the sole button and stop polling only after successful posting. All 392 WinForms and 49 FrontEnd tests pass in an interactive Windows session.
The saved-nest browser opened maximized with MaximizedBounds set from the
owner screen's working area in absolute coordinates. Windows reads that
position relative to the monitor, so on a secondary screen the offset was
applied twice and the modal dialog was placed off-screen, leaving the
disabled main window with no way back to it.
Open it instead as a normal window sized to 90% of the owner screen's
working area and centered there; it still clears the taskbar and moves
between monitors like any other window.
The engine argument's description now names every built-in engine with what
it suits, so a model can choose one; omitting it still means Default. The fill
tools resolve an omitted strategy to Fill directly instead of through the
session's whole-job default. Front-end tests cover the MCP and console
defaults and keep the description in step with the registry's built-ins.
Default is the engine every front end uses when none is named. It now runs
Irregular, then Rectangles, checks both layouts with NestLayoutCheck and keeps
the best: valid first, then fewest unplaced parts, then lowest salvage-credited
cost; ties keep Irregular. A candidate that throws or returns nothing is
skipped, cancellation stops the search, and only the chosen layout's plate
commits are reported. Neither engine wins every job in the lane benchmarks,
and Rectangles adds little time while also covering Irregular's invalid
layouts.
The registry lists Default first and no longer maps the name to Fill; fill
strategy callers still read Default as Fill. A future circle/ring engine joins
as another candidate.
The multi-phase lattice fill (linear, pairs, rectangle best-fit, remainder) is
no longer meant to be the engine used by default, so it gets a name for what
it does. The registry lists it as Fill and maps the old name Default to it;
PlateFillService, PlateNesterFactory and NestJobOptions use Fill, and every
fill-strategy caller still accepts Default. Console --autonest now validates
engine names through NestingEngineRegistry.ResolveName so renamed names work.
Layouts are unchanged: Default and Fill resolve to the same fillers and the
golden layouts pass under the new name.
Plan Cutting refused ordinary filleted parts with "Native contact query is
numerically uncertain." Material capture checks every curve pair of a ring,
adjacent ones included. Where a line meets a tangent arc at their shared
vertex, rounding can drop the tangent root of the native line/circle
quadratic; the exact ray cast from the line's far end then reached the
vertex, which is already recorded as an endpoint contact, and was read as a
contact the native query missed. Rounded rectangles rotated off-axis were
refused 1037 times in 1080 before this change and 0 times after.
The exactness rays now stop short of a line endpoint the other curve already
contains (half-way from each end when both are contained), so together they
still cover every other point of the line and any unrecorded contact still
refuses. The native kernel and tolerances are unchanged.
Regressions: four tangent-fillet rings and a rotated filleted part planned
through CuttingPlanBatch (red before, green after); a line ending inside a
small circle's contact band stays uncertain in both directions. Mutations that
treat either endpoint as always contained, drop the start ray, or count
recorded endpoints as native contacts all fail.
Project Memory: 41880037
Runs the four cross-platform suites as a matrix and the six synthetic
Irregular nests in their own job, with a fail-closed final "tests"
check.
Conflict in ci.yml: take the branch's Linux jobs and keep master's
windows-desktop job unchanged after them. actionlint and the aggregate
checker self-tests pass on the merged file.
Brings in the Plate menu reorganization, Database-mode drag-and-drop
open, the SavedNestsForm look fixes and the Irregular block-fill work
budget fix.
Conflicts:
- MainForm.Designer.cs: keep the branch's Plate menu order (Arrange
submenu, View in CAD last) and add master's Plan Cutting item ahead
of the lead-in commands.
- SavedNestsForm.cs: keep master's browser rewrite (details, preview,
columns) and apply the branch's intent to it: open maximized with
MaximizedBounds clear of the taskbar, the lighter grid palette on all
three grids, and B/KB/MB/GB file sizes.
The second delta review compared the filtered checks with the previous
implementation on 5,400 generated cases. Rapid checks matched in every
case, but 114 lead checks differed: a long lead passing a small circle
or arc well over 0.001 away was reported clear, while the native
line/circle query, through rounding in its squared terms, reports a
contact there. A coordinate limit and a fixed margin cannot bound that
cancellation.
Lead checks therefore examine every other part's material again,
exactly as before the filter; LeadMaterialSnapshot no longer keeps an
extent. Rapid checks, including the pre-post review's, keep skipping
completed contours more than 0.001 clear of the rapid. The 900000-long
lead beside a radius-0.0001 circle is a regression test.
Planning a dense 144-part grid now takes about 19 s again (lead checks
dominate); a new part order is still found where the old search gave
up.