Consult Engenharia · Sanitation engineering
The best thing I built here was a list of questions.
A Revit add-in that generates the model of a sewage pumping station from topography, a 2D layout and a parameter file. I knew nothing about sanitation engineering when it started. This page is about how that gets closed.
- Role
- Product lead & builder
- Stack
- .NET 10 · Revit 2027 API · Autodesk APS Design Automation · C#
- Status
- MVP in validation with the client — no public URL
The knowledge was in one engineer's head.
A pumping station is drawn the same way every time, and never quite the same. Depths come from topography. The volume of the receiving chamber comes from peak flow over three hours. A manhole without a depth parameter cannot simply be dropped, or its cover leaves the pavement. None of this was written anywhere — it was in the practice of an engineer who had done it dozens of times.
I did not know any of it. That is the actual starting condition of most consulting work, and pretending otherwise is how people build confident, wrong software.
Fifty-one numbered questions, in batches, each answer becoming a rule.
Not a workshop, not a discovery call. A document of numbered questions, sent in batches, answered in writing, each answer traced to the rule it produced and the code that enforces it. When an answer changed an earlier assumption, the rule changed with a reference back to the question number.
Questions before code
The architectural decision record for the assembler ends with a line I had to mean: nothing in it gets implemented while the pending questions are unanswered. Six items were pending. The work stopped there and went elsewhere until they came back.
Decisions written down, including the ones that got reversed
The first approach placed the station by fitting a reference project onto the new terrain, aligning plots geometrically and computing the platform level by cut-and-fill balance. The client then said he supplies a 2D layout with the positions already in it. The geometric fit did not get deleted — it became a check that compares the layout against the reference and warns when the difference crosses a threshold.
The answers are the specification
Peak flow over three hours, internal versus external diameter, whether the inlet holds its level, which patterns identify a manhole in the drainage path. Every one of these came back as a number or a yes, and went into the system as a rule with the question number attached.
Anything that cannot move correctly stops and says why.
This is a system that edits a construction model. The failure mode that matters is not crashing — it is moving something almost right and leaving a pipe connection loose where nobody looks. So the definition of done is a refusal: whatever cannot move correctly stays where it is, with a warning naming the reason, and no connection is ever left disconnected.
Ten situations where that happens are catalogued — a short run whose slope would jump from 1% to 39%, a part hosted on a wall that would have to travel, a manhole missing its depth parameter. Each one records what the add-in does, the exact warning text, and where it first appeared. A new case that breaks nothing is not fixed on the spot; it is added to that list as a known warning.
The hardest version of this was Revit's own error handling. In v1.1, an error inside a transaction let Revit apply its default resolution — which can remove a constraint and silently disconnect something. In v1.2 any Revit error undoes the entire operation and reports why. There is exactly one documented exception, and it is allowed only because all three conditions hold: the elements involved are annotations that change no geometry, connection or model parameter; the resolution is chosen by the add-in rather than by Revit's default; and a dimension whose reference no longer exists cannot be repaired anyway. Any other error, even alongside that one, undoes everything.
The same code in the engineer's Revit and headless in the cloud.
The engineer gets a ribbon tab with four commands — deploy onto the new terrain, generate the station, inventory the model, audit it. The cloud path runs the identical generator with no interface through Autodesk Design Automation and returns a model plus a result file. Underneath both, the engine that reads input, validates it, converts units and estimates depths has no dependency on Revit at all, so it is tested offline on every push. Diameter changes are left to Revit's own routing preferences: the generator picks the type, Revit resolves the connections.
I work on a Mac, which does not run Revit. Development targets the API through reference packages that compile without it; testing runs Revit 2027 in a Windows VM; the cloud path never needed a local Revit in the first place.
177 commits in seven days, in a stack that is not mine.
C#, the Revit API and BIM conventions are not where I come from. The code is generated and reviewed with AI under my direction, which is why a week produced this much. What keeps that from becoming confident nonsense is the shape of the work rather than the volume: an engine that runs without Revit and is tested on every push, decisions recorded before they are implemented, and a client who answers in writing.
An honest reading
This is an MVP in validation. There is no public URL, no production run, and no saved-hours figure, because the first real generation in the client's own Revit has not happened yet. If you are looking for delivered outcomes, the other projects on this site are the ones to read.
What this one shows is the part before the outcome: entering a domain I did not know, pulling the rules out of the person who holds them, and building something that refuses to act when it is unsure. That is the work I would be doing in the first month anywhere.
Have knowledge that lives in one person's head?
That is the situation I like most — the rules are real, the expert is right there, and nobody has written them down.