The compiler describes off-the-shelf hardware and generates the printed part that encloses, interfaces with, or augments it. The pallet strap is not the subject of the library, it is the first entry, and it was inlined into Geo rather than described. STOCK.md states what every entry must declare: designation, section, nominal versus actual, fit, stock tolerance, provenance. Geo conflates three things. Width, thickness and count are the stock. Clearance is the fit, a property of the joint. The wall thicknesses are the printed part policy. This commit names the first two and leaves Geo untouched, so no profile imports the new module and the frozen oracle cannot move. test_stock.py proves faithfulness by exact float equality against geom.records across 36 parameter combinations, 5 placements and 3 face modes. Mutation tested before landing: reversed vertex order, halved clearance, dropped lamina offset and a naive round cavity are each caught. Round cavities are circumscribed rather than inscribed. A vertices on circle polygon lies inside the nominal diameter and bites into it by r times one minus cos 180 over n, about 9.6 micron at 9 mm radius and 48 facets, which is enough to stop a press fit. Conduit is deliberately absent from the catalogue until a measurement or citation exists.
139 lines
6.5 KiB
Markdown
139 lines
6.5 KiB
Markdown
# STOCK.md
|
|
|
|
**What the compiler is for, and what every catalogue entry has to declare.**
|
|
|
|
Written 2026-08-22, from CIVICVS's statement of the project's subject.
|
|
|
|
---
|
|
|
|
## 1. The subject of this library
|
|
|
|
This is not a 3D-printing geometry library. BOSL2 is that, and it is vendored in
|
|
`legacy/` because the reference was built on it.
|
|
|
|
This library **describes commercial off-the-shelf hardware, and then generates
|
|
the printed part that encloses it, interfaces with it, or augments it.**
|
|
|
|
The pallet strap is not the subject. It is the **first stock entry**, and it was
|
|
described so thoroughly that the whole of rev 8.0.0 looks like a strap library.
|
|
Electrical conduit is the second. Stock can be anything you can buy or make on
|
|
site: pipe, sheet, net, poured, drilled, bent. Each gets described, one at a
|
|
time, and added to the catalogue.
|
|
|
|
The printed part is the *adapter*. The stock is what it adapts to.
|
|
|
|
### Why this framing changes the code
|
|
|
|
Three things in the current codebase are the same object seen three times, and
|
|
none of them knows about the others:
|
|
|
|
| Where | What it is | How it is expressed today |
|
|
|---|---|---|
|
|
| `Geo.cavity_w` / `cavity_t` | a strap's occupied void | strap width and thickness, plus `fit_clearance_mm`, times `bundle_count` |
|
|
| `three_fin_bore_side_mm` | a polygonal void through the centre | a bare side length in millimetres |
|
|
| `bore_from_members()` | the void left over between members | derived, not declared |
|
|
|
|
The first two are stock occupying space. The third is not stock at all — it is a
|
|
residual cavity, and the name collision between it and a declared bore is
|
|
already a source of confusion. **A declared stock void and a derived residual
|
|
void are different things and should stop sharing a word.**
|
|
|
|
## 2. What a stock entry declares
|
|
|
|
Every entry in the catalogue answers the same questions. An entry that cannot
|
|
answer one of them is not described well enough to generate a part.
|
|
|
|
**Designation.** What you ask for at the counter. `EMT 1/2"`, `PET strap
|
|
15.875 x 0.508`, `#3 rebar`. This is a label, never a dimension — see §5.
|
|
|
|
**Section.** The cross-section the stock presents where the printed part meets
|
|
it, as a closed path in millimetres: a rectangle for strap, a circle for
|
|
conduit, a hexagon for a bolt head, a deformed circle for rebar. Prismatic stock
|
|
has one section along its whole length; non-prismatic stock declares the section
|
|
at the interface and nothing else, because that is all this compiler can hold
|
|
(see `PRECISION.md`).
|
|
|
|
**Nominal versus actual.** These differ, and the difference is where parts
|
|
fail. Trade size is not outside diameter. Nominal lumber is not actual lumber.
|
|
**The catalogue stores actual, measured, with its source.** The designation is
|
|
looked up to reach it, never computed from it.
|
|
|
|
**Fit.** How much room the printed part must leave, and why. A strap that slides
|
|
through a channel, a conduit that is meant to be a press fit, and a bolt that
|
|
must clear a hole are three different numbers even at the same diameter. Fit is
|
|
a property of the *joint*, not of the stock, so an entry declares its default
|
|
and every placement may override it.
|
|
|
|
**Tolerance of the stock itself.** Extruded and rolled stock varies. A part
|
|
designed to the nominal section jams on the fat end of the run. Where a
|
|
manufacturing tolerance is known it is recorded; where it is not, that is
|
|
recorded too, and it is not silently assumed to be zero.
|
|
|
|
**Provenance.** Where the numbers came from — a standard, a spec sheet, or a
|
|
caliper. A measured value with a date beats a remembered one, and a remembered
|
|
one does not go in.
|
|
|
|
## 3. The three roles a printed part plays
|
|
|
|
Naming these keeps profiles honest about what they are doing.
|
|
|
|
**Enclose.** The part surrounds the stock and holds it. The strap channels are
|
|
this. Failure mode: the stock does not go in, or rattles once it is in.
|
|
|
|
**Interface.** The part mates two pieces of stock that were not made to meet, or
|
|
mates stock to a fastener. The Y's conduit core is this — the conduit carries
|
|
load or routes cable, and the printed body is what lets three straps meet it.
|
|
Failure mode: the mating surface is thinner than the load through it.
|
|
|
|
**Augment.** The part adds a feature the stock does not have: a mounting boss, a
|
|
cable exit, a label surface, a keyed orientation. Failure mode: the addition
|
|
compromises the enclosure or interface it is attached to.
|
|
|
|
A profile may do all three. Most useful ones do.
|
|
|
|
## 4. Adding an entry
|
|
|
|
The order matters, and it is the same order that produced the strap:
|
|
|
|
1. **Describe the stock**, per §2, with provenance. No geometry yet.
|
|
2. **State the fit**, and what happens at both ends of its tolerance.
|
|
3. **Generate the section**, and check it against a real sample if one exists.
|
|
4. **Only then** write the profile that uses it.
|
|
|
|
Steps 1 and 2 are where the errors are, and they cost nothing to correct.
|
|
Step 4 is where they become expensive.
|
|
|
|
**Every entry lands additively.** The 123-case oracle is frozen at rev 8.0.0 and
|
|
is the only evidence the geometry is right. A new stock entry, a new parameter,
|
|
or a new profile must leave all 123 cases building byte-identically, which means
|
|
new parameters default to *absent*. If adding a capability perturbs one recorded
|
|
value, the implementation is wrong — not the oracle. See `ACCEPTANCE.md`.
|
|
|
|
## 5. What stays out
|
|
|
|
**No standards tables in the geometry layer.** The map from `EMT 1/2"` to an
|
|
outside diameter is data about the world. It gets revised, it varies by region
|
|
and by decade, and a wrong entry in it is a wrong part. It belongs where it can
|
|
be corrected and cited without touching geometry, and where a person can see
|
|
which number was used. Geometry takes millimetres.
|
|
|
|
**No structural claims.** `PRECISION.md` §7 governs and is scope-locked. That a
|
|
part encloses a conduit says nothing about what the assembly carries. Measure and
|
|
attest; never adjudicate.
|
|
|
|
**No inferred stock.** If a dimension is not measured or cited, the entry is
|
|
incomplete and does not ship. A plausible number is worse than a missing one,
|
|
because a missing one stops the build.
|
|
|
|
## 6. Consequence for what exists
|
|
|
|
`Geo` currently derives its cavity from `strap_width_mm`, `strap_thickness_mm`,
|
|
`bundle_count` and `fit_clearance_mm` — a rectangular stock entry, inlined.
|
|
Expressing it *through* the stock descriptor rather than beside it is the first
|
|
migration, and it is the one that proves the abstraction: if all 123 cases stay
|
|
byte-identical with the strap expressed as a catalogue entry, the descriptor is
|
|
faithful. If they do not, it is not, and the second entry would have inherited
|
|
the flaw.
|
|
|
|
That migration comes before the conduit core, not after it.
|