lowest-common-denominator-output
<!-- SPDX-License-Identifier: CC-BY-SA-4.0 -->
## Learning Record
**Project codename:** blue-marlin
**Date:** 2026-04-26
**Category:** gap
**Severity:** significant
**Framework version:** 0.34.0
### What happened
The project generates DXF drawings as one of its outputs (alongside
STEP / GLB / CSV). After iterating to add DXF dimensions and labels,
the user (Governor-Reviewer) opened the files in a 3D-CAD viewer
(Onshape-style) and reported that **the dimensions were not visible**,
despite the entity count showing the expected 4-7 DIMENSION entities
per file.
Diagnosis: 3D-CAD tools (Onshape, Fusion 360, SolidWorks DXF import,
FreeCAD Part workbench) typically import DXF as sketch geometry only
and silently skip DIMENSION blocks — these are annotation entities,
not sketch geometry. Drawing-focused tools (LibreCAD, AutoCAD,
FreeCAD Draft, Inkscape with DXF plugin) do render DIMENSION blocks
correctly. The format technically supported the dimensions; the
chosen viewer ecosystem did not.
The fix replaced `ezdxf.add_linear_dim()` (which produces DIMENSION
blocks) with manual LINE drawing for the dimension geometry —
extension lines + dim line + arrowhead lines as plain LINE entities,
plus `add_text` for the mm value. Each dimension is now 7 LINE
entities + 1 TEXT entity instead of 1 DIMENSION + INSERT block.
The pattern repeated one layer deeper: after the LINE-based dimension
fix, the user reported dimensions visible BUT the actual mm numbers
still missing. Same root cause: the viewer also ignores DXF TEXT
entities when their font reference (Standard / `txt.shx`) is
unavailable. Same fix pattern — replace TEXT with LWPOLYLINE outlines
via `ezdxf.addons.text2path` which converts each character to outline
paths. Final output: zero TEXT, zero DIMENSION, zero font
dependencies. Every visible mark in the DXF is now LINE, LWPOLYLINE,
or CIRCLE.
This took **two iterations of user feedback** to resolve fully —
once for DIMENSION blocks, once for TEXT entities. Both could have
been addressed in one iteration if the principle had been applied
exhaustively to the entire format usage tree on the first pass.
### Agents involved
coder-tester, governor-reviewer
### Framework section
`framework.md` (no specific section currently);
`rules-template/workflow/tdd-rule.md` (related);
new candidate: file-generator rule.
### Business impact
`prevented_loss` — dimensions now visible in the user's actual
viewer ecosystem. The iteration that produced the DIMENSION-block
output passed every automated check (entity counts correct, file
sizes plausible, validators clean), but the deliverable was unusable
in the user's chosen tool. Without the user's visual review, the
project would have shipped invisible dimensions.
### Recommendation
Add a new framework principle / rule:
> **Lowest-common-denominator output principle.** When generating
> files for unknown or heterogeneous viewer ecosystems, prefer the
> most universally-rendered primitives over advanced format features,
> even at the cost of more verbose code or larger file size.
>
> Apply EXHAUSTIVELY in one pass — audit every branch of the format
> usage tree (entity types, blocks, font references, layer features,
> encoding) and downgrade EACH branch to the most basic equivalent.
> Iterating per defect class wastes user-feedback rounds (this
> project took two rounds: DIMENSION → LINE+TEXT, then TEXT →
> LWPOLYLINE).
Concrete examples (DXF case from this project):
| Format feature | Universal alternative | Trade-off |
|---|---|---|
| `DIMENSION` blocks | LINE + LINE arrowheads + TEXT/polyline | 7-8x more entities per dim |
| `TEXT` entities | LWPOLYLINE glyph outlines (via `text2path`) | ~10x more entities per character; rough Hershey-style fonts |
| `MTEXT` / formatted text | Plain TEXT or LWPOLYLINE | No formatting |
| `HATCH` fills | LWPOLYLINE outline + maybe stipple lines | No fills |
| Layered visibility | Single layer + line-weight differentiation | Loss of toggle-ability |
The principle generalises to other formats:
- SVG: prefer `<line>`, `<polyline>`, `<rect>` over `<filter>`,
`<animate>`, `<feFlood>` if target audience uses heterogeneous
viewers.
- PDF: PDF/A subset over full-feature PDF for archive/exchange.
- CSV: avoid Excel-specific quirks (BOM, formula cells); plain
comma-separated UTF-8.
- JSON-LD: limit to JSON-LD 1.0 features if consumers may not
support 1.1.
Suggested addition to `rules-template/workflow/`: a new
`file-generator-rule.md` capturing this principle plus the audit
checklist (entity types, blocks, font references, layer features,
encoding).
Suggested addition to `framework.md` or `ADOPTING.md`: a short
reference to this principle in the context of any task that produces
files consumed by third-party tools.
---
**Anonymization checklist:**
- [x] No real project, product, or organisation names
- [x] No internal URLs, hostnames, or infrastructure identifiers
- [x] No customer or partner names
issue