Commit Graph
387 Commits
Author SHA1 Message Date
ajandClaude Opus 5.5 2b3f8e7b52 fix(posts): Cincinnati CL sub-program frames, head raises and dead settings
Part sub-program calls restored the sheet frame with G92 at the part
corner while the tool sat at the sub-program's last endpoint, shifting
every later part. The call now raises the head, rapids back to local 0,0
and restores there. Parts share a sub-program only when their posted
toolpaths match, so per-part lead-ins are kept.

Suppressed moves are left uncut: the cut resumes with a rapid past them.

Head raises go before the rapid that leaves a feature, one per rapid:
the safety raise now precedes the rapid to a new part instead of
following its first feature, and sub-program mode no longer posts M47
then M47 P2000. M47Mode.Auto posts M47 before rapids longer than
M47OverrideDistanceThreshold and /M47 otherwise. ExteriorM47 applies to
the contour spanning the part's cut extents.

The sheet GOTO targets FeatureLineNumberStart and is omitted without line
numbers. PrepareForNest pre-selects only the gas- and thickness-matching
library. Part programs are read through absolute copies, never switched
to absolute in place.

Removes the unimplemented UseSheetSubprograms, CoordModeBetweenParts and
ProcessParameterMode (G89Mode); old configs still load.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 01:56:28 -04:00
ajandClaude Opus 5.5 5dc13a03ae feat(diagnostics): warn when parts are closer than the part spacing
Validate Nest, the posting review and console --post now report a
"Part spacing" finding for pairs of parts that do not overlap but sit
closer than the plate's part spacing. Before, only Auto Nest's
Keep/Discard review checked spacing, so hand-edited layouts could be
validated and posted with parts too close together.

Candidates are found with Auto Nest's own outline test, moved into Core
as SpacingOutline (NestLayoutCheck and NestTolerances now use it; Engine
tests unchanged). Because that outline circumscribes arcs by more than
the spacing slack, each candidate is confirmed on native contours
flattened 20x finer than the slack, so arcs placed exactly at the
spacing by interactive fills stay clear. The finding reports the
measured gap and marks the middle of the closest approach. Overlapping
pairs, cut-offs, zero spacing, the plate edge and clamps are not
reported as spacing findings.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 01:56:27 -04:00
ajandClaude Opus 5.5 93cf8007bc feat(cutting): pierce perimeters in open scrap when no lead-in keeps the pierce zone
With a pierce diameter set, a perimeter none of whose configured lead-ins keeps its pierce
clear (a lead shorter than the zone radius, or neighbours closer than it) was only rejected.
Plan Cutting now looks for a pierce in the open scrap around the part instead.

- ScrapPierceSearch (Engine): the window four zone radii around the part, minus every nearby
  part's clean material grown by the zone radius and a margin (ClipperBridge, conservative
  flattening); the clear point nearest each ranked perimeter entry is a candidate. Other
  parts' cutouts count as scrap, the part's own holes do not. With no clear scrap, the
  PolyLabel pole of the free scrap is the best effort, and its shortfall is reported.
- ContourChoice.Pierce / PreparedContours.ScrapPierceEntry: the planner's choice carries the
  pierce; the emitter cuts a straight lead from it to the nearest perimeter point and still
  reads nothing but the contour and the choice.
- Every candidate passes the lead validator like any planner-chosen entry; pinned perimeters
  keep their pins and warn. Without a pierce diameter nothing changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 01:56:27 -04:00
ajandClaude Opus 5.5 6676f9f6f1 feat(cutting): keep lead-in pierces clear of material with an opt-in pierce diameter
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>
2026-10-19 01:56:27 -04:00
ajandClaude Opus 5.5 5dff83cfb8 fix(server): reject duplicate nest ids, invalid metadata and bare --database
- POST /api/nests with an existing id (active or deleted) now returns 409 with
  the current record instead of a 500 from the UNIQUE constraint.
- Uploaded nest metadata must have string text fields and a defined status;
  null fields and undefined statuses (e.g. 99) are 400 instead of a 500 or a
  stored invalid value.
