docs: HANDOFF corrected against the tree, and PROCESS.md put first

A new section 0 gives the reading order with PROCESS.md at the top. The handoff never mentioned it. That is the root cause of three sets of instructions the operator could not execute in one session: an SSH to a host he does not reach that way, a LAN address behind a portless bridge, and a hosts file name that resolves on three machines.

The access model is now stated rather than only defended. The settled decisions said questioning Webmin wasted a session but never recorded what the arrangement is, so it was questioned again. It now records that he works from Webmin on the hub and into the srv-b shell, and that dev.infra names and 10.20.0.x addresses are never to be given as browser URLs.

The module table filed Geo and Member under primitives.py, where they have never been, and omitted records.py entirely. Two modules were read on the strength of it and neither held what it promised. Corrected, with the error named so it is not re-derived, plus rows for stock.py, design_record.py, svg.py and web/app.py.

Sections 3 and 4 described a world with no application in it: main two commits back, 468 passing, the catalogue front end does not exist, deployment blocked on application code. Now 529 passing at a8081e1 with the composer live behind the proxy, and the next work named as per member stock, which is what the conduit core actually needs.
This commit is contained in:
2026-09-11 07:05:59 -05:00
parent a8081e17dc
commit 39a6b02c63
+70 -10
View File
@@ -6,7 +6,7 @@ It is the only handoff you need to read. Dated handoffs in `docs/archive/` are
historical and are not required reading — do not diff them against this to work historical and are not required reading — do not diff them against this to work
out what is true. If something here is wrong, correct it here. out what is true. If something here is wrong, correct it here.
Last updated 2026-08-22, closing F-034. Last updated 2026-09-11, after the composer went live behind the proxy.
This line used to carry the commit hash of its own rewrite. It cannot: the This line used to carry the commit hash of its own rewrite. It cannot: the
hash is not known until the commit is made, so the value was always the hash is not known until the commit is made, so the value was always the
@@ -15,6 +15,25 @@ noticing. Date only, from here.
--- ---
## 0. Read these first, in this order
This document is not the first thing to read, despite being the handoff.
1. **`docs/PROCESS.md`** — how work is done here: who runs what, on which
machine, with which tools. **It constrains everything below.** Reading it
eleventh cost this session three sets of instructions the operator could
not execute.
2. **`docs/STAGING-STATE.md`** — what is true on the host right now.
3. **`docs/FAILURES.md`** — what has already gone wrong and why.
4. This document — where the code stands.
5. `docs/ACCEPTANCE.md`, `docs/STOCK.md`, `docs/PRECISION.md` — the
specifications the code is held to.
When documents disagree, `STAGING-STATE.md` wins on facts about the host and
`FAILURES.md` wins on what was actually observed. This one is corrected.
---
## 1. Invocation — read before typing anything ## 1. Invocation — read before typing anything
These are facts, not examples. Getting one wrong produces an error that looks These are facts, not examples. Getting one wrong produces an error that looks
@@ -128,7 +147,17 @@ terminate rather than recur.
**Settled decisions. Do not reopen any of these:** **Settled decisions. Do not reopen any of these:**
- Webmin is the operator's only remote access. Questioning it wasted a session. - **Webmin is the operator's only remote access.** He works from Webmin on
`wg-pk`, the WireGuard hub, and from there into the `srv-b` shell — not the
other way round. Questioning this wasted a session once and was questioned
again on 11 SEP, because the decision had been recorded without the fact it
rests on. The fact is above. Do not ask again.
- **`dev.infra` does not exist on the internet.** It is a hosts-file name on
`srv-b`, CT 100 and CT 101 only, and CT 101's leaf is signed by a local
staging CA. Never tell the operator to open a `dev.infra` URL or a
`10.20.0.x` address in a browser: `10.20.0.0/24` is a portless bridge with
LAN traffic dropped. The public name is `dev.mechcomp.kane-il.us` and it
needs `WORK-ORDER-004`.
- Backup is deliberately postponed. Entry condition: `ct-baseline.sh` exits 0. - Backup is deliberately postponed. Entry condition: `ct-baseline.sh` exits 0.
Do not raise it again. Do not raise it again.
- `4x` is the end of the N-strap family. - `4x` is the end of the N-strap family.
@@ -140,15 +169,20 @@ terminate rather than recur.
### The port — COMPLETE ### The port — COMPLETE
Gitea `main` at `52d00b5` before this commit. CT 100 clean and matching. Gitea `main` at `a8081e1` before this commit. CT 100 clean and matching.
**Suite: 468 passed, 0 failed.** The 30 expected failures are gone, resolved **Suite: 529 passed, 0 failed.** The 30 expected failures are gone, resolved
rather than suppressed, by the tolerance model in `docs/ACCEPTANCE.md`. A red rather than suppressed, by the tolerance model in `docs/ACCEPTANCE.md`. A red
`make test` now means something is actually wrong. `make test` now means something is actually wrong.
**The composer is live.** `mechcomp.service` in CT 100 serves it on
`10.20.0.10:8770`, behind nginx on CT 101, proven `HTTPS 200` end to end.
`mechcomp-placeholder.service` is disabled and retained as the rollback.
| Module | Ported from | Contents | | Module | Ported from | Contents |
|---|---|---| |---|---|---|
| `geom/primitives.py` | `sb-geom.scad` | Vectors, GEO and MEMBER, sleeve and cavity paths, exact polyline distance, corner-radius derivation, monotone solver | | `geom/primitives.py` | `sb-geom.scad` | **Pure geometry only.** Vectors, degree trig, exact polyline distance, corner-radius derivation, monotone solver. **`Geo` and `Member` are NOT here** — an earlier version of this table said they were, and two modules were read on the strength of it |
| `geom/records.py` | `sb-geom.scad` | `Geo`, `Member`, `place`, `local_rect`, sleeve and cavity paths, reach. The other half of `sb-geom` |
| `geom/rounding.py` | BOSL2 `92d697c2` | `round_corners`, `_circlecorner`, `arc`, `segs`, `deduplicate`, `path_merge_collinear`, `is_collinear` | | `geom/rounding.py` | BOSL2 `92d697c2` | `round_corners`, `_circlecorner`, `arc`, `segs`, `deduplicate`, `path_merge_collinear`, `is_collinear` |
| `geom/region.py` | BOSL2 regions | Shapely booleans, nesting-parity decomposition, area, simplicity, hull, mitred offset, cleaning | | `geom/region.py` | BOSL2 regions | Shapely booleans, nesting-parity decomposition, area, simplicity, hull, mitred offset, cleaning |
| `geom/join.py` | `sb-join.scad` | Butt joints, hull caps, fillets, derived bore, ring fit, section assembly | | `geom/join.py` | `sb-join.scad` | Butt joints, hull caps, fillets, derived bore, ring fit, section assembly |
@@ -159,6 +193,10 @@ rather than suppressed, by the tolerance model in `docs/ACCEPTANCE.md`. A red
| `profiles/four_x.py` | `strap-beam-4x.scad` | Five profiles, defaults, 4x base checks | | `profiles/four_x.py` | `strap-beam-4x.scad` | Five profiles, defaults, 4x base checks |
| `profiles/three_x.py` | `strap-beam-3x.scad` | Six profiles, defaults, 3x base checks | | `profiles/three_x.py` | `strap-beam-3x.scad` | Six profiles, defaults, 3x base checks |
| `profiles/__init__.py` | — | `build()`, `ProfileRejected`, family registry | | `profiles/__init__.py` | — | `build()`, `ProfileRejected`, family registry |
| `stock.py` | — | COTS stock descriptor: `RectStock`, `RoundStock`, `Fit`, `Provenance`. A leaf module — imports nothing from `mechcomp`. See `docs/STOCK.md` |
| `design_record.py` | — | What a model was made from, at full precision, sufficient to regenerate it. `input_id` and `build_id` |
| `svg.py` | — | Cross-section as SVG, separately classed layers for material, cavities and stock |
| `web/app.py` | — | The composer. Standard library HTTP server; binding from `/etc/mechcomp/mechcomp.env` |
`make deps` is complete in CT 100 and **must not be re-run**. `make deps` is complete in CT 100 and **must not be re-run**.
@@ -166,7 +204,7 @@ rather than suppressed, by the tolerance model in `docs/ACCEPTANCE.md`. A red
## 4. What to do next ## 4. What to do next
**Nothing is blocked. F-034 is closed and the suite is green; everything **Nothing is blocked. The composer is live and the suite is green; everything
below is new capability.** below is new capability.**
**CIVICVS stated the goal on 22 AUG: he will not print anything that is not **CIVICVS stated the goal on 22 AUG: he will not print anything that is not
@@ -188,13 +226,27 @@ Roadmap items — read `ROADMAP.md` before starting any:
profiles gives you a member for it. This is the highest-value gap and it profiles gives you a member for it. This is the highest-value gap and it
blocks a catalogue that could otherwise not serve the reference structure. blocks a catalogue that could otherwise not serve the reference structure.
- Rebar- and conduit-core bore as a declared interface. See above. - Rebar- and conduit-core bore as a declared interface. See above.
- The catalogue front end. Nothing of it exists: no SVG emitter, and - **Per-member stock.** This is what the conduit core actually needs. `Geo` is
`src/mechcomp/web/__init__.py` and `worker/__init__.py` are 33- and 36-byte global to a build, so every member is the same rectangular strap by
stubs. `STAGING-STATE.md` records deployment as blocked on application construction and the Y's centre cannot hold something of a different shape.
code, which is still true. Moving stock from the build to the placement reaches into `join.py` and
`arrangements.py`, and it is the first change where the oracle's own
geometry is genuinely at risk rather than merely nearby.
- **The composer, deepened.** It exists and serves; it does not export
anything, persist anything, or show a bill of materials. `payload["defaults"]`
is sent to the browser and nothing reads it — dead weight, and it is what
made a verification grep lie on 11 SEP.
- STL and STEP export. No CAD kernel is installed in CT 100 (§5). - STL and STEP export. No CAD kernel is installed in CT 100 (§5).
- `mechcomp-worker.service`. `src/mechcomp/worker/` is still a 36-byte stub and
nothing needs a worker yet.
- Nodes (non-prismatic) and panels (sheet). No representation exists for either. - Nodes (non-prismatic) and panels (sheet). No representation exists for either.
**`WORK-ORDER-004` publishes the composer at `dev.mechcomp.kane-il.us`.** It is
infrastructure-mode work on `wg-pk`, which this project does not own, so it is
an escalation under `PROCESS.md` §7 and not something to drive with command
groups. The `srv-b` half needs no change; the single gate is `AllowedIPs` on the
hub's peer entry. **Until it closes, CIVICVS cannot see any of this work.**
Note for anyone tempted to shortcut a test print: the OpenSCAD reference in Note for anyone tempted to shortcut a test print: the OpenSCAD reference in
`legacy/` does export printable STL today — `sb_extrude_section` does a `legacy/` does export printable STL today — `sb_extrude_section` does a
`linear_sweep` and `legacy/openscad/README.md` documents the invocation. That `linear_sweep` and `legacy/openscad/README.md` documents the invocation. That
@@ -489,6 +541,7 @@ held to it. When in doubt, narrow.
| 4 | Kane Fabric participant mail, send and receive | Cross-project | | 4 | Kane Fabric participant mail, send and receive | Cross-project |
| 5 | ~~Tolerance model for the three discretisation-limited keys~~ | **Closed 22 AUG.** See §7 and `docs/ACCEPTANCE.md` | | 5 | ~~Tolerance model for the three discretisation-limited keys~~ | **Closed 22 AUG.** See §7 and `docs/ACCEPTANCE.md` |
| 6 | Is the bore's fit class per-material, or one clearance for all inserts? | CIVICVS — raised by the conduit-core requirement, §4 | | 6 | Is the bore's fit class per-material, or one clearance for all inserts? | CIVICVS — raised by the conduit-core requirement, §4 |
| 7 | Public ingress at `dev.mechcomp.kane-il.us` | `WORK-ORDER-004`; CIVICVS executes on `wg-pk` |
Question 4 is real and unaddressed. Containers do not send mail by standard and Question 4 is real and unaddressed. Containers do not send mail by standard and
nothing can reach `vmbr1` from outside, so receiving has no path at all. It needs nothing can reach `vmbr1` from outside, so receiving has no path at all. It needs
@@ -499,6 +552,13 @@ a design conversation, not a configuration change.
## 12. Commit log ## 12. Commit log
``` ```
a8081e1 state: the composer replaced the placeholder; open public ingress
14514b0 web: the composer, served behind the existing proxy chain
e921cac design record: every build emits one
d2827c2 design record: what a model was made from, sufficient to regenerate it
70787ea stock: records delegates to the descriptor, and the descriptor stops gating
f5651d3 stock: name the COTS descriptor; the strap becomes the first entry
6836ece tests: close F-034; bound the derived trio at 8 ULP of the oracle record
52d00b5 docs: HANDOFF header commit line moved to b255ebb 52d00b5 docs: HANDOFF header commit line moved to b255ebb
b255ebb docs: F-034 rewritten from measurement; handoff updated b255ebb docs: F-034 rewritten from measurement; handoff updated
114189c docs: PRECISION.md -- scope, guarantees and limits, for lay readers 114189c docs: PRECISION.md -- scope, guarantees and limits, for lay readers