docs(engines): document built-in engines, renames and change rules

Adds docs/nesting-engines.md: which engine suits which jobs, the old plug-in
names the registry maps, retired engines, and the rule that an engine change
lands only when it beats that engine's current benchmark result with every
layout valid. README, release and automatic-nesting docs drop the bundled
plug-in wording; AGENTS.md now places built-in engines in
OpenNest.Engine/NestingEngines and keeps only external plug-ins out of the
solution.
This commit is contained in:
aj committed 2026-09-29 21:19:27 -04:00
1 parent 7f648e6400
commit 3bdefb1d1c
5 files changed
+71 -13

No files matched your search

+4 -3
View File
@@ -27,9 +27,10 @@ Every invalid result shows the validation report before any plates are changed:
Overlap Check displays material overlaps, not every spacing/stock/rotation failure in the report. A layout passing validation may still be incomplete; completeness and stop reason are separate from geometric validity. This check does not replace pre-post CNC verification.
The selected engine is saved in `%APPDATA%\OpenNest\engine-selection.json`.
Selection is restored after plug-ins load. If the saved engine is unavailable,
Default is selected and the status bar reports the fallback; startup does not
replace the saved missing-engine preference.
Selection is restored after plug-ins load. A saved name from an earlier release
maps to the engine that replaced it (see [nesting engines](nesting-engines.md)).
If the saved engine is unavailable, Default is selected and the status bar
reports the fallback; startup does not replace the saved missing-engine preference.
## Integration constraints
+54
View File
@@ -0,0 +1,54 @@
# Nesting engines
Whole-job engines implement `INestingEngine.Solve(NestJob)` and are selected by name through
`NestingEngineRegistry`. Every automatic nesting front end validates engine output the same way;
see [automatic nesting and validation](automatic-nesting.md).
## Built-in engines
Engines are named for the jobs they suit, not for how or by whom they were built. Engine code lives
in `OpenNest.Engine/NestingEngines/<Name>/`, its tests in `OpenNest.Engine.Tests/NestingEngines/`.
| Engine | Best for | Method |
|---|---|---|
| Rectangles | Plain and near-rectangular plates | Each part packed as the box of its material at its minimum-area rotation, using a maximal-rectangles free list; stock chosen sheet by sheet by salvage-credited look-ahead cost |
| Irregular | Irregular profiles | No-fit-polygon frontier packing with gap filling, six whole-job strategy variants and a tail re-plan |
| StockLadder | Caller-supplied stock ladders | Constrained-first fill with equivalent-demand area repacking |
| Default, Strip, Vertical Remnant, Horizontal Remnant | Single-strategy fills | The fixed placement strategies behind interactive fill |
Rectangles places irregular parts validly, but only as their bounding boxes; it never nests into a
notch or hole. Box sides account for how the layout check flattens arcs, so round-edged parts stay
valid at box contact.
## Renamed engines
Earlier releases shipped these as plug-ins under other names. The registry maps the old names so
saved desktop selections, scripts and API requests keep working:
| Old name | Now |
|---|---|
| `Opus55NestingEngine` | Irregular |
| `RectanglesNestingEngine` | Rectangles |
Gpt6Astra and Qwen38FlashNext are no longer shipped and have no alias. A saved selection of either
falls back to Default with the usual status-bar warning.
## Changing an engine
- A change lands only when it beats the engine's current result on `OpenNest.Benchmark` for the
jobs that engine targets, with every layout valid. Report cost, validity, unplaced parts and time.
- Placement must be deterministic: no clocks, unseeded randomness or environment variables. Budget
work by counting it; wall time may stop work only through the cancellation token.
- Keep each engine's tests passing, including `EngineContractTests<TEngine>` (quadrants, overflow,
priority, cancellation, stock and plate limits, determinism). Every layout in those tests is
checked with `NestLayoutCheck`, the benchmark's validator.
- Engines may share code. Move a helper into shared Engine code when a second engine needs it,
rather than copying it.
## Plug-ins
External engines still load from an `Engines/` folder beside the desktop, console, MCP or benchmark
executable. A plug-in implements `INestingEngine` with a public parameterless constructor and
registers under its CLR type name. A plug-in whose name matches a built-in engine, or a renamed
engine's old name, is skipped: a leftover `OpenNest.Engine.Opus55.dll` cannot shadow Irregular.
Leftover Gpt6Astra or Qwen38FlashNext DLLs still load as ordinary plug-ins until deleted.
+6 -7
View File
@@ -19,13 +19,12 @@ Git refs are owned by Gitea (`aj/OpenNest`) and push-mirrored to GitHub
4. Download the `OpenNest-X.Y.Z-win-x64` artifact and verify its `.sha256`.
It contains `OpenNest.vX.Y.Z.win-x64.zip`, with the .NET runtime, native
dependencies, shipped configurations, all three post-processors, license,
and `build-info.json` identifying the exact source commit. Gpt6Astra, Opus55,
and Qwen38FlashNext are bundled in `Engines/` with their MIT license and source
manifest. `scripts/external-engines.json` pins the external repository revision;
no moving branch or prebuilt third-party DLL is used. The script tests and
builds each engine against this host, then exercises actual packaged registry
discovery and an intentionally missing-DLL failure case. Keep the explicit
engine allowlist; never package the template, shared test kit, or test DLLs.
and `build-info.json` identifying the exact source commit. The nesting engines
are built into `OpenNest.Engine.dll`; no external engine repository or plug-in
DLL is packaged. `scripts/ReleaseSmoke` loads the packaged engine assembly and
checks that every built-in engine instantiates from it, that the renamed
`Opus55NestingEngine` selection resolves to Irregular, and that an unknown
engine name is rejected.
The workflow has read-only repository permissions and does **not** publish
releases. Once present on the default branch, it can also be dispatched manually