Skip to content

Composable scroll case components and versioned styles (educelab.v1, villa.2026-10) - #2

Merged
csparker247 merged 10 commits into
mainfrom
scrollcase-styles
Oct 2, 2026
Merged

csparker247 merged 10 commits into
mainfrom
scrollcase-styles

Conversation

@csparker247

@csparker247 csparker247 commented Oct 1, 2026 •

Copy link
Copy Markdown
Member

Summary

Case design features are now composable components, and a style is a named, immutable preset over them. Two styles ship:

  • educelab.v1 (default, permanent): today's honeycomb case, unchanged.
  • villa.2026-10: ScrollPrize/villa's scrollcase at 7d6a82c. No shell, curved split, square bolted caps, kinematic disc.
Component Options
[split] plane, curve (villa's S, spanning the whole case; amplitude, flip)
[shell] honeycomb, solid, none
[ends] shell (floor + lid), caps (villa's square bolted caps)
[mount] generic-112.5, generic-65, kinematic, none

Components mix freely, e.g. villa's caps and kinematic disc around a honeycomb shell on a curved split. Combinations that can't be built are rejected when the config loads.

Commits

  1. Restructure config into components and presets. Typed sections, presets resolved as defaults → preset → user values. Golden files in tests/presets/ freeze each released preset. The config schema changes (no compatibility shim); examples/generic.toml is updated.
  2. Curved split. split.py defines every split as a profile y = f(x), shared by the mesh and B-rep stages. That keeps undercut removal along ±Y valid. The curve spans the case through the shell wall, so no flat seam lines up with the beam during CT. The divider follows it, the honeycomb leaves it solid, and nubs sit at (x, f(x), z). Nub positions are now checked against the fitted layout.
  3. Villa components and villa.2026-10. Caps are ported from upstream's builder code. New rule: the stand requires shell ends.
  4. Upstream comparison. scripts/villa_reference.py runs upstream's code in its pinned environment; test_villa_reference.py requires our bodies to match its volumes and bounding boxes.
  5. Docs site. MkDocs Material built from docs/ and deployed to GitHub Pages from main by .github/workflows/docs.yml, with a strict build check on PRs. The villa comparison stays in the repo but is left off the site. The README is rewritten to match the repo.
  6. Config template. examples/template.toml, shown on the "Creating a scroll case" page. test_examples_load checks that every example config loads.
  7. Review fixes.
    • With no mount disc, the left label is engraved on the left half's own floor. Before this fix it was silently lost.
    • Marker rings are built on solid shells too. With shell.type = "none" they're ignored instead of rejected, so switching a preset to no shell doesn't also require turning them off. This is documented under [shell].
    • Caps around a shell wider than the mount leave a wall_thickness margin so the shell isn't tangent to the cap sides. Caps without a shell, including villa.2026-10, are unchanged.
    • The build fails if the bottom cap's mounting holes don't fit on the cap, e.g. a small scroll with caps and no mount.

Smaller commits: config errors are reported without tracebacks, and a CLAUDE.md is added.

Verification

  • No geometry change for existing configs. educelab.v1 builds of a generic case, a fully featured case, a solid-shell/65 mm case and PHercParis3 have identical volume, bounding box and face count before and after each commit.
  • Exact match with upstream. At four scroll sizes, the symmetric difference between our villa.2026-10 case bodies and upstream's is 0.000 mm³.
  • End to end on PHercParis3/4 (docs/villa-2026-10-comparison.md):
    • Ours are closed single bodies; upstream's PHercParis3 halves have 26 holes and dozens of fragments.
    • Clearance is 1.95 mm for ours and 1.8 mm for upstream's, against a 2 mm target.
    • No blocked slide-out paths in either.
    • Our scrolls sit 180° from upstream's, because the wide axis's sign is arbitrary in both.
  • 68 tests pass (~80 s).

Test plan

  • uv run pytest
  • Baseline rebuild comparison for educelab.v1
  • Upstream reference regenerates byte-for-byte
  • mkdocs build --strict (CI)
  • Set Pages source to GitHub Actions after merge
  • Print and scan a curved-split honeycomb case before making the curve the educelab default

🤖 Generated with Claude Code

csparker247 and others added 10 commits October 1, 2026 16:46
Replace the flat case flags with typed sections ([split], [shell],
[ends], [mount], [stand]) and resolve configs as dataclass defaults,
then a named style preset, then user values. educelab.v1 is the current
design and the permanent default; golden files in tests/presets freeze
each released preset. Invalid component combinations are rejected when
the config loads.

No geometry change: generic, fully featured, solid/65 mm, and
PHercParis3 builds match the previous outputs exactly.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Model the split as a profile y = f(x) extruded in Z, shared by the mesh
and B-rep stages (split.py). `split.type = "curve"` is villa's two-arc S,
spanning the whole case to the shell mid-wall so no flat seam lines up
with the beam during CT; `amplitude` and `flip` tune it. The divider
follows the curve at constant thickness, the honeycomb leaves it solid,
and nubs sit at (x, f(x), z) with their bases sunk on slopes. Nub
positions are now checked against the fitted layout.

Plane-split builds are unchanged (baseline outputs identical).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
New component types: shell "none" (lining, divider, and ends only, with
the divider ending in round posts), ends "caps" (villa's square bolted
caps, ported from upstream's builder code), and mounts "kinematic"
(villa's V-slot disc) and "none". The villa.2026-10 preset combines them
as upstream does at 7d6a82c. Components mix within the validation rules;
the stand now also requires shell ends.

The caps match upstream's to 0.1 mm^3. educelab.v1 builds are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
scripts/villa_reference.py builds upstream's case bodies in villa's
pinned environment and records their volumes and bounding boxes;
test_villa_reference.py requires ours to match. At four scroll sizes the
symmetric difference between our bodies and upstream's is 0.000 mm^3.

docs/villa-2026-10-comparison.md also reports an end-to-end comparison
on PHercParis3/4, and corrects the stated effect of upstream's looser
cylinder-fit tolerance (0.1-0.2 mm of radius on real scrolls).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Config mistakes raise ConfigError, which the CLI prints as one line
(exit 2). Values are type-checked on load, missing files and bad TOML
are reported, and the split amplitude is checked before building. Nub
errors say which way a nub misses the divider, or that it can't fit.
Build failures print the worker's last error line; -v shows everything.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Engrave the left label on -Y when there is no mount disc
- Build marker rings on solid shells; ignore them with no shell
- Leave a wall's margin between caps and a shell wider than the mount
- Reject cap mounting holes that don't fit on the cap

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@csparker247
csparker247 merged commit 79622d5 into main Oct 2, 2026
2 checks passed
@csparker247
csparker247 deleted the scrollcase-styles branch October 2, 2026 13:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant