docs(engines): template on shared services and a determinism rule

New engines start from the shared test kit (the template's tests are a
one-line EngineContractTests subclass) and the host APIs, so they don't
re-derive geometry reading, work areas or validator tolerances.
BENCH-RULES.md now forbids clocks, unseeded randomness and environment
variables from influencing placement (budgets count work; wall time only
through the host's cancellation token) and lists the kit as read-only.
Build-Engines.ps1 deploys only OpenNest.Engine.* folders, and
New-Engine.ps1 -IncludeBuildFiles copies the kit.

Co-Authored-By: Codex <noreply@openai.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
aj
2026-09-25 09:29:28 -04:00
co-authored by Codex Claude Opus 5.5
parent 0cdef009f8
commit 33cc2ee810
8 changed files with 63 additions and 92 deletions
+19 -12
View File
@@ -7,8 +7,8 @@
placeholder in file names and contents. The new engine builds against OpenNest via
Directory.Build.props, which must sit in <Destination> or a parent folder.
With -IncludeBuildFiles, Directory.Build.props/.targets are copied into <Destination>
too, so the engine can live outside this repo, e.g. in an Engines/ folder inside an
With -IncludeBuildFiles, Directory.Build.props/.targets and the shared Engine.Testing
source kit are copied into <Destination>, so the engine can live outside this repo, e.g. in an Engines/ folder inside an
OpenNest checkout (the props detect that layout on their own).
.EXAMPLE
@@ -29,21 +29,28 @@ $target = Join-Path $Destination "OpenNest.Engine.$Name"
if (Test-Path $target) { throw "'$target' already exists." }
New-Item -ItemType Directory -Force $Destination | Out-Null
Copy-Item $template $target -Recurse
Get-ChildItem $target -Recurse -File | ForEach-Object {
$text = [IO.File]::ReadAllText($_.FullName)
[IO.File]::WriteAllText($_.FullName, $text.Replace('__NAME__', $Name))
}
# Deepest paths first so renaming a folder never invalidates a pending child path.
Get-ChildItem $target -Recurse | Where-Object Name -like '*__NAME__*' |
Sort-Object { $_.FullName.Length } -Descending |
ForEach-Object { Rename-Item $_.FullName $_.Name.Replace('__NAME__', $Name) }
# A built template contains binary/obj files. Copy only source files, never rewrite binaries.
$template = (Resolve-Path $template).Path
Get-ChildItem $template -Recurse -File |
Where-Object { $_.FullName.Substring($template.Length) -notmatch '[\\/](bin|obj)[\\/]' } |
ForEach-Object {
$relative = $_.FullName.Substring($template.Length + 1).Replace('__NAME__', $Name)
$output = Join-Path $target $relative
New-Item -ItemType Directory -Force (Split-Path $output -Parent) | Out-Null
$text = [IO.File]::ReadAllText($_.FullName)
[IO.File]::WriteAllText($output, $text.Replace('__NAME__', $Name))
}
if ($IncludeBuildFiles) {
foreach ($file in 'Directory.Build.props', 'Directory.Build.targets') {
Copy-Item (Join-Path $PSScriptRoot $file) $Destination -Force
}
# The acceptance tests reference the shared, read-only kit beside the engine.
$kitTarget = Join-Path $Destination 'Engine.Testing'
New-Item -ItemType Directory -Force $kitTarget | Out-Null
Get-ChildItem (Join-Path $PSScriptRoot 'Engine.Testing') -File |
Where-Object { $_.Extension -in '.cs', '.csproj' } |
Copy-Item -Destination $kitTarget -Force
}
Write-Host "Created $target"