Files
mechanical-compiler/docs/DIVERGENCES.md
T
TheRON bc291822e1 STAGING-STATE: reconcile against the host, and close DIV-005 as recorded backwards
DIV-005 is withdrawn. It claimed requirements-cad.txt declared a CAD dependency set that was not installed. Verified in CT 100 today: cadquery and OCP both import from the venv. build123d does not, and correctly so - requirements-cad.txt names it as a viable alternative on the same OCCT kernel, not as an installed package. The file declares one requirement, cadquery greater-or-equal 2.4, and it is satisfied. The manifest and the container agree.

The false statement was in HANDOFF section 5, which said no CAD kernel is installed and that cadquery, OCP and build123d are all absent. True when written on 19 AUG, carried forward by hand for three weeks. STAGING-STATE section 5 recorded cadquery 2.8.0 in the venv for the same period. Two documents, each stating it as fact, disagreeing, and neither noticing.

The entry was recorded backwards: it named the manifest as diverging from the container when the container matched the manifest and a third document was wrong about both. Its evidence was a session record rather than an observation, which is why it carried do-not-close, and that marking is the only reason this was checked instead of acted on. The index note is corrected from three-of-six to two-of-six.

A roadmap item was deprioritised on the same false premise. HANDOFF section 4 listed STEP export as needing a CAD kernel that was not installed. It is installed.

STAGING-STATE section 5 opened with a transcribed repository block: HEAD at the seed commit c7e32d8, tests 3 passed and 236 skipped, and absent the Shapely port itself. All three were true on 18 AUG and none after 20 AUG, while the checklist directly below was kept current. Facts three weeks apart in one section, the maintained half lending credibility to the stale half. Removed rather than corrected. One line in it was still accurate - the venv cadquery 2.8.0 - and it was the only correct statement about the CAD kernel in the repository when it was deleted.

Section 3a said Kane Fabric is where SASE, HOA Diagnostics, the Mechanical Compiler and other SASE-consuming projects are implemented. Nothing here is implemented on Kane Fabric. Each project has its own FQDN and container and they share the bridge, the hub and the proxy. SASE was used and never defined anywhere in this repository. Section 3a also said no interface between the two projects exists and none is assumed; IDENTITY-CONTRACT.md specifies one.

Section 4 gave AllowedIPs on the hub peer entry for srv-b as 10.110.0.0/22, four paragraphs after correctly giving it as 10.110.0.12/32. The 22 is srv-b own AllowedIPs for the hub, recorded in section 1. The two ends of one tunnel were conflated, in the paragraph describing the security boundary. WORK-ORDER-004 section 0 settles it: all twenty peers carry a 32.

Also: the toolchain image box is ticked, verified present in CT 100. The baseline result is marked overdue against DIV-006. The Shapely port gates nothing. HANDOFF rewrap owed from 61b8f1e is applied.

Read-only verification was run before writing, per PROCESS section 2. Had it not been, this commit would have deleted the one true CAD statement and left the false one standing. Suite 643 passed, oracle intact. Documentation only.
2026-09-14 04:14:18 -05:00

294 lines
14 KiB
Markdown