- --database <path> is accepted alongside --database=<path>; a missing or
  repeated path fails startup instead of silently using OPENNEST_DB/default.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 01:30:37 -04:00
ajandClaude Opus 5.5 3a7073d38c fix(posts): post Cincinnati CL holes where and as drawn, in sequence
Hole sub-programs are stored incremental but were written under G90 as
if absolute, producing invalid arcs. The registry now posts absolute
copies and leaves the nest's programs untouched.

Sheet-level hole calls omitted the part location from G52, so every
part's holes were cut near the sheet origin. Calls now shift to the
part location plus the hole offset.

Hole calls were matched to sub-programs by call id, which planned
emission numbers 1, 2, ... per drawing, so holes from different drawings
shared the first drawing's sub-program and diameter. Calls are now keyed
by program reference and deduplicated by posted toolpath.

A part opening with a hole call got a synthetic rapid that posted an
empty pierce on the part edge. The rapid is now only inserted before a
contour motion with no rapid ahead of it; the hole call carries the
part comment and safety head raise that feature used to hold.

The sheet writer re-sorted parts bottom-then-left with cut-offs last.
Plate order is the cut sequence, so parts now post in plate order.

Regression tests replay the posted G-code for off-origin parts of
several drawings and check each hole's center and radius.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 01:08:06 -04:00
ajandClaude Opus 5.5 00acaeaaf1 feat(engine): report best whole-job plans from Rectangles, Circles and Default
Desktop Auto Nest's "Best plan so far" strip now fills in for every built-in
whole-job engine except FlatBar, not only Irregular.

- Rectangles makes one sheet-by-sheet run, so it reports the finished job as
  its one plan, then replays its plate commits (token checked as before).
- Circles reports when a stock-preference run or a tail re-plan beats its
  best result so far.
- Default scores each candidate plan as it ranks results (valid, fewest
  unplaced, lowest cost, candidate order) and reports it only when it beats
  every plan already shown, so a later candidate never shows a worse plan.
  The chosen result is always the last plan reported.
- Shared ReportPlan/SameLayout helpers on CandidateProgress; Irregular uses
  them too. Reporting never changes the search.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 23:56:38 -04:00
ajandClaude Opus 5.5 cd2bea054b feat(desktop): show Auto Nest as a sheet strip with a Keep/Discard review
Auto Nest no longer draws parts on the plate view before they are kept:
its result is a set of sheets, possibly of several sizes, not parts on the
current plate. Ghost parts stay with interactive Fill and remnant tools.

- NestJobStage.PlanImproved carries an engine's best whole-job plan so far;
  Irregular reports one whenever a variant or the tail re-plan beats it.
