Document automation

Automating door hardware estimating for a national distributor

No docs, no schema, no vendor support — just exports to diff. Decoding an undocumented legacy file format and building the import pipeline an estimating team actually uses.

opening row · 107 fieldsdecodedunknown
A101tag
2type
41frame mfr
118catalog
HM-1door
07?
0?
3070size
RHhand
·?
16gauge
1?
US26Dfinish
·?
126catalog
WD-1door
2?
·?
STClabel
0?
A101tag
2type
41frame mfr
118catalog
HM-1door
07?
0?
3070size
RHhand
·?
16gauge
1?
US26Dfinish
·?
126catalog
WD-1door
2?
·?
STClabel
0?
col 48 → manufacturer catalog id · decoded by diffing exports
107
Fields in a single opening row
0
Pages of format documentation
2-way
Round-trip validated imports
min
From spec PDF to import file
STEP 1
Architect's spec PDF
hundreds of pages of openings and hardware sets
STEP 2
AI extracts openings
tags, sets, hand, finishes — structured
STEP 3
Converter builds rows
fixed-column format, 107 fields per opening
STEP 4
Import into the system
field counts and placeholders handled by rule
STEP 5
Round-trip verify
export again, diff against what went in

The re-keying problem

When a commercial building goes up, an architect issues a door hardware specification — often hundreds of PDF pages listing every opening, its hardware set, and its finishes. At a national door hardware distributor, an estimator re-keys that document into a decades-old estimating system, opening by opening. It is exactly the kind of work that eats a skilled person's week and produces typos.

The estimating system can import jobs from a file. The catch: the file format is a fixed-column text format from another era, and there is no documentation for it. None. No schema, no manual, no vendor support channel that knows.

Decoding a format with no manual

The only Rosetta stone available: the system can also export. So the method was archaeology — build a small job in the UI, export it, change one thing, export again, diff the files. Repeat until the columns give up their meanings. Field by field, a working model of the format emerged: which positions carry the door and frame data, which integers are actually foreign keys into the system's manufacturer catalog, which blocks repeat per opening.

None of that model lives in anyone's head anymore — it's written down, versioned, and encoded in a parser, which means the next person doesn't have to do the archaeology twice.

One opening row — 107 fixed columns, zero documentation
A101opening tag
2row type
41frame mfr
118catalog id
HM-1door material
07?
0?
102 more fields

The decode method — change one thing, export, diff

export AA101|2|41|118|HM-1|07|0|…
export BA101|2|41|126|HM-1|07|0|…

Swap the door series in the UI, export again, and column 48 gives itself up: it's a foreign key into the manufacturer catalog. Repeat until the row runs out of secrets.

The traps

Undocumented formats fail in undocumented ways. An opening row must carry exactly 107 fields — one short and the import rejects it. Worse: some malformed imports succeedin the UI, show a success message, and then silently roll the data back after the dialog closes. And some real-world records don't fit the format's assumptions at all — a product with no catalog entry needs a documented placeholder convention, not a guess.

Every one of those traps is now a rule in the converter: field counts are preserved structurally, required columns are always emitted, and unknown entities map to explicit, documented placeholders.

Trust, but round-trip

A converter you can't verify is a liability. The proof loop: generate an import file, load it into the real system, export the result, and diff it against what was sent in. A dedicated test order exists purely to prove the round trip stays clean as the converter evolves. When import and re-export agree, the estimating team isn't trusting my code — they're trusting their own system's output.

What it unlocks

A spec that used to cost days of re-keying becomes an import file in minutes: AI reads the architect's PDF and extracts the openings, deterministic code assembles the fixed-column rows, and the estimating team reviews a job that's already in their system. The pattern generalizes — most industries have one of these legacy formats everyone re-keys into by hand, and the same diff-decode-validate method applies.