expected.json `continuity`: over the tangent seams wholly within `within_mm`
of `near`, the curvature jump across them (exact surfaces, 65 stations a
seam) at most `curvature_jump_per_mm` clear (`clear_mm` along the seam) of the
vertices where two of them turn, where a neighbour's own G1 seam ends.
07/015, the box corner's three r5 rounds with corner: g2: one valid body of 10
faces within the box, its patch's twelve seams jumping at most 1e-3 per mm
clear of the hole's six corners by 1.2 mm (2.7e-4 measured; the ball corner
of 009 jumps 0.2). Its golden entry is the passing run's.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
SMLib is the only kernel now. cargo xtask kernel-cases ran every case once
per kernel asked for (--kernel default|smlib|both), setting
SOLIDCRAFT_KERNEL per run, and wrote a column per kernel; solidcraft-cli no
longer reads that variable.
The rig and the ladder run each case once, through solidcraft-cli built with
--features smlib (cargo run passes it), and report one result per case:
--kernel and the env var are gone. Each run has an output folder (--out,
default target/kernel-cases, target/kernel-ladder for the ladder) holding
results.json (every case's full result, which --results used to write on
request) and dumps/<area>-<case>/: every case runs with
solidcraft-cli kernel-cases --dumps=<out>/dumps, so a failed SMLib call
leaves its inputs for replay.
The ladder's golden holds one entry per case: golden.json is the last
recording's smlib entries, which predate SMLib running every case (its
reason says so); record it again after the first SMLib-only run.
docs/kernel-cases.md (until the next run regenerates it),
tests/kernel-cases/README.md, docs/kernel-smlib-sweeps-shell.md (its truck
column and comparisons dropped), xtask's and solidcraft-cli's usage text:
one kernel. Nothing was run.
clippy -p xtask --all-targets: clean.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017itGh5fpMEousnZ91cYcVt
A rig case whose SMLib call fails left nothing to replay it from: nothing called
solidcraft_smlib::set_dump_dir. `solidcraft-cli kernel-cases --dumps=DIR` now points SMLib's
dump folder at DIR/<area>-<case> before each case runs, so a failing call leaves its
arguments and B-reps there (smlib_brep_read reads them back into a scratch C program), and
turns it off after the run. Off without the flag. The kernel exposes it as
smlib_dump_dir, beside smlib_built (the CLI reaches SMLib only through the kernel).
(not built: base in progress)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017itGh5fpMEousnZ91cYcVt
All operations move to SMLib at once, so the selector is no longer the booleans' own:
`SOLIDCRAFT_KERNEL=smlib|truck` (read once, unset is truck, the same refusals for an unknown
value or SMLib in a build without it) is answered by `solidcraft_kernel::backend()`
(crates/kernel/src/backend.rs), which every operation's dispatch calls. The boolean's SMLib path
moves to smlib_boolean.rs. The regression rig's kernel check (`boolean_kernel`) now answers from
the switch, and the rig and CLI set SOLIDCRAFT_KERNEL.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QWhMwdqJYQKQq8RCLSL1LT
Two faults made simple curved solids look open (#818's blind hole: 80 open edges, a stadium
slot: 52):
- It meshed with `refine`, the measuring mesh, which splits triangles across curved faces on
their own and leaves T-junctions on the edges they share with neighbours. It now checks the
display mesh, whose faces share each edge's points.
- It matched vertices by rounding to a 1e-6 mm grid, which splits points a rounding error apart
across a cell boundary. It now joins vertices closer than `tolerance.weld_mm` (default 1e-4 mm).
Both cases now have 0 open edges, also with the weld at 1e-6 mm.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
For the history areas' cases (threads, tessellation):
- A count may be an inclusive range `[min, max]`, where the geometry only bounds it (a modelled
thread's faces).
- `"watertight": true` meshes each body (chord tolerance `tolerance.mesh_mm`, default 0.01 mm)
and requires no open and no over-shared edges, with vertices matched by position.
- `"timeout_s"` gives a case longer than the run's timeout, at most 30 min.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- tests/kernel-cases/sources.json gives each looked-at number's kind: an open or closed issue, a
merged PR, one of the frozen truck-geometry PRs, a kernel-paused PR. The report's coverage by
source counts how many of each were looked at, became cases or were skipped.
- crashes/2357: one join of a ring of 90 overlapping cylinder segments. The right answer is one
closed ring body. The old kernel still panics in its intersection curves and runs past the
timeout.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Runs are compared with the golden's times, so a run sharing the machine between cases flags
slowdowns that are only contention (seen with --jobs 4: four cases two to ten times slower).
--jobs still overrides it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QWhMwdqJYQKQq8RCLSL1LT
The ladder orders kernel operations by complexity instead of by random goldens: a manifest
(tests/kernel-cases/ladder/ladder.json) lists tiers in order and each tier's cases in order;
every case is graded against its own answer like any rig case, and a golden
(tests/kernel-cases/ladder/golden.json) records per case and kernel the status, the commands'
time and what the kernel made. A run compares with the golden and flags slowdowns (over twice the
time and 0.25 s more), status changes and changed counts. `--record REASON` re-measures one case
at a time, rewrites the golden with its reason and sorts each tier by the first kernel's time.
The report, docs/kernel-ladder.md, gives per tier and kernel the counts per status and the
frontier: the first case in ladder order the kernel fails. It reuses the rig's process-per-case
runner, timeout and cells; results now carry their path under tests/kernel-cases/ so cases from
other areas can be listed in a tier. The README documents `base`, `missing` and the ladder.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QWhMwdqJYQKQq8RCLSL1LT
`"outcome": "solid_or_refused"` takes a clean refusal, or else grades the result as usual. Two
bodies that touch along a circle only (#168, #3841) have no one-solid union: a refusal or the two
bodies left apart are both right; fusing them is wrong. The two cases said opposite things
(two bodies, a refusal) and now agree.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- `"shells": N` in expected.json grades the total number of shells: a body with a sealed void
holds two, and some joins keep several lumps in one body. Those cases (#3175, #3455, #3526,
#3730) are graded on validity again instead of being marked not valid.
- When SMLib's record conversion says "not supported yet" (revolved surfaces, traced intersection
curves), its check gives no verdict. That's shown but not graded, since it isn't a fault of the
body. solidcraft_kernel::SmlibCheck carries the three outcomes.
- `$OUT` in a recipe is a scratch directory outside the repository, for files a case writes. The
two STEP-export crash cases write there instead of /tmp.
- cargo xtask kernel-cases --results FILE keeps every result as JSON.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- solidcraft-cli and solidcraft-engine forward an `smlib` feature to solidcraft-kernel/smlib, so
`cargo build -p solidcraft-cli --features smlib` gives the rig SMLib's check.
- solidcraft_kernel::boolean_kernel() says which kernel this process runs booleans on.
`default` until the SMLib switch (SOLIDCRAFT_BOOLEANS=smlib) lands and answers there. An smlib
run on a build without the switch reports "not supported yet" instead of grading the default
kernel under SMLib's name.
- An area may keep its skipped list in parts (skipped-<part>.json).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Every geometry case the old kernel got wrong becomes tests/kernel-cases/<area>/<id>/: an
engine script or oracle recipe, and expected.json with the right answer, from analysis or a
hand calculation, or else the invariants. Never a kernel's output.
- solidcraft-cli kernel-cases <dir>...: runs a case and grades it. The checks are the outcome
(succeeds, or refuses cleanly), the body count, and one closed shell per body that passes the
record's structure and geometry checks and, with SMLib built, SMLib's check(All). Counts,
volume, area, centroid and box are graded where the case gives them. Each run is pass, fail,
not supported yet or crash.
- cargo xtask kernel-cases [--kernel default|smlib|both]: one process per case, so a native crash
or a hang (--timeout) is that case's result. It writes docs/kernel-cases.md: coverage per area
and source, results per kernel, and the sources looked at and skipped (<area>/skipped.json).
- solidcraft_kernel::validity and smlib_built, which the rig's checks use.
tests/kernel-cases/README.md gives the format.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>