Desktop Auto Nest, Console --autonest, MCP autonest_plate and the API NestRunner all run through NestPipeline, so nothing calls the old orchestration any more. Delete MultiPlateNester (with MultiPlateNestOptions, MultiPlateResult, PlateResult, PartClass and PartSortOrder), PlateOptimizer and PlateOptimizerResult, plus their tests. The explicit-strategy contract those tests checked now lives at PlateFillService.ResolveStrategy, which keeps its null-means-Default, canonical-name and unknown-name tests. CreateFiller loses its internal visibility, which only the deleted orchestrators used. This breaks source and binary compatibility for external callers of the removed types; whole-job callers use NestPipeline.Run or INestingEngine.
8.5 KiB
Automatic nesting pipeline
NestPipeline.Run is the shared whole-job boundary in OpenNest.Engine:
- Snapshot caller requirements and stock into a
NestJob. - Resolve the selected name through
NestingEngineRegistry(built-ins and plug-ins use the same path). - Run the engine without mutating caller drawings or plates.
- Check returned placements with the independent
NestLayoutCheckused by the benchmark. - Bind a representable result back to the caller's drawing references; the caller decides whether to commit it.
NestStockBuilder.FromTemplate snapshots sheet options and spacing settings for multiple-sheet jobs. SinglePlate offers exactly one physical sheet, regardless of the legacy plate repeat quantity. NestPipelineCommit.ApplyToEmptyPlates applies accepted desktop proposals to empty/new plates with the checked size, quadrant, spacing and quantity-one semantics. It never fills occupied plates.
Desktop Auto Nest
Every engine selected in Nest > Auto Nest uses the pipeline. Part-First and its sorting controls are removed. Use interactive Fill Area/remnant tools for leftover space on occupied sheets; these are not whole-job nesting.
Auto Nest starts on empty/new sheets and does not change existing populated plates. Stock Options offers sheet sizes and salvage settings; minimum salvage size is part of that section, not a Part-First option. When enabled, its grid keeps a blank last row for adding another size (W x L) and cost, including after loading saved options. Unused blank rows are not offered as stock. The maximum remains 100 physical sheets per run.
Progress is owned and modal so the input drawings cannot be edited while a worker uses them. Stop or closing progress cancels and discards the whole proposal. The dialog waits for the worker to finish; no engine has an Accept-early button on this path. A plug-in that ignores the cancellation token cannot commit its late result.
Every invalid result shows the validation report before any plates are changed:
- Discard is the default button and the Escape action. No proposed parts or sheets are applied.
- Keep anyway requires an explicit click and keeps the entire representable proposal, then enables Overlap Check.
- Malformed output (unknown requirements or nonfinite poses) is not keepable. It cannot be faithfully represented as the proposed layout; no partial/truncated proposal is offered.
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. A saved name from an earlier release
maps to the engine that replaced it (see nesting engines).
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
Callers must hold drawings and target state stable from snapshot through attachment. Do not append whole-job placements to an occupied target or flatten multiple returned sheets onto one plate: that would commit a layout different from the one checked. Do not trust arbitrary engine fulfillment metadata as a substitute for counting returned placements.
Interactive fills are outside this contract and still use PlateFillService. The benchmark invokes the same independent validator.
The pre-pipeline multi-plate orchestrator and plate-size optimizer have been removed from OpenNest.Engine; this is a source and binary break for external code that called them. Whole-job callers use NestPipeline.Run (or implement INestingEngine as a plug-in); multiple stock sizes and salvage credit are expressed as job stock and NestJobOptions.
Console and MCP
Console --autonest uses the selected jobs engine against one physical sheet. The selected plate's old parts are replaced only after acceptance; other plates are unchanged. Default demand is still one of each drawing unless --quantity is supplied. A partially fulfilled, valid result may be saved; a successful placement is not a claim that all demand was met.
Invalid output is printed and rejected with exit code 2 without saving or posting. --allow-invalid explicitly accepts representable layout violations. Malformed output, multiple returned sheets, and zero placements are never saved by this path. Unknown engines exit 1. --autonest --keep-parts rejects an occupied target: use the plain interactive fill path for existing obstacles instead.
MCP autonest_plate requires an empty target. The stdio server serializes all tool calls sharing its mutable session, so another request cannot change drawings or occupy a target during a solve. allow_invalid defaults to false. It reports violations and makes no changes on rejection, including with an override when the output is unrepresentable or contains multiple sheets. Existing fill tools remain separate. Console and MCP load jobs plug-ins from Engines/ beside their executable.
MCP engine development harness
test_engine builds and runs OpenNest.Console in a configured, trusted checkout.
nestFile is required; there is no machine-specific sample default. Drawing,
plate and output arguments and the stdout / === Errors === / nonzero-exit
response format are unchanged. Relative nest/output paths resolve from the MCP
server's working directory, before launching the checkout's console.
The existing .NET host configuration accepts:
EngineHarness:SourceRoot: required absolute checkout path containingOpenNest.Console/OpenNest.Console.csproj.EngineHarness:DotnetPath: optional existing absolute executable path; defaults to the dotnet host in the active .NET installation, never a PATH search.EngineHarness:TimeoutSeconds: positive integer, default 120, maximum 2147483. The single deadline covers build/run, process exit and both concurrent output drains. MCP request cancellation uses the same bounded path.
For environment variables, use EngineHarness__SourceRoot,
EngineHarness__DotnetPath and EngineHarness__TimeoutSeconds. These are
server/operator settings, not caller-supplied executable or checkout overrides.
Timeout/cancellation returns a clear error, kills the owned live process tree,
waits up to five additional seconds for direct-process cleanup, and closes local
pipe readers. Cleanup failures are reported. A descendant already detached when
its parent exits cannot reliably be found by Process.Kill(entireProcessTree);
it may remain alive, but inherited pipe writers cannot hold the tool open.
The harness does not scan for or kill unrelated processes. Windows process-tree
semantics still need Windows runtime acceptance; the private process regressions
also execute on Linux without customer nest files.
.NET API and saved responses
Set NestRequest.Engine to a registered engine name; null retains PlacementStrategy / legacy Strategy behavior. Library hosts own plug-in discovery via NestingEngineRegistry.LoadPlugins before calling the API. Explicit request requirement IDs are preserved in response fulfillment even when multiple requirements use the same source DXF.
The API returns a detached proposal. ValidationStatus is Valid, Invalid, or Unrepresentable, and Violations lists the problems. Representable invalid proposals retain their parts for caller review; unrepresentable proposals contain no sheets. Consumers must inspect validation before applying, quoting or posting the proposal. Status describes fulfillment, not acceptance: counts, stock usage and completeness are derived from returned placements rather than trusting plug-in summary metadata.
Response archive schema 3 persists validation status and violations. Older archives with no validation metadata load with null status; null must not be interpreted as a successful check. Saving a proposal archive records it and does not authorize CNC posting.
Verification
dotnet test OpenNest.FrontEnd.Tests/OpenNest.FrontEnd.Tests.csproj exercises Console, MCP and API rejection/override, cancellation, physical-sheet settings, response IDs and archive round-trips. Its current target matches MCP's net8.0-windows marker but does not use WindowsDesktop and executes on Linux as well as Windows. It is included in the solution and Windows test workflow. Desktop interaction tests remain in Windows-only OpenNest.WinForms.Tests.