Commit Graph
1462 Commits
Author SHA1 Message Date
aj 962ae8c825 feat(cutouts): propose bounded mixed lattice and NFP inserts 2026-10-09 17:20:41 -04:00
aj d3e325f36c fix(ui): restore manual part sequencing and close control 2026-10-09 17:06:17 -04:00
aj 575412a464 feat(cutouts): propose certified single inserts with inner-fit geometry 2026-10-09 16:59:11 -04:00
aj 60fb009329 fix(ui): expose Auto Nest stock row selectors for deletion 2026-10-09 13:16:40 -04:00
aj 41737a4f4c feat(mcp): complete jobs with finite mixed sheet stock 2026-10-09 13:14:34 -04:00
aj f1d1df3f17 fix(mcp): preserve job constraints and compatible stock 2026-10-09 12:34:30 -04:00
aj 81404fc673 feat(mcp): complete whole jobs across matching plates 2026-10-09 12:22:40 -04:00
aj a5b6c8a00e fix(mcp): warn on unmet quantities rather than sheet ratio 2026-10-09 11:09:51 -04:00
aj 2a6e5504cd fix(mcp): report zero packing demand accurately 2026-10-09 10:52:41 -04:00
aj 3d5c73a353 fix(mcp): report requested and placed drawing mix 2026-10-09 10:48:59 -04:00
aj 8b94e49711 feat(mcp): delete unused session plates 2026-10-09 10:45:28 -04:00
aj 2623517219 fix(mcp): reject negative plate indices 2026-10-09 10:42:35 -04:00
aj eff148c24e fix(test): unpool direct transient server databases v0.4.0 2026-10-08 20:03:10 -04:00
aj 648ffbca65 fix(test): own and close private server database before cleanup 2026-10-08 19:55:56 -04:00
aj 4d94273a00 fix(test): release transient SQLite handles for Windows server tests 2026-10-08 19:49:09 -04:00
aj 028adee046 ci(release): pin Poppler for Windows PDF verification 2026-10-08 19:42:13 -04:00
aj 3ddfff242d fix(test): read PDF text by visual rows across platforms 2026-10-08 19:36:33 -04:00
aj 5fc563bbca test(report): retain Windows PDF extraction with diagnostic 2026-10-08 19:30:15 -04:00
aj 785a861ab9 test(report): place diagnostic PDF in CI artifacts 2026-10-08 19:26:31 -04:00
aj 986ba3dee1 test(report): retain Windows PDF for failed release diagnosis 2026-10-08 19:22:25 -04:00
aj a73a85ebc0 ci(server): skip image publication for GitHub prereleases 2026-10-08 19:17:15 -04:00
aj 8628c69098 fix(ui): settle shift-click cloned parts with repeated directional pushes 2026-10-08 18:57:39 -04:00
aj c1c4b18f17 fix(ui): keep closed etch-only parts selectable 2026-10-08 13:50:12 -04:00
aj 7e887921ea fix(cutting): expose every unverified warning before consent 2026-10-08 13:50:12 -04:00
aj f50705c491 merge: integrate golden-angle Workshop colors 2026-10-08 13:34:23 -04:00
aj 81f3c006ab merge: integrate best-effort cutting on current master 2026-10-08 13:34:05 -04:00
aj b83518feac merge: integrate reviewed cutting-start planner fixes (#10)
Preserve reviewed cutting-start and plate-label commits; operator accepted A1-A4 and B1-B7. Excludes best-effort cutting and color trials.
2026-10-08 11:01:21 -04:00
aj 1826e6d5b5 feat(ui): add Workshop palette with distinct drawing colors
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.
2026-10-08 10:24:11 -04:00
aj fc300705a8 fix(cutting): aim round cutouts toward the next cut 2026-10-07 20:55:40 -04:00
aj 1c923976a8 fix(cutting): explain missing leads and suggest clearance remedies 2026-10-07 17:50:31 -04:00
aj f4d5cfe98e fix(ui): translate absolute-coordinate part paths by placement
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.
2026-10-07 17:22:06 -04:00
aj e7e4012974 style(ui): format graphics helper before placement repair 2026-10-07 17:18:48 -04:00
aj 9196d9157f fix(cutting): reuse clear candidates across side coverage scans 2026-10-07 16:05:25 -04:00
aj 7468483a10 fix(cutting): retain closest-arrival fallback for the last part 2026-10-07 15:56:20 -04:00
aj 432eb54633 fix(cutting): validate choice ownership before cached verdicts 2026-10-07 15:53:28 -04:00
aj 64459f7bc8 fix(cutting): try endpoint alternatives before hole combinations 2026-10-07 15:21:09 -04:00
aj 7622d63556 test(cutting): cover facing starts and safe fallbacks 2026-10-07 15:12:06 -04:00
aj 414e9b4e75 fix(cutting): prefer hole entries facing the next contour 2026-10-07 14:58:23 -04:00
aj 76f73f7a87 fix(cutting): exclude scribes from downstream pierce targets 2026-10-07 14:46:30 -04:00
aj 6b7d0d7f90 feat(cutting): chain preferred hole entries to the actual pierce
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.
2026-10-07 13:18:05 -04:00
ajandClaude Sonnet 5 47140cc59e perf(ui): prefetch nearby nests in the Database Open dialog
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>
2026-10-07 13:13:25 -04:00
aj fa3c5e348e feat(cutting): propose hole paths toward the perimeter entry
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.
2026-10-07 11:43:26 -04:00
aj d4544ea358 fix(cutting): aim perimeter entries toward the next part
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.
2026-10-07 11:01:08 -04:00
aj acd1f21293 feat(cutting): cap feasible entries with side fallback coverage
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.
2026-10-07 06:25:16 -04:00
aj 2399cc3936 feat(cutting): precheck emitted entry leads with the shared validator
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.
2026-10-07 05:27:05 -04:00
aj bd3f529ccd refactor(cutting): isolate candidate emission for lead validation
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.
2026-10-07 04:28:09 -04:00
aj a791b74945 feat(cutting): rank contour entries toward the next cut
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.
2026-10-07 02:51:06 -04:00
aj 4e60cebf68 feat(cutting): add native fallback contour entries
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.
2026-10-07 02:07:34 -04:00
aj 63f2a4b555 feat(cutting): enumerate preferred contour entry candidates
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.
2026-10-06 23:58:01 -04:00
aj ed35b94e7f test(cutting): keep both edge selections in corner classification theory
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.
2026-10-06 23:58:01 -04:00