- NestPipeline adds PlanSheets: the plan on detached drawings built from
  the job geometry (with the caller's names and colors), so previews never
  touch caller drawings or quantities.
- SheetStripControl draws every sheet side by side at one scale, repeats
  once with their count, captioned with size, parts and utilization.
- The progress window shows "Best plan so far"; a review window shows the
  final sheets, totals, cost summary and unplaced parts before commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 23:56:38 -04:00
aj a2fb945669 Revert "feat(engine): live sheet preview while Irregular packs"
This reverts commit 9f0e536eeed85e4417f285b94913e03f594400f7.
2026-10-18 23:56:38 -04:00
aj b11225135e Revert "feat(desktop): draw Auto Nest previews on the trial sheet"
This reverts commit bf42cdc63d5e475fa6921a3ddac06d7a39152bec.
2026-10-18 23:56:38 -04:00
ajandClaude Opus 5.5 d384e63068 feat(desktop): draw Auto Nest previews on the trial sheet
NestProgress gains PreviewSheet, a detached plate for the stock the preview
parts lie on; Irregular builds one per stock. PlateView draws it (size, edge
spacing, clamps) in place of the plate while the preview is shown and drops
it whenever the preview is cleared or the plate changes. Auto Nest zooms out
when a trial sheet falls outside what it has already shown.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 23:56:38 -04:00
ajandClaude Opus 5.5 c997b2e588 feat(engine): live sheet preview while Irregular packs
The frontier packer reports its placements after each choice; the engine
turns them into preview parts at most four times a second and sends them as
NestProgress.BestParts with the stock work area, which desktop Auto Nest
already draws on the plate view. Reporting only reads finished placements,
so layouts are unchanged with or without a progress sink.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 23:56:38 -04:00
ajandClaude Fable 5.1 e6c87df372 perf(engine): pool best-fit pair searches by part geometry across jobs
Every Auto Nest run, and every Default-engine run, recomputed each part's
best-fit pairs: job snapshots are fresh objects and BestFitCache keyed
its entries on Drawing reference, so the Irregular engine paid
PairCatalog.Build (about half of a 118-part solve) on every run of the
same drawings.

BestFitCache now keeps a process-wide, bounded (512 sets, least recently
used first) pool of unfiltered candidate sets keyed by the exact content
of a PartGeometrySnapshot (mode and every motion value, bit for bit;
PartGeometrySnapshot.ContentComparer) and the spacing. Every drawing
DrawingJobMapper.CreateDrawing reconstructs from a snapshot declares
that geometry (BestFitCache.ShareByGeometry), so the Irregular pairs and
blocks, the cutout lattice and the Fill/Default job paths all read and
fill the pool. Candidates depend on the program geometry and spacing
alone, so a pooled set is the set the search would produce: benchmark
layouts, costs and placements are unchanged on the synthetic nests (all
engines) and on the 67-drawing, 118-part job. Failed searches are not
pooled, Invalidate leaves the pool alone, Clear empties it, and a
drawing whose Program is replaced stops vouching for its geometry.

Same 118-part job solved twice in one benchmark process (--parallel 1):
the second solve now takes 13.1 s after a 33.0 s first; before, 35.6 s
after 41.8 s.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-18 22:17:53 -04:00
ajandClaude Opus 5.5 13ab8e02f8 fix(cutting): plan with staged scrap cut-offs within budget
Staged cut-offs were appended after every part, so a kept order (the
"Keep the current part order" option, or the fallback after a free
search runs out of budget) always conflicted with any cut-off crossing
a part. PlateSequencing.PlaceCutOffs moves each new cut-off to just
before the first part it crosses, separators last, without moving
anything else; the panel applies it after staging.

The free search also learned "cut the cut-off first" only after a full
stall, re-planning the many-holed parts before it. A cut-off is a fixed
program that never gets harder to cut earlier, so a crossing approach
into a non-separating cut-off now teaches that rule at once. On the
reported 35-part plate this drops the plan from 23,930 expansions (over
the 20,000 budget) to 15,605.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 22:14:28 -04:00
ajandClaude Opus 5.5 ee8be3d79e fix(cutoffs): accept absolute arc roundoff in automatic cut-off planning
Rotated imported arcs whose start and end radii differ by ~5e-11 are
converted without refitting their centre, so their rebuilt start point
lands just outside the cached part bounds. The allowance scaled with
coordinate magnitude (4096 steps, ~2.9e-11 here) and rejected them,
which stopped Plan Cutting's "Add scrap cut-offs" with "Converted
material extends outside cached part bounds". Use the existing 1e-10
cap as an absolute allowance; larger mismatches still block planning.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 22:14:21 -04:00
ajandClaude Opus 5.5 fb505ef0ff fix(cutting): plan outlines with a seam gap before an arc, and memoize lead checks
A converted outline whose seam closes within the admitted 1e-6 gap could
only be entered at its seam: entered anywhere else, the arc after the
seam started off its own circle and every emission was refused as an
inconsistent radius. The search then spent its whole budget on that
part and the plate never planned. Emission now bridges the gap with a
straight move and cuts the arc as drawn; the verifier already admits
that slack. An entry on the seam vertex is left as before.

Each prefix of a part re-checked its earlier contours' leads against
every other part's material. One search now remembers each verdict by
the lead curve's exact bits and the material's reference, charging the
same native query budget; replay never uses it. On the reported plate
the memo alone gives a byte-identical result in 57 s instead of 12 min 47 s;
with the seam fix the plate plans Ready in about 17 s.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 21:21:20 -04:00
ajandClaude Fable 5.1 d317a90f1e perf(engine): cut Auto Nest time on many-part jobs
A 67-drawing, 118-part job took about six minutes through the desktop
Auto Nest path and was cancelled before any layout appeared. Almost all
of it was the cutout pre-pass, the rest the Irregular engine.

Cutout pre-pass (317 s -> 8 s on that job, same bundles and poses):
- The lattice and NFP searches prepare the frame's and the occupants'
  validation outlines once per search (NestLayoutCheck.Prepare) instead
  of re-outlining and re-triangulating the frame at every candidate, and
  test candidates against the small occupants before the frame. Answers
  match the pairwise check exactly, including its leftmost-inflated rule.
- A hole's proposal is replayed for the same frame, hole and offered
  inserts: automatic-rotation inserts ask the same question at every
  frame angle.

Irregular engine (40 s -> 15 s, benchmark 42 s -> 19 s, same layouts):
- Concave no-fit polygons are built as the union of pairwise convex sums
  of each footprint's convex pieces (ear clipping plus Hertel-Mehlhorn
  merging on the Clipper lattice) instead of n*m edge-pair quads; a
  footprint that cannot be decomposed keeps the old sweep.
- Pair and block catalogs share one private drawing per part geometry,
  owned by the engine instance, so each part's best-fit search runs once
  per instance and across a pipeline's trial and ordinary solves.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-18 21:13:15 -04:00
ajandClaude Opus 5.5 f26c75ada5 feat(ui): let Drawing Properties return a custom color to automatic
Drawing Properties now says whether the drawing's color is custom or comes
from the color scheme, and an Automatic button clears the custom color. On
save the drawing gets its palette slot back through RecolorDrawings when the
nest is known, otherwise by its non-cutoff index.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 20:30:18 -04:00
ajandClaude Opus 5.5 f009fab31d feat(ui): make color schemes app-wide and keep only hand-picked drawing colors
- Add Drawing.HasCustomColor, set when a color is picked in Drawing
  Properties or comes from a library record with a stored color.
- Persist it as customColor in .nest files (omitted when false) and keep it
  out of drawing packages; split pieces inherit it.
- Recolor non-custom drawings from the active palette when a nest opens and
  when the scheme changes; custom colors keep their palette slot.
- Library settings store a color only when it is custom.
- Document drawing colors in nest-file-format.md and nesting-view-colors.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 20:24:33 -04:00
aj 9d68945e75 Revert "feat(ui): make Blueprint the default color scheme"
This reverts commit c875edcdd1.
2026-10-18 20:14:18 -04:00
ajandClaude Opus 5.5 c875edcdd1 feat(ui): make Blueprint the default color scheme
- Add the Blueprint scheme: navy canvas, pale blue sheet, dark navy part
  outlines, orange-red rapids and twelve distinct, readable part fills.
- Use it as the settings default and the fallback for unknown scheme names,
  and list it first in Options. Saved scheme choices are kept.
- Run the palette spacing and readability tests over Blueprint and Classic.
- Document the default in nesting-view-colors.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 20:04:41 -04:00
ajandClaude Opus 5.5 bbe0f17a64 feat(ui): allow clearing lead-ins and cut-offs while a cut plan runs
The Clear Lead-ins & Cut-offs button stays enabled during planning.
Confirming cancels the running plan, clears once the cancellation lands
so the plates never change under the planner, then replans.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 18:45:31 -04:00
ajandClaude Opus 5.5 78ca08efe1 feat(reporting): show estimated cut time in nest reports
The nest report PDF gains an estimated cut time: the job total on the
summary, an Est. cut time column in the plates table, and per-plate and
all-copies times on each plate page. Times come from the cut simulation
with the settings last used in Calculate Cut Time, plus clamp removal.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 17:40:33 -04:00
ajandClaude Opus 5.5 d3cb23f117 fix: time display-layer cuts, add hole feed and etch skipping
The cut simulation treated Display-layer contour moves (what cutting
strategies emit) as head-up travel, so plates with assigned lead-ins were
timed as rapids. They now cut, matching the verifier and posts, and
suppressed moves are left out.

