10 KiB
ROADMAP.md
What the Mechanical Compiler is for, and the order in which it gets built.
| Updated | 2026-08-15 |
| Companions | ENVIRONMENT.md, STAGING-STATE.md, FAILURES.md |
1. Mission
Build the capacity to construct real structures from reclaimed and commodity materials, using whatever fabrication a person actually has.
The reference case is a faceted timber shell: planar panels meeting along straight fold lines, converging on nodes, sitting on a platform. Buildable without a factory, from 3D printing, tabletop CNC, welding, cement casting, and COTS stock — provided someone has worked out what the pieces are and how they meet.
That last clause is the whole project. The Mechanical Compiler exists to make the pieces computable, qualifiable, and reproducible by someone who was not present when they were designed.
Explicitly not in scope: building codes, permitting, and jurisdictional approval. Qualification and compliance are different animals. A qualification says this member is what it claims to be, made this way, from this stock. Compliance is a jurisdiction-specific argument someone else may build on top. Plenty of legitimate contexts — agricultural, temporary, accessory, artistic — never need the second thing.
The cheap hedge, taken deliberately: record physical claims, never verdicts. Section modulus, moment of inertia, material provenance, process parameters. Those cost nothing to capture, since the geometry layer computes most of them anyway, and they are what any future argument would need. Recording a pass/fail verdict would bake in a jurisdiction we do not want to be bound to.
Measure and attest. Never adjudicate.
2. Three artifact classes
Reading the reference structure back into components gives three kinds of thing, only one of which currently exists.
Members — prismatic, exists
Straight runs where panels meet along a fold line. Fixed cross-section, 10 to 100 feet, made from pallet-strap bundles in a printed enclosure.
This is the strap-beam work. Eleven profiles, locked at revision 8.0.0, frozen as a 123-case fixture oracle.
Read as edge conditions rather than as shapes, the catalogue stops looking arbitrary:
| Profile | Edge condition |
|---|---|
| T | panel-edge stiffener — flange takes the sheet, stem is the web |
| Y, Three-Fin | seams where three surfaces converge along a line |
| A Frame | a gable in section |
| Ring profiles | closed torsion boxes — perimeter, sill, deck edge |
The fins are not decoration. They are where the panel gets fastened.
Nodes — non-prismatic, does not exist
Where fold lines converge. Look at the hipped ends of the reference structure: four or five edges meeting at a vertex, at angles that differ at every corner.
Short, geometrically unique, almost certainly fully printed or cast. Not a strap beam, and will not come out of the current library. No representation exists yet.
Panels — sheet, does not exist
The planar faces. CNC-cut from sheet goods. Every face in the reference structure is planar, which is a hard constraint on the form and also exactly what makes it buildable from sheet plus edge members.
Convenient technical note: planar polygon algebra, edge extraction and unfolding are precisely what Shapely and CadQuery are good at. The toolchain choice looks better after seeing the reference than before it.
This is why interface contracts sit at the centre of the design. A node declares what member ends it accepts; a member declares what end it presents; a panel declares its edges. Without that, three artifact classes are three unrelated generators.
3. The gap that changes the backlog
If two panels meet at 137°, none of the eleven profiles gives you a member for it.
a_frame_leg_angle_deg is the only dihedral-ish parameter anywhere, and the
crossbar geometry pins it to 20–53°. The Three-Fin's fins are locked at 120°
because they derive from a regular polygon. The library solves placement
against webs — the PLA between strap channels — but nothing solves
placement against the angle between attachment faces.
Closing this is an addition the architecture already supports:
sb_member_on_edge takes an arbitrary direction, sb_fin_profile takes N, and
the solver converges on measured quantities. A dihedral-parameterised family is
a new call into the same machinery, not a new machine.
It moves ahead of the rebar-core bore variant in priority.
4. Sequence
Done
- Rev 8.0.0 generators. Six 3x profiles, five 4x profiles, shared N-generic library. Every wall measures its declared minimum; symmetric profiles are provably non-chiral; profile parameters are isolated from one another.
- Fixture oracle frozen. 123 cases,
ddd0f154…, pinned to OpenSCAD 2021.01 and BOSL292d697c. The ten rejected cases are part of the contract. - Staging environment. In progress — see
STAGING-STATE.md.
Next — the port
Port sb-geom to Shapely; pytest -n auto green against all 123 cases. A port
that accepts the ten rejections is wrong.
Why this rather than more OpenSCAD: exceptions can be caught. Roughly half the
defensive complexity in the current library exists because an OpenSCAD assert
is fatal and uncatchable — sb_path_max_round() exists solely because a radius
could not be probed and the failure caught. Testing becomes pytest in CI rather
than bash scraping echo lines. And SVG generated from Python can emit the
outline, each strap channel and the bore as separately classed paths, which is
what makes hover and layer toggling possible in the catalogue.
Then, roughly in order
- Dihedral-parameterised members — see §3.
- Rebar-core bore variant — Utility One's 40-ft side member is three strap chords around a rebar core. The bore stops being a byproduct of the inside walls and becomes a declared interface with a diameter and a fit class.
- Catalogue front end — the reason for the web application. Customizer is too limiting; SVG plus JavaScript, driven by the same generators.
- Node connectors — new artifact class, new representation.
- Panels and unfolding — new artifact class.
- Interface contracts — formalised once two classes exist to connect. Not before; §6 of Part I is right that use cases precede interface proliferation.
- Qualification and attestation — physical claims bound to a generator
revision.
SB_REVISIONalready exists for this. - Production instance — automation derived from the proven staging procedure. See §5.
- YunoHost packaging — see §6.
Higher polygon counts are not on this list. 4x is the end of the N-strap family; hexagons and above compose from triangles and squares rather than getting their own generators.
5. Staging to production
srv-b is standalone and will remain so. Promotion is export/restore, not
cluster migration.
The order is deliberate: manual first, then automation derived from the
proven procedure. FAILURES.md is the evidence for why. Three specification
assumptions were wrong in ways only contact with a host revealed, and scripts
written from the specification alone would have faithfully reproduced all
three — one of them producing a container that booted, looked healthy, and had
four broken services.
When production is provisioned, the automation is written from FAILURES.md
first and ENVIRONMENT.md second.
Production differs from staging in four known ways, recorded so they are not invented under pressure:
| Staging | Production | |
|---|---|---|
| Certificate | local staging CA | Let's Encrypt, per-name, no wildcard |
| FQDN | mechanical-compiler.dev.infra |
mechanical-compiler.manufacturing.kane-il.us |
| Proxmox firewall | disabled | must be revisited |
| Proxy location | CT 101 on the same host | undecided — not on the WireGuard side, since the current NAT is outbound-only |
Three variables change in mechcomp.env: MECHCOMP_ENV, MECHCOMP_BIND,
MECHCOMP_BASE_URL. Nothing else.
6. Distribution
YunoHost and Docker are parallel targets, not sequential. YunoHost apps install natively — apt, venv, systemd, nginx — and the project does not want Docker inside YunoHost. Neither blocks the other, and neither should be built "in order to" reach the other.
On the catalog's weight criterion: it reads "resource-hungry compared to
their features" and is aimed at marginal apps. fab-manager_ynh is in the
catalog; paperless-ngx_ynh declares nine apt dependencies including
postgresql and redis. The useful comparison is those, not a hello-world.
On provenance: the project is LLM-generated under human direction, stated
plainly in the README and in any submission. The catalog policy is a quality
bar with a disclosure requirement, not a ban — it rejects generated packages
that do not follow example_ynh, citing verbose code, hallucinated helpers and
non-standard directory architectures, then explicitly permits AI use where the
maintainer is transparent and can explain every line.
Two consequences. The package is drafted against example_ynh and reviewed by
CIVICVS as his own work; anything he would not defend in a review thread does
not ship. And disclosure belongs in the README, not in the pitch — if
provenance becomes the pitch, the project gets judged on that axis instead of
on whether it makes distributed manufacturing capacity legible.
7. Standing principles
- Measure, do not assume. Every wall thickness in rev 8 is a measured value. Connectivity is necessary and never sufficient — revision 7 passed cross-sections joined by 0.13 mm.
- Solve numerically against the real quantity. Closed-form placement is where the wrong-by-a-cosine errors came from.
- Structure before decoration. Members butt through their neighbours; fillets are applied on top of that overlap, never instead of it.
- Hash inputs, not outputs. Mesh bytes are not reproducible across toolchain versions. Hashing parameters plus generator revision keeps a qualification valid across an upgrade that did not change the geometry.
- A permanent deviation is not a deviation — it is the specification. Promote it and delete the exception.
- Record the failure before correcting it. Then apply the smallest corrective change, not the one that also fixes three things you were worried about.