Last Updated: 2026-09-29
The solid half of the MADFAM hyperobjects commons: parametric cartridges for printed and machined bodies, rendered from CadQuery (B-Rep) or OpenSCAD (CSG).
A hyperobject here is not a mesh. It is the family a mesh regenerates into: a
project.json manifest declaring parameters, modes, parts and presets, plus the
source that turns a parameter point into geometry. Every cartridge is verified
fail-closed — each (mode, part) pair must render watertight, positive-volume
and free of inverted bodies, at its defaults and at every preset it ships.
502 cartridges — the five slugs once withdrawn for licence reasons have all
returned as clean-room re-creations (see NOTICE.md). Licensed
CERN-OHL-W-2.0, with the carve-outs recorded there.
Measured on 2026-09-29: 502 manifests · 502/502 with a declared body count · 502/502 carrying at least one feasibility constraint · 20 animated assemblies · 5 cartridges with a reasoned cross-kernel parity exemption or widened tolerance.
Per RFC 0038 §9 — platforms are separated from commons, and the contracts are packaged once:
| Repo | Holds |
|---|---|
yantra4d |
the solid platform: studio, API, tiers, render workers, admin |
fashion-cabinet |
the soft platform: studio, API, kernel runtime, the MTM seam |
solid-hyperobjects (this repo) |
the solid cartridges, catalog, indexes |
soft-hyperobjects |
the garments, fc indexes, fabric cards, bodies |
hyperobjects-spec |
schemas, sandbox, validators — the verification bar itself |
The keystone rule: the bar lives in hyperobjects-spec, never in platform
code. CI here installs that package and runs it. A contributor can therefore
check a cartridge without cloning a platform, and passing that check and passing
CI are the same thing.
The platform mounts this repo as a single submodule at projects/, which is why
every cartridge sits at <slug>/ in the root here: <slug>/project.json in this
repo is projects/<slug>/project.json there, unchanged.
pip install "hyperobjects-spec[geometry] @ git+https://github.com/madfam-org/hyperobjects-spec@3ff3736e5989f381ebc841a4af38ff43cd9d0b51"
y4d-spec check ./gridfinity # manifest + files, under a second
y4d-spec check ./gridfinity --render # + geometry, every (mode, part) and every preset
# Whole commons, manifests only; exclude library/helper directories.
for manifest in */project.json; do
y4d-spec check "${manifest%/project.json}" -v || exit 1
done
y4d-spec rules # what is checked, and where each rule came fromManifest conformance is pure Python. --render pulls a CAD kernel (~400 MB);
on Debian/Ubuntu it also needs libgl1, libglib2.0-0 and libxrender1.
OpenSCAD cartridges resolve their library includes through OPENSCADPATH:
third-party libraries from the pinned libs/* submodules, and the first-party
helpers in commons-lib/ from the repository root:
git submodule update --init --recursive
export OPENSCADPATH="$PWD/libs:$PWD"The keystone pin CI installs is 3ff3736e (SPEC_PIN in
.github/workflows/ci.yml). Every gate below is
that package's, run from this repo — there is no second, hidden bar.
Compiler warning/error lines are retained as bounded notes identified by mode,
part and preset, even when OpenSCAD exports a valid partial mesh. Review them:
a geometry pass is not proof that every include or module resolved. Notes stay
nonblocking until whole-commons false-positive analysis supports a stronger rule.
-
Manifest conformance runs on every PR for all 502 cartridges (
y4d-spec check, seconds), alongside the unit tests for this repo's own CI scripts (python3 -m pytest .github/scripts) and the reporter's selftest. -
Render lane (per PR, chunked).
render-scopetakes the fork-point diff and decides which cartridges need geometry, thenrender-changedruns them as a matrix of groups of at most eight (max-parallel: 2, 60-minute jobs). Each group runs:y4d-spec check ./<slug> --render --require-openscad --parityBoth kernels, every
(mode, part), at defaults and at every preset.--require-openscadmeans a missing binary is a failure, never a skip (the runner image ships OpenSCAD 2026.02.13, the version the platform image pins, enforced by the spec'sy4d-spec render-envcontract and by enclii's own drift check on the runner image).--paritycompares the two kernels' meshes — it has been a merge-path gate since 2026-09-06. -
What
render-scopeskips, and why. A cartridge whose only change is manifest metadata is dropped from the scope: the allow-list in.github/scripts/render_scope.pycovers attribution, prose, tags, lineage, and — since 2026-09-06 —constraints(feasibility rules the configurator evaluates on the parameter set; they never reach a kernel) andanimations(parameter-state sequences the API re-renders on demand; a cartridge's own render never reads them). Anything else —.py/.scadsource,fonts/,parameters,parts,modes,presets,engine,verification, or any file the script does not recognise — keeps the cartridge in scope. An unparseable manifest keeps it in scope too: the lane fails closed, never open. -
Nightly full sweep (chunked, 09:00Z / 03:00 CDMX).
nightly-scopecuts the whole commons into deterministic groups of at most eight and uploads the scope as an artifact;render-nightlyrenders them (max-parallel: 3, 90-minute jobs, per-group log artifact, same--render --require-openscad --parity);nightly-reportconcatenates the logs and decides the verdict. A cartridge measured slower than five minutes locally gets a group of its own —zipperdoes, at 39 min 12 s for 18 renders. -
The nightly verdict is three conditions, all required. Green needs (1) every render group green, (2) the completeness check — the union of the cartridges actually rendered must equal the scope artifact, so a job that dies before reaching its tail cannot pass as green, and (3) zero FAIL rows in the concatenated log, failing closed on an empty count. The group step runs under
set -o pipefailwith a sticky return code and prints aGROUP VERDICT:line; without pipefail a… | teepipeline reportedtee's exit 0 and produced a false green (run 34023334942: 67 green jobs over 62 FAIL rows).nightly_report.py --greenrefuses a log that still contains FAIL rows. -
A red sweep opens one tracking issue, not one per night.
.github/scripts/nightly_report.py(stdlib only) parses the FAIL lines into a table —cartridge | mode/part | preset | engine | reason— and maintains a single issue labellednightly-sweep: it creates the issue, rewrites its body on later red runs (latest table on top, dated history below) with a delta comment naming what broke and what got fixed, and closes it when the sweep goes green. A never-rendered cartridge appears as aNEVER RENDEREDrow. Auth is the job'sGITHUB_TOKEN(issues: write), retrying once withMADFAM_BOT_PATon 403; a reporting failure never turns a green sweep red. -
The bar per render. Watertight, positive volume, no inverted (negative-volume) body, B-Rep validity before tessellation (
BRepCheckplus a per-solid signed-volume test — aReversed()solid isIsValid()yet negative, and a macOS-green render is not proof: the tripod-hub fuse is invalid on macOS OCCT and valid on Linux OCP), the declared body count, and cross-kernel parity. -
Parity is three gates. Extents (AABB), volume, and — since keystone
3aa57133— shape: the placement offset (AABB-centre delta) is reported as a note, or fails under a per-part"placement": "strict", and the Hausdorff distance is computed after alignment and fails abovemax(0.5 mm, tolerance). A pair may be exempted or given a wider tolerance only with a written reason (seeCONTRIBUTING.md); the summary line readsparity=N/M ok, warn=K, exempt=E, failures=J. -
Declared body counts.
verification.stages.geometry.checks.body_count.expectedat the base, with per-mode/part overrides underverification.mode_overrides.<mode>.part_overrides.<part>using stage-qualified keys ("geometry.body_count"); parametric counts use thepart_quantitiesexpression dialect.
<slug>/project.json the manifest — single source of truth for the cartridge
<slug>/*.py CadQuery source
<slug>/*.scad OpenSCAD source
<slug>/LICENSE CERN-OHL-W-2.0 (or the cartridge's own, if it differs)
<slug>/NOTICE third-party attributions, where any apply
libs/* pinned third-party OpenSCAD libraries (submodules)
commons-lib/* first-party shared helpers, resolved via OPENSCADPATH
One cartridge per PR, born bilingual (en/es), CERN-OHL-W-2.0. See
CONTRIBUTING.md.
Automated contributors start at AGENTS.md, which maps the CI
lanes and the rules that are not obvious from reading the code.