Skip to content

fix(node-ui): read SWM/VM attribution across all sub-graph partitions (B2)#1055

Merged
Jurij89 merged 4 commits into
rc17-vm-wipfrom
fix/b2-swm-attribution-subgraph-scoping
Jun 8, 2026
Merged

fix(node-ui): read SWM/VM attribution across all sub-graph partitions (B2)#1055
Jurij89 merged 4 commits into
rc17-vm-wipfrom
fix/b2-swm-attribution-subgraph-scoping

Conversation

@Jurij89

@Jurij89 Jurij89 commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Fixes B2 (DKG-NODE-ISSUES-FOR-RC17): the node-UI SWM Attribution legend under-counted contributing agents in one-agent-per-sub-graph deployments — it showed 1 agent when 5 had attributed (live on-disk: Curator 1, Literature 11, Trials 4, Mechanism 4, Synthesis 1).
  • Root cause: useSwmAttributions already scopes its query to the context graph (CG) inside the SPARQL via FILTER(STRSTARTS(STR(?g), "did:dkg:context-graph:<cg>") && CONTAINS(STR(?g), "_shared_memory_meta")), so it intends to read every sub-graph's …/<sg>/_shared_memory_meta partition. But it also sent contextGraphId in the /api/query body. With contextGraphId set and no view, the query engine constrains the GRAPH ?g variable to a CG-direct allow-list (dkg-query-engine.ts graph-variable allow-list) that excludes per-sub-graph _shared_memory_meta partitions, so the STRSTARTS filter can never bind them. Only the CG-direct partition's agents were counted.
  • Fix: omit contextGraphId from the POST body. The SPARQL's own STRSTARTS filter already scopes to the CG and reaches all partitions — the same raw-query pattern the integration's swm-scan runbook uses. Note: includeContextGraphPartitions:true would not fix this (per A4 the partition-discovery allow-list skips _shared_memory_meta entirely); omitting contextGraphId is the proven path.
  • Also fixes the identical bug in useVerifiedMemoryAnchors (VM on-chain anchor decorations) — same STRSTARTS + _shared_memory_meta query whose own docstring says it enumerates "every sub-graph's _shared_memory_meta", silently scoped to the CG-direct partition by the same contextGraphId. Directly relevant to this VM-focused base branch.
  • Safe by construction (B2a): the per-entity detail view ("Proposed by" / provenance trail) reads the entity's own prov:wasAttributedTo (data-graph scoped, a separate path) and is unchanged. useAssertionLifecycleEvents is intentionally left alone — it targets a hardcoded CG-level GRAPH <…/_meta> (no sub-graph partitions), where contextGraphId is legitimately required.

Related

  • Fixes B2 in DKG-NODE-ISSUES-FOR-RC17.md (medical-research showcase feedback).
  • Regression origin: 4935dafc1 ("feat(node-ui): dkg-v9 subgraphs PoC") added contextGraphId to the attribution fetch — harmless before sub-graphs existed (all SWM attribution lived in CG-direct graphs), but it began dropping per-sub-graph partitions once data moved into them.
  • Related deferred query-engine items (not addressed here): A1/A2/A4 — declarative view / includeContextGraphPartitions routing for sub-graph SWM. This PR is the client-side one-line workaround that makes the UI correct today.

Files changed

File What
packages/node-ui/src/ui/hooks/useSwmAttributions.ts Drop contextGraphId from the /api/query body so the attribution query reaches every sub-graph _shared_memory_meta; comment explaining why it must not be re-added.
packages/node-ui/src/ui/hooks/useVerifiedMemoryAnchors.ts Same fix for the VM anchor query (same bug class).
packages/node-ui/test/use-swm-attributions.test.ts New regression test asserting the POST body omits contextGraphId; update the stale-on-switch mock to route by the cgId embedded in the SPARQL (body no longer carries it).
packages/node-ui/test/use-verified-memory-anchors.test.ts New test asserting the VM anchor POST body omits contextGraphId.

Test plan

  • vitest run test/use-swm-attributions.test.ts test/use-verified-memory-anchors.test.ts4 passed (3 SWM incl. the new B2 guard + the existing Code5/Code7 cases; 1 VM anchors).
  • Full node-ui suite (pnpm --filter @origintrail-official/dkg-node-ui test): 0 test-assertion failures, +2 passing vs the clean base. The branch has ~10 pre-existing flaky file-level failures in stateful suites (db / notifications / messenger-stores / chat-memory / etc.) — reproduced on the clean base with these changes stashed, and the failing set shifts run-to-run; none relate to SWM/VM attribution.
  • pnpm --filter @origintrail-official/dkg-node-ui build (tsc) → clean.
  • Live-verified on the showcase node (rc.16): with contextGraphId the daemon returns 1 agent (~16s); without it, 5 agents / 2,084 rows (~0.23s). The legend now renders all five contributing agents.