# DIVERGENCES.md
**Requirements that stand and are not met.**
| | |
|---|---|
| Tier | record |
| Audience | whoever is deciding what to fix next |
| Tense | past — each entry describes a moment |
| Status | 6 entries; 5 verified, 1 unverified |
| Defers to | `FAILURES.md` on what was observed; `STAGING-STATE.md` on host facts |
| Opened | 2026-09-12, from the documentation audit against `cdde394` |
---
## 0. What this document is, and how it differs from `FAILURES.md`
`FAILURES.md` records **something that went wrong**: an action was taken, it did
not work, and the entry says why.
This document records **something that is wrong now**: a requirement was
written, it stands, and the thing it governs does not comply. Nothing failed.
Nobody was surprised. The divergence was simply never written down, because
there was no notation for it.
That absence is the reason this file exists. `ENVIRONMENT.md` carries six markers
for a requirement's strength and provenance — **REQ**, **PREF**, **PROVEN**,
**ASSUMED**, **DEFERRED**, **INSTANCE** — and none meaning *this requirement is
not currently met*. Every entry below was visible in the documents for weeks and
recorded in none of them.
### The rule these entries follow
A requirement is never made true by lowering it to match what was built. The
requirement stays where it is, the divergence is recorded against it, and the
correction is owed by the thing, not by the document.
### Form
Append-only. Never edit an entry except to add a `Resolution` line. Each entry
carries:
- **Requirement** — what is required, and the document and section stating it
- **Actual** — what is true at the stated commit
- **Evidence** — how that was established, and how far it was checked
- **Consequence** — what it costs. An entry with no consequence is either not
understood or not worth recording
- **Owed by** — code, configuration, host, or a decision
Ids are assigned when an entry is recorded, not by severity. The index in §7
carries priority.
---
## 1. DIV-001 — AGPL section 13 is not satisfied on a live public deployment
**Requirement.** Root `README.md`: section 13 obliges an offer of source to
users interacting with the software over a network, so any deployed web tier
carries a visible link back to this repository. The document calls this *a
licence obligation, not a courtesy*.
**Actual.** At `cdde394` the served page carries no such link.
**Evidence.** `src/mechcomp/web/app.py` read in full. The page is the single
`PAGE` constant. Its `<header>` holds the title and one line of description. The
document contains no anchor element except the one created in JavaScript at
download time to save the STL blob. `do_GET` serves `/`, `/api/build` and
`/m/stl`, and 404s everything else — there is no `/source` route. The composer
became publicly reachable at `https://dev.mechcomp.kane-il.us` on 2026-09-11
(`1fdb115`, `WORK-ORDER-004`).
**Consequence.** The obligation the front door states in its own words is unmet,
on a public name, and has been since 11 SEP. This is the only entry in this
register whose consequence falls outside the project.
It is also the only one where the **document is right and the code does not
comply**. Every other entry is a requirement the code declined to follow for
reasons that may be sound; this one has no such reading.
**Owed by.** Code. A visible link in `PAGE`'s header, and nothing else.
**Priority: first.** Smallest remedy in the register, largest exposure.
---
## 2. DIV-002 — the specified service architecture was never built
**Requirement.** `ENVIRONMENT.md` §9, marked **REQ**: two units split along a
control-plane / execution-plane boundary.
- `mechcomp.service` — FastAPI/uvicorn; serves the catalogue, accepts jobs,
returns cached artifacts, and **never runs geometry**
- `mechcomp-worker.service` — consumes the queue, runs generators, writes
artifacts
§9 further REQs a SQLite-backed in-process job queue. §15 gate 3 requires both
units active. §1.1 calls the control-plane / execution-plane separation a
requirement *regardless of distribution*.
**Actual.** `web/app.py` is a standard-library HTTP server that builds geometry
synchronously in the request thread. `src/mechcomp/worker/` is a 36-byte stub.
There is no queue and no database, and nothing has ever written to
`MECHCOMP_DATA_DIR`.
**Evidence.** `app.py` read in full at `cdde394`. Its imports are `json`, `os`,
`traceback`, `http.server`, `typing`, `urllib.parse` and `mechcomp.svg`. It runs
a `ThreadingHTTPServer`; `do_GET` calls `build_payload` -> `build(...)` inline.
Its own docstring states the constraint deliberately: *standard library only —
`http.server`. No framework, no build step, no new dependency.*
`requirements-base.txt` read: it does declare `fastapi`, `uvicorn`, `pydantic`,
`sqlalchemy` and `jinja2`, matching `ENVIRONMENT.md` §8.3 exactly. Those five are
not imported by the composer. **Not checked across the rest of `src/`** — only
`app.py` was read.
**Consequence.** Geometry runs in the request path on a world-reachable service
with no authentication. A long build occupies a request thread; the ceiling at
`MECHCOMP_MAX_EXPORT_MM` bounds the response size but not the computation, and
`/api/build` has the same exposure with no ceiling at all. The separation §1.1
requires is the mitigation, and it does not exist.
Five declared dependencies are installed on every instance and appear unused.
**Owed by.** A decision before any code. Either the architecture is built, or §9
is formally superseded by a written decision — not edited away.
---
## 3. DIV-003 — the instance is publicly reachable against three REQs
**Requirement.** `ENVIRONMENT.md` §1.3: staging is not publicly reachable and
does not use the public FQDN, *so the promotion path is exercised rather than
assumed*. §5.2, marked **REQ** for non-production instances: no public DNS
record, and no publicly-trusted certificate — because it consumes rate limit
against a name production needs clean, and puts a development host on the
internet.
**Actual.** `dev.mechcomp.kane-il.us` has public `A` and `AAAA` records and
terminates a Let's Encrypt certificate on `wg-pk`, expiring 2026-12-10.
**Evidence.** `WORK-ORDER-004`, closed 2026-09-11, §1 and §2. All eight
acceptance criteria met and recorded.
**Consequence.** Three **REQ**-marked statements are false of the running
instance, and §5.2's reasoning is a live claim nobody has rebutted: a rate limit
is being consumed against a name, and a non-production host is on the internet.
`WORK-ORDER-004` §3 records a related open item: the first renewal for this name
is due before 2026-12-10 and **no renewal has ever been observed to succeed**.
The other four certificates on `wg-pk` are managed identically, which is
reassuring but not evidence.
**Owed by.** A decision. Either §5.2 is superseded — the name may no longer be
"non-production", since `WORK-ORDER-004` §3 records that `dev` abbreviates
*Mechanical Compiler Developers*, the name is production, and it appears on
printed material — or the exposure is closed. The two documents currently
disagree about what kind of instance this is.
---
## 4. DIV-004 — the configuration contract declares eight keys nothing reads
**Requirement.** `ENVIRONMENT.md` §11 and `STAGING-STATE.md` §1 both carry the
`MECHCOMP_*` contract; `/etc/mechcomp/mechcomp.env` sets twelve keys.
**Actual.** The composer reads four: `MECHCOMP_BIND` and `MECHCOMP_PORT`
(`resolve_binding`), `MECHCOMP_MAX_EXPORT_MM` (`max_export_mm`), and
`MECHCOMP_BASE_URL` (`base_url`) — each checking the process environment before
the file.
Not read in `app.py`: `MECHCOMP_ENV`, `MECHCOMP_DATA_DIR`, `MECHCOMP_LOG_LEVEL`,
`MECHCOMP_DB_URL`, `MECHCOMP_WORKER_CONCURRENCY`, `MECHCOMP_CAD_BACKEND`,
`MECHCOMP_ARTIFACT_RETENTION_DAYS`, `MECHCOMP_SECRET_KEY`.
The omission also runs the other way: **`MECHCOMP_MAX_EXPORT_MM` is read by the
code and absent from `ENVIRONMENT.md` §11.** It was added at `cdde394`.
**Evidence.** `app.py` read in full. **Not checked across the rest of `src/`.**
**Consequence.** Most of the eight belong to the architecture DIV-002 records as
never built, so this is largely the same divergence seen from the configuration
side. It is recorded separately because it is the cheapest thing here to check
and the easiest to mistake for settled: a key present in an env file, a
specification and a state document looks live from all three.
`MECHCOMP_SECRET_KEY` deserves its own note. A secret that nothing reads is not
protecting anything, and its presence implies a session or signing mechanism
that does not exist.
**Owed by.** Documentation, once DIV-002 is decided. §11 should state which keys
are live and which are reserved for unbuilt components, and should add
`MECHCOMP_MAX_EXPORT_MM`.
---
## 5. DIV-005 — `requirements-cad.txt` declares a set that is not installed
**Requirement.** `requirements-cad.txt` declares a CAD dependency set and,
per `HANDOFF-2026-08-19.md` §3, says it is installed by default.
**Actual.** That same section records that `cadquery`, `OCP` and `build123d` are
**all absent from CT 100**, and notes the absence *will matter when STL and STEP
export starts*.
STL export started. It landed at `0545b79` on 2026-09-12.
**Evidence.** `HANDOFF-2026-08-19.md` §3, a session record, not a current
observation. **Unverified at `cdde394`.** `requirements-cad.txt` (347 b) and
`src/mechcomp/stl.py` (11,318 b) have not been read. **Do not close on this
evidence.**
**Consequence.** Unknown until verified. Note that the absence may be correct:
`ACCEPTANCE.md` E-8 requires the 2D path to import no CAD kernel, and asserts it
by test. If `stl.py` also needs none, the divergence is only that the manifest
describes an installation that does not happen — the same shape as DIV-002 and
DIV-004, and the third instance of a manifest describing an unbuilt architecture.
**Owed by.** Two cheap reads before anything else.
**Resolution 2026-09-13 — NOT A DIVERGENCE. Closed.**
Verified in CT 100: `cadquery` and `OCP` both import from
`/var/www/mechcomp/venv`. `build123d` does not, and correctly so —
`requirements-cad.txt` names it as a viable alternative on the same OCCT kernel,
not as an installed package. That file declares exactly one requirement,
`cadquery>=2.4`, and it is satisfied. The manifest and the container agree.
The false statement was in `HANDOFF.md` §5: *no CAD kernel is installed in
CT 100; `cadquery`, `OCP` and `build123d` are all absent.* True when written on
19 AUG, carried forward by hand for three weeks, and corrected in the same
commit as this line. `STAGING-STATE.md` §5 had recorded `cadquery 2.8.0` in the
venv throughout.
**This entry was recorded backwards.** It named the manifest as diverging from
the container, when the container matched the manifest and a third document
disagreed with both. Its evidence was a session record rather than an
observation — which is why it carried *do not close*, and that marking is the
only reason this was checked rather than acted on.
---
## 6. DIV-006 — conformance has not been re-run since the host changed
**Requirement.** `PROCESS.md` §9a, marked **REQ**: run `ct-baseline.sh` after any
change to a container or to host firewall rules.
**Actual.** `STAGING-STATE.md` §3b records the last run as **2026-08-18**,
62 passed, 0 failed.
Since then: a DNAT rule was added to `nat PREROUTING` and persisted
(`WORK-ORDER-004` §1, 2026-09-11), and `mechcomp-placeholder.service` was
replaced by `mechcomp.service` in CT 100. Both are changes the REQ names.
**Evidence.** Documents only. **It is not known whether the check was run and
not recorded, or not run.** Either way the record is wrong: a conformance result
with no date after the changes it is supposed to cover is not evidence.
**Consequence.** The conformance claim is the basis for *the three containers are
configured identically*. That claim currently rests on a run that predates two
host changes by three and a half weeks.
`WORK-ORDER-004` §2 is partial mitigation — it verified `POSTROUTING` order
unchanged and confirmed mail still delivers after `iptables-save` rewrote the
ruleset. That is careful work and it is not the same as the baseline.
`FAILURES.md` F-037 is also relevant: `ct-baseline.sh` exits 0 with the F-037
condition present, so a passing run does not cover everything the standard is
believed to cover.
**Owed by.** One run, and a dated line in `STAGING-STATE.md` §3b.
---
## 7. Index
| Id | Divergence | Verified | Owed by | Status |
|---|---|---|---|---|
| DIV-001 | AGPL §13 link absent from a public deployment | yes, `app.py` | code | **open — do first** |
| DIV-002 | Specified service architecture never built | yes, `app.py` | a decision | open |
| DIV-003 | Instance public against three REQs | yes, `WORK-ORDER-004` | a decision | open |
| DIV-004 | Eight declared config keys unread | yes, `app.py` | documentation | open, blocked on DIV-002 |
| DIV-005 | `requirements-cad.txt` vs CT 100 | yes, 2026-09-13 | — | **closed — recorded backwards** |
| DIV-006 | Conformance not re-run since host changed | documents only | one run | open |
**Two of six — DIV-002 and DIV-004 — are the same shape:** a manifest or
specification describing an architecture that was not built, with nothing
recording the difference. That pattern is the reason this file exists.
DIV-005 looked like a third and was not. The manifest was honest, the container
matched it, and a third document was wrong about both. The pattern is real, and
matching a new observation to it without checking is how that entry came to be
written backwards — which is worth watching for in anything written next at
least as much as the pattern itself.