Skip to content

feat: nested sub-menus in the node menu, on every client - #1255

Merged
rbuergi merged 5 commits into
mainfrom
worktree-agent-a87121b1b26443237
Aug 12, 2026
Merged

rbuergi merged 5 commits into
mainfrom
worktree-agent-a87121b1b26443237

Conversation

@rbuergi

@rbuergi rbuergi commented Aug 12, 2026 •

Copy link
Copy Markdown
Contributor

Why

The node menu had grown to ~15 flat entries. "is there a possibility to create sub-menus? it gets very big otherwise"

What Children did before

NodeMenuItemDefinition.Children has existed for a while and the contract already recursed through it (Localized, Equals). No web client rendered it:

Client Before
Blazor FlattenMenuItems deleted the parent and spliced children inline behind a divider
portal-next same, a literal port, and pinned by a test
React Native MenuItem had no children field — the subtree was invisible
MAUI recursive expander — the only correct one

A live bug, not just a gap: GitHubSyncMenuProvider emits one parent per sync source, so two repos gave two identical Sync now / Update to latest / Check branch triplets with the disambiguating label + 🐙 + repo tooltip thrown away. The docs meanwhile promised "an expand-on-hover sub-menu" nothing implemented.

Renderers now

Each uses its component library's own nesting — no bespoke dropdown, no HTML strings:

  • Blazor — NodeMenuItemList.razor recurses via FluentMenuItem.MenuItems → <fluent-menu slot="submenu">. Collapses the four duplicated @foreach blocks into one component; the GitHub one had been dropping icons.
  • portal-next — MenuEntries recurses via nested Fluent v9 Menu/MenuTrigger/MenuPopover.
  • React Native — a drill-down, not a flyout (below). Extracted to leftMenu.tsx so it is testable without the Expo-bound connection.

Roles, aria-haspopup/aria-expanded and the keyboard model come from the libraries; a test asserts the submenu opens on ArrowRight — never hover-only.

Mobile is deliberately different. A second panel beside its parent needs hover and width; a phone has neither. Tapping a parent replaces the list with its children plus a back control; › chevron, 44 pt targets. Parity means equivalent capability, not an identical gesture.

Grouping

📦 Export holds 📄 PDF (27) · 📤 Email (28) · 📝 DOCX (29). Decks use the same parent (PDF + Email). #1248's labels, icons, orders and tooltip keys are taken verbatim — both providers were reset to main's file and only re-wrapped.

Composing with #1252 (menu presentation as data)

#1252 landed in the same aggregation seam. A textual merge would have shipped two silent defects; all three points are covered by MenuNestingCompositionTest:

  1. Normalize ran BEFORE the overlay. The overlay is itself a source of nesting (Parent moves an item under another), so normalizing the pre-overlay slice sorted and pruned a tree that did not exist yet — a grouping created purely by data got neither Order-sorted children nor empty-group pruning. Normalize now runs immediately after MenuPresentationOverlay.Apply (still before Localized): one rule for both origins. A dangling Parent still leaves its entry top-level — it is not a group, so pruning cannot touch it.
  2. _group as one shared sentinel made every group the same catalog key. Area is the key the catalog matches on and the key a child names as its Parent, so an admin could not re-word / re-icon / re-order / hide a specific group, and only the first was addressable as a parent. Now a prefix: NodeMenuItemDefinition.GroupArea(name) → _group:Export.
  3. The overlay only patched top-level items, so grouping PDF/Email/DOCX under 📦 Export would have made all three un-editable by data — a regression of feat: menu presentation is editable data, not compiled code #1252's promise that every entry is addressable by its stable area. Apply now descends into provider-emitted Children for patch/hide. Re-parenting stays top-level-only, so Parent nesting remains exactly one level deep and a parent cycle stays structurally impossible.

⚠️ Point 3 changes #1252's overlay semantics (additively). Flagging it explicitly rather than folding it in silently — happy to drop it if you would rather nested entries stay un-addressable.