Known limitations (accepted)

  • The query scopes to the CG via an exact STRSTARTS(?g, "<cgUri>/") prefix, which correctly excludes siblings like cg-10/cg-1-foo. However, validateContextGraphId permits / inside CG ids (convention <addr>/<name>), so a path-extending child CG <cg>/<x> produces a graph URI byte-identical to a real sub-graph <sg>=<x> of <cg>. Only the sub-graph registry can disambiguate the two; doing so authoritatively is the deferred server-side sub-graph SWM routing (A2/A4).
  • A client-built registry allow-list (/api/sub-graph/list) was considered and rejected: it re-introduces a B2-class under-count whenever a present sub-graph's _meta registration is missing — a condition this showcase hit live (deriveCuratorDidFromCgId and the runbook's "missing sub-graph registration step" exist for exactly that). The raw-prefix read surfaces whatever partitions physically exist, which is more robust under those gaps.
  • Net: this is the deliberate client-side bridge until A2/A4 lands; the residual child-CG case requires a non-conventional multi-slash CG id with a prefix collision co-resident on the node. Documented in code (e2466174a). Maintainer-accepted.
  • Authoritative fix tracked in Query engine: union all sub-graph SWM + attribution partitions for CG-wide view reads (A2/A4) #1056 (CG-wide sub-graph SWM + attribution view routing, A2/A4) — builds on discoverKnownChildContextGraphUris from Enable subGraphName scoping with view-based routing in the query engine #184/Support subgraph-scoped view routing #1037; once it lands, these hooks can drop the raw-prefix read.

… (B2)

The SWM Attribution legend (useSwmAttributions) and the VM anchor
decorations (useVerifiedMemoryAnchors) query every sub-graph's
_shared_memory_meta partition via a STRSTARTS(?g, <cgUri>) filter, but
also sent contextGraphId in the /api/query body. With contextGraphId and
no view, the query engine constrains GRAPH ?g to a CG-direct allow-list
that excludes the per-sub-graph _shared_memory_meta partitions, so the
filter could never reach them: the legend showed 1 agent when 5 had
attributed in a one-agent-per-sub-graph deployment.

Fix: omit contextGraphId from both fetch bodies. The SPARQL's own
STRSTARTS filter already scopes to the CG and reaches all partitions (the
same raw-query pattern the integration's swm-scan runbook uses).
Per-entity detail-view attribution (B2a) is unaffected: it reads the
entity's own prov:wasAttributedTo, a separate data-graph path.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Comment thread packages/node-ui/src/ui/hooks/useSwmAttributions.ts
Codex review (PR #1055): with contextGraphId removed (B2), scoping rests
entirely on the SPARQL STRSTARTS prefix. The bare
"did:dkg:context-graph:<cg>" prefix is not exact and would also match a
sibling CG (e.g. cg-10, cg-1-foo), merging its _shared_memory_meta rows
into the legend/anchors.

Add a trailing slash so the prefix is exact: every partition graph is
did:dkg:context-graph:<cg>/[<sg>/]_shared_memory_meta, so "<cgUri>/"
matches all of this CG's partitions and excludes siblings. Applied to
buildAttributionsQuery and buildAnchorsQuery; added query-shape guards
asserting the exact prefix.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Comment thread packages/node-ui/src/ui/hooks/useSwmAttributions.ts
…fix scoping

Codex flagged that, since CG ids may contain "/", a path-extending child CG
`<cg>/<x>` is URI-identical to a real sub-graph `<sg>=<x>` and would still
match the exact "<cgUri>/" prefix. Disambiguating needs the sub-graph
registry (the deferred server-side SWM routing, A2/A4). Document this as a
known limitation in both query builders and the rationale for preferring the
raw-prefix read over a client-built registry allow-list (which would re-drop
partitions whose _meta registration is missing — a condition seen live).

No behavior change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Comment thread packages/node-ui/src/ui/hooks/useSwmAttributions.ts
Comment thread packages/node-ui/test/use-swm-attributions.test.ts Outdated
…ining cgId

Codex: the deferred-promise mock recovered the cgId via `[^"/]+`, which
truncates a canonical `<wallet>/project` id at the first slash, so the
Code7 test could pass while routing under the wrong key. Parse the full
quoted STRSTARTS prefix up to the trailing `/"` instead, and switch the
test's ids to slash-containing (`acme/alpha`, `acme/beta`) so it actually
exercises that path — the old regex would now route them under `acme` and
fail the test.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Comment thread packages/node-ui/src/ui/hooks/useSwmAttributions.ts
@Jurij89 Jurij89 merged commit 0e7e849 into rc17-vm-wip Jun 8, 2026
3 checks passed
branarakic added a commit that referenced this pull request Jun 8, 2026
Brings in #1055 (node-ui SWM/VM attribution) + the rc.17 CI fixes (file-serving route, handle-request, hermes tests) so the #1019 PR diffs cleanly against the current base. Sole conflict was publish-jsonld.test.ts: both branches independently repointed the 3 confirmed-publish VM-read fixtures at the per-KA _verified_memory graph — resolved to the base's canonical read-both queries (root OR _verified_memory/, staging-excluded); my 4 async-lift it.skip deferrals are preserved.
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.

1 participant