Cut time now follows the CI Fiber post: closed clockwise contours and
cut-offs take an outside feed, other contours a hole feed, and etch-only
contours can be skipped like its SkipScribe default. The settings are
shared by Calculate Cut Time and the simulator, and plate/nest times now
always come from the simulation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 17:32:38 -04:00
ajandClaude Opus 5.5 095b4d6e72 feat: time cuts with machine acceleration limits
A Grbl-style lookahead planner re-times the cut simulation with
trapezoidal acceleration, junction-deviation corner speeds and a
centripetal cap on arcs. Machines gain cut/rapid acceleration and corner
deviation in Machine Configuration, with placeholder values until the
controller's are entered. The simulator and Calculate Cut Time pick the
machine (or full speed), and the simulator shows the live head speed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 16:36:43 -04:00
ajandClaude Opus 5.5 dd2c00aed4 perf(engine): replay cutout pre-pass clearance checks and trim hole subtraction
Profiling the cutout pre-pass on real round-part jobs put ~97% of its time in
the frame-wall NestLayoutCheck.Clears inside CutoutCirclePacker.Fill. Ear-clipped
round frames make every perimeter/insert triangle pair overlap, so a clear pair
runs hole subtraction for every pair. The same question repeats for every frame
angle and repeated frame instance, because Automatic inserts get identical
frame-local poses.

- CutoutMemo, one per Prepare, replays geometry reads, circle items and Clears
  answers. Keys hold geometry by reference, pose bit patterns, argument order
  and spacing. It is threaded through CutoutCirclePacker.Fill and the router's
  round-only path.
- TriangulatedRegion.SubtractAllHoles measures each piece's bounds once, skips
  holes and hole triangles that no piece reaches, and ping-pongs the remainder
  between scratch buffers instead of copying it into pooled ones. Clip
  arithmetic and order are unchanged.

Bundles are byte-identical on 14 real and 10 synthetic ring jobs. Pre-pass time
over the real set drops from 99.6 s to 10.1 s (N0414-02 35.8 s -> 0.6 s).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 15:36:02 -04:00
ajandClaude Opus 5.5 f01b2cec67 perf(engine): speed up round cutouts and re-plan Circles' last sheets
- The cutout router uses the circle packer alone for a round hole whose
  inserts are all round. Lattice and NFP never placed more there, and when
  demand exceeded what fit they spent 20+ minutes on one job.
- The cutout pre-pass skips a hole whose area is smaller than an insert's
  outline, so bolt holes no longer run the searches.
- Circles re-packs its last sheet, and its last two sheets together, onto
  each single stock and keeps the result when the whole job gets cheaper.

On 14 real round-part jobs costs are unchanged and pipeline time drops from
262 s to 144 s for Circles and 355 s to 245 s for Default.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 14:54:01 -04:00
ajandClaude Opus 5.5 278252fe79 feat(console): allow multi-sheet autonest with --max-sheets and --stock
--autonest can now use more than one physical sheet. The first layout
replaces the target plate's parts, further layouts are inserted as new
plates after it, and --stock offers explicit sheet sizes (with optional
costs) built from the target's spacing, quadrant and clamp rail.
NestPipelineCommit gains ApplyToPlates for callers without a
PlateManager. Per-sheet results and overlap checks cover every
committed plate.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 13:27:14 -04:00
ajandClaude Opus 5.5 b115b9dcb0 feat(ui): add Halloween, Christmas and 4th of July color schemes
Built-in festive schemes theme the background, sheet and accents while
keeping 12-color part palettes distinct, light enough for black part IDs
and clear of the green etch stroke. They are only applied when chosen;
there is no automatic seasonal switching.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 12:49:48 -04:00
ajandClaude Opus 5.5 9f2e3d5291 feat(engine): compare clamp-hit dropping with filling past the clamp strip
Dropping the parts that land on a clamp suits small parts, which fill the
gaps between clamps. Large parts often do better if the fill area stops
short of the clamps. The rows still fit, and no part is lost on a clamp.

