ROADMAP opened by saying nothing in it is a promise. Section 7 holds eighteen standing principles cited by number as settled law from commit messages and from other documents - 4 governs what is hashed, 13 defines what a standard is, 17 governs what may write to a record, 18 governs how a contribution is admitted. A reader taking the header at its word would conclude Principle 17 is optional. The disclaimer now says what it always meant: it covers section 4 sequence and section 5 assumptions, not section 7.
Principle 5 gets the same qualification PROCESS section 8 got. A permanent deviation is the specification is right about facts on a host and would be licence to lower a REQ if read without limit.
PRECISION section 10 requires every section 7 entry to say whether it is a limit that work may lift or a boundary that was chosen. The prismatic-only entry said neither, which is the single most consequential ambiguity in the document. It is a limit, and the reason is now recorded: the oracle is a two-dimensional oracle with a scalar length multiplier - every recorded value is a property of the cross-section except LENGTH_MM, VOLUME_MM3 and MASS_G, and volume equals rounded section area times length to within 3.6e-12 across all 113 accepted cases. Lift it carelessly and that relation stops holding; nothing fails, it just stops meaning what it means. Anything keeping each station two-dimensional preserves it.
Also in PRECISION: STL export landed and is no longer planned. An absent export format is a limit; the refusal to emit toolpaths is a boundary.
ROADMAP section 4a corrected to match STAGING-STATE section 3a: nothing here is implemented on Kane Fabric, and SASE was used and never defined. The port is recorded done. The seed commit and test count are removed as derivable.
IDENTITY-CONTRACT: the rewrap owed from a76879f.
Applied by anchored patcher. Suite 643 passed, oracle intact. Documentation only.
354 lines
17 KiB
Markdown
354 lines
17 KiB
Markdown
# ROADMAP.md
|
||
|
||
What the Mechanical Compiler is for.
|
||
|
||
**This document records intent, not commitment.** It is a reference for what the
|
||
project aims at and why; it does not schedule work and nothing here is a promise
|
||
that something will be built. `HANDOFF.md` §4 holds the actual order. Where the
|
||
two disagree, §4 wins on sequence and this document wins on purpose.
|
||
|
||
**§7 is the exception, and it is binding.** The eighteen standing principles are
|
||
cited by number as settled law from commit messages and from other documents —
|
||
Principle 4 governs what is hashed, 13 defines what a standard is, 17 governs
|
||
what may write to a record, 18 governs how a contribution is admitted. A reader
|
||
taking the paragraph above at its word would conclude Principle 17 is optional.
|
||
It is not. The disclaimer covers §4's sequence and §5's assumptions; it has never
|
||
covered §7, and said so nowhere until 2026-09-13.
|
||
|
||
§§1, 2, 3 and 7 are the durable parts and are still correct. §4's sequence and
|
||
§5's production assumptions had both drifted since 18 AUG. The documentation
|
||
audit of 2026-09-13 corrected what was factually wrong here and in the companion
|
||
documents; questions that remain genuinely open are in `HANDOFF.md` §11, and
|
||
requirements that stand and are not met are in `DIVERGENCES.md`.
|
||
|
||
| | |
|
||
|---|---|
|
||
| Updated | 2026-09-13 |
|
||
| Companions | `PROCESS.md`, `ENVIRONMENT.md`, `STAGING-STATE.md`, `FAILURES.md`, `DIVERGENCES.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 BOSL2 `92d697c`. The ten rejected cases are part of the contract.
|
||
- **Staging infrastructure accepted, 2026-08-16.** Host, both containers,
|
||
network isolation, bastion access, TLS trust, reverse proxy and the
|
||
application filesystem foundation are proven on `srv-b`. Mail alerting and
|
||
explicit disk monitoring are deferred; backup strategy is postponed by
|
||
operator decision; application deployment remains blocked on application
|
||
code. See `STAGING-STATE.md`.
|
||
- **Mail alerting accepted, 2026-08-17.** Delivered end to end and received
|
||
twice.
|
||
- **Disk monitoring accepted, 2026-08-17.** Four P410i members explicitly
|
||
monitored, four test alerts received, serial numbers recorded, reboot-proven.
|
||
- **Container SMTP egress blocked, 2026-08-17.** The project-local half of F-025
|
||
is corrected; the estate question about `wg-pk` client trust remains open.
|
||
- **Repository seeded, 2026-08-18.** Reference implementation, frozen oracle,
|
||
pinned toolchain and test harness. Dependencies installed and the oracle
|
||
verified in-container. The commit and the test count are not recorded here —
|
||
`git log` and `make test` report them, and the figures that used to sit on
|
||
this line described the repository for two days.
|
||
- **Container baseline established, 2026-08-18.** All three containers on
|
||
`srv-b` conform, asserted by an executable check rather than by inspection.
|
||
|
||
### The port — done, 2026-08-20
|
||
|
||
`sb-geom` is ported to Shapely and the suite is green against all 123 cases. A
|
||
port that accepted the ten rejections would have been wrong; this one does not.
|
||
|
||
The reasoning below is kept because it explains a choice that is now
|
||
load-bearing rather than prospective.
|
||
|
||
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
|
||
|
||
1. **Dihedral-parameterised members** — see §3.
|
||
2. **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.
|
||
3. **Catalogue front end** — the reason for the web application. Customizer is
|
||
too limiting; SVG plus JavaScript, driven by the same generators.
|
||
4. **Node connectors** — new artifact class, new representation.
|
||
5. **Panels and unfolding** — new artifact class.
|
||
6. **Interface contracts** — formalised once two classes exist to connect. Not
|
||
before; §6 of Part I is right that use cases precede interface
|
||
proliferation.
|
||
7. **Qualification and attestation** — physical claims bound to a generator
|
||
revision. `SB_REVISION` already exists for this.
|
||
8. **Production instance** — automation derived from the proven staging
|
||
procedure. See §5.
|
||
9. **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.
|
||
|
||
---
|
||
|
||
## 4a. Parallel project
|
||
|
||
**Kane Fabric** — a separate project on the same host. Each project has its own
|
||
FQDN and its own container; they share the service bridge, the WireGuard hub and
|
||
the proxy.
|
||
|
||
An earlier version of this paragraph called Kane Fabric the platform on which
|
||
SASE, HOA Diagnostics, the Mechanical Compiler and other SASE-consuming projects
|
||
are implemented. Nothing here is implemented on Kane Fabric, and `SASE` was used
|
||
without being defined anywhere in this repository. Corrected 2026-09-13 on the
|
||
operator's statement of the topology.
|
||
|
||
It is recorded here so its existence is known, not because it creates work.
|
||
Kane Fabric owns geographic state; the Mechanical Compiler owns member
|
||
geometry, qualification and workflow state. Both sets of documents describe a
|
||
future interface between them; **neither defines it, and that is deliberate.**
|
||
Part I §6 holds that use cases precede interface proliferation, and no use case
|
||
crosses the boundary yet.
|
||
|
||
The contract becomes real work when a compiled member first needs to be sited
|
||
somewhere. It will be cheaper to define then, against a concrete artifact.
|
||
|
||
---
|
||
|
||
## 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
|
||
|
||
1. **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.
|
||
2. **Solve numerically against the real quantity.** Closed-form placement is
|
||
where the wrong-by-a-cosine errors came from.
|
||
3. **Structure before decoration.** Members butt through their neighbours;
|
||
fillets are applied on top of that overlap, never instead of it.
|
||
4. **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.
|
||
5. **A permanent deviation is not a deviation — it is the specification.**
|
||
Promote it and delete the exception. **This governs facts about a host, not a
|
||
requirement the code has not met.** A REQ is never lowered to match what was
|
||
built: it stands, the gap is recorded in `DIVERGENCES.md`, and the correction
|
||
is owed by the code. A specification that agrees with whatever exists
|
||
specifies nothing.
|
||
6. **Record the failure before correcting it.** Then apply the smallest
|
||
corrective change, not the one that also fixes three things you were
|
||
worried about.
|
||
7. **Prove the negative.** Isolation is asserted by showing the forbidden path
|
||
fails, never by showing the interface is gone (F-018). Health is asserted
|
||
after a reboot, never before (F-021).
|
||
8. **Handoff is not delivery.** An upstream acceptance code proves the message
|
||
left, not that it arrived (F-023). The same distinction applies wherever a
|
||
subsystem reports success on behalf of something downstream.
|
||
9. **Record what a change grants, not only what it repairs.** A trust rule
|
||
added to fix one rejection may authorise far more than the case that
|
||
prompted it (F-025).
|
||
10. **Shared infrastructure is not ours to reconfigure.** An instance may
|
||
configure its own client side; changes further down the chain are escalated
|
||
with evidence.
|
||
11. **A test must distinguish tool failure from the condition it tests.** One
|
||
whose failure mode is indistinguishable from success manufactures
|
||
confidence (F-027). Every negative assertion first establishes that it could
|
||
have observed the positive case.
|
||
12. **A component surviving its own restart is not proven to survive the
|
||
host's.** Different machinery; assert against the one that matters (F-026).
|
||
13. **A standard must be executable.** If conformance cannot be asserted by
|
||
running something, it is not a standard but a recollection, and it will
|
||
drift. A property not checked is not part of the standard (F-031).
|
||
14. **Check the thing, not something related to it.** An assertion inferred
|
||
from an adjacent observation is not evidence, however reasonable the
|
||
inference (F-031).
|
||
15. **Verify by counting, not by scanning.** A long, correct-looking list is
|
||
exactly where an unexpected 437 files hide (F-029).
|
||
16. **Conformance precedes backup.** Backing up an unverified configuration
|
||
preserves the confusion along with the data, and a restore returns it
|
||
faithfully.
|
||
17. **Nothing approximate may write to anything reproducible.** Principle 4
|
||
governs what is hashed; this governs what may reach the thing being hashed.
|
||
A search index, a documentation system or a language model may read design
|
||
records freely and may suggest anything to a person. None of them may
|
||
originate a parameter that lands in a record. The failure is silent and
|
||
compounding: if suggestions become records and records become the corpus,
|
||
the corpus teaches itself its own guesses, and every record is still
|
||
perfectly correct about what it was built from. A suggestion is an input to
|
||
a person, never an input to a build — and where one informed a build, the
|
||
record's `note` field says so, being already excluded from both hashes.
|
||
18. **A contribution is admitted by the oracle, not parsed by the compiler.**
|
||
The path from a new profile to the catalogue runs: author it in whatever
|
||
notation suits you, freeze its cases inside the pinned toolchain, port it,
|
||
and admit it when the oracle passes byte-identically. This has happened
|
||
twice, with both `.scad` generators. The consequence is that no second
|
||
geometry engine is ever kept in step with the first, and `legacy/` holds the
|
||
reference tier rather than superseded code. When someone asks for another
|
||
input format, the answer is that notation never runs in production — only
|
||
the kernel does.
|