BuildResult set PlateIndex to the stock index, so every sheet cut from
the same stock shared one index; OpenNest.Api maps plates by it.
Part geometry filtered only rapids, so scribe/etch moves counted as
material - the bug OpenNest fixed in 1b5e1b1. Use SpecialLayers.IsMaterial.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The 0.022 margin assumed validators flatten arcs at 0.01; NestValidator
uses 0.001, so a pair can read at most 0.002 closer than true. 0.003
covers that plus the 1e-4 Clipper grid, returning ~0.019 per gap. Arc,
disc, obround and zero-spacing tests still pass.
Part geometry filtered only rapids, so scribe/etch moves counted as
material - the bug OpenNest fixed in 1b5e1b1. Use SpecialLayers.IsMaterial.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Priority was sorted descending, the reverse of the host (StockLadder and
NestJobCandidateComparer treat a lower number as more important), so a
priority-9 part beat a priority-0 part for scarce stock. The existing test
encoded the inverted rule and now asserts the host's direction.
Part geometry filtered only rapids, so scribe/etch moves counted as
material - the bug OpenNest fixed in 1b5e1b1. Use SpecialLayers.IsMaterial.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Runs with Claude have to happen on the Windows PC, where the archive is
mapped as Y:\Archive rather than hermes' /mnt/rogers mount.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Qwen3.8-Flash-Next's final version after a 14.5-hour optimization run
(its commit 7d7fca3): cost-first sheet trials, largest-area-first
demand order, and a cached-triangulation exact gate that brought a
219-part production job from timeout to ~106 s. 13/13 tests pass
against OpenNest master.
README cleaned for publishing: the model-facing template rules are
replaced by a one-line independence statement, the production job is
described generically instead of by its PEP job/file name (also in a
JobSolver comment), results show both sheet pools as re-measured here
(the 9-size claim in its report didn't reproduce: it grabs 96x240 and
under-fills them), and the stale StockLadder-crash note is gone now
that core leaves etch marks out of nesting.
Also drops a stale Aurora plugin reference from Opus55's README and
lists the engine in the repo README.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Rules for the runs were being made up mid-run (git for rollback, access
to the real-part drawing archive), so each model started under a
different rule set. BENCH-RULES.md writes them down in one place, stamped
into every new engine, so all models work under the same rules:
workspace limits and no searching for other engines, git init plus
commit-per-working-state, the archive as read-only with nothing
customer-identifying kept in the (publishable) engine folder, tests may
only be added to, and what the final report must cover.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
It was the starting point for the Qwen3.8-Flash-Next run, which now
continues as OpenNest.Engine.Qwen38FlashNext (stamped from _Template).
The unimplemented scaffold under the bare "Qwen" name would only
collide with or be confused for that engine once it lands here.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
OpenAI reuses model codenames across generations (GPT-6 reused
GPT-5.6's Sol and Luna), so a bare codename like "Astra" can't
identify which model built the engine. Prefixing the model version
keeps engine names unambiguous as more runs are added. The CLR type
is now Gpt6AstraNestingEngine, so benchmark reports show the new name.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Each engine-building run started from a hand-copied scaffold (Qwen's),
which carried that engine's name and stale notes. _Template holds the
generic scaffold with a __NAME__ placeholder, and New-Engine.ps1 stamps
out a named copy. The template's starter tests go through the
benchmark's NestValidator, so a model gets a real pass/fail target
instead of a plumbing-only check; they were verified to pass against
Opus55.
Directory.Build.props now also detects when it sits in an Engines/
folder inside an OpenNest checkout, so an engine stamped there with
-IncludeBuildFiles builds without passing OpenNestRoot.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Engines are moving out of OpenNest so they can be published on their own
and so OpenNest checkouts handed to a model for an engine-building run no
longer contain the competing engines. History for Engines/ (and the
pre-move root-level engine folders) was carried over with git filter-repo.
Engines now build against a sibling OpenNest clone via $(OpenNestRoot),
overridable with /p:OpenNestRoot, with a clear error when it is missing.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Replace the Terra scaffold with an independent configuration-space contact placer and bounded stock-plan search. Include plugin tests, synthetic and DXF benchmark drivers, results, and deployment documentation.
Correct shared collision clipping and hole subtraction so curved-hole inserts validate consistently. Cover translated layouts, spacing violations, operand order, winding, and independent boolean-area comparisons.
Validation: 1,293 tests passed with 12 fixture skips; all 34 synthetic/generated and four DXF cases are valid and complete.
Reusable Fill/, BestFit, RectanglePacking and CirclePacking components are
fair game; whole-engine delegation and run-all-pick-best stay banned.
Improvements to shared components go in the engine's own project and are
reported, not applied to OpenNest.Core/OpenNest.Engine.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Plugin engines (Opus55, Qwen, Terra) each add two projects at the repo
root, and more are coming; at a dozen they would outnumber the core
projects. They are also a different kind of thing: out-of-solution,
runtime-loaded plugins. Grouping them under Engines/ keeps the root
readable.
Engines/Directory.Build.props now holds the shared TFM, nullable and
implicit-usings settings and the OpenNest.Engine reference, so a new
engine's csproj is nearly empty. The tests/ compile exclusion lives in
Directory.Build.targets because a removal in .props runs before the SDK
adds its default Compile glob and has no effect.
Build-Engines.ps1 replaces the per-README manual build-and-copy steps
for deploying engines into the benchmark's runtime Engines/ folder.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Rename the OpenNest.Engine.Sonnet5 scaffold to OpenNest.Engine.Opus55 and
implement an independent whole-job INestingEngine (no built-in engine,
registry, or best-fit internals are called or copied).
- PartCatalog: snapshot perimeter -> polygon per allowed orientation, with
adaptive chord tolerance and MBR-aligned rotations for Automatic parts.
- NoFitCache: spacing footprints and cached Clipper2 Minkowski NFPs (convex
fast path; concave sweep plus both containment terms).
- FrontierPacker: per-(type, orientation) free regions (inner-fit rectangle
minus NFPs), updated incrementally; gap-fill-largest, else least front
advance per area^beta.
- Engine: look-ahead stock choice by estimated whole-job net area, six
deterministic variants, tail re-plan of the last 1-3 sheets.
- Tests judged by OpenNest.Benchmark's NestValidator, including an NFP
containment regression guard.
P260805-10.nest (219 parts), all 9 stock sizes: 219/219 valid, 27 sheets,
91.7% utilization, ~7 s.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Three standalone INestingEngine plugin projects (Solve() unimplemented,
throws NotImplementedException), each outside OpenNest.sln and discovered
at runtime via NestingEngineRegistry.LoadPlugins, same pattern as
OpenNest.Engine.Aurora. Each README spells out that Solve() must be an
independently designed placement algorithm and must never call/wrap/select
over the built-in engines (StockLadderNestingEngine, FixedStrategyNestingEngine,
PlateNesterFactory, NestingEngineRegistry).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>