When every clamp in the fill area lies on one edge, interactive Fill now
also fills the area with that edge moved just past the clamp keep-outs,
as a larger edge spacing would. It keeps whichever layout the strategy's
comparer ranks better, and a tie keeps the dropped-parts layout. Clamps
on more than one edge skip the comparison. The second fill reuses the
cached best-fit pairs. While it runs, a preview counts as the new best
only when it beats the first layout, so the preview never gets worse.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 12:49:48 -04:00
ajandClaude Opus 5.5 05aac952ba feat(engine): fill clamped plates ignoring clamps, then drop clamp hits
Interactive Fill on a plate with clamps used to split the plate into
clamp-free rectangles and fill each one separately. It showed no progress,
so Accept did nothing until the end, and Stop discarded the result. Packing
around the clamps also tends to give a worse layout than losing the few
parts that land on them.

FillItem and FillGroup now fill the area as if there were no clamps. They
then drop each part that enters a clamp keep-out or sits too close to an
existing part, using the same check as before. For a multi-part group, the
whole copy is dropped when any member fails. Progress previews are filtered
by the same check, so a layout accepted early is clamp-clear. A quantity
request that loses copies asks for that many more, up to two more times.
Pack and whole-plate Nest still pack only into the clamp-free areas.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 12:49:48 -04:00
ajandClaude Opus 5.5 859d10b31d feat(engine): offer a box layout before best-fit pairs in Fill
Interactive Fill ran the best-fit pair phase first. The first pair
computation for a drawing can take about a minute, and until it finished
the progress dialog showed no layout, Accept stayed disabled and the
status text did not change.

The fill now packs the part boxes (RectBestFit) before the pair phase and
reports that layout, so Accept is available at once. The layout is only a
fallback: strategies still run in their usual order, and a completed fill
picks the same winner as before. While the pairs are computed, the detail
line reads "Computing best-fit pairs (may take a minute)...". Accept or
Stop now stops the wait. The computation keeps running in the background
and is cached for the next fill.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 12:49:48 -04:00
ajandClaude Opus 5.5 de845a5818 feat(engine): add Circles engine for round parts
Circles packs every part as its minimum enclosing circle at centers tangent
to two of the work-area walls, placed discs and clamp keep-outs, bottom-left
and left-bottom, with hexagonal and square lattice seeds. It bids only when
every part fills at least 0.8 of its enclosing circle and otherwise returns
everything unplaced at once. Default runs it as a third candidate.

Rectangles' sheet-by-sheet stock loop moves to NestingEngines/SheetByStock
(Rectangles output unchanged) and Default's candidate scoring and commit
forwarding become shared helpers. Circles also runs the whole job preferring
each offered stock and keeps the best result. Contract tests take shapes an
engine can override.

Synthetic round jobs, salvage-credited: Circles wins or ties all six with
valid layouts; Default cost falls about 4% versus Irregular alone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 12:49:48 -04:00
ajandClaude Opus 5.5 a430da89d0 feat(engine): nest round frames inside larger round frames
The cutout prepass now bundles frames smallest first, so a larger frame's
round cutout can take a ring part or an earlier bundle as one insert through
the circle packer: a flange holds a washer that holds a smaller washer that
holds a slug. Chains stop at four parts deep. Lattice and NFP proposals never
take these inserts, since they could seat a part in a ring's bore.

Expansion and released demand recurse, so placed order cuts innermost first
at every level and an unplaced outer frame returns its whole chain to demand.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 12:49:36 -04:00
ajandClaude Opus 5.5 f3a6af7f09 feat(engine): pack round inserts into round cutouts as circles
Add CutoutCirclePacker, a circle-in-circle proposal for the cutout
router. When a cutout is one circle and every insert fills at least 0.8
of its enclosing circle, it packs the inserts largest first at centers
tangent to the wall or placed discs, trying a center-out pass (a single
insert sits concentric) and a wall-first pass (optimal counts for up to
nine equal discs). Every pose passes NestLayoutCheck.

