Diagnose controls rendered as text

A control displayed as its own description, such as StackControl { … }, reached the escaped-text fallback after every registered view map declined it. Loading a view assembly is not proof that its map was registered, and registering a map is not proof that it accepted the particular control or skin.

The diagnostics answer those questions separately:

The registration event runs once per layout-client aggregation, not on every control. The fallback event is limited to failed view selection. These are persistent operational signals whose value is diagnosing a visible rendering defect; they are not a temporary increase in general render logging. They do not change the health endpoint's readiness behavior.

Which hub is measured

Module HubConfigurations install the view maps on the root mesh hub. Ordinary portal circuit hubs inherit its service scope, so DispatchView resolves the root ILayoutClient; the health check reads that same registration. A circuit with its own layout-client registration needs separate investigation: the root health result does not establish which maps that circuit uses.

Descriptor consumers

The fallback descriptor includes HtmlView.IsFallback, a real Blazor component parameter. Consumers can forward the entire parameter bag, including that flag, without a special filter. The flag only identifies the rendering path; it does not alter the content or its encoding.

The initial implementation put the flag in the parameter bag but stripped it only inside DispatchView. A direct descriptor host forwarded it to an HtmlView that did not declare the parameter and threw an unmatched-parameter exception. A real HtmlRenderer regression reproduced that failure; another regression reproduced the misleading no-layout-client health message. Registration and fallback tests also capture the event category, level and structured fields, and verify that a normal HTML view emits no fallback event.

These diagnostics do not repair a missing view map, an incompatible module, or a node whose latest compiled assembly was refused by its consumer. They provide the evidence for identifying that defect. A healthy registration check alone must not be used to claim the affected page works.

A render pack that never reached the installation

The packs that render the platform's own pages — EntityViews (every text, number, date and choice input), GraphViews (the picture upload, MeshNode picker, card and content editor), Chat (the composer) and the collaborative markdown editors in Essentials — are registry packages, not image entries. An installation receives them only through its install pass, and that pass has two lanes: the registry's preInstalled baseline, and the packages the deployment names in PluginCatalog:InstallByDefault (its record's preInstall) together with their requires.

A list that names packages exactly is an explicit set (core policy declared-package-set-is-exact): the baseline lane is off and only the named packages and their dependency closure install. So the render packs must be in the closure of what an installation names, not only in the baseline. Essentials — the package new installations pre-install — therefore requires EntityViews, GraphViews and Chat, and Memex.Hosts.Test → ViewPackDeliveryPathTest.AnInstallThatDeclaresOnlyEssentials_StillReceivesEveryRenderPack reads the repository's package roots and fails when the closure stops reaching one of them.

Measured 2026-10-17 on a freshly provisioned customer installation whose record pre-installs Essentials alone. Nothing errored and the pods were ready. The readings that named the defect:

The Settings → Profile page painted TextFieldControl { Id = , … } where the display-name field belonged, while its headings, nav and back arrow (all default-pack controls) rendered normally.

Three gates now cover this failure: