system

Revit Connector

The seam between Autodesk Revit and the BuildPlan platform — the installable add-in that classifies a model, colours it, writes classifications back, surveys and measures duplicate parameters, and exports a contract artifact for the cloud.

SystemImplemented in the add-in

Why it sits at catalog top level, and is not called revit-desktop

It is the machinery several domains reach Revit throughdesign-management, bim-ontology and construction-management all meet a customer’s model here — so by this catalog’s own rule it stays at the top rather than nesting under one of them:

System — Nest under a domain when that domain owns the capability. Keep at catalog top level when the grouping is machinery that spans domains.

backend-platform is the precedent and says the same of itself: “catalog top-level because api-v1 is not owned by a single domain. It is the HTTP machinery other domains call.”

🔴 THE OLD BLOCKER WAS A MIS-FRAMED QUESTION, NOT AN OPEN ONE. These pages were held back for two days on “which platform domain owns the desktop add-in?” — a question with no answer, because a System need not sit inside a domain at all. The rule above was already written in eventcatalog/CONVENTIONS.md, in the same document the handoff quoted.

And the name went with it. revit-desktop describes where it runs; revit-connector describes what it does, which is the thing several domains depend on.

What this is

One installable today, two codebases. The add-in ships as a single Revit add-in: a C# host that owns everything touching the Revit API, and a React panel that runs in an embedded WebView2 and compiles into assets/ inside the same binary.

Warning

It is a System with two Services and not one Service, and the distinction is load-bearing. The System is what says these ship as one binary — nobody should read the two services as a network boundary. But the bridge between them is a real contract between two independently-authored codebases with independently-run test suites, and it has already shipped a defect a contract would have caught: a refusal built as a second object literal, missing keys the panel read.

The cloud half of this seam is built, and is not a third service here

A connector has two ends. The desktop end is here. The end that ingests the export artifact is Project Delivery Graph on api-v1Ingest Revit Export (requestRevitImportUploadUrl → PUT artifact → registerRevitImportprocessRevitImport or cron → rematerialize → import-run log).

RevitContractExporter produces a contract-v1 JSONL artifact delivered through object storage (this repository’s ADR-43, backend ADR-0071). api-v1 already reads it. That HTTP surface is not added as a third services: entry on this System: it is the same seam, but the deployable is already api-v1, and inventing a box here would render as a missing service.

Info

This index.mdx is carried from bp_revit_extension by eventcatalog/scripts/sync-revit-plugin.mjs. A later plugin sync will overwrite a local-only edit. Update the plugin catalog copy when that checkout is present.

🔴 project-delivery-graph is NOT part of this System, and that is a decision. It is a cataloged domain — the project delivery graph and the project definition graph — and backend ADR-0069 makes it a top-level module in its own right.

The connector owns the SEAM: transport, translation, and the anti-corruption edge. The graph domain owns the MODEL the data lands in. Folding the graph into this System would make the connector responsible for what the platform does with what it carries.

The two halves, and the line between them

revit-addinthe C# host. Owns the Revit seam, the classifier, the parameter engine and every command handler
revit-panelthe React UI. Owns what a person sees and every decision they make
between them25 wire names — commands, queries and one pushed event. Generated into bridge-messages.json from the C# constants

The dependency points inward. Revit knows about the classifier and the parameter engine; neither of them learns Revit exists. Two things rest on that: almost everything is testable with Revit closed, and the add-in may hand long work off the Revit API thread, because the snapshots it passes hold no Revit objects.

What it can do

  • Classify a model into BuildPlan Object Classes, and colour it by the result.
  • Write back an accepted classification into the model — as a shared parameter and an extensible storage stamp — and defend it with an updater that reverts a hand edit.
  • Survey every duplicate parameter, work out where each lives and what removing it would cost, validate a reviewer’s decisions, and measure what carrying them out would cost.

🔴 What it deliberately CANNOT do

It cannot perform a parameter migration. The write half of that engine was deliberately not ported: there is no apply command in any form, and a test asserts the absence over every wire name. The dry run’s own response carries canApply: false and a sentence saying why, because a person looking at a dry run beside no apply button cannot otherwise tell a missing feature from an unfinished one.

The apply is still run from a bench session against the skill, exactly as it was before.

Costs a person will notice

🔴 Two different buildings, because the two halves were measured on two different models — and saying “a real building” for both would size a reader’s expectations against a model the number was never taken on.

measured on
classifya 53,800-node building~1.5 s of classification on top of extraction
survey the parametersa 734-type, 142-instance, 116-category building~28 s, all of it holding Revit’s main loop — and there is no Stop
map, dry run, diffthe same small building6 ms, 254 ms and 242 ms
Warning

⚠️ The survey’s 28 seconds is the SMALL model’s number, and it will not scale flat. Most of that time goes into opening unplaced families one at a time — 316 of them here — so a building with more families on the shelf is slower, not merely bigger. Nobody has measured it on the 53,800-node model.

Danger

The survey freezes Revit for half a minute — on a small model — with no way to abort. The classifier raises an escape window during its long run; the parameter commands take neither the cancellation source nor the escape window, and nothing inside the survey reader checks a token — so there is nothing to trip even if a window were raised. Do not present a Stop button over it.

Entities it consumes

Every one belongs to bim-ontology and is referenced, never redefined: ObjectClass · ParameterKey · RevitParameterProjection.

They are declared on the revit-addin service, which is what actually consumes them, and a test asserts this list and that one are the same set — an earlier draft named two more here that the service did not declare, one of which appears nowhere in this repository at all.

Decisions

The reasoning lives in this repository’s docs/ADR.md and is linked rather than restated. The ones that shape this System most: ADR-4 (all UI-originated Revit work goes through one external-event dispatcher), ADR-11 (work needing no Revit API is answered beside it), ADR-31 (the parameter commands’ thread split, and where decisions live), ADR-34 (the connector boundary) and ADR-42 (the engine’s ontology ships as its own asset).