The router runs it first and skips the lattice and NFP searches when it
places all demand; otherwise the higher count wins and existing
proposals keep ties. On synthetic disc jobs the prepass drops from
minutes to seconds and places as many or more inserts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 12:49:36 -04:00
ajandClaude Opus 5.5 d87302a189 feat(cad): exclude entities and set cut/etch/display-only roles
Select entities in the CAD converter (click, or drag a window/crossing
box) and right-click to exclude/include them or set them to cut, etch or
display only, regardless of their DXF layer. Delete excludes the
selection.

Roles are stored per source entity on the drawing and persisted in the
entity set as an optional `roles` map. Display-only geometry is kept out
of the program, so posts, nesting and verification never see it; placed
parts draw it as a dashed overlay. Load-time scribe repair skips
etch-layer entities set to cut. Per-entity exclusions now survive filter
changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 05:14:55 -04:00
ajandClaude Opus 5.5 27a03b9caf feat(engine): add FlatBar nesting engine for flat bar stock
Reads each stock as a bar and cuts parts in one row along its length, packing
part lengths with a port of the CutList saw cut-list packer (first-fit
decreasing with swap optimization, exhaustive search for small jobs) plus a
best-fill subset-sum candidate. Each part is packed at its length less its
measured self-nesting gain, and a slide-left compaction pass nests shaped ends
(turning alternate mitred parts) and refills the freed length. Every slid pose
is confirmed with NestLayoutCheck.Clears.

On five synthetic flat-bar jobs every layout is valid and complete; total cost
33696 vs Rectangles 36816 and Default 34080.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 01:54:48 -04:00
ajandClaude Opus 5.5 0186ccfbff feat(nest): keep parts out of tabbed cutouts
A tabbed cutout's slug stays attached while the sheet is cut, but nesting
saw a closed hole and could place parts inside it. Nesting and layout paths
now read material through NestingMaterial.ForNesting, which drops closed
contours with tab spans so the slug counts as part. That covers part
outlines and collision lines, the cutout router, fill expansion, best-fit,
NestLayoutCheck and the GPU bitmaps. Area, overlap diagnostics and cutting
keep the hole, and programs without tabs read exactly as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 01:14:22 -04:00
ajandClaude Opus 5.5 ba39c3dc55 feat(cad): add tabbed cutouts with draggable tabs
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>
2026-10-18 00:50:11 -04:00
ajandClaude Opus 5.5 6cdda38d35 fix(verify): pass tabbed cutouts that provably retain their slug
A cutout cut in several pieces around tabs, as PEP programs often are, made
pre-post review report every piece's lead-out and the part's open fragments
as incomplete. Review now proves such open cuts release nothing: within the
part they touch other cuts only at their own ends and form no loop (each
closed contour with its leads counting as one point), and leads at open ends
stay out of the gap beyond them. Anything else stays incomplete. Plan Cutting
keeps refusing to certify its own tabs followed by a lead-out.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 00:15:06 -04:00
ajandClaude Opus 5.5 8f73704bef feat(server): migrate v4 drawing library data to schema v5
The v4 upgrade now keeps existing library data: each distinct package
blob is stored once by hash, every revision and current row is copied
with default nesting settings, and the v4 drawing tables are dropped,
all in the migration transaction. Pre-v4 databases get the v5 tables
directly.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 22:52:25 -04:00
ajandClaude Opus 5.5 5a374aa3f4 feat(library): content-addressed packages and editable nesting settings
Schema v5 stores each distinct drawing package once in drawing_packages,
keyed by SHA-256; revisions point at it, so details, settings, archive and
restore revisions add no blob. The v4 drawing tables are replaced outright
(no production library existed); nest tables are untouched.

Nesting settings (cut first, priority, rotation constraints, color) become
structured record fields (DrawingLibraryRecord.Settings), returned on every
read, filterable by cutFirst, editable through the metadata endpoint and
applied by LibraryDrawingInsert. Canonical packages now leave every
record-owned field at its default, so renaming or changing settings never
changes the package hash. Saving a nest drawing to the library carries its
settings into the record.

