Skip to content

fix(node-ui): WM Assertions tab surfaces sub-graph assertions (#706)#710

Merged
Jurij89 merged 8 commits into
mainfrom
fix/wm-assertions-subgraph-visibility
May 27, 2026
Merged

fix(node-ui): WM Assertions tab surfaces sub-graph assertions (#706)#710
Jurij89 merged 8 commits into
mainfrom
fix/wm-assertions-subgraph-visibility

Conversation

@Jurij89
Copy link
Copy Markdown
Contributor

@Jurij89 Jurij89 commented May 26, 2026

Summary

  • The Node UI's Working Memory → Assertions tab silently dropped every assertion stored in a named sub-graph. Sub-graph entities were visible in the WM Entities tab and graph view, but the corresponding assertion rows never appeared — blocking promote workflows on sub-graph-scoped assertions with no empty-state hint that anything was missing.
  • Root cause: listAssertions(cg, 'wm') in packages/node-ui/src/ui/api.ts ran a permissive SELECT DISTINCT ?g SPARQL and then client-side-filtered with a hardcoded prefix did:dkg:context-graph:<cgId>/assertion/ — sub-graph assertions live at <cgId>/<subGraphName>/assertion/… and silently failed the startsWith check.
  • Fix mirrors the known-good wmSparql filter pattern (useMemoryEntities.ts:171) and adds a quiet sub-graph indicator to each affected row so the user can see which sub-graph each assertion belongs to.

Related

Files changed

File What
packages/node-ui/src/ui/api.ts WM filter widened to startsWith(<cgPrefix>/) && includes('/assertion/'); added subGraph?: string to AssertionInfo; sub-graph slug populated via the existing subGraphFromAssertionGraphUri() helper from useAssertionLifecycleEvents.ts. SWM branch also surfaces the field for uniformity.
packages/node-ui/src/ui/views/project/components.tsx AssertionsList row renders an inline 🗂 <slug> chip in .v10-item-meta-row when assertion.subGraph is set. Reuses .v10-item-count styling exactly (low-contrast, no fill, no border) so the chip reads as quiet structural metadata, not a state-change pill. 18-char middle-ellipsis via local truncateMiddle; full slug in title="In sub-graph: <slug>". Non-clickable in this PR — click-to-navigate lands with S3.
packages/node-ui/test/context-graph-empty-stat-components.test.ts Extended fixture pins root-no-chip / short-slug-verbatim / long-slug-middle-ellipsis-with-full-slug-in-tooltip behaviours.

Test plan

  • pnpm --filter @origintrail-official/dkg-node-ui exec tsc --noEmit clean
  • pnpm --filter @origintrail-official/dkg-node-ui exec vitest run test/context-graph-empty-stat-components.test.ts test/use-assertion-lifecycle-events.test.ts — 27/27
  • pnpm build:ui green
  • Source-side spec verification by ux-lead against the bundled CSS (all 5 spec points: glyph + slug + middle-ellipsis, --text-tertiary, position after .v10-item-count, threshold = 18, tooltip wording)
  • Live walk on user's WSL node: WM Assertions tab on a CG with both root and sub-graph assertions surfaces all rows; sub-graph rows carry the 🗂 <slug> chip; root rows don't; hover tooltip reads In sub-graph: <full-slug>
  • Live walk: SWM Assertions tab on the same CG shows uniform chip treatment
  • Live walk: a root-only CG's WM Assertions tab renders unchanged (regression sanity)

Notes

  • Out of scope (intentional): the dkg_query view: "working-memory" agent-tool half of dkg_query view: "working-memory" does not include data from sub-graphs #675 (separate code path in packages/mcp-dkg; lay-down decision deferred to its own cycle); the SubGraphBar chip-scope behaviour (S3 territory); grouping assertions by sub-graph in the list (badge-only treatment per user direction).
  • ux-lead flagged a non-blocking Windows-rendering caveat: Segoe UI Emoji can ignore CSS color on the 🗂 glyph, so it may render more saturated than the chip's --text-tertiary text. CSS-only mitigation exists (font-variant-emoji: text;) if needed after live review.

The WM Assertions tab silently dropped sub-graph-scoped assertions
because the client-side filter only matched the root URI shape:
`did:dkg:context-graph:<cg>/assertion/<agent>/<name>`. Sub-graph
WM assertions live at
`did:dkg:context-graph:<cg>/<sg>/assertion/<agent>/<name>` (sub-graph
segment between `<cg>/` and `/assertion/`), and `startsWith('…/assertion/')`
rejected them outright.

Sibling fix to PR #675 (SWM Assertions tab) shipped earlier; this
brings WM to parity. Both tabs now uniformly surface root + sub-graph
assertions with an inline `subGraph` field on each `AssertionInfo`.

api.ts:
- `AssertionInfo.subGraph?: string` — undefined for root, slug for
  sub-graph-scoped. Uniformly populated on both WM and SWM branches.
- WM filter switched to `startsWith(cgPrefix) + includes('/assertion/')`
  to mirror the daemon's `wmSparql` discriminator. Sub-graph slug
  recovered via `subGraphFromAssertionGraphUri` (the same parser
  the lifecycle hook uses; defensive on malformed input).
- SWM branch surfaces its already-computed `subGraphName` on the
  returned `AssertionInfo` — no behaviour change, just uniformity.

components.tsx (`AssertionsList`):
- Inline sub-graph chip per row, locked spec: glyph + slug, mirror
  `.v10-item-count` styling exactly (10px / tertiary / mono / no
  border / no background), middle-ellipsis truncation at 18 chars,
  full slug in tooltip. Position: after `.v10-item-count`, separated
  by the existing meta-row gap.
- Glyph chosen: `🗂` (reads as containment — right semantic for
  sub-graph membership; `📑` would read as "multiple pages" which
  misleads).
- Chip is non-clickable in this PR per the locked plan; tooltip
  reads "In sub-graph: <full-slug>". Click-to-navigate lands with S3.
- `truncateMiddle(s, max)` helper added near the component; the
  prefix-weighted split preserves common namespace prefixes
  (`epcis-*`, `github-*`) in full on typical slug widths.

Tests:
- `context-graph-empty-stat-components.test.ts` — new case pinning
  the three states: root row → no chip; short slug → verbatim
  chip text + tooltip with full slug; long slug → middle-ellipsis
  applied, full slug preserved in tooltip. All three rows render
  (no silent drop on sub-graph rows).

URI parsing pinned by `subGraphFromAssertionGraphUri`'s existing
cases in `use-assertion-lifecycle-events.test.ts`; not duplicated.
Comment thread packages/node-ui/src/ui/views/project/components.tsx
Comment thread packages/node-ui/src/ui/api.ts Outdated
Comment thread packages/node-ui/test/context-graph-empty-stat-components.test.ts
User visual review on `84a2fdbab` flagged the `🗂` (FOLDER) glyph
rendering full-colour on Windows despite `--text-tertiary` on the
chip — colour-emoji fonts override the CSS colour, so the chip
shouted vs the rest of the meta-row.

ux-lead pick: `›` (U+203A, single right-pointing angle quotation
mark). Monochrome Unicode (dodges the color-emoji caveat),
inherits `--text-tertiary` cleanly, reads as "scope into / drill
in" — semantically right for "this assertion is inside that
sub-graph". Considered + rejected by ux-lead:
- `▸` reads as expand/play (state action, not containment)
- `└` implies tree hierarchy that doesn't exist here
- `◫` sparse monospace coverage

Single-character edit in `components.tsx` at the chip render
site. No layout / CSS / helper / conditional change.

Tests: `context-graph-empty-stat-components.test.ts` asserts on
slug text + ellipsis + tooltip, never on the glyph itself, so
they need no update. Confirmed by grep — only one `🗂` literal
existed in the codebase (the swap site).

CSS-style verification:
- `tsc --noEmit` clean.
- Focused suite: 27/27 (13 lifecycle + 14 empty-stat).
- `pnpm build:ui` produced `index-C5vosJX4.js` (content hash
  flipped from prior bundle). Binary check: `e2 80 ba` (U+203A)
  present, zero `🗂` occurrences in the bundle.
Comment thread packages/node-ui/src/ui/views/project/components.tsx
Comment thread packages/node-ui/test/context-graph-empty-stat-components.test.ts
Comment thread packages/node-ui/src/ui/api.ts Outdated
…er test

Fix A — promote handlers thread `subGraph` to the daemon. Sub-graph
assertions surfaced in the WM/SWM list (PR #706) became clickable,
but the four `promoteAssertion()` call sites only sent
`(contextGraphId, name)`. Daemon's lookup key is
`(contextGraphId, name, subGraphName)`, so promoting a sub-graph
assertion either 404'd or silently hit a same-named root one. Wire
shape stays root-bucket-compatible — `subGraphName` is only spread
when supplied.

api.ts:
- `promoteAssertion(contextGraphId, assertionName, entities='all',
  subGraphName?)`. Daemon route already accepts `subGraphName` in
  the body (`packages/cli/src/daemon/routes/assertion.ts:820-823`);
  no daemon change.

components.tsx — four call sites + one closure-shape touch:
- `LayerWidgetStrip` bulk-promote loop (line ~1564) → passes
  `a.subGraph`.
- `AssertionsList.handlePromote(name, subGraph?)` per-row handler
  (line ~2689) + the per-row button (line ~2812) now passes
  `a.subGraph` through.
- `AssertionsList.handlePromoteAll` bulk loop (line ~2722) →
  passes `a.subGraph`.
- `EntityPromoteButton` per-entity promote (line ~3100) → uses
  `sgBinding!.subGraph`. `sgBinding` reshaped from `binding | null`
  to `{ binding, subGraph } | null` so the matched slug travels
  with the binding (it was already known in the lookup loop —
  just discarded). All `sgBinding.sourceAssertion` references
  updated to `sgBinding.binding.sourceAssertion`.

Fix B — module cycle broken by relocating the parser.
`api.ts → useAssertionLifecycleEvents.ts → api.ts` worked under
ESM hoisting but was brittle, and conceptually wrong (pure string
parser pulled into the transport layer via a React hook module).

- New `packages/node-ui/src/ui/lib/sub-graph-uri.ts` —
  `subGraphFromAssertionGraphUri` moved verbatim (JSDoc preserved,
  plus a note explaining why it lives in `lib/`).
- `api.ts` import path updated.
- `useAssertionLifecycleEvents.ts` — local definition deleted,
  helper now imported from `lib/`. No re-export shim per
  dkg-v9 no-backwards-compat rule.
- Tests for `subGraphFromAssertionGraphUri` moved out of
  `use-assertion-lifecycle-events.test.ts` into a new focused
  `test/sub-graph-uri.test.ts` (4 cases, contents identical).

Fix C — direct test for `listAssertions` URI parsing. The
existing `context-graph-empty-stat-components.test.ts` mocks
`listAssertions` itself, so a regression in the api.ts parser
wouldn't be caught.

- New `packages/node-ui/test/list-assertions.test.ts` (5 cases):
  root-bucket parse + subGraph=undefined; sub-graph + root in
  one response (#706 regression guard); malformed graph URIs
  silently dropped; `cgPrefix` scoping (other-CG bindings AND
  `cg-A-suffix` shape both rejected by the trailing-slash
  prefix); empty-result path.
- Mocks `globalThis.fetch` rather than `vi.mock`ing the api
  module — `listAssertions` calls `executeQuery` intra-module,
  and ES intra-module refs don't pick up the mocked export.
  Same pattern as `use-swm-attributions.test.ts` from PR #694.

SWM-branch test deferred (the brief listed it as optional —
`dkg:ShareTransition` binding shape needs more fixture setup);
the `subGraph` field on SWM is already covered by the existing
component test via the mocked `listAssertions` shape.

Verification:
- `tsc --noEmit` clean.
- Focused suite: 32/32 (context-graph-empty-stat 14 +
  use-assertion-lifecycle 9 [4 fewer — helper tests moved] +
  sub-graph-uri 4 [new] + list-assertions 5 [new]).
- `pnpm build:ui` green; bundle picks up the new promote
  handler wiring.
Comment thread packages/node-ui/src/ui/api.ts
…710 follow-up)

Second consumer of `listAssertions('wm')` missed by the prior
Fix A pass — `MemoryLayerView.tsx`'s `AssertionList` has the same
single-row + bulk-loop shape as `AssertionsList` in components.tsx
but lives in its own file, so it didn't surface in the prior grep
sweep. Same data path → same daemon `(cg, name, subGraph)` lookup
bug if a sub-graph-scoped assertion is promoted from this view.

Three-touch fix mirrors the AssertionsList pattern verbatim:
- `handlePromote(name, subGraph?)` — adds the optional 4th arg
  and threads it to `promoteAssertion`.
- Per-row button onClick — passes `a.subGraph` through.
- `handlePromoteAll` bulk loop — passes `a.subGraph` per row.

No tests changed; the data contract is pinned by
`list-assertions.test.ts` and the callsite-correctness is
mechanically identical to the now-tested AssertionsList path.

Verification:
- `tsc --noEmit` clean.
- Focused suite: 32/32 (context-graph-empty-stat 14 +
  use-assertion-lifecycle 9 + sub-graph-uri 4 + list-assertions 5).
- `pnpm build:ui` green.
Comment thread packages/node-ui/src/ui/views/project/components.tsx Outdated
Comment thread packages/node-ui/src/ui/views/MemoryLayerView.tsx Outdated
Two more identity-by-name leaks in the same root-cause family as
the prior promote fixes: `name` is no longer a unique identifier
once root + sub-graph partitions can share names.

Fix D — busy state + React keys must use `graphUri` (🔴):

`AssertionsList` (`components.tsx`) and `AssertionList`
(`MemoryLayerView.tsx`) both keyed transient UI state on `name`.
A root + sub-graph pair with the same name (e.g. both partitions
have a `draft`) would render duplicate React keys, highlight both
rows as busy on a single click, and surface the wrong result
message. Switched both to `graphUri` (daemon-produced, unique).

`handlePromote` reshaped from `(name, subGraph?)` to
`(assertion: AssertionInfo)` — pulls all three fields (name,
subGraph, graphUri) from one source rather than threading
positional args that drift apart. `AssertionInfo` type import
added to `components.tsx` (was inferential through
`listAssertions` return); already imported in MemoryLayerView.

Touch list:
- `components.tsx` lines ~2691 (handler), ~2792 (key), ~2812
  (onClick), ~2813/2815 (busy comparisons).
- `MemoryLayerView.tsx` lines ~399 (handler), ~457 (key), ~473
  (onClick), ~476 (busy comparison).
- `'__all__'` sentinel kept — not collidable with any graphUri.

Fix E — file preview / extraction-status by name only (🔴):

`previewName: string | null` + `fetchExtractionStatus(name, cg)`
lost the sub-graph context. Clicking a sub-graph-scoped imported
assertion's filename queried the root-bucket assertion → 404 or
wrong file. Daemon route already accepts `subGraphName` query
param (`packages/cli/src/daemon/routes/assertion.ts:3364`).

`api.ts:fetchExtractionStatus` extended to accept `subGraphName?`
4th arg, built with `URLSearchParams` (per the brief's "cleaner
than hand-rolling `&subGraphName=…`"); only set when supplied.

`FilePreviewModal` props gained `subGraphName?`; the useEffect
forwards it to `fetchExtractionStatus` and lists `subGraphName`
in its deps array so a preview change re-triggers the fetch.

`MemoryLayerView` `previewName: string | null` reshaped to
`preview: { name; subGraph? } | null`; all setters and the
`<FilePreviewModal …>` mount updated to carry the slug.
`FilePreviewModal` is mounted at only one site (grep confirmed)
so no other consumers to update.

Test fixtures: the prior #706 + SWM fixtures in
`context-graph-empty-stat-components.test.ts` were missing
`graphUri` — pre-Fix D the React key fell back to `name` (always
defined); post-Fix D the key is `graphUri` (would have been
undefined). Updated three fixture lines to include `graphUri`
with the canonical daemon shape; re-run confirms no React
key-warning in stderr. Per brief: no net-new test cases — D/E
are identity-shape changes, not new parsing rules; existing
`list-assertions.test.ts` pins the upstream data contract.

Verification:
- `tsc --noEmit` clean.
- Focused suite: 32/32 (context-graph-empty-stat 14 +
  use-assertion-lifecycle 9 + sub-graph-uri 4 + list-assertions 5).
  React key-warning gone from stderr.
- `pnpm build:ui` green; bundle picks up the threaded
  `subGraphName` on `fetchExtractionStatus` calls.
Comment thread packages/node-ui/src/ui/api.ts Outdated
The prior `g.indexOf('/assertion/')` searched the full URI. Because
`validateContextGraphId` permits slashes, a cgId can literally
contain `/assertion/` as a substring, and the indexOf would have
hit the cgId's internal `/assertion/` rather than the delimiter
after the cg prefix — mis-parsing both the name and the sub-graph.

Tail-scope the parse: take everything after `cgPrefix`, then
discriminate inside the tail. Branches:
  - tail starts with `assertion/`            → root-bucket
  - tail contains `/assertion/`              → sub-graph-scoped
  - otherwise                                → drop

This subsumes the prior outer `.includes('/assertion/')` filter and
removes the cgId-substring failure mode. Same family as the earlier
wmSparql asymmetry — `subGraphFromAssertionGraphUri` was already
tail-scoped; only this site and the outer filter still operated on
the full URI.

Test pins the regression: a cgId containing `/assertion/` should
still parse a binding whose tail is `assertion/<agent>/<name>` to
`{ name: 'foo', subGraph: undefined }`.
Comment thread packages/node-ui/src/ui/api.ts Outdated
The prior `tail.indexOf('/assertion/')` branch admitted any tail with
`/assertion/` anywhere inside, including shapes like
`foo/bar/assertion/<agent>/<name>` (3+ segments before `assertion/`).
`subGraphFromAssertionGraphUri` returned `undefined` for those —
`segments[1]` isn't `'assertion'` — so the row got admitted as a
root assertion with a mis-derived name. Promote/preview lookups
key on `name` and would silently miss.

Replace the indexOf-based branches with a strict segment-count parse
on the tail (post-cgPrefix):

  ['assertion', <agent>, <name>]              → root-bucket   (3 segs)
  [<sg>, 'assertion', <agent>, <name>]        → sub-graph     (4 segs)
  anything else                                → drop

Drop the call to `subGraphFromAssertionGraphUri` from this site (and
the now-unused import) — the strict segment parse derives the slug
in one pass and the helper stays in `lib/` for the lifecycle hook.

Tests pin both edges of the strict contract: a 3+-segments-before-
`assertion/` binding is rejected, and a sub-graph binding with an
extra segment after `<name>` is rejected.
Comment thread packages/node-ui/src/ui/views/MemoryLayerView.tsx
…moryLayerView

After #706 surfaced both root + sub-graph assertions in the same WM
list, two rows literally labeled `draft` are indistinguishable in
the `MemoryLayerView` `AssertionList` row, even though the promote
and preview handlers already key on `graphUri` and route correctly.
The `› <slug>` chip closed the same gap for `AssertionsList`
(components.tsx) in the original #706; we missed the second
consumer.

Three small changes:

  1. Lift `truncateMiddle` from `components.tsx` into
     `lib/truncate.ts` so both consumers share one definition —
     same `lib/` pattern as `sub-graph-uri.ts` from the prior
     PR #710 fix.
  2. Render the chip in the `MemoryLayerView` row using the
     identical JSX pattern from `AssertionsList` (same class,
     same `›` glyph, same 18-char mid-truncation, same tooltip).
  3. Disambiguate the success message by carrying `subGraph` on
     `promoteResult` and rendering `" (in <slug>)"` after the
     assertion name when set. Root rows keep the prior wording.
Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

Codex review completed — no issues found.

@Jurij89 Jurij89 merged commit 387b0e0 into main May 27, 2026
36 checks passed
Jurij89 pushed a commit that referenced this pull request Jun 1, 2026
…877 c1)

Drafts created before #710 carry `dkg:assertionGraph` in `_meta` but no
`dkg:subGraphName`, so the _meta-derived WM listing would surface them as
root-bucket and mis-scope promote/preview lookups for that migration window.

Re-bind `?assertionGraph` in the WM SELECT and derive the sub-graph scope as:
explicit `dkg:subGraphName` literal when present (authoritative, since #710),
else parse the sub-graph segment out of the assertion-graph URI via the
existing `subGraphFromAssertionGraphUri` helper (the same migration fallback
the lifecycle hook uses). `graphUri` stays the lifecycle URN (?assertion); no
data-graph/triple filter is added (that would reintroduce the promoted-
assertion-leak the _meta approach fixes).

Tests: list-assertions.test.ts adds pre-#710 compat (subGraph from URI when
subGraphName absent; root-bucket legacy URI stays root) + literal-wins-over-
URI precedence — 9 tests. node-ui tsc --noEmit clean; full node-ui suite 87
files / 1246 passed / 38 skipped / 0 fail (--no-file-parallelism), modulo the
known openclaw-bridge flake.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Jurij89 added a commit that referenced this pull request Jun 1, 2026
… _meta) (#877)

* fix(node-ui): derive WM assertions list from _meta (fix #844 empty-state regression)

Merge #844 added an opt-in includeContextGraphPartitions flag to the query
engine; by default a `GRAPH ?g { ?s ?p ?o }` enumeration is clamped to a
meta-only allow-list (<cg>/_meta, <cg>/_shared_memory_meta), so per-assertion
data graphs are no longer enumerated. useMemoryEntities.ts was migrated (the
count badges work), but the WM branch of listAssertions was missed: its
`GRAPH ?g` enumeration returned only meta graphs, every assertion row was
filtered out, and the Assertions subtab rendered "No Working Memory
assertions yet." despite WM having data.

Fix is frontend-only (the gate is intentional and security-reviewed): derive
WM assertions from the <cg>/_meta lifecycle graph (which IS in the default
allow-list, so no opt-in needed), filtering dkg:Assertion + dkg:memoryLayer
"WM" + dkg:assertionName. memoryLayer is mutable and flips to "SWM" on
promote, so promoted assertions correctly drop out of the WM list. graphUri
is the lifecycle URN (?assertion) — SWM-consistent and stable across promote;
subGraph comes from dkg:subGraphName (#710). Dedup on the lifecycle URN.
Mirrors the proven SWM branch; reuses bv(). No triple-count chip on WM rows
(SWM-parity; renderer guards tripleCount != null).

Rewrites list-assertions.test.ts WM fixtures around the _meta contract
(?assertion ?name ?sg): root-bucket, sub-graph-scoped, skip-incomplete,
DISTINCT dedup, no-tripleCount, empty — 7 tests.

node-ui tsc clean; list-assertions.test.ts 7/7; full node-ui suite 87 files /
1244 passed / 38 skipped / 0 fail (--no-file-parallelism), modulo the known
pre-existing openclaw-bridge flake. Live node: new query returns 6 WM rows for
ui-refresh / 1 for medical-data; negative control (old GRAPH ?g) returns only
the two meta graphs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(node-ui): pre-#710 sub-graph fallback in WM listAssertions (Codex #877 c1)

Drafts created before #710 carry `dkg:assertionGraph` in `_meta` but no
`dkg:subGraphName`, so the _meta-derived WM listing would surface them as
root-bucket and mis-scope promote/preview lookups for that migration window.

Re-bind `?assertionGraph` in the WM SELECT and derive the sub-graph scope as:
explicit `dkg:subGraphName` literal when present (authoritative, since #710),
else parse the sub-graph segment out of the assertion-graph URI via the
existing `subGraphFromAssertionGraphUri` helper (the same migration fallback
the lifecycle hook uses). `graphUri` stays the lifecycle URN (?assertion); no
data-graph/triple filter is added (that would reintroduce the promoted-
assertion-leak the _meta approach fixes).

Tests: list-assertions.test.ts adds pre-#710 compat (subGraph from URI when
subGraphName absent; root-bucket legacy URI stays root) + literal-wins-over-
URI precedence — 9 tests. node-ui tsc --noEmit clean; full node-ui suite 87
files / 1246 passed / 38 skipped / 0 fail (--no-file-parallelism), modulo the
known openclaw-bridge flake.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Jurij Skornik <jurij.skornik@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
matic031 pushed a commit to KilianTrunk/dkg that referenced this pull request Jun 2, 2026
Brings forward 3 node-ui UI bug fixes that landed on main but hadn't
yet flowed into the release branch:

  - 902a618 fix(node-ui): entity tripleCount matches Triples tab
    (count type + multi-value + incoming) (OriginTrail#728)
  - 76b86b9 fix(node-ui): SubGraphBar "All" pill now matches layer
    tab badge (OriginTrail#725)
  - 387b0e0 fix(node-ui): WM Assertions tab surfaces sub-graph
    assertions (OriginTrail#706) (OriginTrail#710)

All three touch only node-ui files (UI + UI tests); no runtime / chain
/ publisher / agent surface area touched. Auto-merge with rc.12 was
clean — one file (`packages/node-ui/src/ui/api.ts`) merged
automatically with no conflicts.
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.

Node UI: WM Assertions tab silently drops sub-graph assertions

1 participant