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

14 KiB

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.