What It Was
A vibration analysis web app for industrial machinery.
An analyst uploads vibration data from a machine and gets a professional fault report: severity zone, identified faults with the frequency evidence, and recommendations. Sold to vibration analysts as a tool.
How It Worked
A deterministic Python analysis core computes every finding: numpy/scipy DSP, ISO 20816 severity zones, bearing defect frequency matching.
A language model drafts the narrative text only. Consistency contracts verify every claim in the narrative against the computed findings before the report ships.
FASTAPI + POSTGRESQL · GOOGLE SIGN-IN · STRIPE CREDIT PACKS · WEASYPRINT PDF · DIGITALOCEAN DROPLET
What The Engine Matches
Severity is classified against ISO 20816 zones. Faults are identified by matching bearing defect frequencies against the spectrum, which means separating tones that are synchronous with running speed from tones that are not.
Engineering Receipts
- ~2,500 automated tests; a 174-file regression corpus run before merges; validated against the public CWRU, MFPT, and MAFAULDA bearing-fault datasets.
- Protected core: the analysis engine directory was write-locked for AI coding agents and opened per file by hand; every change verified by diff and test count, not the agent's summary.
- Silent-wrong bugs caught before customers saw a wrong number: a UTF-16 encoding RMS miscalculation, European decimal-comma parsing, an amplitude ceiling overflow.
- A renderer segfault (weasyprint + threads) fixed properly with subprocess isolation after a lock proved insufficient.
- A privacy defect found and fixed: uploaded raw data could still be on disk for a moment after the API reported an error; purge order was corrected so deletion completes before the wire answers.
- Automatic file-format and schema detection for mixed instrument exports (.txt/.dat/.asc).
- Report revisions shipped from reviews by a certified Category IV vibration analyst and an SFU professor.
Three Bugs And A Rule
The renderer segfault
- Symptom
- WeasyPrint segfaulted when run under threads.
- First fix
- A lock. It proved insufficient.
- Real fix
- Subprocess isolation.
The privacy defect
- Symptom
- Uploaded raw data could still be on disk for a moment after the API reported an error.
- Fix
- Purge order corrected, so deletion completes before the wire answers.
Three silent-wrong bugs
- Class
- Bugs that return a plausible number instead of failing loudly.
- Instances
- A UTF-16 encoding RMS miscalculation. European decimal-comma parsing. An amplitude ceiling overflow.
- Outcome
- All three caught before a customer saw a wrong number.
The protected core
- Rule
- The analysis engine directory was write-locked for AI coding agents and opened per file by hand.
- Verification
- Every change checked by diff and test count, not the agent's summary.
Why It Died
Nobody who tried it used it a second time.
- Analysts do their analysis in the vendor software that came with their instruments, and they write reports in their own templates customized per client.
- My tool sat outside that workflow and asked for manual uploads.
- They did not want AI anywhere near a signed, liability-bearing deliverable.
- The people who liked it were employee analysts, who do not control budgets.
I spent five months building and twelve days asking. When four independent sources told me the same thing in one weekend, I shut it down that night.
What I Took From It
Talk to the person who signs the cheque before anything exists. Money is the only validation. A build budget should be funded by revenue.