Also corrects MenuPresentation's XML doc, which claimed the overlay creates a container for a parent no provider emits — it does not, and must not, since nothing here filters on RequiredPermission. MenuAsData's worked example used exactly that non-existent area (a pure no-op emitting two warnings); it now uses the real _group:Export key and demonstrates hiding a nested entry.

Depth, grouping parents, empty groups

  • Depth is unbounded in every renderer (the overlay's own Parent stays one level by construction). Nothing ships deeper than two.
  • A parent is never activatable — neither FAST nor Fluent v9 can express "activates and opens"; both toggle.
  • Empty groups are pruned bottom-up. Filtering happens in the provider (or via catalog hidden), so an emptied group is a normal outcome of access control. A parent with a real Area survives.

Tests

  • MenuNestingCompositionTest (new, 9) — the composition above; all 14 of feat: menu presentation is editable data, not compiled code #1252's overlay tests pass unchanged
  • NestedMenuTest (new, 4) — child ordering, empty-group pruning, bottom-up, navigable-parent survival
  • MarkdownExportMenuTest (+2) — grouping, submenu ordering, group addressable + tooltip key; the whole-menu emoji invariant now descends into children, which it never did
  • headerMenus.test.tsx (new, 9) · leftMenu.test.tsx (new, 10) · shell.test.ts retargeted from the destructive flatten to isSubmenuParent

i18n: menu.exportGroup + menu.exportGroup.tooltip (adopting #1248's .tooltip convention) in both catalogs; drift guard green.

Verified locally

dotnet build memex/Memex.Portal.Monolith -c Release -p:CIRun=true -warnaserror clean · Graph.Test 23 · Security.Test 19 · DocumentationLinkIntegrity · LocalizationTest · portal-next 92 · react-native 153 · react i18n 15 · both JS typechecks. No lockfiles regenerated.

🤖 Generated with Claude Code

rbuergi and others added 2 commits August 12, 2026 08:09
The node menu had grown to ~15 flat entries. Menu items can now nest: a
parent opens a sub-menu instead of acting, and the three export actions
(PDF / DOCX / email) sit behind one "Export" entry.

Children were already modelled on NodeMenuItemDefinition and already
recursed through Localized/Equals, but NO web client rendered them.
Blazor's FlattenMenuItems (and its portal-next port) DELETED the parent
and spliced its children inline behind a divider; React Native had no
`children` field at all, so a whole subtree was invisible there. With two
GitHub sync sources configured that produced two identical "Sync now /
Update to latest / Check branch" triplets with nothing to say which repo
either belonged to — the parent's label, 🐙 icon and repo tooltip were the
only thing distinguishing them, and all three were thrown away.

Contract
- GroupArea ("_group") sentinel, sibling of the existing "_separator", for
  a parent that exists only to hold children. IsSubmenuParent: ANY entry
  carrying children is a parent and is never activatable — neither FAST nor
  Fluent v9 can express "activates AND opens", both toggle instead.

Aggregator (one place, so renderers stay dumb)
- Children sorted by Order at every depth. Only the top level was sorted
  before, so a sub-menu came out in provider-append order.
- A _group parent with no surviving children is pruned, bottom-up. Items
  are permission-filtered by the PROVIDER, never the renderer, so an
  emptied group is a normal outcome of access control, not a bug — and
  rendering it would open onto nothing. A parent with a real Area of its
  own survives; it still has somewhere to go.

Renderers — all use their component library's own nesting, nothing hand-rolled
- Blazor: NodeMenuItemList.razor recurses via FluentMenuItem.MenuItems →
  <fluent-menu slot="submenu">. Replaces the four verbatim-duplicated
  @foreach blocks; the GitHub one had silently dropped icons entirely.
- portal-next: MenuEntries recurses via nested Fluent v9 Menu/MenuTrigger/
  MenuPopover. Roles, aria-haspopup/aria-expanded and the keyboard model
  (Enter/ArrowRight to open) come from the library — never hover-only.
- React Native: drill-down, not a flyout — a second panel beside the first
  needs hover and width and a phone has neither. Tapping a parent replaces
  the list with its children plus a back control; parents carry a ›
  chevron and rows clear the 44pt touch target. Extracted to leftMenu.tsx
  so it is testable without the Expo-bound connection module.

Parity across clients means equivalent CAPABILITY, not an identical
gesture; the mobile difference is deliberate and documented.

i18n: menu.exportGroup + menu.exportGroupTooltip in both catalogs.
Docs: NodeMenu.md promised an "expand-on-hover sub-menu" no renderer ever
implemented — corrected, with the per-client table.

Tests: NestedMenuTest (child ordering, empty-group pruning bottom-up,
navigable-parent survival), MarkdownExportMenuTest (grouping + ordering;
its emoji invariant now descends into children, which it never did),
headerMenus.test.tsx (9: submenu render, keyboard open, aria, ordering,
parent-not-activatable, depth), leftMenu.test.tsx (10: drill-down, back,
ordering, a11y, 44pt, depth).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings August 12, 2026 06:09

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR implements true hierarchical (nested) node-menu rendering across all clients, backed by server-side normalization (recursive child sorting + empty-group pruning) and updates the export/share entries to use an Export submenu. It also fixes “Connect Microsoft 365” / instance OAuth connect navigation by ensuring those server endpoints are reached via full browser loads and by centralizing the EA consent route definition.

Changes:

  • Render NodeMenuItemDefinition.Children as real nested sub-menus in Blazor and portal-next, and as a drill-down hierarchy in React Native; add shared parent classification (IsSubmenuParent / _group sentinel).
  • Normalize menu trees server-side (sort children by Order at every depth; prune empty _group parents bottom-up) and group export/share actions under 📦 Export.
  • Fix connect flows by centralizing EA consent route constants + adding a routability test, and using forceLoad: true for server endpoints.

Reviewed changes

Copilot reviewed 34 out of 34 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
test/MeshWeaver.Security.Test/NestedMenuTest.cs Adds integration coverage for server-side nested menu normalization (sorting + pruning).
test/MeshWeaver.Security.Test/MarkdownExportMenuTest.cs Updates tests to validate export grouping under a parent and to assert icon invariants across nested entries.
test/Memex.Portal.Shared.Test/EaConnectRouteTest.cs Pins EA consent route constants to real ASP.NET routing + verifies Blazor catch-all doesn’t swallow the endpoint.
src/MeshWeaver.Messaging.Hub/Localization/strings.en.json Adds new menu/export keys and updates send-document dialog strings (EN).
src/MeshWeaver.Messaging.Hub/Localization/strings.de.json Adds new menu/export keys and updates send-document dialog strings (DE).
src/MeshWeaver.Mesh.Contract/NodeMenuItemDefinition.cs Introduces _group sentinel + clarifies submenu-parent semantics via HasChildren/IsSubmenuParent.
src/MeshWeaver.Mesh.Contract/IEmailSender.cs Adds ConnectAsUserHref to advertise deployment-specific connect flows to UI.
src/MeshWeaver.Mesh.Contract/HubEmailExtensions.cs Exposes ConnectAsUserHref() helper for UI callers.
src/MeshWeaver.Markdown.Export/Layout/SendDocumentLayoutArea.cs Refactors share-by-email dialog UX and adds just-in-time identity choice + connect navigation via forceLoad.
src/MeshWeaver.Markdown.Export/Layout/MarkdownExportMenuProvider.cs Groups PDF/DOCX/Email under a single Export submenu parent and adds emoji icons + label/tooltip keys.
src/MeshWeaver.Markdown.Export/Layout/DeckExportMenuProvider.cs Aligns Deck export entries with Markdown export group + restores localization keys/icons for parity.
src/MeshWeaver.InstanceSync/InstanceSyncLayoutArea.cs Fixes instance connect navigation to a server endpoint by using forceLoad: true.
src/MeshWeaver.Graph/Configuration/NodeMenuItemsExtensions.cs Normalizes menu trees: recursive child sorting and empty-group pruning.
src/MeshWeaver.Graph/ApprovalExtensions.cs Adds an emoji icon to Request Approval menu entry for consistency.
src/MeshWeaver.Documentation/Data/WhatsNew/2026-08-12-the-node-menu-groups-related-actions-into-sub-menus.md Adds release note for nested node menus + export grouping.
src/MeshWeaver.Documentation/Data/WhatsNew/2026-08-12-sharing-a-document-by-email-is-quicker-to-fill-in.md Adds release note for the streamlined share-by-email dialog.
src/MeshWeaver.Documentation/Data/WhatsNew/2026-08-12-connect-microsoft-365-no-longer-leads-to-a-missing-page.md Adds release note for fixed connect navigation + route centralization.
src/MeshWeaver.Documentation/Data/GUI/NodeMenu.md Updates docs to match new submenu behavior and server normalization rules.
src/MeshWeaver.Blazor.Portal/Layout/PortalLayoutBase.razor.cs Removes flattening helper and documents why it was incorrect.
src/MeshWeaver.Blazor.Portal/Layout/PortalLayoutBase.razor Replaces duplicated menu rendering loops with recursive NodeMenuItemList.
src/MeshWeaver.Blazor.Portal/Layout/NodeMenuItemList.razor New recursive Blazor component rendering nested submenus via Fluent/FAST.
src/MeshWeaver.Blazor.Portal/Layout/NodeMenuItemLabel.razor New shared icon+label renderer to keep behavior consistent across menu contexts.
memex/Memex.Portal.Shared/Email/GraphEmailSender.cs Implements ConnectAsUserHref only when delegated Graph auth is configured.
memex/Memex.Portal.Shared/Email/ExecutiveAssistantPlugin.cs Uses EA controller constants to build the absolute consent link reliably.
memex/Memex.Portal.Shared/Authentication/EaConsentController.cs Centralizes route constants and builds attributes/paths from them.
clients/react/src/i18n/strings.en.json Mirrors new menu/export and send-document keys into the React catalog (EN).
clients/react/src/i18n/strings.de.json Mirrors new menu/export and send-document keys into the React catalog (DE).
clients/react-native/src/Shell.tsx Extracts left menu into a separate testable component module.
clients/react-native/src/leftMenu.tsx New drill-down nested menu implementation for mobile + menu item typing incl. children.
clients/react-native/src/leftMenu.test.tsx Pins drill-down semantics, ordering, and a11y/touch-target behavior for nested menus.
clients/react-native/docs/shell.md Documents the drill-down nested menu model and how it maps to $Menu:* streams.
clients/portal-next/test/shell.test.ts Updates tests from flattening behavior to submenu-parent classification.
clients/portal-next/test/headerMenus.test.tsx New DOM/a11y/keyboard tests for Fluent v9 nested submenus.
clients/portal-next/src/client/HeaderMenus.tsx Renders nested submenus recursively using Fluent v9’s native submenu pattern.
Suppressed comments (1)

clients/react-native/src/leftMenu.tsx:148

  • The Home entry label is hard-coded ("⌂ Home") instead of localized (common.home exists). This will show English UI in German.
        <NavRow label="⌂  Home" active={!clientScreen && nav.address === home.address} onPress={() => onNavigate(home)} />

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +132 to +136
<NavRow
label="‹ Back"
active={false}
onPress={() => setDrill((d) => d.slice(0, -1))}
accessibilityLabel={`Back to ${drill.length > 1 ? (drill[drill.length - 2].label ?? "menu") : "menu"}`}
Comment on lines 141 to +145
{
Label = host.Localize("ui.sendDocument.recipient"),
Placeholder = host.Localize("ui.sendDocument.searchUsers"),
Placeholder = "name@example.com",
DataContext = dataContext
}.WithQueries("nodeType:User").WithMaxResults(15).WithStyle("width: 100%; margin-bottom: 12px;"));
}.WithStyle("width: 100%; margin-bottom: 4px;"));
Comment on lines +219 to 222
{items.length === 0 && (
<div style={{ padding: "6px 12px", fontSize: "0.8rem", color: "var(--colorNeutralForeground3)" }}>
No actions available
</div>
@github-actions

github-actions Bot commented Aug 12, 2026 •

Copy link
Copy Markdown
Contributor

Test Results (shard 0)

707 tests  ±0   707 ✅ ±0   13m 50s ⏱️ -1s
 10 suites ±0     0 💤 ±0 
 10 files   ±0     0 ❌ ±0 

Results for commit b5d44e4. ± Comparison against base commit ac72779.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Aug 12, 2026 •

Copy link
Copy Markdown
Contributor

Test Results (shard 5)

1 798 tests  ±0   1 606 ✅ ±0   8m 27s ⏱️ -19s
   11 suites ±0     192 💤 ±0 
   11 files   ±0       0 ❌ ±0 

Results for commit b5d44e4. ± Comparison against base commit ac72779.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Aug 12, 2026 •

Copy link
Copy Markdown
Contributor

Test Results (shard 1)

1 278 tests   - 11   1 278 ✅  - 11   6m 58s ⏱️ + 1m 1s
   11 suites ± 0       0 💤 ± 0 
   11 files   ± 0       0 ❌ ± 0 

Results for commit b5d44e4. ± Comparison against base commit ac72779.

This pull request removes 158 and adds 147 tests. Note that renamed tests count towards both.
MeshWeaver.Hosting.Monolith.Test.MeshNodeStreamCacheNegativeClassifierTest ‑ ForwardingReject_IsTransient_NotMissingNode
MeshWeaver.Hosting.Monolith.Test.MeshNodeStreamCacheNegativeClassifierTest ‑ NoNodeFound_IsMissingNode_NotTransient
MeshWeaver.Hosting.Monolith.Test.MeshNodeStreamCacheNegativeClassifierTest ‑ NonTransientMessages_AreNotTransientDatabaseFaults(message: \"Access denied: user lacks Read permission\")
MeshWeaver.Hosting.Monolith.Test.MeshNodeStreamCacheNegativeClassifierTest ‑ NonTransientMessages_AreNotTransientDatabaseFaults(message: \"\")
MeshWeaver.Hosting.Monolith.Test.MeshNodeStreamCacheNegativeClassifierTest ‑ NonTransientMessages_AreNotTransientDatabaseFaults(message: \"duplicate key value violates unique constraint\")
MeshWeaver.Hosting.Monolith.Test.MeshNodeStreamCacheNegativeClassifierTest ‑ NonTransientMessages_AreNotTransientDatabaseFaults(message: \"relation \\\"mesh_nodes\\\" does not exist\")
MeshWeaver.Hosting.Monolith.Test.MeshNodeStreamCacheNegativeClassifierTest ‑ NonTransientMessages_AreNotTransientDatabaseFaults(message: \"syntax error at or near \\\"SELCT\\\"\")
MeshWeaver.Hosting.Monolith.Test.MeshNodeStreamCacheNegativeClassifierTest ‑ Null_IsNeither
MeshWeaver.Hosting.Monolith.Test.MeshNodeStreamCacheNegativeClassifierTest ‑ PostgresConnectFailure_AsNack_IsTransient_NotMissingNode
MeshWeaver.Hosting.Monolith.Test.MeshNodeStreamCacheNegativeClassifierTest ‑ RawOrleansRejectionException_IsTransient
…
MeshWeaver.Hosting.Monolith.Test.MeshNodeStreamCacheIdleReleaseTest ‑ EntryWithLiveSubscriber_SurvivesIdleWindow_AndKeepsDeliveringUpdates
MeshWeaver.Hosting.Monolith.Test.MeshNodeStreamCacheIdleReleaseTest ‑ IdleEntry_IsReleasedAfterIdleWindow
MeshWeaver.Hosting.Monolith.Test.MeshNodeStreamCacheIdleReleaseTest ‑ IdleRelease_DisposesUpstreamSyncStream_EveryGeneration
MeshWeaver.Hosting.Monolith.Test.MeshNodeStreamCacheIdleReleaseTest ‑ ReadAfterRelease_TransparentlyReopensAndServesFreshState
MeshWeaver.Hosting.Monolith.Test.MeshNodeStreamCacheRecycleResetTest ‑ CreateAfterFailureEra_ClearsBreakerAndFaultedEntry_ViaChangeFeed
MeshWeaver.Hosting.Monolith.Test.MeshNodeStreamCacheRecycleResetTest ‑ RecycleBroadcast_ResetsBreaker_SoHealthyNodeResolvesWithoutWaitingOutBackoff
MeshWeaver.Hosting.Monolith.Test.MeshNodeVisibilityUnitTests ‑ IsExcludedFromContext_DotfilePath_ExcludedFromSearchOnly
MeshWeaver.Hosting.Monolith.Test.MeshNodeVisibilityUnitTests ‑ IsExcludedFromContext_ExplicitOptOut_HonoredIndependentlyOfPath
MeshWeaver.Hosting.Monolith.Test.MeshNodeVisibilityUnitTests ‑ IsExcludedFromContext_OrdinaryNode_NeverExcluded
MeshWeaver.Hosting.Monolith.Test.MeshNodeVisibilityUnitTests ‑ IsHiddenPath_DetectsLeadingUnderscoreSegments(path: \"ACME/Project/Foo\", expected: False)
…

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Aug 12, 2026 •

Copy link
Copy Markdown
Contributor

Test Results (shard 3)

   11 files  ± 0     11 suites  ±0   8m 25s ⏱️ +33s
2 120 tests + 6  2 017 ✅ + 6  103 💤 ±0  0 ❌ ±0 
2 354 runs  +10  2 251 ✅ +10  103 💤 ±0  0 ❌ ±0 

Results for commit b5d44e4. ± Comparison against base commit ac72779.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Aug 12, 2026 •

Copy link
Copy Markdown
Contributor

Test Results (shard 4)

1 308 tests  +2   1 298 ✅ +2   12m 27s ⏱️ -33s
   11 suites ±0      10 💤 ±0 
   11 files   ±0       0 ❌ ±0 

Results for commit b5d44e4. ± Comparison against base commit ac72779.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Aug 12, 2026 •

Copy link
Copy Markdown
Contributor

Test Results (shard 2)

2 115 tests  +23   2 114 ✅ +23   6m 47s ⏱️ - 1m 47s
   11 suites ± 0       1 💤 ± 0 
   11 files   ± 0       0 ❌ ± 0 

Results for commit b5d44e4. ± Comparison against base commit ac72779.

This pull request removes 147 and adds 170 tests. Note that renamed tests count towards both.
MeshWeaver.Hosting.Monolith.Test.MeshNodeStreamCacheIdleReleaseTest ‑ EntryWithLiveSubscriber_SurvivesIdleWindow_AndKeepsDeliveringUpdates
MeshWeaver.Hosting.Monolith.Test.MeshNodeStreamCacheIdleReleaseTest ‑ IdleEntry_IsReleasedAfterIdleWindow
MeshWeaver.Hosting.Monolith.Test.MeshNodeStreamCacheIdleReleaseTest ‑ IdleRelease_DisposesUpstreamSyncStream_EveryGeneration
MeshWeaver.Hosting.Monolith.Test.MeshNodeStreamCacheIdleReleaseTest ‑ ReadAfterRelease_TransparentlyReopensAndServesFreshState
MeshWeaver.Hosting.Monolith.Test.MeshNodeStreamCacheRecycleResetTest ‑ CreateAfterFailureEra_ClearsBreakerAndFaultedEntry_ViaChangeFeed
MeshWeaver.Hosting.Monolith.Test.MeshNodeStreamCacheRecycleResetTest ‑ RecycleBroadcast_ResetsBreaker_SoHealthyNodeResolvesWithoutWaitingOutBackoff
MeshWeaver.Hosting.Monolith.Test.MeshNodeVisibilityUnitTests ‑ IsExcludedFromContext_DotfilePath_ExcludedFromSearchOnly
MeshWeaver.Hosting.Monolith.Test.MeshNodeVisibilityUnitTests ‑ IsExcludedFromContext_ExplicitOptOut_HonoredIndependentlyOfPath
MeshWeaver.Hosting.Monolith.Test.MeshNodeVisibilityUnitTests ‑ IsExcludedFromContext_OrdinaryNode_NeverExcluded
MeshWeaver.Hosting.Monolith.Test.MeshNodeVisibilityUnitTests ‑ IsHiddenPath_DetectsLeadingUnderscoreSegments(path: \"ACME/Project/Foo\", expected: False)
…
MeshWeaver.Graph.Test.MenuNestingCompositionTest ‑ ACodeDefinedGroup_CanBeHiddenWholesale
MeshWeaver.Graph.Test.MenuNestingCompositionTest ‑ ACodeDefinedGroup_EmptiedByCatalogHiding_IsPruned
MeshWeaver.Graph.Test.MenuNestingCompositionTest ‑ ACodeDefinedGroup_IsAddressableByItsOwnArea
MeshWeaver.Graph.Test.MenuNestingCompositionTest ‑ ACodeDefinedGroup_KeepsSurvivingChildren
MeshWeaver.Graph.Test.MenuNestingCompositionTest ‑ ADanglingParent_LeavesTheEntryTopLevel_AndNeverLosesIt
MeshWeaver.Graph.Test.MenuNestingCompositionTest ‑ DataCreatedGrouping_ChildrenAreSortedByOrder
MeshWeaver.Graph.Test.MenuNestingCompositionTest ‑ DataCreatedGrouping_HonoursACatalogOrderOverrideOnAChild
MeshWeaver.Graph.Test.MenuNestingCompositionTest ‑ DataCreatedGrouping_RendersAsASubMenu
MeshWeaver.Graph.Test.MenuNestingCompositionTest ‑ NoCatalog_StillNormalizes
MeshWeaver.Hosting.Monolith.Test.MeshNodeStreamCacheFaultedEntryReprobeTest ‑ FaultedEntry_InsideAnOpenBreakerWindow_StillShortCircuits
…

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Aug 12, 2026 •

Copy link
Copy Markdown
Contributor

Test Results

   65 files  ± 0     65 suites  ±0   56m 57s ⏱️ - 1m 5s
9 326 tests +20  9 020 ✅ +20  306 💤 ±0  0 ❌ ±0 
9 560 runs  +24  9 254 ✅ +24  306 💤 ±0  0 ❌ ±0 

Results for commit b5d44e4. ± Comparison against base commit ac72779.

♻️ This comment has been updated with latest results.

rbuergi and others added 3 commits August 12, 2026 08:51
…b1b26443237

# Conflicts:
#	clients/react/src/i18n/strings.de.json
#	clients/react/src/i18n/strings.en.json
#	src/MeshWeaver.Documentation/Data/GUI/NodeMenu.md
#	src/MeshWeaver.Markdown.Export/Layout/DeckExportMenuProvider.cs
#	src/MeshWeaver.Markdown.Export/Layout/MarkdownExportMenuProvider.cs
#	src/MeshWeaver.Messaging.Hub/Localization/strings.de.json
#	src/MeshWeaver.Messaging.Hub/Localization/strings.en.json
Sibling GUI pages use ../../Architecture/<page>; the two MenuAsData links
were one level short and failed DocumentationLinkIntegrityTest.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants