Task 6 of the whole-job engine API: adapt the public NestRequest/NestRunner/
NestResponse surface to delegate to the whole-job runner instead of a manual
quantity loop.
- NestRequest: optional explicit Plates stock list (null keeps the legacy
unlimited SheetSize fallback; empty list means no available stock),
optional per-part Id (derived as part-{index} when absent), and an explicit
PlacementStrategy that takes precedence over the legacy Strategy.
- NestRequestPlate: one physical-stock type (id, size, quantity, spacing,
quadrant).
- NestRunner: imports each DXF once, propagates priority/rotation constraints,
runs a single NestJobRunner solve, materializes ID/pose placements exactly
once, and reports aggregate utilization as total placed part area over total
physical sheet area.
- NestResponse: exposes status, stop reason, part fulfillment, stock usage,
and plate-to-stock mapping; .nestquote save/load gains a schema version and
reports completion as unknown for old archives lacking fulfillment metadata.
- Tests: extend the Api request/runner/persistence suites for legacy SheetSize,
explicit mixed finite stock, stock exhaustion, weighted utilization, old
archive loading, and new-archive round trips.
Verification: cross-compiles clean on net8.0-windows (Linux). The Api tests
require a Windows runner (net8.0-windows) and are NOT executed here; the
delegated engine logic is covered by the 70-test net8.0 Engine.Tests suite
(committed in Task 5). Windows runtime verification remains outstanding.
- NestRunner now assigns Material to plates from request.Material
- NestResponse.LoadAsync uses descriptive exceptions instead of null-forgiving operators
- Fix pre-existing FillExtents.Fill signature mismatch (add bestFits parameter)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds NestResponse type to OpenNest.Api with SaveAsync/LoadAsync for .nestquote format — a ZIP containing request.json, response.json (metrics), and an embedded nest.nest.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>