Replies: 7 comments 15 replies
|
Hi Steffen, First, apologies for the delayed reply—I only just saw your message. Thank you for reaching out, and for the extraordinarily thoughtful work behind it. This is the first substantive outside contribution to rvt-rs, and it means a great deal to hear that the reconnaissance document has been useful to another team building in this space. Everything you described is highly relevant, especially the checksum-page decompression finding and its potential for silent corruption on larger streams. I would be very glad to dig into all six findings with you. Please do not feel that you need to turn everything into polished issues, probes, tests, and documentation before sharing it. If you send the full write-ups, existing scripts, reproducible artifacts, sample provenance, or even rough research notes that you already have and are able to share, I’m happy to take on the repository-side work: independently reproducing the results, organizing and opening the tracking issues, implementing fixes, writing regression tests and probes, and updating the reconnaissance documentation. I’ll make sure the issues and resulting work clearly credit you and your team for the discoveries. If you would enjoy preparing the focused container-layer pull request for the decompression issue, I would be excited to review it—but that is entirely optional. I’m equally happy to implement it here based on your evidence. I’ll begin investigating the decompression finding now using the details you’ve already shared. Whenever it’s convenient—now or later—please feel free to send anything else you already have, even rough notes, and I’ll incorporate it into the work from there. I would also really value your perspective as an actual user of this work. I started rvt-rs because this part of the AEC ecosystem seemed underserved, but I don’t want to assume that the library’s current API, tooling, documentation, or priorities match real-world workflows. If you’re willing, I’d love to understand what your team is building, which Revit releases and file types matter most, where rvt-rs created friction, and which features, outputs, integrations, or compatibility improvements would make it more useful. I’m actively looking for that feedback and would be glad to put engineering effort into the improvements your workflow genuinely needs. If your team has any representative files it is fully authorized and comfortable sharing—publicly as fixtures, privately for research, or only through locally run probes—that corpus and its known expected results would be extraordinarily valuable, with absolutely no expectation to share confidential or customer material. Your clean-room, public-file approach is aligned with the project’s Apache-2.0 contribution requirements. We can keep the technical record public in this discussion and linked issues, unless anything is security-sensitive or cannot be redistributed. Thank you again—not only for the findings, but for approaching the project with such care. I’m excited to learn more about your work and to help turn these discoveries into improvements for the wider community. Best, |
|
Hi Griffin,
Nice to hear from you! I'll start sending you the details tomorrow, and I can already tell you that I'm an architect who gets annoyed from time to time that suppliers of building equipment sometimes only offer Revit families — and we don't use Revit. On the other hand, I did some research on design automation 20 years ago and know the current AEC software landscape quite well. I've also been using AI since 2019 (first image generation, now LLMs), and in June something changed: Claude Fable was the first LLM that could understand geometry (by now also Opus 5 / Sonnet 5, to some extent). So I thought it was worth a try to see whether they could decode Revit files if I gave them matching IFCs. They could — but the crucial input (those CRCs) came from Kimi K3.
In the end I was able to extract the geometry I needed into Rhino. New times ahead ;-)
Talk to you soon,
Steffen
… DrunkOnJava ***@***.***> hat am 29.08.2026 20:54 MESZ geschrieben:
Hi Steffen,
First, apologies for the delayed reply—I only just saw your message. Thank you for reaching out, and for the extraordinarily thoughtful work behind it. This is the first substantive outside contribution to rvt-rs, and it means a great deal to hear that the reconnaissance document has been useful to another team building in this space.
Everything you described is highly relevant, especially the checksum-page decompression finding and its potential for silent corruption on larger streams. I would be very glad to dig into all six findings with you.
Please do not feel that you need to turn everything into polished issues, probes, tests, and documentation before sharing it. If you send the full write-ups, existing scripts, reproducible artifacts, sample provenance, or even rough research notes that you already have and are able to share, I’m happy to take on the repository-side work: independently reproducing the results, organizing and opening the tracking issues, implementing fixes, writing regression tests and probes, and updating the reconnaissance documentation. I’ll make sure the issues and resulting work clearly credit you and your team for the discoveries.
If you would enjoy preparing the focused container-layer pull request for the decompression issue, I would be excited to review it—but that is entirely optional. I’m equally happy to implement it here based on your evidence. I’ll begin investigating the decompression finding now using the details you’ve already shared. Whenever it’s convenient—now or later—please feel free to send anything else you already have, even rough notes, and I’ll incorporate it into the work from there.
I would also really value your perspective as an actual user of this work. I started rvt-rs because this part of the AEC ecosystem seemed underserved, but I don’t want to assume that the library’s current API, tooling, documentation, or priorities match real-world workflows. If you’re willing, I’d love to understand what your team is building, which Revit releases and file types matter most, where rvt-rs created friction, and which features, outputs, integrations, or compatibility improvements would make it more useful. I’m actively looking for that feedback and would be glad to put engineering effort into the improvements your workflow genuinely needs.
Your clean-room, public-file approach is aligned with the project’s Apache-2.0 contribution requirements. We can keep the technical record public in this discussion and linked issues, unless anything is security-sensitive or cannot be redistributed.
Thank you again—not only for the findings, but for approaching the project with such care. I’m excited to learn more about your work and to help turn these discoveries into improvements for the wider community.
Best,
Griffin
—
Reply to this email directly, view it on GitHub #112?email_source=notifications&email_token=CMFEVHVL4LFQUAXOGXHLJV35MMRHVA5CNFSNUABIM5UWIORPF5TWS5BNNB2WEL2ENFZWG5LTONUW63SDN5WW2ZLOOQXTCOBSGAYTCMJSUZZGKYLTN5XKMYLVORUG64VFMV3GK3TUVRTG633UMVZF6Y3MNFRWW#discussioncomment-18201112, or unsubscribe https://github.com/notifications/unsubscribe-auth/CMFEVHUDFXZUNBMOCB7PLS35MMRHVAVCNFSNUABJKJSXA33TNF2G64TZHMYTEMJVGE4TAMBSGQ5UI2LTMN2XG43JN5XDWMJQGY3DANBRHGQXMAQ.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS https://github.com/notifications/mobile/ios/CMFEVHSZHSC4TSKHZHWTFBT5MMRHVA5CNFSNUABIM5UWIORPF5TWS5BNNB2WEL2ENFZWG5LTONUW63SDN5WW2ZLOOQXTCOBSGAYTCMJSUZZGKYLTN5XKMYLVORUG64VFMV3GK3TUVJTG633UMVZF62LPOM and Android https://github.com/notifications/mobile/android/CMFEVHTUA7VCP2TSM2LYPP35MMRHVA5CNFSNUABIM5UWIORPF5TWS5BNNB2WEL2ENFZWG5LTONUW63SDN5WW2ZLOOQXTCOBSGAYTCMJSUZZGKYLTN5XKMYLVORUG64VFMV3GK3TUVZTG633UMVZF6YLOMRZG62LE. Download it today!
You are receiving this because you authored the thread.Message ID: ***@***.***>
|
|
slik_rvt_scripts_260902.zip Hi Griffin, you asked for our raw material rather than polished issues — here it is. Attached/below is a consolidated English digest of all six findings (F1–F6), with byte offsets, evidence, per-claim confidence marks, and — deliberately — a "Retractions" section: two claims we made while our own dump was still silently corrupted, plus one broken heuristic of ours, so nobody chases those ghosts. Our Python reference scripts (decompressor, schema parser, parameter reader, form-geometry decoders) are included; consider them Apache-2.0, use them freely as evidence or test references. The two 2014 sample files are manufacturer-published (Stertil BIM library); we won't redistribute them, but the digest carries their SHA-256 hashes for provenance, and they are publicly downloadable. On the container-layer PR: please go ahead and implement it on your side — you'll be faster in your own codebase, and honestly our team's Rust is not our strong suit. What we can genuinely contribute is verification: we'll run your stream-evidence harness over our 2014 corpus and post the JSON reports, and we can re-run our full geometry pipeline against any fix candidate — our gzip-trailer and catalog-value oracles make regressions visible within seconds. Releases that matter to us. Both ends, unfortunately: manufacturer libraries lag years behind (2014–2020 .rfa is the norm, which is why the 2014 layouts in our digest matter), while consultant .rvt files are current (2021–2026). Where rvt-rs created friction. The decompression issue (now #151) — silent, and it poisoned weeks of our early analysis. We'll keep everything in this discussion public; nothing in the digest is sensitive. Looking forward to seeing what you build from it — and we'll happily test every step against our corpus. Best, Steffen |
|
Hi, Notes from a parallel effort, with answers to a few of your open issuesWe have been reverse engineering the same format from the other side for a Caveat before the details: our corpus is Revit 2024, 2025 and 2026, and most of First: thank you for F1, it was a live bug in our reader@STE1200, your checksum-page finding cost us an evening and was worth every Measured on our corpus, the same stream inflated raw against page-stripped:
Zero failures after the strip in all three. That is the self-check that confirms Why we never saw it: we split the stream at the gzip magics and inflate each That matters to us beyond the missing bytes. Our wall reconstruction is exact on The sentence we will be quoting internally for a while is yours: "Ran without Two things in your digest we did not haveF2, ElemTable as an ownership tree. This is the one we should have found and F6, the curve records. We read sketch lines from the record bounding box, Our own caveat applies in both directions: your offsets are from a 2014 family, #238, the wall join decision does have a carrier: the record bounding boxYou write that "Revit's per-pair join decision (allow/disallow join, butt vs The bounding box in a wall record is join resolved, but only upward. It is the
The loser's cutback is not in the box. That asymmetry is the signal. A wall whose Amounts, measured:
That gives you the disqualifying predicate you asked for. Your 31 over trimmed Measured on a purpose built test file with Revit API ground truth and on #223, +0x46 and +0x4a are flags, not a schema class joinIn our corpus the u32 at +0x46 is a flag word, and we have attributed its low two
+0x4a we have not attributed. If that holds on your records, the correlation with class you are seeing is Honest scope: we measured these on form records inside family definitions in 2026 #228, the reference listsWe see the same structure and read it as several lists rather than one. Two
#88, compound layer thicknesses are fully decodedThe layer list is 40 bytes each, with a leading 0x01 from the second layer onward. The index field One trap that cost us a release: the f64 sitting at the block entry is layer one Verified against the Autodesk sample: "Exterior - Brick on Mtl. Stud" comes out #95, curtain walls: the grid is in the fileGrid lines are their own records under CurtainGridsWall (-2000321), class 1028, Two things follow that are worth more than the grid itself:
That reproduces all 48 panels of the sample project, 40 of them within 1 percent #90 and #92, two results that save timeRoom area and volume are not persisted. We checked three ways: no numeric Ceilings are nearly free. On a large public sample, 50 of 67 ceilings match The record envelope, since it is your stated blockerFor files written by Revit 2024 and newer: Scanning for the marker at +0x0c and validating against the length field finds The category is the documented BuiltInCategory enum, so typing records does not The n x 22 block declares which parameters are set, not their values. It is Marker to Revit versionRead from BasicFileInfo and correlated across 253 files: Your 2014 family reads 0x49D, which drops cleanly between our 2013 and 2017 The break is between 2023 and 2024. From 2024 on you get the layout above. 2023 Parameter valuesValue blocks are framed as
Slot ids are constant only inside one Revit version. 2024 and 2026 disagree. Sketches and solids, for #156The kind of a solid is not in a class number. It follows from how many sketches A sketch line is a record whose bounding box is the line, same as the curtain grid One more negative resultFamily geometry of loaded families is usually not in the file as resolvable Where we areWe are a small BIM consultancy in Austria. We built this because we needed to You can throw a file at it yourself here: https://hirn.consulting/rvtreader The geometry side is work in progress and we will not oversell it. Walls are Tell us what shape of contribution is useful: a spec document, a reference This is just the start of it, let's crack the matrix together and end information |
|
Hi Jakob, hi Steffen, Thank you both, and sorry for the silence on this thread. Jakob's notes and Steffen's cross-measurement on three more files are the kind of independent check this project needs. Several of them landed on issues we had marked as having no identified carrier, and three are now merged, each credited to you in the issue, the report and the changelog. Merged since your posts, measured on our fixtures (Core Interior 2024, the four MIT RE1 models 2025, Autodesk Snowdon Towers 2024 locally):
Still open:
Two questions:
Thank you for the scripts and the digest; we are working through them. A 2019 to 2023 file either of you can share would be very valuable, since that range is where neither of us has an oracle. Best, |
|
Hi Griffin, here are the Einhoven vectors you asked for, plus the same for 2024_Core_Interior since both sit in the same MIT repo (fetched from origin today, hashes in the README, nothing redistributed). slik_rvt_vectors_magnetar_260928.zip Marker off the schema, two more rows. Einhoven: BasicFileInfo says Format 2023 (Build 20230828_1515), ElementHeader tag 0x576. Core Interior: Format 2024 (Build 20230509_0315), tag 0x59F. Both equal your table and both are the u16 record marker of the file. Header records chain through the length field at 99.77 % in both files (4,386 records on Einhoven, 42,319 on Core Interior). Einhoven uses the pre-2024 envelope ([u32 id][u32 len][u16 marker][u16 n], 12-byte head); Core Interior the 2024+ one. #152, your two open points, measured on your own files.
So the frame rule is now measured on 2014, 2023, 2024 and 2026; I'd expect 2015–2022 to follow, since the 28-byte layout with the 19-byte tail is unchanged from 2014 to 2023. Vectors. element_header records with id, marker, category, flags, m_classDef resolved through the file's own schema, and the box: three SWall plus one FamilyInstance on Einhoven, three SWall plus one Floor on Core Interior, and in the ElemTable JSON six further SWall records of Core Interior with distinct length/thickness (5,867 × 152 up to 41,783 × 152 mm, one 16,612 × 152 × 9,449) with their full bytes. No IFC oracle here: the 20 KB 2024_Core_Interior.ifc in the repo carries no IfcWall. One label to check. Our BIMcollab STR project reports "Autodesk Revit Architecture 2015 (Build 20141119_0715)" in BasicFileInfo and carries tag 0x4B1; your table lists 0x4B1 under 2016 for a family. One of the two labels is off by a year — if your 2016 family was saved by a 2016 build, the tag would be shared across the two releases, which would be worth knowing before #421 relies on it. Best, Steffen |
|
Hi Griffin, thank you for measuring it, and for both corrections. Both hold on our side too. The repeated ids were ours. Our header reader is a scanner: it takes every position that carries the ElementHeader tag and has a plausible size, and it did not check that the record sits in a run. Walking the runs (a record whose end is the next record's start) on fresh dumps: Einhoven: 4,386 candidates, 4,381 of them in 5 runs (2,520 · 657 · 556 · 424 · 224). That is your 4,376 plus the last record of each run your 2023 walk loses, and our 2,520 against your 2,519 for the leading chain. The other 5 candidates lie outside every run and are false hits. On your question about the tag outside a record, from these two files only (we have no RE1 models): the 49 false hits on Core Interior fall into three groups. Four lie inside the payload of real records in a run (three in two GeoLocation records, one in a GeoSite record, at 5.51 MB). Forty-two lie in long stretches with no records at all between 48.4 and 76.7 MB, as six positions that repeat seven times with the same lengths (1,456 · 753 · 410 · 420 · 708 · 494 bytes), surrounded by what reads as float64 data: seven copies of one structured block. The last three (two overlapping at 34.1 MB, one at 77.3 MB) we have not looked at. It may be worth checking whether RE1 Architecture's 1,707 also come in repeated groups. We have not identified the block. We will drop the declared/undeclared field idea and, if a field helps, mark whether a record lies in the leading chain, as you suggest. Best, Steffen |
Uh oh!
There was an error while loading. Please reload this page.
Hi,
we are building tooling to read Revit files without a Revit installation, and rvt-rs — especially your reconnaissance document — has been our starting point and by far the most useful public resource. Thank you for putting it out there!
Over the past days we did our own reverse-engineering pass, mainly on a Revit 2014 manufacturer family (.rfa) plus a 2026 project file, with hard oracles (gzip trailers, manufacturer type catalogs, exact f64 bit patterns). We ended up with a set of findings that we believe close several of your open items, and one that corrects a layer your docs mark as complete. Before filing issues, I wanted to check with you directly — you haven't had third-party contributions yet, and I'd rather ask how you want this than flood your tracker.
What we have, in decreasing order of impact:
Decompression bug (silent corruption). Revit streams are checksum-paged: every full 65249-byte stored page = 64896 bytes of payload + 353 bytes of checksum. The tails must be stripped before inflating; the bitstream itself is standard RFC 1951. Without the strip, inflate terminates cleanly but drifts after the first page boundary — on our file, Formats/Latest silently loses ~48% of the schema. Verified against per-chunk gzip trailers (209/209 members, two files) and independently consistent with ahzs645/reviter's constants. This affects rvt-rs on any stream beyond ~190 KB.
Global/ElemTable body decoded: it is an ownership tree (2014: 28-byte records, owner as trailing u32; 2026: 40-byte/u64 variant). Your docs list the body as "partial".
Element record framing: ElementHeader records are locatable via a marker; the element id sits at a fixed offset before it, the element's class tag at a fixed offset after it. That makes ~63% of records immediately class-resolvable — likely useful for your CLASS-xx decoder issues.
Formats/Latest full parse on 2014 (3619 classes, no abort), with two small grammar fixes, plus evidence on how the real serialization tag is assigned. This one overlaps partly with your Q4 addendum.
Parameter store wire format (two record shapes, BuiltInParameter ids for extrusion/revolution, shared-parameter name resolution via PartAtom GUIDs) — and a practical trap: Revit computes feet as mm/25.4/12, which differs from mm/304.8 by 1 ulp, so bit-pattern searches must try both.
End-to-end geometry: sketch curve records → closed loops → extrusion/sweep/revolve parameters → solids. We rebuilt 85 of 86 extrusions of a real family in a CAD kernel from the raw streams.
Everything is clean-room black-box work on publicly available files — no decompilation, no NDA material — so Apache-2.0 contribution is no problem. Per your CONTRIBUTING.md we'd file each item as an issue with evidence, confidence and repro steps, and we can follow up with dated addenda for the reconnaissance doc plus Rust example probes and tests with synthetic fixtures. For item 1 we could also prepare a PR for the container layer if you'd take it.
Would that flow work for you, or do you prefer a different route? Happy to share the full write-ups directly as well.
Best regards, Steffen
All reactions