A correctness release. Most of it came from your reports — several of which were sharp enough to reproduce from directly, and two of which turned out to be the tip of something larger.
Downloads
| Engine | Asset |
|---|---|
| UE 5.7 | Monolith-v0.22.0-UE5.7.zip |
| UE 5.8 | Monolith-v0.22.0-UE5.8.zip |
| legacy updaters | Monolith-v0.22.0.zip (a copy of the 5.7 build) |
Blueprint-only users: unzip into your project's Plugins/ folder. Nothing else to do.
Monolith was reporting values that were not your project's
get_component_details read the C++ parent's class-default object for any component inherited from native code, so it returned Epic's constructor defaults dressed up as your settings. A Character Blueprint overriding its capsule half-height to 96 read back 88. It returned null rather than an error, so the result looked deliberately empty rather than unresolved — which is exactly why it survived scrutiny.
There were five independent component resolvers in the Blueprint module and three disagreed about which CDO to read; the write path had it right and the read path did not. That divergence was the bug. There is now one resolver, used by both, reporting how it resolved (scs, cdo_native, ich_override, inherited_scs, parent_cdo_fallback).
Thanks @DanaFo (#116) — the 96-vs-88 comparison isolated it precisely, and picking a float rather than a null was what made it undeniable.
Also in this area: set_component_property can now write to components inherited from a parent Blueprint via an Inheritable Component Handler override, which is the scriptable equivalent of ticking that property in the child's Details panel. Thanks @Thomasbehan (#102) for the approach. The "Mesh" alias resolving to the capsule is fixed, and get_inherited_component_override's ich source could never actually fire — it compared handler records against a CDO component's name.
Enum variables were compiling to int
Type tokens like enum:EStreamlineDLSSGMode built a pin with PC_Enum, which is a picker-only category and never a valid pin category — so the variable compiled through the generic FIntProperty fallback while the API still reported the correct enum type. That produced the memorable error EStreamline DLSSGMode Enum is not compatible with EStreamlineDLSSGMode Enum: the spaced name is the broken pin rendered through a display-name path, the raw one is a correct pin.
Half of this shipped in v0.21.2 for the blueprint path. The Widget path was still broken, which is exactly where a graphics-settings menu lives. Both now build PC_Byte + subcategory through one shared grammar, and an unresolvable enum is a hard error instead of a silent plain byte.
An interrupted index no longer throws away its work
A full index wiped the database at the start and wrote its completion marker only at the end. Any crash, kill or power loss left no marker — and the next launch started another full index, which immediately erased every batch the previous run had finished. On a large project one crash cost hours; repeated crashes meant the index might never complete.
It now checkpoints and resumes. Assets already indexed at their current content hash are not redone. An asset that repeatedly kills the editor mid-index is detected, skipped, and surfaced through project get_stats rather than retried forever — the attempt marker is committed outside the batch transaction specifically so a crash cannot roll away the evidence that the crash happened.
bDeferFirstTimeIndex is honoured when resuming, and a monolith_reindex without force now resumes instead of resetting.
Thanks @Hvizeu (#117), whose diagnosis and lifecycle design this follows (#120).
Risk mining worked only on my machine
risk_query mined git history from a hardcoded list of plugin folders and never probed the project root — so for anyone whose project root is the git repository, which is most people, every root was skipped and the whole namespace returned empty data forever with no explanation. Roots are now discovered at runtime, configurable via GitRepoRoots, and an empty result tells you why it is empty.
Thanks @nanbarada (#119) — including the observation that the configured roots have to participate in stale detection, or changing the setting silently does nothing.
Discovery and search
monolith_discover(filter="…")with no namespace now searches every namespace instead of silently ignoring the filter and handing back the namespace inventory. Rows carry their owning namespace; absentlimitcaps at 50, explicitlimit=0still means all.- A pagination overflow:
offset=1withlimit=2147483647overflowed to an empty result and a negativenext_offset. project searchno longer reports genuine errors as zero results — invalid query syntax is now a caller error, storage and schema failures are internal errors, and column-qualified searches keep working.
Thanks @kunkunGames (#112, #113).
Monolith was disabling other plugins' HTTP routes
Stopping or restarting the server called a process-wide "stop all listeners", which took down every other plugin's HTTP listener in the editor as a side effect. Now only Monolith's own routes are unbound.
Alongside it: three use-after-frees on the indexing worker's game-thread callbacks, live asset-registry callbacks never re-armed after a failed run (so the index silently went stale until an editor restart), two paths that latched "indexing already in progress" until you restarted the editor, honest reindex results instead of unconditional success, and a blocking port probe that stalled the game thread during startup.
Thanks @kunkunGames (#114) for the report the fixes came out of.
Animation
set_anim_graph_node_property treated graph_name / state_name as advisory: an unresolved scope fell through to a global search by node id, and node ids repeat across graphs — so the write landed in an unrelated animation layer, compiled fine, validated fine, and played the wrong animation. A supplied scope is now authoritative, nested state machines resolve at any depth, and the response reports where the write actually landed.
Verification
Each per-engine zip is built with optional dependencies forced off, checked under both -DisableUnity and full unity, and its DLL imports are inspected for hard links to plugins you may not have installed. The offline CLI is rebuilt and byte-compared against its Python sibling (27/27 identical this release).
Monolith-SHA256-v2-UE5.7: 3bd87472f50c87f2259e573bf253c5f6d10a69a10fe1e08c0ed9ea9cf196cd51
Monolith-SHA256-v2-UE5.8: 92d65d2f070e2f89589f25303335a91dd44575bc2b65004b415f8e301e780e6e
Monolith-SHA256-v2: 3bd87472f50c87f2259e573bf253c5f6d10a69a10fe1e08c0ed9ea9cf196cd51
The in-editor updater verifies the download against the marker for your engine before installing.
Not taken this release
UE 5.6 support (#103, @Puche) — declined, and I owe you a proper reply on the PR rather than silence. The short version: I cannot compile-verify 5.6 here, there is no CI, and I would rather not advertise support I cannot test. Your pose-search analysis was correct about what changed between versions.
MCP Toplist badge (#118, @chrstphe) — thanks, but I keep the README badges to facts about the repo itself.
Generic graph-node property writes (#102 part 2) — deferred rather than rejected; the need is real, but as submitted it writes any property on any object by path, and that wants a narrower design first.