The desktop library browser gains a Cut first column and an Edit Settings
dialog that saves notes and settings as a new revision with the same package.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 22:47:18 -04:00
ajandClaude Opus 5.5 42d99f296c feat(sequencing): add per-drawing Cut first priority
Drawings flagged CutFirst (e.g. test squares) are sequenced ahead of
every other part: they get their own route with the chosen method, then
the remaining parts follow. Cutoffs crossing a cut-first part still
precede it. The flag is editable in Edit Drawing, persists in .nest as
`cutFirst` (omitted when false) and is kept by split pieces.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 22:19:03 -04:00
ajandClaude Opus 5.5 6f555345e3 feat(cad): cut breakoff joining lines as tabbed open break cuts
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>
2026-10-17 17:46:35 -04:00
ajandClaude Opus 5.5 6fd14c5452 feat(cad): tab breakoff scrap to the part in the CAD Converter
Forming backgauge tabs drawn as open cuts came off the sheet loose and could not be
planned. A breakoff merges the scrap into the outline and cuts the shared edge as
closed slots between tabs, so it stays attached and every pierce lands in scrap.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 15:42:37 -04:00
ajandClaude Opus 5.5 bc363cc904 feat(engine): name every unplaced part and why
NestPipelineResult.Unplaced lists each requirement's unplaced copies with a
typed NestUnplacedReason, counted from the returned placements: no stock fits
at the sampled rotations, reserved in a cutout of an unplaced frame, stock
exhausted, plate limit, no position found, or proposal not keepable. Desktop
Auto Nest, Console --autonest and MCP autonest_plate/autonest_job report them;
the API returns NestResponse.Unplaced, persisted from response schema 5.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 12:51:24 -04:00
ajandClaude Opus 5.5 4a1587d6bd feat(engine): fill cutouts first in every whole-job run
NestPipeline.Run now bundles parts that fit other parts' enclosed cutouts
into their frames before the selected engine, for desktop, Console, MCP and
API alike. A valid complete bundled trial is kept; a refused trial falls back
to the ordinary solve (reason on RefusedCutoutTrial), and an incomplete trial
is compared with it, keeping whichever valid proposal places more. An
incomplete but valid trial is now keepable like any incomplete result.
Expanded sheets list each frame's inserts before the frame, so the committed
order cuts every insert before the cutout that releases its slug.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 12:51:18 -04:00
ajandClaude Opus 5.5 6ac56c4a3f feat(core): pre-post checks for parts nested in cutouts
Posting review now proves containment exactly as the cutting planner does
(shared NestedPartContainment) and warns when a nested part is cut after its
host (NestedCutOrder) or when a host's hole lead or the nested part's lead
meets the other's material (NestedLead), including subprogram hole poses.
Ambiguous containment is incomplete, never clear; fixed-lead motions are not
reported twice. A committed cutout preview warns until Plan Cutting cuts the
insert first.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 12:09:55 -04:00
ajandClaude Opus 5.5 9816326429 fix(engine): legacy lead assignment respects pins
Assign Lead-ins (LeadInAssigner) now leaves every unlocked part with active
drawing pins unchanged and returns those parts, so it never overwrites a pin
with the plate's settings; the desktop names them ("N parts kept their
drawing lead-ins (plate P: parts ...); use Plan Cutting to apply their
drawing pins."). Parts without pins, with pins switched off, or locked are
assigned or skipped exactly as before.

The pre-post review now covers drawing pins. A part with active pins whose
placed program does not cut each pinned contour exactly as the pin's own
emission (re-emitted with the part's cutting settings and matched motion for
motion) warns "Drawing pins not applied", as do locked lead-ins overriding
pins and a pin that no longer matches the geometry; pins switched off are
not reported. The contours that are cut as pinned join locked programs in
the fixed-lead re-check against every part's clean material, and fixed
leads are now also checked against active clamps (Plan Cutting itself does
not model clamps).

AGENTS.md records the fixed-emission safeguard and the characterization
digests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 15:33:26 -04:00
ajandClaude Opus 5.5 a18f8c9b56 feat(engine): pinned contours use the fixed-lead warning path
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>
2026-10-16 15:33:25 -04:00