> For the complete documentation index, see [llms.txt](https://docs.openbrim.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.openbrim.org/release-notes/openbrim-release-notes/2026-platform-releases.md).

# 2026 Platform Releases

## **Unreleased**

**AI Agent & Automation API**

* **Open a Shared Revision Link:** `open_project` now takes a `revision` in every form a user actually holds one — a revision share link, a `.librevision` link, an app URL with `?snapshot=`, a `REV-…` id, or a bare revision number. Previously an agent handed a revision link could only strip the project id out of it and open the project's **current head**, answering `loaded:true` with nothing saying a revision had been asked for and dropped — so every later read described a different state than the one the user pointed at.
* **A Project Id That Does Not Resolve Now Fails:** Opening a project id belonging to another workspace reported success — an empty husk carrying the requested id compiles clean, and the health check corroborated it — so an agent could run an analysis against a model it never opened. Both calls now fail closed and name the tenant honestly, in agent mode as well as the normal one.
* **Object Creation Waits, and a Save Can Be Forced:** `ObjCreate` returned success before its library clone had finished, describing a tree that did not exist yet. It now awaits the create, and a new deterministic save action flushes the debounced autosave — previously a busy tab could still be holding a create when the agent reloaded, and nothing on the API could flush it.

**Finite Element Analysis**

* **Line Loads on Merged Shell Edges:** A shell whose corners were merged in from another object — integral-abutment backwall nodes welded into the deck end edge — was clipped using each node's own frame, so the shell sat roughly 90° tilted in clipping space and captured load lines belonging to its neighbours. Measured **+10–27%** on wind, snow-fence, glare-screen and barrier line loads on a real model. Clipping now runs in a frame-consistent node space.
* **Region Soil Springs Follow the Stage They Bear On:** A generated region spring left without an explicit spring group carried no activation group at all, and a stage's active set is built purely from groups — so the region was active in **no** stage. A staged mat read as soil-supported and solved as if the soil were never there, with no error anywhere. Springs now inherit the activation group of the elements they bear on, with the explicit group still available as an override.
* **Region Spring Filters Evaluate Per Node Again:** `FESpringArea` / `FESpringLine` use `Filter` as a per-node expression, but it was being evaluated **once** with the candidate node unbound and the result baked into a constant. An elevation-band filter therefore collapsed to a fixed answer and a staged backfill generated no springs at all.

**Modeling & Geometry**

* **Behavior change — the left-hand transverse alignment rule is removed.** The transverse hand rule is gone outright rather than defaulted away: `TransAlignRule`, the `?alignrule` query parameter and the rule argument on the whole alignment transform API no longer exist, so it is structurally impossible for two call sites to disagree about which hand applies. **The old fallback was Left, not Right** — a model whose ancestor chain carried no `TransAlignRule` resolved left-hand, which covers projects saved before the attribute was added to the templates. Those models now transform right-hand, i.e. they mirror across the alignment. Re-check any legacy model whose objects are placed off the alignment.
* **One Keyboard Undo, and a Section Editor That Redraws:** Ctrl+Z in the section editor undid **two** steps — a 2023 document listener in the editor and the app-wide one added in 2025 both popped the same stack on one keypress — and whatever it undid never appeared in the Active Shape Points sheet. One listener now, one gesture per undo step, and the sheet redraws.
* **Consistent Outward Mesh Winding:** Nothing in the geometry pipeline guaranteed a facet's orientation, and the renderer could not show the damage — it has no lighting and face culling is off — so the mix was invisible in the app and shipped intact to every consumer that does respect orientation. Measured on a live model, roughly half the object families were inside-out: deck, piles and girders back-facing, abutment stem and wingwalls front-facing. Every generated mesh now carries a consistent outward winding.
* **Cutout Scan No Longer Drops Walls or Hangs the Tab:** A loop counter shared between the extrusion sweep and the inner cutout scan dropped side-wall segments and left open shells, drew the border only on the first pass, and in one branch never advanced at all — an infinite loop and a hung tab.
* **Bulk Delete From the Workflow Tree:** A node's count badge now carries a trash icon that deletes everything the badge counts — a whole subtree for a group row, one type for a type row. It goes through the ordinary delete path, so it keeps the confirmation, the reference repair, one undo step and the recompile. Clearing a project down to a starting point no longer means deleting rows one at a time. Suppressed in the Generated and CAD views, where the badge counts compiled objects a delete would not reach.

**Section Analysis**

* **Behavior change — `sectionPerimeter` is the outer boundary.** The ParamML function summed every boundary ring, so a pipe, an HSS or a box cell answered inner + outer, while the section property calculation stored the exterior ring only, and the two disagreed on the same section. One definition now: the boundary reachable from outside — enclosed cutouts excluded, a cutout open to the outside counted as the exposed face it is, disjoint parts summed. Both ParamML engines resolve it through the same code, so a section can no longer answer two numbers. The function returns the stored Perimeter when the section carries a usable one, and a geometry edit clears that value so it is recomputed.

  **This moves results on hollow and box sections wherever the perimeter is read, not only for piles.** Through `OBPSectionProperty.PerimeterSection` it reaches the concrete, segmental, spliced, prestressed-I and post-tensioned box girder code checks, the pier, pier cap, pile cap and drilled shaft checks, and the concrete girder load rating — including AASHTO 5.7.2.5 torsion (`Tcr`), where the outer boundary is the correct definition and the previous value was too large. Also affected: drilled shaft side surface area `A_s`, column stirrup length and weight (so stirrup pay items and embodied carbon), and the pipe pile skin-friction springs in `OBPSoilCurveGenerator`. Verification boards carrying a hollow pier, box girder, HSS or pipe pile should be expected to move.

  **Still open for a decision:** creep and shrinkage take their notional size from the same perimeter. The inner face of a ventilated box cell is a drying surface, so the wetted perimeter — not the outer boundary — may be the right input there. This release does not change which one that calculation asks for; it is tracked separately.

**Import/Export**

* **CSiBridge Staged Construction Imports Faithfully:** A production `.b2k` could not be imported at all — 20 of its 168 links are zero-length (joint I equals joint J, ordinary for bearings), and building a rotation matrix from that geometry threw on the first one, aborting a 15.8 MB file with no per-row guard. Zero-length and unresolved-joint links now fall back to identity axes, which is SAP's own default. With the file readable, the staged-construction mapping was rebuilt: SAP never enumerates its built-in `ALL` group, so every "Add Structure ALL" added nothing and **four of ten staged cases came out empty**, including the final service condition every other case initialises from. Pour Concrete and Remove Forms were dropped in silence because the wet-concrete table they resolve through was never read, so the deck never entered the model; they now map to a weight-only state and then a stiffness-only one, keeping the locked-in non-composite dead load a staged pour exists to capture. Initial conditions are honoured, so a continuing case chains onto its parent instead of restarting from an empty structure, and durations and ages carry into stage days and element casting days.
* **LARSA Groups No Longer Name Spring Rows That Do Not Exist:** Group records referenced an index into the project's spring **object** list rather than a row in the exported springs block. A grouped two-node spring exported one real row plus a bogus id, and a grounded spring exported **only** the bogus id.

**Project & Library Management**

* **Copy and Replace a Project's Source Code:** Two new project-menu entries. **Copy Source Code** puts the serialized project on the clipboard; **Replace Project from Source Code…** takes a paste and replaces the open project with it, through the same path the Source panel's Update button and revision-revert already use. Moving a project between workspaces previously meant hand-selecting 10–50 MB of XML out of the Source panel.
* **Summary Report Export Discloses Its Cost:** Exporting a Summary Report starts one browser download per selected report, and nothing said how many files were about to land or how long it would take. The Save Report dialog now carries a live file count and time estimate, restated as the selection changes; past eight files it becomes a warning that names the consequences (download throttling, one viewer window per file) and gates Confirm behind an acknowledgement.

**Desktop App**

* **A Supported Electron, and Control Over Updates and Exports:** The desktop app moves from Electron 32 to **Electron 44**, closing twelve majors of unpatched Chromium. Auto-update was a hardcoded public GitHub feed on a six-hour timer — a guaranteed-failing request on any corporate network that blocks the release CDN. Two environment variables now cover the managed-fleet case: `OPENBRIM_DISABLE_AUTO_UPDATE=1` and `OPENBRIM_UPDATE_URL=<internal mirror>`; a malformed override leaves updates **off** for the run rather than silently reverting to the public feed. **Exports now prompt for a location** instead of being written silently to `Documents\OpenBrIM Exports` (agent exports keep their fixed, predictable path). The installer grows from \~82 MB to \~113 MB.
* **v1.0.30 Was Unbootable — Fixed:** The packaging file list is an **allowlist**, and a module the new export path requires was never added to it, so the packager silently dropped it and every installed client died in the main process before the first window. Nothing local would have caught it: the app runs from disk in development, where the file is present, and the installer builds successfully — the omission only surfaces when the packaged app boots. This is the second time the allowlist has shipped a broken installer, so the fix is not just the entry: a new packaging test walks the real require graph and asset references and fails when the allowlist does not cover something they reach. It runs first in the suite the release workflow already gates on.
* **Update Channel Repaired:** v1.0.30 also published twice, each time carrying a single artifact where a usable release needs three, because the packager uploads in parallel and every loser of that race failed to create the release. A release without its update manifest still becomes "Latest" and 404s every installed client's update check, so nobody could update — including away from it. Releases are now assembled as a verified draft and published only once complete.

**Documentation**

* **Barrier Load** documented in all ten bridge workflows, alongside the barrier **deck-edge offset** input.
* **Construction Moving Load DL/LL separation** documented — the three result cases, their combination-factor usage, the double-counting warning and the upgrade note for models that picked a per-position sub-stage directly. The four near-identical workflow pages are now thin wrappers around one shared include.
* **Pick-a-bearing rotation** documented across all eight workflows that carry bearings: you choose the bearing this one should face, and the rotation needed to aim a guided bearing at its neighbour on a curved bridge is computed and kept up to date.

## **v3.260826**

**Finite Element Analysis**

* **Erection-Stage Buckling:** The analysis capability behind erection-stability checks for steel I-girder bridges, in three pieces. A **geometric-nonlinearity tier** (`None` / `P-Delta` / `Large Displacement`) replaces the old on/off switch, matching SAP2000's control — the default is Large Displacement, so a case that never carried the parameter keeps today's behavior and only an explicit opt-down changes tier. **Staged corotational shells** carry a reference configuration per stage. And eigenvalue screening plus a nonlinear limit-load trace bracket the answer. This also fixes a pre-existing export mislabel: every large-displacement case was written to SAP at its *middle* level.
* **Region Soil Springs** *(new)*: `FESpringArea` / `FESpringLine` assign grounded springs over a **region** of finite elements — an `FEGroup` plus a `Filter`, the idiom `SurfaceLoad` and `TempLoad` already use — scaled by each node's tributary measure, instead of authoring one spring at a time. `FESoilLevelArea` / `FESoilLevelLine` add a depth profile interpolated at each node's own elevation, with a limiting pressure that makes the spring elastic-perfectly-plastic rather than an unbounded linear spring. Springs are generated at compile as real `FESpring` objects, so the nonlinear solver, stage activation, the `FESpring Forces` tables, the 3D view and the SAP / LARSA / Midas exporters all work unchanged. `FESpring` also gains an opt-in explicit axis.
* **Stiffness-Only Shell Thickness** *(new)*: `PropThStiff` is a per-element thickness the constitutive side uses and weight does not — a bending thickness distinct from the membrane one, an effective thickness for a stiffened panel smeared into a flat shell, a haunch carried by uniform elements. Self weight, mass, the drawn extrusion, tendon face offsets and the through-thickness thermal gradient all stay on the physical thickness. It now also reaches **meshed** surfaces and composite results, not only hand-authored shells; unset (0) is byte-identical to before.
* **Behavior change — a station-varying shell `Thickness` now actually varies.** The element-centre station was being passed as the *absent-parameter fallback* while the expression evaluated at **station 0**, so a haunched deck taper silently resolved uniformly across every element. Models carrying such an expression were getting one thickness where they asked for a varying one, and will now get the varying one.
* **Member End Releases via equalDOF Constraints** *(new, opt-in)*: a per-element **End Releases** method — `Penalty Spring` (the default, unchanged) or `equalDOF Constraint`. Fixed release directions are tied by equation elimination instead of a penalty stiffness, which is exact rather than approximate and conditions the matrix better. Releases at a node participating in a rigid diaphragm fall back to the penalty spring automatically.
* **Behavior change — the live-load variable axle actually moves.** The three trial positions computed for a wheel carrying an alternative longitudinal position were all evaluated at the same station, so the HL-93 truck's **14–30 ft variable axle spacing was pinned at 14 ft** and negative moment over interior supports was under-estimated. The spacing state is now a property of the vehicle, chosen independently for the min and max envelope, and mirrors with the vehicle when reversed. It ships on the US, PA and IDOT design-lane databases.
* **Temperature Load No Longer Aborts the Run on Springs:** A uniform temperature load scoped to "Superstructure and Substructure" swept springs into a path that cannot build a thermal vector for them, and the whole analysis died with a null-length error reported under the first stage. Springs are excluded (they carry no thermal strain); volumes in the target now raise a visible warning instead of being silently omitted.
* **A Report-Only Diagnostic No Longer Fails the Compile:** The far-merge report posted at error severity from inside the compile worker, which treats any error-styled progress message as a task failure — so a warning aborted the entire project compile and raised the generic error dialog. Three verification projects died this way on one build with nothing wrong in them.

**FEA Results & Display**

* **Influence Contours Show the Sign:** The contour used a linear scale over the raw range, so on a support-reaction surface running −0.077 to +1.022 the entire negative region rendered identically to zero — the Min trucks stood on apparently blank deck, which read as the Min row showing the Max row's truck. The min/max association was correct end to end; the picture was not. Also fixes stale vehicle placements being drawn after a change, and a pre-existing row-mapping bug.
* **Soil Springs Are Drawn, and Say What They Are:** The spring glyph was a flat four-vertex zigzag, black, identical for every behavior — and a flat squiggle vanishes edge-on, which for a mat of vertical soil springs is most of them. It is now a tapered 3D helix carrying a behavior marker at the free end: two plates across a gap for compression-only, an open hook for tension-only, a two-slope tick for a multilinear curve, with colour following the same classification. Grounded springs get the hatched ground symbol; two-node springs are drawn as a coil along the chord.
* **equalDOF Constraints Are Drawn:** `FEConstraintEqual` had no draw path, leaving equalDOF ties invisible in the FEA view and inspectable only through the Equal Constraints sheet. It now draws a line between separated joints, or a three-axis cross where master and slave are coincident (how member end releases are generated, and the case a line cannot show), with colour encoding the DOF pattern.

**Modeling & Geometry**

* **CAD-Style Selection Highlight:** Selecting an object in the 3D view used to mark everything **except** the selection — every other instance dropped to half opacity and all lines went black — so you read the selection by noticing what faded. The selected object now carries the cue, as Revit / Navisworks / Tekla do it: a blended face tint that keeps the object's own shading and form readable, a crease-edge silhouette plus a depth-disabled x-ray wash so an object buried under the deck is still findable, and a lighter hover pre-highlight showing what a click will select. FE elements are cued too.
* **The Alignment Centerline Is Pickable:** The centerline is drawn on top of the deck but the pick pass drew it depth-tested, so wherever it visibly crossed the deck it was the deck that answered the click — visible and unpickable at the same time. The on-top pass now runs for picking too, and a CAD-style 6 px hover aperture lets the one-pixel-wide line beat an exact hit.
* **Measure Distance Reads the Frame the Model Was Drawn In:** Picked points were converted in a frame the alignment is not in, so the Station/Offset readout came back shifted by the alignment's own placement. It was accidentally right only on the default alignment, and wrong on precisely what the panel's "Measure relative to:" selector exists to choose.
* **Vertical Clearance — Explicit Runs and Stored Results:** The check stops recomputing inside the graphics refresh. A sweep is now an explicit action, its answer is stored on the check, and a staleness signature says whether that answer is still about the model in front of you. Alignment-generated boundaries accept explicit stations, a terrain boundary uses the real triangulation outline, and scope resolves at any depth — an exclusion on a nested pier cap used to do nothing, silently. Snapping is separated from the measure tool, so picking region points no longer opens the measure panel. The solver also stopped being optimistic: it probed one candidate per triangle on the argument that the minimum sits at a vertex, which is false when the floor under a soffit rises and falls by feet.
* **A Zero Rebar Spacing No Longer Hangs the Compile:** Opening a model with a footing showing flexural reinforcement wedged the compile in the geometry pass and grew the heap until the tab died. It reads like a leak; it was an infinite loop — a zero spacing divided to infinity and the line-split loop was bounded by that value. Bad input now surfaces as an error naming the object.
* **Reserved Values Are Named on the Sheet:** A parameter that takes a free number *except* for one reserved magnitude — 0 meaning "As Modelled" or "Auto" — can now declare it (`[SENTINEL:As Modelled=0]`) instead of hiding it in the description, where the rendered column header stripped it out and nothing offered to set it.

**Import/Export**

* **DXF Seed File With Layer Mapping:** DXF export wrote layers named after the model's own CADD levels, so every exported drawing had to be re-layered by hand before it could be issued. A seed configuration now maps OBrIM level names onto a CAD standard's layer names, with optional colour, linetype and lineweight overrides — the AutoCAD counterpart of the existing MicroStation seed file. Uploading a `.dxf` seed is optional; when one is present its layer table is parsed and cached, so the target-layer list is instant and survives a reload.

**Reliability & Performance**

* **Six Enumerations Were Broken in the Production Build:** A non-const TypeScript enumeration emits a definition the minifier leaves alone while renaming every read of it, so the two halves refer to different names and every read returns `undefined` — invisible to the type-checker and to both development builds, present only in the shipped bundle. Confirmed against the live bundle: six were broken in production, covering CADD section-view line classification, the FEA surface output coordinate system and four others. All twelve remaining enumerations are converted.
* **Parallel Library Loading at Compile:** Project compilation loaded every library object strictly serially — one round trip and parse per object — which on a 193-object project meant minutes of loading per refresh. Library dependencies are now prefetched in parallel under a bounded budget, and local-library sessions cache the cloud copy instead of re-fetching it on every load.

**Project & Library Management**

* **Branch Overrides Update in Place:** A local-library branch override can be updated in place rather than re-created, and a stale override pair can be unlinked.

**Documentation**

* **WS Custom** — the user-supplied-pressure wind load, including the point readers are most likely to get wrong: the pressure entered is the **resultant** at the given attack angle and is resolved geometrically, and the AASHTO 3.8.1.2.3 skew table is deliberately *not* applied on top of it.
* **Link Slab** and **Link Slab Construction** workflow items, whose documentation links previously 404'd.

***

## **v3.260820**

**Finite Element Analysis**

* **Behavior change — stresses on a Combination were divided by the wrong section.** A combination forwarded *section properties* to the same factor-and-sum path as load effects, so on `1.25 DC + 1.5 DW + 1.75 LL` the section area became 4.5 × A and **every stress on every Combination read roughly 1/Σ(factor) of correct, unconservatively** — on the dominant read path for both line and surface stresses. Wind combinations shared the fault; construction stages had short-circuited it long ago. Section properties now come from a representative contributing leaf. In the same pass, **live-load line stresses were dropping both bending terms**, and every remaining read in the result-extraction audit was settled.
* **Nonlinear Buckling From an Imperfect Geometry:** Linear buckling and geometrically-nonlinear collapse both shipped, and nothing connected them — a mode shape could be computed and never applied, and a nonlinear run reported no collapse multiplier, so the imperfection-sensitive workflow could not be done and the linear bifurcation factor (an upper bound) was the only number available. `ImperfectionSet` displaces the model by a scaled mode shape before anything is assembled, written to the compiled project rather than the parametric source, and the limit-load trace walks the arc-length path past the applied load to its peak. Nineteen verification objects cover it.
* **Per-Step Load Multipliers for Pushover:** New `getPushoverLambda()` returns the converged load multiplier of each pushover step. Results persisted by older builds return empty for displacement-controlled cases rather than silently reporting the control displacement as λ — re-run the analysis to populate them.
* **Influence-Surface Truncation That States an Error Bound:** The live-load coefficient tolerance was one absolute magnitude applied to every component, so a slot whose entire influence peak is small had values discarded that amounted to a 10% error on that element — under a setting whose stated purpose is not to move the answer. It is now relative to that slot's own running peak, with only a noise floor beneath it, and the sweep's cost is roughly halved. Live-load result writes are durable now, with a coefficient union cache.
* **Vertical Clearance** *(new)*: `ClearanceZone` defines the region a clearance is measured over, and `VerticalClearanceCheck` finds the answer over it. Both use the standard object-reference cell menu, which was the root cause of every reported pick problem. Adds a general mechanism for read-only computed columns on a core object — declaring them as parameters gave one engineering result two values, since the declared default of 0 was what every schema read, `Verify` and sync diff saw while the sheet showed the solved number.
* **The Weight-Only Construction Ghost Is a Model-View Idea:** Elements carried by a stiffness-free structure state render dimmed to say "not constructed yet, but its weight is already on the structure". That reads correctly in the model and loading views; in a **result** view it asserts something false — the element has no stiffness, so it painted as the legend's zero colour in force and stress modes and hung off the deflected shape undeformed. Reported as ghost deck elements that vanish at the stage where they gain stiffness.
* **Meshing:** Target-merged nodes stay aligned to the target surface.
* **Rebar-Only Inertia for Native Circle Sections:** A section whose concrete is authored as a native circle was never stripped when computing the reinforcement-only inertia, so it returned the gross concrete-plus-rebar value. That feeds the AASHTO 5.6.4.3 flexural stiffness and therefore the slenderness moment magnifier, so an authored-circle column and a section-from-3D column covering the same geometry produced different interaction and shear ratios.
* **A Model That Solves Nothing Now Says So:** A run in which every construction stage erected nothing and each solved zero degrees of freedom completed with `analyzed:true`, no error, and \~6,000 elements of zeros — indistinguishable from a real result. Empty solves and empty result tables are now diagnosed rather than reported as success.

**FEA Results & Display**

* **Live-Load Result Tables No Longer Exhaust Memory:** Reading one live-load cell walks every coefficient sub-case of the case (2,436 on a real bridge), and every one of those analysis outputs was pinned in memory — so copying a live-load results table grew the heap until the tab died. The raw-output cache, the intermediate live-load cache and the number of rows and distinct composites computing at once are now all bounded, the raw outputs are released once a compute finishes, and result values are unchanged throughout. **Escape now cancels for real:** it stops the sweeps in flight as well as the queued rows, on an ordinary sheet draw as well as during a copy, and says which of the two it did. Cancelled rows load again when you scroll or click in the sheet. A row whose computation *fails* now reads **error** rather than sitting on **loading** forever.
* **Behavior change — displayed deflections and reactions on skewed and curved models.** Result tables and the 3D view now request results in the frame they actually draw and label. Previously some of these reads asked for the node-local frame while presenting the numbers as global, so on a skewed or curved model the displayed value was a component of the right vector in the wrong axes. **Displacements changed by up to 92% on a measured skewed model**; reactions ride the same path and change for the same reason. Nothing about the analysis changed — the same solve now reports in the frame the column heading claims. Re-read any deflection or reaction values recorded from a skewed or curved model against this release before reusing them.
* **Known limitation — a stress point with no section state reads 0.00.** `FELine` normal stresses divided by a zero section property, producing `±Infinity` across the Max/Min and point columns of a live-load case (and in the 3D stress contour). The division is now guarded, so those cells read **0.00**. Where the zero came from a genuinely unavailable section state, that is a quiet zero in place of a loud infinity: treat `0.00` in a stress-point column as "not computed" and check the section is resolved for that element.
* **Several Analysis Cases in One Results Sheet:** The results spreadsheet was bound to exactly one case, so comparing a node or element across construction stages meant changing the dropdown N times and copying by hand. Cases can now be ticked — from the FEA cases tree or the case dropdown — and their rows stack into one table, each named by the "Analysis Case" column every result table already carries, with the sheet's own sort and filter narrowing it.
* **Support Reactions Are a Force View Type:** Reaction and spring-force arrows move out of a collapsed disclosure on the Deflection panel and become their own member of the Force family, chosen alongside Line / Surface / Composite — and the default type when Force is opened from outside the force and stress families.
* **"Select All Elements" on an Empty Result View:** Every result mode but one opens scoped to the selection, so the empty-result card is the first thing a user meets in a result view — and its button opened the element **picker**. What the user wants from an empty result view is to *see the result*, so the button now widens the scope to All and redraws. The panel's Elements row then reads "All elements", which both discloses what the button did and undoes it.
* **"Draw On" for the Composite Result Ribbon:** The composite ribbon has always been plotted on the section's centre of gravity, which is where the resultant acts but is recomputed at every station from the elements engaged there — so the ribbon jogs sideways wherever that set changes: a deck engaging, a cover plate starting, a stage boundary. A new setting plots it on the composite's own path line instead. **The values are identical either way; only where they are drawn changes**, and the default is unchanged.
* **Hiding One Element No Longer Hides the Whole Mesh:** Under "Hide 3D" in a result view, hiding one more shell element made every element disappear — an ordinary hide cleared the latch that suspends the derived-visibility sweep while the mode's own blanket hide was still in place.
* **The Case / Stage Menu Opens at the Active Option:** On a staged model with more stages than fit the list box, the menu opened on the first stages with the highlighted active one below the fold — which reads as if no stage is selected and loses your place in the stage sequence. It now scrolls to the active option, and arrow keys step a cursor through the list.
* **The Analysis Window Says Where It Is:** The progress percentage is computed per solver loop, so it restarts several times in one run and never says how much is left — and when a run stopped, the one fact that would let a user fix it themselves (which stage) lived in a log line a support screenshot usually crops out. A strip now carries elapsed wall time and "construction stage k of n / analysis case k of n" with the stage name, and it survives the end of the run: a run that failed or was cancelled relabels to "Stopped at stage" and stays on screen.

**Modeling & Geometry**

* **CAD View Rewrite:** An AutoCAD-quality 2D drawing subsystem, audited against the rest of the app. The CAD view also gets its compile bar back — it had been hidden outright to avoid colliding with the drawing ruler, which took the 3D / FEM / DETAILING toggles away from a view whose drawings are generated from the model those toggles control — and the canvas is flush at the top of the page, so the ruler runs along it and the drawing gets the full height.
* **Federated Child Objects Behave as Regular Objects:** A federated model's 3D used to arrive as one merged mesh with one identity — an un-queryable blob in the consuming model. Each source object's read-only and quantity parameters now travel with the mesh, a pick resolves back to the object it hit, and the reference states what it exports. Nothing transferred becomes a parameter or a compile input in the consumer.
* **Rotate About What You Are Looking At:** "Set Rotation Center" was a zoom-to-extents in disguise — the pivot was written in exactly one place, as a whole object's bounding-box centre, so it could not move without re-framing and was invisible. The pivot is now a first-class thing that can be set *without* moving the image, and the control no longer lives in the transient pick info-bar, where it did not exist until you had already selected something.
* **Color & Opacity Menu Rebuilt:** The menu rendered *underneath* the 3D overlays and was visually inconsistent with the other settings popovers. Fixing the stacking exposed a series of lifecycle and persistence defects around it — the bar being destroyed out from under the menu by the next pick or by the pane's mouse-leave, and per-property commits — all of which are fixed with it.
* **Opacity Resolution Was Exponential:** The inherited-opacity lookup walked its parent chain twice per level, making it exponential in the distance to the nearest ancestor carrying an opacity — which is exactly why the cost appeared only *after* a user changed an opacity, and only on detailed models where the chain is deepest. It is read once per rendered primitive.
* **Sections With Their Own Material Inputs:** A section that declares its own `Material`-typed inputs — a concrete-filled steel pipe's separate steel and concrete materials — can now be imported, with one project-material dropdown per material parameter instead of a single section-wide one.
* **LandXML Kinks Import Without Asking:** A LandXML import stopped on a "Kinked Alignments Detected" prompt whenever a segment's declared direction disagreed with the tangent-continuous chain. The directions the file declares are what the import should produce, every time; the dialog is gone and each segment's direction is written unconditionally.
* **An Import's Files Stay With the Project:** An imported terrain surface survived a refresh only in the browser it was imported in, because its points and triangles lived only in local storage and the one path that kept the source LandXML did so through a callback that never fired — so the rebuild-from-source fallback could not run for anyone, and the miss failed in silence: no dialog, no empty state, no terrain. Every import now stores what it consumed and what it produced.
* **Never Show a Background You Cannot Trust:** Three ways the background layers lied to the user, reported together. **Setting the project local origin crashed in the production build only**, because the map library had no type declarations for the minifier to respect. **No imagery is an answer, not a failure** — the provider publishes no satellite tiles above about 72° N, and that was being collapsed into a server error the client could not tell from an expired session, so it minted a fresh session once per dead tile every 20 seconds. And where there is genuinely no background, the app now says why.
* **Coordinate Systems Travel as Objects:** Assigning a project's coordinate system copied only its *name*, so a child project synced from a master named a coordinate system that was nowhere in it — its terrain and alignments then drew in completely the wrong place, with no error. The adoption path is hardened too: it compares the real projection rather than a raw parameter that zone-authored systems never set (two look-alikes in different zones used to compare equal and place the model wrong), and it no longer keeps a name that collides with a non-coordinate-system object.
* **Geometric Criteria in Every Bridge Workflow:** Clearance Zone and Vertical Clearance Check are added to all ten bridge workflows, in the slot the GIS group vacated. GIS is dissolved rather than renamed: the basemap became a view setting, and the geographic coordinate system is a project-level singleton edited from the Project Site panel.
* **Varying Sections Vary Again:** A station-dependent section built from a list of `[Section, Station, Variation]` entries read each listed section with no execution context, so a section carrying its own station-dependent parameters contributed identical numbers at every station and the built expression came out constant.
* **Indexed Object References Resolve All the Way Down:** An identifier such as `sec_list[0][0]` resolved as `sec_list[0]` — invisible for a plain number, fatal for an object-reference parameter, where the path must reach the object itself.
* **`volumesideareas` on a Vertically Extruded Solid:** The horizontal-face modes returned zero, because the end caps — which for a vertical extrusion *are* the horizontal faces a caller wants, a column's top and bottom — were never counted.
* **Generated Children Can Keep a Live Expression:** Generation baked every generated parameter to its evaluated value, so a generated child could not reference a generated sibling — bearing loads mapped to result-extraction outputs froze at 0. A child can now list parameter names that keep their authored expressions, with sibling references rewritten to the final generated names.
* **Highway Project Master:** A new workflow and template in which one project owns the corridor and the rest reference it, with its own gallery card.

**Spreadsheets & Reporting**

* **Filter a Numeric Column by Many Values and Many Conditions:** A numeric filter could express exactly one condition against one number, and only one filter record was kept per column — so picking N specific stations out of a results table meant filtering N times, one value per pass. The numeric branch now has the multi-select value list the text branch already had (searchable, and accepting a column of numbers pasted straight out of Excel), and conditions are repeatable, combining with "all" by default so two conditions on one column read as a range.
* **Input Display Units for Spreadsheets, and One Project Settings Dialog:** Unit-system and decimal-precision settings are consolidated into a single project settings dialog, and applying it refreshes the dependent UI without a reload.
* **Reference Cells Show the Object, Not `0.0000`:** Every object-reference column in a parameter-interface drill-in sheet — "Applied Elements" on the AASHTO wind load, and every column shaped like it — rendered `0.0000` where the referenced object's name belongs.
* **Name a Version:** Every accepted save already writes a full snapshot, so the Revisions list was dozens of indistinguishable autosaves and users copied whole projects to keep a version. A version can now be given a name — either riding along with a forced save, so a collaborator's save cannot land in between, or applied afterwards to a stored snapshot — and named versions sit in their own auto-expanded section at the top of the panel. (The "Named versions only" filter that briefly accompanied this was removed: it only ever hid context, and the one moment it drew the eye was when it read "(0)".)

**Import/Export**

* **3D DXF Export Landed at the Wrong Place and Scale:** An exported 3D DXF opened in Civil 3D **12× too large** and nowhere near the survey data, while DGN export of the same model was correct. Two independent defects: the file declared no units at all while vertices stayed in raw internal units, and the export took the live viewport's sets, which are rendered relative to the project origin rather than in survey coordinates.
* **Georeferenced IFC Exports:** The projected CRS and map conversion were already written, but in a state no consumer could use — the model's offset was baked into the representation context while the map conversion was written all-zero. Readers that ignored the offset got no georeferencing at all; readers that honoured it double-counted. The world coordinate system is now the identity and the offset lives in the map conversion, with eastings, northings and scale derived from the real projection.
* **The Agent Surface Exports an IFC With Objects in It:** `Export("ifc")` wrote a header-only file of about 1.1 KB whatever the model held, while the same export from the Import/Export dialog came out whole — the two callers disagreed on one schema string, and passing it dropped every export node, including the one the hierarchy is rooted on.
* **Import Tools Name Their Source:** Section, object and material imports resolved a preset by **name alone**, taking the first library database that happened to contain it — and a preset name identifies nothing on its own ("FiveCells" is defined by \~20 box-girder databases, twice within one of them). An import could report success, compile clean and validate green having cloned a different object with different dimensions. The database and category now narrow the set, and an ambiguous name is refused with the candidates listed rather than silently picked.

**AI Agent & Automation API**

* **Result Shaping Pushed Into the Extraction:** `get_results` gains element filtering (glob-capable), component selection, sort-with-top-N and summary modes — applied **during** extraction rather than to its output, so unasked-for rows are never computed.
* **Read Honesty and Silent Acceptance:** The health check gains a real compile channel (state, stalled, terminal with a reason, and advice), a terminal compile forces an unhealthy verdict, and the FE build rejects stray keys instead of silently accepting them and reporting success. Response envelopes are de-duplicated, with a response-size cap behind them.
* **Desktop Shell:** Find-in-page, build-mismatch recovery, and per-window agents with window targeting.

**Reliability & Performance**

* **Project Open No Longer Freezes After the Compile:** The main thread froze for about 1.2 s right after a compile finished, on project **open** only — which is why it hid from every recompile profile. The validation pass was rebuilding each library proxy's parameter surface once **per instance** although it depends only on the library class and version: on a large model that is roughly 43× more work than the model contains, plus one object construction per instance purely to read a constant string, each of which retired every cached lookup in the program.
* **Front-End Memory Down 27.5%:** A deserialization pass built every parameter expression separately, so a large benchmark model held 2,587,133 separate expression strings for only 184,611 distinct texts. Duplicate expressions are now pooled for the duration of a load pass and the pool is dropped afterwards, so only the sharing survives and nothing outside a load is touched.
* **FE Drawing Scales With Batches, Not Elements:** Every FE element had its own graphics object, so a large model paid one GL bind plus several draw calls **per element per frame**, and up to three times per interaction — on a 100,000-element mesh, roughly a million GL calls a frame, which is why an FE model was slow to orbit. Elements now share batched objects while each keeps its own identity, so pick, hover, show/hide and the spreadsheet link resolve exactly what they resolved before.
* **Merge-Nearest Candidates Are Indexed:** The nearest-merge lookup rescanned every group and every member for each node carrying a merge target, discarding all but the handful sharing the requested id.
* **Library Updates Stop Duplicating the Base:** A library update cloned every base object once **per** `Extends` entry, so with N extends the first base was cloned N times. Measured on a real project, one object went from 213 to 74 direct children and the project shed about 167,000 characters.

**Security & Accounts**

* **Deploy Dispatch Is Admin-Only:** Manual deploy and provisioning workflows were authorized by repository push access alone. Each now resolves the actor's repository role live and proceeds only for an admin, checking both the dispatcher and the re-run triggerer so a second account cannot replay an admin's deploy.

**Documentation**

* New template documentation for the **custom girder**, **concrete segmental**, **BEBO precast arch**, **retaining wall** and **FEA library** workflows, from an audit of documentation links across 14 workflows and 1,801 workflow items.
* Early Access library release notes restored, covering the box-girder hinge joint, integral-bent material, pile capacity check, and vertical clearance / geometric criteria objects.

***

## **v3.260808**

**Modeling & Geometry**

* **Photorealistic 3D Terrain** *(new)*: OGC 3D Tiles as a background layer. The basemap was previously a model object with a fixed centre, a fixed footprint and one fixed zoom, baked into textured quads on every redraw — zoom in and the imagery turned to mush; zoom out and we had already paid for imagery nobody could see. It is now a view setting under the 3D cog, with show/hide, imagery type and elevation: location comes from the project's own origin and coordinate system, and extent and resolution come from the camera, the way every map application works. Tiles stream at the resolution the viewport needs, the coarser level stays underneath while the finer one loads, and what leaves the view is disposed.
* **A Terrain Surface That Looks Like Terrain:** An imported LandXML surface drew as a flat neon-green sheet under a black mat of wireframe. Three causes: the engine has no lighting, so the wireframe was the only thing in the picture saying the ground was not a sheet; the elevation ramp was a green-to-red hazard scale driven by the raw minimum and maximum over every point, so one outlier flattened the whole site onto the green end; and the wireframe was three line primitives per triangle, on by default. Shape cues are now baked into the vertex colours, and the surface reports what it is worth.
* **Read the Ground at the Cut Plane:** With a section active, the hover probe answered for the whole surface, including ground the plane had cut away — a number for something invisible, which is worse than no number. Clipped hits are now skipped **inside** the ray search, so the answer is the nearest *visible* hit, and the cut boundary is drawn, so a reading taken near it need not be taken on trust.

***

## **v3.260807**

**Finite Element Analysis**

* **Six Engine Defects Found by Verification-Suite Measurement:** Three of these were shipping **wrong answers**, not merely slow ones, and none had a test that could see it. A spurious rotation was applied to every solid element's stiffness — up to 19% on a constant-stress patch test, and removing it took the twisted-beam benchmark from 0/4 to 4/4; it cancelled on rectangular grids and under rigid-body motion, which is exactly why nothing caught it. Trilinear hexahedra shear-locked, 10.8× and 39.7× too stiff in bending, now corrected with incompatible bending modes and static condensation. The rest cover tapered thermal loading, shell geometric stiffness, corotated prestress, and stalled solves.
* **Case-Level Geometric Nonlinearity Switch:** Nonlinear static analysis was unconditionally large-displacement, which is not what every published reference is. A case-level switch — default on, so every existing model is bit-identical — keeps every material and link nonlinearity (gaps, hooks, tension- and compression-only) while solving small-displacement kinematics. Verified against a SAP2000 gap-element benchmark that publishes a small-displacement reference.
* **Influence Lines Are Reachable From the Spreadsheet and UI:** Influence-**line** live load was already supported by the engine and invisible in the product — a beam-line model needs no dummy deck to carry live load, and nothing in the FEA tab said so. One path also crashed outright: an influence line with an alignment and a non-zero longitudinal or transverse force — exactly the centrifugal and braking case those inputs exist for — threw.
* **Warp Interpolation Fallback:** Restores the elevation-field elevation, the local/global sync and force-on-line behavior in the fallback path, and drops a write that provably changed nothing except to corrupt the out-of-plane axis on vertical surfaces.
* **Composite Stress Rows Are a Published Contract:** The composite stress row layout is pinned, so downstream readers cannot be silently re-shaped.

**FEA Results & Display**

* **"Add to Verification" Follows the Visible Rows:** Both actions built their row set by slicing the underlying array between the two selection endpoints, so under a filter every hidden row in between was silently verified too — and under a descending sort the slice came back empty and the action did nothing at all.
* **An Authored Empty Reference Is an Assertion:** A guard added to stop an extraction that produced nothing from manufacturing agreement could not tell an authored empty list from a reference that was never written, so it started failing verifications whose author deliberately asserts "expected: nothing". Booleans also now compare as numbers.
* **Test Tab:** A test whose only failing checks are warning- or info-level is no longer folded into the red "Failed" card — warning and info have their own buckets and summary cards, with failed > warning > info > passed priority. Also fixes explorer checkbox persistence and several reference-picker defects.

**AI Agent & Automation API**

* **Global Parameters, Described and Validated:** The Global Parameters sheet is the front door to making a project parametric and was too thin for the job — a project with 40 globals was one flat, undocumented list. It gains Description, Category, Validation Criteria, Issue Label and Check columns, with tabs built from the distinct categories. Agents also get guard-driven element counts through new global-parameter and guard tools.
* **Guards Are Readable and Plural:** One count parameter may now drive **many** guard pools — pool identity lived in a single slot, so a second pool definition stripped the first pool's guards and handed ownership over, leaving a quarter of the members unconditionally active, which looks correct at the default count. Parameter identity and write-verification are fixed alongside.
* **Library Update and Summary Report Verification From the API:** Project-level workflows that lived only in the UI — the "Library Update Available" banner and its confirm sequence, and the summary-report verification — are reachable as actions returning data, instead of requiring an agent to screenshot the window and click coordinates. About 20 issues in one sweep, also covering model import/export, tenancy honesty and per-workspace credentials.
* **An App Update No Longer Silently Stales an Agent's Tool List:** An MCP client negotiates its tool list once, at session start, and the desktop app auto-updates on quit — so a client attached across that update keeps the previous build's list and reports a tool the update *added* as a missing capability. The user now gets a toast and the agent gets a banner on its own tool results.
* **Verification Baselines and Test Runs:** Re-baselining refuses an unwritable record before it runs or uploads — publication immutability was only discoverable at the save, so a dry run could report 84 confident updates against a write that would then be refused. The run lifecycle is fixed with it: cancellation actually clears the run pool, a stale run cannot overlap the next batch, and cancellation is re-checked before every write.

**Spreadsheets & Reporting**

* **Print / PDF for Spreadsheets:** The sheet is drawn on a canvas, so the browser's own print had a single element and nothing to paginate — it scaled that one canvas onto one page. A new **Print / PDF…** action rebuilds the visible data as a real table in a new window so the print engine can flow it across pages, printing through the active sort and filter; saving as PDF is then the browser's own destination. The printed sheet is branded and carries the sheet's own cell styling, including the result colours, and the preview no longer stops dead partway through when the tab loses focus.
* **Move Rows Within a List:** The list editor offered only Delete Rows, so a list could not be reordered without retyping it. It gains Shift Row(s) Up/Down and Move Row(s)…, matching the object spreadsheet. Delete is fixed with it: it removed rows **by value**, so with duplicate entries — routine in a numeric list — it deleted the wrong one.
* **"New Window…" Actually Opens the Sheet:** The remote spreadsheet never loaded — not intermittently, on every open. It waited behind a check that could only take its first branch, then bet a hard-coded 1000 ms against a popup that measurably takes about 2.3 s to be ready.
* **Aliases in Design Guard Panels:** The two design-guard panels were the one place in the design report still showing raw internal parameter names, and disagreed with the "where …" list printed directly beneath them.

**Modeling & Geometry**

* **An Extending Section Can Re-Select the Base's Guarded Shapes:** Extension was one-directional — a shape that is guard-false in the base was never cloned, so no instance-level override could turn it back on, and a shapeless clone rendered nothing with no error. `GuardX` by contract survives compilation so it can be re-evaluated in another scope, and "cloned into an extending section" is exactly such a scope. A follow-up fix preserves the guard condition of a container the shape was nested under, rather than destroying it.
* **Section Colour Reflects Material Type:** A section's default colour now follows its material type.
* **One Look for the Canvas Settings Panels:** View Settings, Show/Hide Objects, Alignment Display and Load Generation each built their own panel — three of them copies of the same hardcoded card, fixed to the top centre of the *window* regardless of which pane opened it, with their own drag implementation and native checkboxes. All four are rebuilt on one themed, anchored panel component, deleting about 560 lines of duplicated chrome.
* **A Library Migration No Longer Hangs:** A version migration froze indefinitely at "16 of 17 loaded", with the whole app greyed out and no error shown, because a guard dereferenced an unbound input during the standalone parse and the loader never unwound. Only a guard that *throws* during a standalone parse is treated as non-blocking; guards that evaluate cleanly decide exactly what they always did.
* **A Lambda's `=>` Is No Longer Read as an Assignment:** The dev console split an entry on the first `=`, tearing every lambda at the arrow and breaking every comparison operator — `a==b` became name `a`, expression `=b`.

**Import/Export**

* **CSiBridge / SAP2000 Round-Trip Fidelity:** Round-trip testing across all 282 verification files found data silently lost or mangled by the interop — most of it one root cause, where the export writer emits a table the importer has no case for. **16 fixes**, covering unnamed rebar / aluminium / other materials, frame point loads, and export cosmetics such as re-quoted values and floating-point coordinate noise. All 282 files now import and export with zero crashes.
* **LARSA Loads Import:** The LARSA reader had drifted behind the writer — a member thermal loads block the exporter emits had no matching import branch, so a round trip silently lost every line temperature load, and plate load directions were parsed into an empty switch, leaving every imported surface load pointing wherever the default happened to be. Unsupported load types are now reported rather than dropped quietly.

**Reliability & Performance**

* **A Tab Left Open Across a Deploy No Longer Corrupts Every Compile:** The main thread runs one build while every worker it spawns loads whatever is deployed *now* — and because property names are minified per build, the compile payload's keys stop resolving across that boundary. Every project died in deserialization, and **143 of 144 FEA verification projects failed at compile while the batch still reported success**. The build identity is now stamped and handshaked so a mismatch fails loudly, the page's own bundle bytes are frozen at load so later workers cannot drift, and that frozen copy is spent only once the handshake reports an actual drift — a first cut applied it unconditionally and cost every session the bundle's code cache.
* **The Component Catalog Is Not Rebuilt Per Request:** Listing components was the single slowest request of a warm project open — 8.9 s for a 2.7 MB response, 30.7 s under load — running three unfiltered datastore scans in-request, one of which the server already had in memory as a maintained snapshot.
* **Batched Datastore Lookups:** Two read paths — reassembling a partitioned blob, which is the read path for both project data *and* library objects, and replaying a message inbox on socket open — fetched entities one key at a time, serially. Measured over two hours on one workspace: 2,894 HTTP requests produced 35,750 datastore operations, 23,964 of them single-key lookups, while the container averaged 1.9% CPU. The server was not busy, it was waiting.

**Project & Library Management**

* **The Create Project Dialog Drops the Team Picker:** The dialog is now project name plus destination folder. The removed control *displayed* a team as selected while creating the project in the user's personal space, because programmatic selection fired no change event — so this removes a display/submit mismatch rather than changing where projects land.

**Desktop App**

* **Naming and Packaging:** Task Manager now shows "OpenBrIM" rather than a long description blurb, "OpenBrIM Agent" is renamed to "OpenBrIM Platform" across the app surface, the About dialog no longer clips its update status or gets pushed out of reach by a long updater error, and new windows open at a sensible size and in front. Packaging had been broken on master and is fixed, along with the per-workspace credential store.

***

## **v3.260803**

*Also covers the interim releases v3.260716, v3.260717 and v3.260718.*

**AI Agent & Automation API** *(new)*

* **Model From an AI Assistant:** The `openbrim-modeler` agent API (used by the OpenBrIM desktop app and by external AI clients) now covers the full modeling loop — build, analyze, design, and read results — including the complete FEA object family (elements, loads, cases, groups, construction stages, influence lines).
* **Workflows & Coordinate Systems From the API:** New tools list, import, and delete bridge-type workflows in an open project, so a session can start as a Steel I-Girder model and add a Prestressed I-Girder workflow mid-session. Another pair sets the project's State Plane / geographic coordinate system and local origin — the prerequisite for importing a DTM/terrain surface.
* **Safer Result Extraction on Big Models:** Result reads are now filtered *before* they are computed rather than after, so pulling a few hundred rows out of a 17,000-row table no longer computes the whole table. New calls enumerate what result elements exist and estimate what a read will cost (cold vs. warm), batch sizes are measured from real timings, and an over-large read returns a truncated result instead of exhausting memory. Reading results from a model that was never analyzed is now refused instead of returning zeros as a success.
* **Wood-Armer Design Moments:** `WaXTop` / `WaYTop` / `WaXBot` / `WaYBot` are now extractable for shell surface forces, in a caller-specified output frame.
* **Enum Values Accept What You Type:** String-enum parameters (side selectors and similar) now accept the friendly label, the bare keyword, or the exact stored token — `Left`, `'Left'`, and `left` all land correctly. Previously an unquoted keyword failed silently.
* **Version Handshake:** The desktop app now asks the connected workspace what it supports and refuses a call the workspace can't serve, naming the missing capability and the workspace revision — instead of sending a call that quietly does something else.
* **Parameter Chain Debugging:** A new call returns the computed value of every parameter as the compiler resolved it, targeted by object type — the direct answer to "why did this formula produce that value".
* **Better Errors:** Generation errors keep their original throw site, object types can be enumerated, an FE model can be built from a file, thermal gradients are no longer silently dropped, and feedback reports attach the last 200 tool calls instead of 10.

**Finite Element Analysis**

* **Solver Verification Program:** A broad accuracy and validation program measured against an independent benchmark suite of reference problems with published results. Improvements span the element and solution libraries: release-consistent fixed-end forces, so distributed loads on members with end releases are transferred exactly; a consistent load vector for distributed torque; improved conditioning of skewed supports, with joint-local reactions now reported; an improved shell formulation, including staged thermal stress; stress-stiffened modal analysis; and linear buckling.
* **Unified Time-History Analysis:** One `AnalysisCaseTimeHistory` object now covers all three solution methods — `Modal`, `Direct`, and `FNA` (fast nonlinear analysis).
* **Time-Varying Nodal Loads:** A node load can now carry a time function and scale factor, so a time-history case can be driven by a prescribed force history at a joint — not only by uniform base acceleration.
* **Multi-Support (Spatially Varying) Excitation:** New `SupportMotion` prescribes a displacement record per joint and DOF, any number per case, with an optional per-support time shift so wave passage can be expressed from one shared record. Uniform base motion of a long or multi-span bridge is rigid-body translation and produces no member demand at all; differential support movement does.
* **equalDOF Constraints and PMM Plastic Hinges:** New stage-aware `FEConstraintEqual` element, plus PMM plastic hinges evaluated on line-end springs for pushover. Displacement-controlled solving is hardened with load-factor rollback on failed steps and better step-size control.
* **Loads in a User Coordinate System:** Node, line, and point loads can now be given in a referenced `CoorSys` frame (`Sys="2"`), and point loads gained frame support for the first time. **Behavior change:** line loads set to `Sys="1"` (node-local) are now honored by the solver — they were previously drawn local but solved global, so models with line loads on alignment-heading nodes will see result changes.
* **Displacements in a User Coordinate System:** New `dispUCS()` / `dispTx…RzUCS()` result functions report nodal displacements rotated into any coordinate system. The rotation is applied at the result leaf, so every combination path — modes, combinations, envelopes, construction stages, live load, and response spectrum — combines already-rotated results.
* **Thermally Expanding Rigid End Offsets:** New per-member `OffsetExpandsThermally` option (default off). A rigid end offset is normally strain-free, which forced a fictitious lack-of-fit force into cross-frames under a temperature change. With the option on, the member's stress-free length becomes the full node-to-node span, matching an explicit rigid steel element to 0.1%. Set on 72 members across the cross-frame, internal-cross-frame, spliced-diaphragm, and top-lateral-bracing library objects.
* **Composite Results Report Their Station:** A composite result now reports the alignment station it was taken at.
* **Remote Mesh Fixes:** Missing FE surfaces in remote-meshed models are restored, an empty or invalid mesh response is never cached, overhang nodes on custom-edge decks are warped into place correctly, and deck edges can follow a custom alignment line.
* **Nodal Mass Contributes to Modal Analysis:** A `NodeMass` object contributed no modal mass; it now does.
* **Creep Verification Fix:** The trailing-substage anchor is restricted to the fit substage, identified by a dedicated flag rather than inferred from load type.

**FEA Results & Display**

* **Verification Values No Longer Stuck at 0.0000:** Verify rows could read `0.0000` permanently after a successful analysis — a read taken while the solve was still running was cached as a plausible zero and served for the rest of the session. Result caches are now invalidated at the run boundary, and verification extraction refuses to start mid-run instead of recording and persisting zeros.
* **Verification Report:** A project whose checks are its Verify objects now has a report. The Design button reads **Verify** with a **Run Verifications** action, rendering the same check report the Online Verification System produces.
* **Display Panel Restructured:** The hidden `⋮` menu is gone — every display toggle is a visible row that shows its state, and toggles that did nothing in a given mode are no longer offered there. Display units split three ways (Displacements / Forces / Stresses), so kip-ft moments and inch deflections are no longer mutually exclusive. The Deflection panel no longer scrolls at default size, and the reaction quantity is eight visible chips instead of two controls silently relabelling each other.
* **Visibility & Isolate Fixes:** Fixed a redraw loop that froze the FEA view on large models, an isolate being silently undone by a derived visibility sweep, and an isolate being destroyed on every construction-stage step. "Elements = Selected" can now resolve a composite from a mesh pick, and a failed composite contour no longer leaves the view stuck on a missing contour and a progress bar that never finishes. Design runs can be cancelled, covering both extraction and report build.
* **Result Diagrams Read in Elevation:** Axial force and torsion are now plotted in the vertical plane, so four of the six components read correctly in the elevation view a bridge is normally read in. Composite girders follow the same plane rules as members, honor the plot-side / fill / height settings, and hang their moment ribbon on the tension side.
* **Consistent Results Tree Order:** The per-element result tables now appear in a fixed order rather than in whichever order the model happened to create its elements, so the same table is in the same place in every project. Spring forces reported in local axes under a "(Global)" heading are fixed, with an explicit local/global pair.
* **Honest Empty-Result Notice:** The empty-result notice can be dismissed and no longer claims nothing is drawn when something is. "No reactions" is no longer announced while results are still loading.
* **Canonical Spreadsheet Tabs:** The FEA spreadsheet had 59 different tab names across 46 classes with two sources of truth. They are now one vocabulary of 54 names, with synonyms collapsed. **Relearning:** `Point Load` / `Forces & Moments` / `Displacements` / `Temperature` / `Surface Load` are now `Loading`; `Stiffness Option` + `Stiffness Matrix` are now `Stiffness`; the Combination `Items` tab is gone, so a sheet left open on it lands on `Cases 1-5`.
* **N/A Means N/A Everywhere:** 36 parameters showed **N/A** in the spreadsheet while staying editable in the object dialog and exporting as real numbers to Excel. Applicability is now decided once and honored by the sheet, the dialog, and the export alike.
* **Per-Check Tolerance Reporting:** Verification checks report their tolerance, with tolerance and log level authored in the project sheet, and OpenBrIM baselines can be recorded from a run.

**Project Data Integrity**

* **Special Characters No Longer Corrupt a Project:** Text containing `&` or `<` was written into the stored project unescaped, and the loader then saved the loss back — silently destroying content. Saving now escapes exactly what XML forbids, and the loader guards against a malformed document.
* **Lambda Arrows Preserved on Save:** A follow-up fix: for one release, saving any object rewrote every ParamML lambda arrow `=>` as `=&gt;` throughout the object, turning a one-line edit into an unreviewable diff. Only the three characters XML actually forbids are escaped now.
* **In-Session Objects Report Their Own Type:** Objects created during a session — as opposed to loaded from a saved project — carried no type parameter of their own and silently inherited the nearest neighbour's. The visible symptom was cross-frames missing from the FE model until a page refresh or a source **Update**.

**Real-time Collaboration**

* **The Update Notice Tells the Truth:** The "Updated by …" notice could name *you* as the collaborator when the change came from your own second tab, window, or desktop app — that case now reads **"Updated in another session"**. It could also appear with nobody else in the project at all, because a session that had merely loaded the project was read as infinitely behind and had the last save replayed at it.
* **Conflict Dialogs Behave:** Conflict prompts no longer stack over an open change review, and choosing "Use cloud copy" no longer hangs a running batch import.

**Security & Accounts**

* **MFA Phone Entry Rebuilt:** Entering a phone number with separators or without a country code used to produce a code-entry box for an SMS that was never sent — no error, no way forward. First-login enrollment now uses the same country-aware widget as Settings, validates before sending, and shows the masked destination, an expiry countdown, resend with cooldown, and a change-number option. A refused send reports the gateway's actual reason.
* **Country-Aware Phone Entry Everywhere:** All five surfaces that collect a phone number (MFA enrollment, 2FA settings, registration, profile update, first-admin setup) now use one shared country-aware widget with E.164 canonicalization. Registration's free-text Country box, which could contradict the phone number, is gone.
* **Carrier Verification:** Numbers are checked against carrier data when they are *set*, reporting the resolved country and carrier and rejecting a number that cannot receive texts. Sign-in never performs this lookup.
* **MFA Codes by E-mail:** An admin can now deliver a user's sign-in codes by e-mail instead of SMS — necessary in regions where carrier-level filtering of international senders blocks SMS delivery entirely.
* **Admin Sees the Verified Number:** The admin user table showed only the contact phone, so an admin could be reading one number while codes went to another. Both are now shown and reconciled.

**Project & Library Management**

* **Copy Project to My Account:** New project-menu item that copies the currently open project into your own account and opens the editable copy — including a read-only project opened via a shared link that you don't own. This previously required copying tens of thousands of lines of XML out of the source panel by hand.
* **Orphaned Library Components Recovered:** A bulk workspace library copy could half-create components that were invisible in the library but still blocked their names ("shows as new in pull, not found in search, can't create: name taken"). Such components now appear under an **Unknown** author, admins get a **Fix Owner** mass action, and component creation is atomic so the state can't recur.
* **Mass Publish Hardening:** A 694-object mass publish that crashed at 7% behind a frozen progress dialog now rides out contention with retries, releases its worker slot on every path, reports a real conflict deterministically, and shows inline per-item progress. The underlying contention is addressed at the root by sharding the catalog-generation counter (\~32× less write contention on every component create, save, delete, and publish).
* **Admin Console Fixes:** Model-compilation buttons (3D / FEM / DETAILING) no longer appear in the admin console, which never loads a project. Project links in the Data view are real links again — hover preview, copy link address, and middle-click work, and projects opened from the console no longer run in a degraded child-window mode that filtered alignment geometry out of the render.
* **Usage Report:** Fixed cross-transaction contention that could blank the admin usage report, made it substantially faster on large workspaces, and removed a duplicate wait-screen card.

**Modeling & Geometry**

* **Footing Face Triangulation:** Fixed top and bottom face triangulation on concave footing polygons.
* **Finwall Section Quantities:** Group-wrapped points are now included when gathering section points, so finwall areas are computed correctly.
* **Drill-In Survives a 3D Pick:** Picking an element in the 3D view no longer bounces you out of a parameter-interface drill-in — the panel was being destroyed and rebuilt around every pick.
* **The "(New)" Row Accepts Typing:** With any 3D selection active, typing into a plain cell of a sheet's trailing `(New)` row created nothing at all — no row, no object, no message.
* **Object-Group View-State Selector Removed:** The "View All" selector was removed from the model UI.

**Import/Export**

* **Tekla Surface-Drawn Solids:** Objects drawn as surfaces (e.g. footings) now export to Tekla Structures as shell items instead of being dropped, shipped alongside OBrIMTekla v1.3.0. A separate fix restores literal field names in the production Tekla export payload.

**Reliability & Performance**

* **Cloud Run Outage Hardening:** Addresses the July 429 "no available instance" storms, including a \~55-minute hard outage. Per-version revision tagging stops an idle-instance leak, saturated requests fast-fail instead of wedging, the project catalog cache became a generation-keyed single-flight snapshot instead of a shared mutable map, the async project-get path is concurrency-gated, and alerting on 429/5xx is provisioned per project. Verified against a 500-concurrent flood: peak four instances, no wedge, no 5xx.
* **Scale to Zero:** Idle services now scale to zero across all environments, safe given \~2s cold start and Datastore-backed live state.

**Desktop App**

* **Quiet Update Pill:** The native "Update ready — Restart now / Later" modal is replaced by a small **"Relaunch to update"** pill in the bottom-left of each editor window. Click to relaunch, hover → ✕ to hide it for this run, or ignore it — the update installs on quit either way. A desktop update that lands mid-session now announces itself instead of silently changing behavior.

**Documentation**

* **Truss Bridge LFD Load Rating:** New workflow pages covering the LFD load-rating workflow for truss bridges.
* **Concrete Box Girder Element Loads:** Corrected the Element Loads pages for the concrete box girder workflow.
* **Bolted Gusset Plate Code Check:** Documented the Design basis toggle.

***

## **v3.260714**

**Real-time Collaboration** *(new)*

* **Live Multi-User Projects:** Multiple people can now open the same project and work together live. You can see who else is in the project (Google-Docs-style presence), and collaboration is on by default.
* **Review Changes Before They Apply:** A per-project "review before applying" mode (toggle in the top bar, on by default) lets you review a collaborator's incoming changes as a neutral change report with a spreadsheet cell-highlight preview before accepting or rejecting them.
* **Safe Save-Conflict Resolution:** When two people edit the same project, a collaborator's save is never silently overwritten. You get a clear notice and a simple choice — **Keep my copy** or **Use cloud copy** — with an optional informational review. Conflict prompts no longer stack over an open review.
* **Reliable Live Connection:** Server-side keepalive prevents the live connection from dropping when idle, auto-reconnect recovers dropped sockets, and the app now starts up normally even if collaboration can't connect.

**Finite Element Analysis**

* **Cross-Frame Fit Conditions (NLF / SDLF / TDLF):** Model steel cross-frame fit-up so the analysis automatically accounts for locked-in (lack-of-fit) forces from no-load, steel-dead-load, and total-dead-load fit, with the resulting applied strains readable in the results.
* **Cable Stressing:** Apply pretension to cable elements and drive a staged cable-stressing load through a dedicated Cable Stressing Loads spreadsheet.
* **FE Surface Stress Results:** New surface-stress contour views for shell/plate elements, with correct construction-stage handling and combination/live-load stress envelopes. Adds Sxx/Syy/Sxy plus longitudinal/perpendicular (Slong/Sperp) components and an alignment picker that rotates each node's stress tensor for a continuous contour.
* **CQC3 Response-Spectrum Combination:** New CQC3 spatial combination rule for combining orthogonal ground-motion components, with a user-supplied γ ratio and automatic critical-incidence-angle computation (γ=1 reduces to SRSS).
* **Displacement-Controlled Pushover:** Corrected the displacement-controlled pushover solver so the control degree of freedom advances by the prescribed increment, with adaptive step reduction on non-convergence. Pushover can also now track per-step hinge status (linear / yielded / crushed) for a group of hinges.
* **Weight-Only Members Shown During Staging:** Members that contribute weight but no stiffness at a construction stage now render ghosted (25% opacity) during stage playback instead of disappearing, so you can see the self-weight being applied.
* **Height-Varying Mesh Thickness:** FE mesh surfaces can now vary station-dependent thickness by elevation or transverse direction (e.g. a battered retaining-wall stem), not only along the alignment.
* **Mesh Elevation Field:** FE meshes can drape node elevations onto a surface/elevation field, including a gridline-aware path for meshing between lines.
* **Targeted Node Merging:** Mesh nodes can now be merged into a specific tagged group rather than the globally nearest point.
* **End-Release Condensation Fix:** Fixed a crash and unstable/incorrect results when analyzing elements with end releases, and corrected the self-weight fixed-end forces for released members.
* **Composite Stress Graph Fix:** Fixed the composite-section stress readout when a row emits a variable number of stress points.
* **Tendon Load Distribution Fix:** Tendon loads now distribute over the correct FE group nodes.

**FEA User Interface**

* **Analysis Results Excel Export:** New "Analysis Results" export (Analytical Model → Excel) lets you pick Result Types, Cases, and Elements, choose an envelope (None/Max/Min/Fx–Mz), Stage Reporting (Cumulative/Incremental), and a Load Type filter, with a live sheet/row-count estimate. Produces a formatted, branded workbook with an index sheet (hyperlink navigation), frozen headers, and interleaved Min/Max rows for combinations and live loads.
* **Applied Strain Loads Table:** New "Applied Strain Loads (Last Run)" subsheet showing the equivalent fixed-end forces from lack-of-fit strains, per load, in display units.
* **FEA Result Spreadsheet Fixes:** Corrected the eigenvalue / response-spectrum and pushover step displays in the FEA Result spreadsheet.
* **Design Memory Limit:** New "Design Memory Limit…" dialog to set the design result-extraction memory ceiling (persisted locally), showing detected heap and a warning that recommends the desktop app for large models.

**3D Rendering & Measurement**

* **Faster FEA View + AutoCAD-Style Selection:** Eliminates filter/selection freezes on large FE models and adds AutoCAD-style window (left-to-right) and crossing (right-to-left) rubber-band selection.
* **3D Element Name Search:** Type-ahead search box to find an FE element by name and select + zoom to it in the 3D view.
* **3D-to-Spreadsheet Stall Fix:** Removed a multi-second stall that occurred when clicking a 3D object into the spreadsheet tree.

**Section Analysis**

* **Unified Rebar & Tendon Spreadsheets:** New per-section spreadsheets list every rebar and tendon layout in one editable grid (profile, material, counts, spacing, reference edge, radius, angles, force, tensioning, debonding, position), with two-way sync to the section canvas.
* **Section First-Moment Functions:** New `sectionQx` / `sectionQy` ParamML functions expose the first moment of area for code-check formulas (e.g. web principal-tension checks).

**Verification**

* **Go To Offending Cell:** Each validation issue now renders as a card with a **GO TO** link that opens the spreadsheet, switches to the right category tab, and selects the exact row/column.
* **Inline Test Progress:** The Tests screen now shows per-item progress inline instead of stacked cards.
* **Verification Runner Reliability:** The verification/test runner uses an app-parity memory model, fixes a per-batch memory leak, and recovers from a stalled worker pool instead of hanging.

**Alignment**

* **Unsaved-Changes Prompt:** Closing the Alignment Editor (Cancel, X, or ESC) with unsaved edits now prompts Save / Discard / Keep Editing instead of silently losing changes.
* **Vertical Alignment (Warp) Fix:** Warp-ruled volumes now follow the alignment's vertical profile instead of a straight-line segment.
* **Duplicate Point Fix:** Avoids duplicate points when projecting onto an alignment.

**Import/Export**

* **Tekla Structures Native Parts Export:** Export a model to Tekla Structures with native geometry — plate girders export as native Lofted Plates, OpenBrIM materials map to Tekla catalog names, and source colors map to Tekla classes so parts show distinct colors. Includes tub-girder multi-plate export and diaphragm manhole cutouts, with correct position/orientation, vertical column rotation, and centroid anchoring. After export, the app automatically opens the OBrIMTekla Importer quick-guide.
* **DXF/DGN Export for Document CAD Objects:** New export button to save a document's CAD objects out to DXF/DGN.
* **DGN Mesh-Only Object Recovery:** Smart-solid DGN export no longer silently drops objects built as surface groups (e.g. foundations) — a second pass emits them as mesh so nothing disappears from the exported file.
* **IFC Quantities Fix:** Fixed material and section name export when using the IFC "include quantities" option.
* **Section Import Dropdown Fix:** Fixed a bug in the "Add Shape…" section-import dialog where changing a dropdown wrote the value to the wrong parameter.

**ParamML**

* **Live-Syncing Library Inputs:** Read-only computed inputs flagged `SyncFromLib` now re-sync from the library template on every load/refresh, so they no longer go stale when the library expression changes.
* **New Functions:** `triangulatePolygon3D` (3D polygon triangulation), `convexhull`, `elevationfield` (sample a Z elevation field), `linerefine`, and `splitpolylineat{x,y,z,length,fraction}` (split a polyline at a coordinate/length/fraction).
* **`startswith` / `endswith` Fix:** These now return no-match (instead of misbehaving) when given a non-string subject, so filter/lambda expressions evaluate correctly.
* **`bufferPolyline` / `rangelist` Fixes:** Corrected `bufferPolyline` endpoint handling and a `rangelist` station-dependency leak.

**User Interface**

* **Project Settings Popup:** Replaced the on-canvas Params/Objects explorer buttons with a Project Settings popup.
* **Spreadsheet Decimal Precision:** Numeric spreadsheet cells now respect the configured decimal-place / display-precision setting.
* **Modal Dropdown Clipping Fix:** Select-object and reference dropdowns inside dialogs are no longer clipped by the dialog edge.
* **New-Project Screen Polish:** Template previews fit without cropping, folders are visually distinguished in the project list, duplicate "Modified" dates were removed, and OpenBrIM template cards hide internal object name/author.
* **Accurate Version Label:** The version shown in the top bar is read from the actual shipped build so it can't lag behind a deploy.
* **Documents View Cleanup:** Hid the compile toggle controls in the Documents view where they don't apply.

**Project Management**

* **Search Filter Preserved on Sort:** Sorting the projects list no longer clears the active search filter.
* **Workspace-Mandated MFA:** Workspace admins can now require multi-factor authentication — new users must enroll a second factor at first login, enforcement covers all password endpoints, and the admin Users list shows per-user MFA state (On / Off / Required).

**Performance**

* **Faster Spreadsheet Mass-Edits:** Range/mass edits are batched so the object map isn't rebuilt per row, removing a large slowdown on big edits.
* **Memory-Safe Live-Load Results:** Live-load surface stress/displacement results use chunked warm-up to bound peak memory (fixing out-of-memory on dense live-load models), cache envelopes to avoid recomputation, and keep the contour stable during zoom.
* **Design-Report Memory Leak Fix:** Reopening the same design report no longer leaks memory each time.
* **FE Result Cache Relief:** Under memory pressure the FE result cache now sheds its oldest entries to reduce crashes on large models.

**Desktop App**

* **Software Update Button:** The desktop app now checks for updates on launch and periodically, downloads in the background, and offers a "Restart now" prompt to install — with a manual check button in the About window.
* **Exports Revealed in File Manager:** User-initiated exports now open/reveal the saved file in the OS file manager, plus a "File → Open exports folder" menu item.

***

## **v3.260407**

**Finite Element Analysis**

* **Composite Section Weight:** Exact weight-per-length calculation for composite sections in FELine elements, improving self-weight accuracy for mixed-material members.
* **Composite Section ParamML Functions:** New `compositeSection` family of ParamML functions for querying composite section properties.
* **FE Mesh Deduplication:** `DeduplicateMesh` is now enabled by default for remote mesh operations.

**FEA User Interface**

* **6x6 Equivalent Stiffness Stage Switching:** The 6x6 Equivalent Stiffness spreadsheet now dynamically updates when the active stage/case changes, without needing to reopen the sub-sheet.
* **Global Load Point List & 3D Picking:** SurfaceLoad, LineLoad, and PointLoad spreadsheets now support editable point lists with "Select Polygon/Polyline/Point (3D)" cell actions for picking FE nodes directly in the 3D view.
* **FEGroup Mass Paste Fix:** Fixed FEGroup View/Edit mass paste only adding one row.
* **FEA Spreadsheet N/A Fields:** Inapplicable fields (direction, coefficients, section-at-end) now correctly show N/A based on element and load type context.

**Verification**

* **Auto-Naming with Result Type:** Verification items now auto-generate descriptive names including incremental/cumulative and min/max context (e.g., "Verify Incremental Results SubStrStage.STAGE at Node...").

**Section Analysis**

* **Concrete Stress-Strain Model Fix:** Fixed interaction analysis material lookup to scan strip segments for the correct concrete material instead of assuming the first segment, fixing steel-cased concrete sections.
* **Gross Area Performance:** Fixed eager `GetGrossArea()` computation on every `Ag` getter call and resolved gross area memory handling issues.

**3D Rendering & Measurement**

* **Extended Measurement Tool (6 Modes):** New measurement tool with Point-to-Point, Polyline, Edge, Point-to-Face, Face-to-Face, and Angle modes. Includes alignment selector, face/edge snapping, results panel with unit conversion, and GCS coordinates.
* **Elevation Profile Clipping:** New Plan view clipping mode that follows the alignment's vertical elevation profile with adjustable offset, using a 2D height map texture for shader-based clipping.
* **Window Selection Fix:** Hidden elements are now excluded from window selection.
* **Pick Nodes Fix:** Fixed Pick Nodes selection when the 3D model is active by hiding non-FEA instances during FEA-only pick sessions.
* **Cross-Slope Rendering Fix:** Added unified break fallback to ForceSynchronization for cross-slope rendering artifacts.

**Alignment**

* **Alignment Editor Redesign:** Extracted Alignment Editor to a dedicated module with a new read-only Station column in the Horizontal spreadsheet, multi-row delete support, and segment delete action for Transverse data.
* **Duplicate Point Removal:** Alignment lines now automatically remove duplicate points.
* **GCS Coordinate Translation:** Stabilized alignment coordinate translation under active Geographic Coordinate System, scoped to projection and export operations.
* **Map Tile Fix:** Restored sub-tile centering in MapTile to correct lat/lng positioning.

**Import/Export**

* **DGN Additional Properties Report:** New cell action for 3D DGN exports showing all objects with their DGN properties, grouped by element, with copy-to-clipboard support and conflict validation.
* **DGN Text Style Fix:** Fixed null `DgnTextStyle.GetSettings` errors in AddNote, TextString, and AddDimensionLine.
* **DGN Server Processing Fix:** Suppressed "No WorkSet Alert" dialog blocking server-side DGN processing.
* **DGN Service Health Monitoring:** Added health monitoring with Slack alerts for the DGN MicroStation service, including external health ping to detect process crashes.

**Performance**

* **FEA Compilation Optimization:** Skip SetParams for FEMesh-generated objects, cache section lookups per station index, pre-filter sections by 3DOnly flag, and restructure non-prismatic section assignment.
* **Bounding Box Pre-Filtering:** Added bounding box pre-filtering for LineDist mesh region checks.
* **Cache Optimization:** Optimized Cache GetCtx/PutCtx with bundled entries and memoized keys.
* **Reference Project Caching:** Improved reference project caching with in-memory cache and timestamp validation.
* **Model Deserialization:** Deferred slow model deserialization to avoid UI blocking.
* **Memory Leak Fixes:** Fixed memory leaks in notification system and jQuery dialog closures (756MB → 160MB reduction).
* **Compilation & Rendering:** Optimized PML tree search with cached parent weight maps, added StaticGuard for early removal of guarded objects during CloneInto, and skipped Document children during rendering compilation.

**ParamML**

* **`pairwise` Function:** New array function for pairwise element processing.
* **`GetArrayDimension` Utility:** New utility for detecting array dimensionality, with 3D point array support in `GetObjPoints`.
* **Result Extraction Enhancements:** Added NegExt, PosExt, NegGlobal, and PosGlobal to result extraction pattern matching, with dynamic suffix combination generation.

***

## **v3.260227**

**Finite Element Analysis**

* **Binary Export/Import for FEA Results:** Export and import FEA analysis results to transfer models with completed analysis to another computer. Since results are stored locally in browser IndexedDB rather than the cloud, this feature enables sharing analysis results across machines.
* **6x6 Equivalent Stiffness Matrix:** Added comprehensive equivalent stiffness matrix calculation with flexibility matrix reporting (unaveraged and averaged).
* **Auto-detect Floor Stiffness:** Automatic detection of floor stiffness for softening curves with improved stiffness editor UI.
* **Spring Activation Displacements:** New boolean property to bypass pre-activation displacement subtraction for verifying activation-aware displacement logic.
* **Spring Force Recovery Fix:** Fixed spring force recovery to consider displacements after element activation and zero out previous force for springs that just became active.
* **Nonlinear Curve Sorting Fix:** Sort nonlinear curves by displacement instead of force to handle user input errors gracefully.
* **Node Merge Priority:** Prioritize keeping nodes with 6x6 stiffness matrix during same-location merge operations.

**Code Editor**

* **Enhanced CORE Object IntelliSense:** Added inline parameter suggestions and example children for improved code completion experience.
* **Template Params Fix:** Fixed IntelliSense to get params from template object correctly.

**3D Rendering**

* **Cross-Slope Rendering Fix:** Resolved rendering artifacts in deck surfaces with cross-slope geometry.

**Performance**

* **xxHash for Geometry Cache:** Use xxHash for geometry cache keys for faster lookups.
* **Faster Stage Filtering:** Speed up constructed-only stage filtering in FEA.
* **JsParser Optimization:** Optimized JsParser.Execute with property caching and frequency ordering.
* **Compilation Performance:** Faster compilation with fast-path and O(1) lookups.
* **GetIdentifierValue Optimization:** Skip GetObjA when param found at distance 0 for faster parameter resolution.
* **Reduced GC Pressure:** Reuse Float64Array buffer in Rotate3d operations.

**ParamML**

* **`insertinto` Function:** New JsParser array function with dual-lambda support for advanced array operations.
* **`trimPolyline` Function:** New function to trim polylines with support for negative offset to extend polylines.
* **Z-Coordinate Interpolation:** Added z-coordinate interpolation for XY plane intersections.
* **Alignment Projection Enhancements:** Added refinement and includeControlStations arguments to alignProjection function.
* **US Survey Foot Support:** Added US Survey Foot (ftUS) unit string representation to ToStrLength.

**Import/Export**

* **DGN Export Error Handling:** Improved DGN Writer error handling with client-side validation for custom properties.
* **ExtObj Validation:** Improved validation for missing object references in external objects.

**User Interface**

* **Isolate (Picked) Action:** New spreadsheet cell action for object reference columns to quickly isolate referenced objects.
* **Spreadsheet Row Version Fix:** Fixed project object version when adding new spreadsheet rows.

**Project Management**

* **Guard/Reference Ordering Fix:** Fixed operation ordering to remove refs before guarding and unguard before adding refs.
* **Guarded Objects Fix:** Fixed guarded objects being incorrectly added to references.
* **ParamDesc Migration:** Added ParamDesc support to ParamValueSet for version migration.

**Geometry**

* **Polygon-Line Intersection:** Implemented polygon-line intersection handling with optimized line filtering logic.
* **Line Projection Optimization:** Reduced line projection to a single point for constraint points array.

***

## **v3.260204**

**DGN Seed File Configuration**

* **Custom Seed File Support:** You can now upload and assign your own MicroStation seed files for DGN export, giving you control over levels and line styles in the exported DGN. See [DGN Seed File Configuration](https://docs.openbrim.org/templates/steel-i-girder-bridge-workflow/export-sig/dgn-seed-file-config-sig) for details.

**Finite Element Analysis**

* **Partial Completion Handling:** Nonlinear FEA analysis now supports partial completion, preserving results from completed load steps when analysis is interrupted or fails to converge.
* **Cancel Confirmation Dialog:** Added a confirmation dialog when canceling a running FEA analysis to prevent accidental interruptions.
* **Download Log Button:** Added a download log button to the analysis completion and FEA logs dialog.
* **Auto-Scroll Resume:** Added a floating button to resume auto-scroll in the FEA log textarea when the user manually scrolls.
* **Spring Gap Handling:** Fixed penalty stiffness calculation for springs with gaps.

**Section Analysis**

* **Phi Factor Improvement:** Improved phi factor interpolation in the interaction diagram transition zone.

**Alignment and 3D Rendering**

* **COG Support in Alignment:** Enhanced `alignLine` function with center of gravity (COG) support and configurable alignment rules.
* **Skewed Station Solver:** Added skewed station solver with intersection detection for improved 3D rendering of skewed structures.
* **Control Locations:** Enhanced alignment control location management and line splitting functions.

**Sections**

* **Custom Variation Paths:** Added custom variation path support for non-prismatic sections, enabling more flexible section transitions.
* **Station-Dependent Shape Coordinates:** The `sectionShapeCoords` function is now station-dependent, returning shape coordinates that vary along the member length.
* **Circle Section Support:** Circle-type sections are now supported for station-dependent section generation.

**ParamML**

* **`ClosestPointOnPolyline` Function:** New ParamML function to find the closest point on a polyline from a given location.
* **`volume()` Surface3D Support:** The `volume()` function now supports Surface3D geometry types.
* **`formatstation` Function:** New `FormatStation` utility and `formatstation` ParamML function for formatting station values.
* **`makestadep` Expansion:** The `makestadep` function has been expanded with additional capabilities.
* **Gross Area Fix:** Fixed `RebarCircularLayout` being incorrectly included in gross area calculation.

**Import/Export**

* **LandXML Import:** Improved azimuth calculation and added multi-file support for LandXML imports. Fixed curve `StartAzimuth` direction handling.
* **LARSA4D Import:** Fixed sanitization of illegal characters in names during LARSA4D import.
* **CSi Export:** Added support for exporting FE groups to CSi Link format.
* **IFC Fixes:** Various bug fixes for IFC export robustness.

**User Interface**

* **Work Point Picking:** Introduced Work Point picking feature with parametric and boundary point support for precise point selection.
* **Delete Objects UX:** Improved delete objects experience with progress feedback for large deletion operations.
* **Branch Search:** Added search box to the branch UI for finding objects.
* **Spreadsheet Fix:** Fixed spreadsheet cell staying active when clicking cell actions or scrolling.
* **TypeParamSelect:** Added TypeParamSelect cell action for ParamInterface spreadsheets, enabling type-based parameter selection.

**Project Management**

* **GCS Sync:** Projects now automatically sync their Geographic Coordinate System (GCS) from the source project if the local project doesn't have one defined.
* **Project Duplication Fix:** Fixed project duplication issues caused by `PopulateExtends` race condition and IndexedDB caching.
* **Project Folder UI:** Improved project folder interface with better validation.

**Performance**

* **Faster Local Data Access:** Optimized how the platform reads locally cached data (used extensively by FEA and project storage), resulting in up to 38x faster data retrieval.
* **Spreadsheet Copy:** Improved large spreadsheet copy operations using time-based yielding to prevent UI freezes.
* **Expensive Parameters:** Simplified and improved expensive parameter computation to require compiled project, with expression-based cache keys.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.openbrim.org/release-notes/openbrim-release-notes/2026-platform-releases.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
