N26-295's PT42 pairs saved spacing in slice 1 but every shared edge was
still cut twice, costing a pass per edge and risking a freed part
tipping under the head on the second pass.
Plan Cutting now cuts a plate's common lines once unless the plate is set
to cut them twice. Each group is cut member by member, owner before
partner (a captured dependency that search and replay enforce, so a kept
order cutting the partner first is a constraint conflict): the member's
holes, then the shared cuts it owns as open CommonLine centerline cuts
entered through the notch on the span's axis, then its remainder pieces,
each ramped in from the kerf the shared cut opened. Capture marks the
shared spans as tabs on the owned clean copy, so replay's contour
accounting proves each perimeter is cut exactly once; a lead that fits
at neither end refuses as UnsupportedGeometry naming the span, never
shortened. Material still comes from the drawing, so utilization,
quantity and overlap results do not change. Members are never
support-tabbed; locked or excluded members and broken groups refuse.
The CI Fiber post writes shared cuts in the cut-off form with a lead-in
and no G41/G42, and remainders in the contour form on their perimeter's
compensation side, named by a remainder comment. Cincinnati CL (whose
PreApplied mode offsets nothing) and Gravograph refuse such nests, as do
the desktop and console for any post without ICommonLinePostProcessor;
nothing falls back to a silent double cut. Plate > Arrange > Cut Common
Lines Twice keeps slice 1's behavior, persists with the plate and makes
an open plan stale.
Pre-post review now checks each span is cut once, on its centerline, by
the member cut first, and the rapid check treats a finished member's
remainders as an obstacle. Compensation start in void and cancel in
kerf are unconfirmed on the CI FIBER 4020; release waits on a 3/16
stainless coupon trial.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Nobody tabs every part, but tabbing by size is useful even on a plate
that has a support grid. Cutting Settings > Tabs now offers "Only tab
parts the support grid can't hold level" or "Tab parts by size"
(CuttingParameters.TabBySize), which ignores the bed and tabs each part
whose minimum-area bounding rectangle's narrow side is in the range.
The support grid choice still falls back to that range on plates with
no bed, as before.
The range fields become TabSizeMinWidth/TabSizeMaxWidth; their JSON
keys stay noBedTabMinWidth/noBedTabMaxWidth so saved settings and nests
read unchanged. TabsEnabled stays as the per-contour flag Plan Cutting,
Place Lead-in and drawing pins set on the parts they tab.
Saved user settings with "Tab every part" read as tabs by size from 0
to 9999, which tabs the same parts. Only the user's settings migrate;
a plate's recorded parameters and pins replay as planned.
Plan Cutting, Place Lead-in and the pre-post review all go through
SupportTabSettings, so they agree on which parts need a tab. A
size-tabbed part is held by any clear tab, so it is never a rapid
obstacle.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A support-tabbed part that no single tab can hold level may tip once cut,
yet its tabbed outside was crossable like any retained part, so Plan
Cutting could rapid back across a row of long strips. Its outside is now a
rapid obstacle, closed across its tab gap, in the search, replay, cut-off
insertion and the safest route.
Its fallback entries are ranked toward the next cut rather than steadiest
first, so a long strip can be left toward the next part, and the "cut those
two the other way round" rule applies only when the approach crosses no
other part.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The repo mixed variants such as center/centre and color/colour, so a
name could be spelled either way and searches missed half the hits.
Standardize on the US spelling, matching .NET's own APIs (Color, Center).
Wire values owned by other systems keep their spelling: the material
ledger's "Cancelled" hold status and GitHub's "cancelled" job status.
No behavior change beyond the spelling of a few status messages.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Plan Cutting spent most of its time on work that never changed the outcome:
many-holed parts paid quadratic shape-pair and ring-containment costs before
any search, every plate was captured twice, and failing plates burned their
whole budget in exhaustive fallback passes that never found a plan on 127
production plates.
- OverlapMaterial: skip native shape pairs whose bounds are clear by more
than the query allowance; gate polygon touch and winding tests on vertex
bounds.
- LeadMaterialSnapshot: gate ring enclosure tests on ring extents when
finding the perimeter and rejecting nested cutouts.
- CuttingPlanBatch: capture each plate once; the kept-order retry derives
from the same capture through CuttingPlanSnapshot.WithPreservedOrder.
- JointCuttingPlanSearch: end the kept-order full pass and the sequence-free
recovery and full passes after FallbackStalls (2) stalls' worth of
expansions when programs are regenerated; plates with only fixed programs
keep the exhaustive search so a refusal stays genuine.
On 127 archive plates (lead-ins cleared, 35" scrap cut-offs) total time fell
from 164 s to 102 s with identical outcomes; the problem-nest corpus gives
the same status and expansion count on every plate.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
When no search finds a route that keeps every rapid off parts already
cut, Plan Cutting used to offer only an unverified safest route needing
explicit acceptance. Cincinnati's own software instead raises the head
for such a rapid. Now the safest-route fallback marks each planner-chosen
rapid that still crosses cut parts with a HEAD RAISE comment, and the
plan is Ready with every raise listed. The strict search never marks a
rapid, and the batch prefers fewer broken checks, then fewer raises,
then less travel, so a plate that can be cut head-down never gets one.
The reader flags marked rapids and the checker sets their crossings
apart, in replay and pre-post verification alike. The Cincinnati CL
post writes M47 before a marked rapid whatever the M47 mode (the
distance-based safety raise is unchanged); the CI Fiber post writes a
new Head raise block and refuses marked nests while it is blank, since
its raise code is unconfirmed. Rapids into locked programs, cut-offs
and hole sub-programs are never marked and keep their findings.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With support tabs on and no support bed, nothing was tabbed and nothing
said so. A new no-bed width range (NoBedTabMinWidth..NoBedTabMaxWidth,
the short side of the part's minimum-area bounding rectangle) now picks
the parts to tab instead. SupportTabSettings.Analyze makes the choice
for Plan Cutting, hand-placed lead-ins and the pre-post review; without
a bed any tab clear of inside corners counts. With no bed and no range,
the plan notes that nothing was tabbed. Cutting Settings > Tabs gains
the range fields, and the values persist with the cutting parameters.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Stock can arrive up to 1.5 in wider than nominal, so only the origin-side
edge is certain. A cut-off with a head-locked overcut cuts past the nominal
far edge with the head height locked, covering the oversize. With that lock,
Plan Cutting may start the far-edge segment at the far edge: overcut outward,
rapid back still locked, unlock, cut toward the origin. Without it the
direction stays fixed, as decided in Project Memory a20ea455.
- CutOff.HeadLockOvercut / FarEdgeFirst, persisted in .nest; HEAD HEIGHT
LOCK/UNLOCK comment markers; far edge is quadrant-aware.
- Planner offers the reversed far-edge segment in the joint search, the
safest route and segment insertion; Apply records the direction.
- Cincinnati CL and CI Fiber posts gain lock/unlock code settings and refuse
head-locked cut-offs while either is empty.
- Automatic cut-off dialog setting (off by default, 1.5 in), kept between
sessions and used for new cut-offs.
Lock codes and machine behaviour with the head locked are unconfirmed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Cut planning should rank routes safest first, then fastest, but a plate whose
strict search hit its expansion budget was simply refused ("no plan found
within the search limit"), even when a route with a few reviewable rapid
crossings existed. Scrap cut-offs make this common: their trimmed segments
can wall off a column of parts, and rapids are straight.
When both the free-order and current-order searches stop at the limit, the
batch now walks a greedy safest route from each input, replays it with fresh
checks, and keeps the one with fewer violations (material first, then rapid
crossings, then the rest), then less rapid travel. A route that passes every
check is an ordinary Ready plan; otherwise it is an unverified BestEffort
that lists every violation and applies only with explicit acceptance. Routes
with any motion into material are never offered, so the strict refusal and
its lead-in advice stand.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Model the machine's support bed as a grid of contact points measured
from the plate origin, and check each part's center of gravity against
the convex hull of the grid points under its material. The bed is
extensible so straight and CAD-imported curved slats can follow.
- Core: SupportBed/SupportGrid, SupportMaterial and SupportAnalyzer
(margin with registration tolerance, best single tab point)
- Nest-wide support bed that every plate follows, saved in
plateDefaults.supportBed; machine defaults in support-grid.json
- CuttingParameters.SupportTabs: Plan Cutting tabs only unsupported
parts and limits their perimeter entries to points where the tab
steadies the part, falling back to any fitting entry
- Desktop: Nest > Support Grid..., View > Draw Support overlay and a
"Tab parts the support grid cannot hold level" tab option
- docs/support-tabs.md, nest file format and planner notes
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Thick plate pierces leave a crater wider than the kerf. CuttingParameters.PierceDiameter
(Cutting Settings > Pierce Diameter, 0 = off) requires every lead-in pierce to keep half
of it from all part material: its own contour, its holes and every other part.
- LeadPathValidator checks the zone during Plan Cutting candidate checks and final
replay; fixed emissions warn as usual. No-fit findings explain the zone.
- PierceZoneReview reports Pierce zone warnings before posting for leads from any source.
- Holes whose configured pierce is inside the zone move it toward the hole's PolyLabel
pole (round holes: the centre), as close to the contour as the zone allows; a hole
too small for the zone is pierced at its pole and the shortfall is still reported.
- Straight corner leads and round-hole clamping use the larger of PierceClearance and
the zone radius. The manual lead-in preview shares the Core rules.
- Persisted through the DTO, owned copies and state fingerprint.
Perimeter fallback is not included; see docs/geometry/pierce-zone.md.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A hole can now be declared a tabbed cutout in the CAD Converter: pick a
circle or any edge of a closed hole, set the tab count and width, and drag
the tabs around the hole. The definition persists on the drawing and in the
nest file, and stays editable from the source entities.
The builder replaces the hole with open cut pieces and uncut spans on a new
Tab layer. Tabs are material, so area, nesting and overlap checks still see
a closed hole, but they are never cut. Plan Cutting and Assign Lead-ins cut
each piece from the slug with the internal lead-in and no lead-out. A lead
that would reach back over a tab is mirrored, and an arc lead onto an arc
pierces straight in. Planning accounts for each span between tabs and runs
the open-cut proof, so its own tabbed cutouts certify; tabs followed by a
lead-out are still refused. Pre-post review flags programs that still
contain tab motions.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Breakoffs are now picked by their joining line, default to the smaller side as scrap
(flippable), and cut that line between tabs on a new Break layer instead of slots.
Plan Cutting and Assign Lead-ins enter each cut from the scrap with the nest's internal
lead-in, or pierce on the line without one; checks treat break cuts as intentional open
cuts that are not material.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A drawing-pinned contour is now a fixed emission like a locked program. A
regenerated placement maps its execution motions onto the emitted contour
choices (one group per choice after the program's scribes, opened by its
rapids) and owns as fixed the lead-in, cut, lead-out and tab of every pinned
contour; the rapids between contours, including the one into a pinned
contour, stay the planner's and strictly checked. If the motions do not
split cleanly into one group per choice, nothing is treated as fixed.
So a pinned lead that meets another part's material or its own part's no
longer rejects the candidate: the feasibility precheck accepts a pinned
entry as given, the search keeps it in place, and replay reports a FixedLead
warning naming the part, cutting contour, pin and the part hit, with the
advice to increase spacing or switch off drawing pins for the part. The
plate is UNVERIFIED and needs acceptance; the lead is never shortened and
the entry never moved. The unpinned control and the same plate with pins
off are Ready.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
D1a (user, 2026-10-14): one locked cutout must not refuse the whole layout.
With confirmed parameters a locked program is now a fixed emission, accepted
as given. The replay checker and the lead validator take a per-motion owner:
a violation inside the fixed emission (a lead meeting another part's or its
own material, a rapid inside the locked program crossing a cut contour, an
uncertifiable tab gap or a partial/reversed/retraced cut) is recorded apart
instead of failing the candidate. The search never rejects or learns an order
rule from them, so fixed emissions never steer it; the planner's rapid into
the locked program and every regenerated lead keep every strict check.
Replay turns those violations into typed FixedLead findings that name the
part, contour and the part hit. A plate whose only findings are these is
BestEffort with IndependentlyReplayed set: never Ready, applicable only with
the per-proposal acceptance, and CuttingPlanService.Apply still rejects it.
Overlap, unreadable programs, stale input and cancellation still block, and
unlocked programs a caller left ineligible and the no-parameter route keep
refusing as before.
Pre-post review now re-checks locked leads against every part's clean
material, so the same violations reappear before posting.
Existing tests that encoded the old locked refusal now assert the warning;
two batch tests that used a locked crossing as their hard block use an
overlap instead. The 5.1 digests are unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Plan Cutting findings dropped the checker's geometry, so selecting one could only
zoom to part extents, and overlap-blocked plates (no preview) did nothing at all.
Findings now keep the check's world-coordinate witness (overlap regions, rapid,
contacts); selecting a row draws it with the Validate Nest overlay, on the proposal
or a blocked plate's live sheet. The witness is excluded from finding equality so
repeated search rejections still collapse to one finding.
The side panel's scrolling report was a wall of text operators skipped. It is now
a colored outcome line, one line for the shown plate, and one remedy or marker
hint above the issue grid, with secondary detail moved to tooltips.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A CuttingPlanRequest constructor overload taking a Plate made the existing
detached call new CuttingPlanRequest(null) ambiguous (CS0121). Plate scope
is now requested with CuttingPlanRequest.ForPlate, and the result summary
describes dependencies and Apply as they now behave.
The cutting planner now accepts cutoffs on plate-scoped requests and
plans whole-part prerequisites captured from owned values:
- A cutoff precedes every part its nominal span crosses, using the same
rule and drawing-reference matching as automatic sequencing; a cutoff
without a definition precedes every part. Cutoffs stay fixed programs,
need no lead-in and never become rapid obstacles; rapids into and out
of them are still checked.
- A part proven, on native clean material, to lie inside a cutout of
another part precedes that host. Touching or crossing boundaries are
ambiguous and refuse; a part in a concave pocket has no dependency.
- Both searches only expand ready parts, a preserved order that breaks a
prerequisite is a constraint conflict, and final replay rechecks the
captured prerequisites instead of trusting the search.
Plate-scoped cutting plan requests now record the plate's exact state at
capture, and CuttingPlanService.Apply installs Ready, replayed proposals
for a whole scope at once:
- Any change after capture (order, pose bits, program reference or
in-place content, drawing program, lock/lead-in flags, settings,
quantity, size, quadrant or cutoff definitions) returns Stale with
nothing changed.
- Order changes without PartAdded/PartRemoved, so drawing quantities and
sentinel plates are untouched; ObservableList.Reorder exposes the same
operation and Plate.PartsReordered is raised once per changed plate.
- Regenerated parts receive owned copies of the replayed program and of
the settings captured with the request; fixed programs stay in place.
- An install failure restores every plate exactly; an observer failure
after publication is reported as a refresh error, not a rollback.