Skip to content

feat(intelligence): add Graph Core (k-core decomposition)#2980

Open
aashir-athar wants to merge 2 commits into
tinyhumansai:mainfrom
aashir-athar:feat/graph-core
Open

feat(intelligence): add Graph Core (k-core decomposition)#2980
aashir-athar wants to merge 2 commits into
tinyhumansai:mainfrom
aashir-athar:feat/graph-core

Conversation

@aashir-athar
Copy link
Copy Markdown
Contributor

@aashir-athar aashir-athar commented May 29, 2026

Summary

Adds a new read-only "Core" tab to the Intelligence view: k-core decomposition of the memory knowledge graph. Where Centrality asks "which entities are important" (PageRank), this lens asks "how deep in the densely-connected core does each entity sit" — separating the load-bearing core of the user's knowledge (entities mutually reinforced by many interlinked facts) from the periphery of leaves and bridges.

The key insight: a high-degree hub of one-off facts still has coreness 1, while a modest entity embedded in a dense cluster has high coreness. Depth, not degree, marks the core — and neither a frequency count nor PageRank captures it.

Design

  • Pure deterministic engine (lib/memory/graphCore.ts): treats the (subject)-[predicate]->(object) triples as an undirected simple graph (direction dropped, parallel edges collapsed, self-loops dropped) and computes:
    • coreness per node via the Batagelj–Zaversnik O(V+E) bucket algorithm (the largest k for which a node survives in the k-core),
    • degeneracy (the max coreness — the depth of the densest shell) and the shell decomposition,
    • kCoreSize(k) for the nested k-core sizes.
    • Coreness is a graph invariant, and the peel is seeded from an id-sorted vertex list, so the result is byte-identical regardless of relation input order. No clock, no RNG, all-integer math.
  • Zero new core surface: composes the already-shipped memoryGraphQuery / memoryListNamespaces JSON-RPC wrappers. Read-only — recomputed live, never persisted.
  • Container/presentational split; the container guards load-on-mount with a monotonic request token. i18n across all 13 locales.

Test plan

  • vitest — 28 tests (engine: empty / triangle (uniform 2-core) / path (1-core) / star-tree (hub high-degree but coreness 1) / K4 (uniform 3-core) / triangle-with-pendant (core=2, pendant=1) with hand-derived coreness; shell decomposition; kCoreSize nested cores; self-loop drop; parallel-edge & direction collapse; malformed-row drop; no case-folding; order-independent output — plus api facade, panel states + shell histogram + core badge, container load/namespace-requery/error)
  • tsc --noEmit — clean
  • eslint — 0 errors
  • prettier --check — clean
  • i18n coverage gate — EXIT 0, no missing/extra/drifted keys across 13 locales

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added a "Graph Core" analysis view in Intelligence showing k‑core metrics (entities, connections, degeneracy), shell decomposition progress, and a ranked list of deepest‑core entities with namespace filtering, loading/error/empty states, and retry.
  • Localization

    • Added translations for the Graph Core UI across 12 languages.
  • Tests

    • Added comprehensive unit and UI tests for core decomposition, API interactions, and the new UI behaviors.

Review Change Stack

@aashir-athar aashir-athar requested a review from a team May 29, 2026 20:32
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 29, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ff418bda-d035-41b9-ade2-177aa61bba34

📥 Commits

Reviewing files that changed from the base of the PR and between c597bc9 and e7af154.

📒 Files selected for processing (23)
  • app/src/components/intelligence/GraphCorePanel.test.tsx
  • app/src/components/intelligence/GraphCorePanel.tsx
  • app/src/components/intelligence/GraphCoreTab.test.tsx
  • app/src/components/intelligence/GraphCoreTab.tsx
  • app/src/lib/i18n/chunks/ar-1.ts
  • app/src/lib/i18n/chunks/bn-1.ts
  • app/src/lib/i18n/chunks/de-1.ts
  • app/src/lib/i18n/chunks/en-1.ts
  • app/src/lib/i18n/chunks/es-1.ts
  • app/src/lib/i18n/chunks/fr-1.ts
  • app/src/lib/i18n/chunks/hi-1.ts
  • app/src/lib/i18n/chunks/id-1.ts
  • app/src/lib/i18n/chunks/it-1.ts
  • app/src/lib/i18n/chunks/ko-1.ts
  • app/src/lib/i18n/chunks/pt-1.ts
  • app/src/lib/i18n/chunks/ru-1.ts
  • app/src/lib/i18n/chunks/zh-CN-1.ts
  • app/src/lib/i18n/en.ts
  • app/src/lib/memory/graphCore.test.ts
  • app/src/lib/memory/graphCore.ts
  • app/src/pages/Intelligence.tsx
  • app/src/services/api/graphCoreApi.test.ts
  • app/src/services/api/graphCoreApi.ts
✅ Files skipped from review due to trivial changes (4)
  • app/src/lib/i18n/chunks/en-1.ts
  • app/src/lib/i18n/chunks/bn-1.ts
  • app/src/lib/i18n/chunks/de-1.ts
  • app/src/lib/i18n/chunks/id-1.ts
🚧 Files skipped from review as they are similar to previous changes (13)
  • app/src/components/intelligence/GraphCoreTab.test.tsx
  • app/src/lib/memory/graphCore.test.ts
  • app/src/lib/i18n/chunks/ru-1.ts
  • app/src/lib/i18n/en.ts
  • app/src/lib/i18n/chunks/hi-1.ts
  • app/src/lib/i18n/chunks/fr-1.ts
  • app/src/pages/Intelligence.tsx
  • app/src/lib/i18n/chunks/ko-1.ts
  • app/src/components/intelligence/GraphCoreTab.tsx
  • app/src/services/api/graphCoreApi.test.ts
  • app/src/lib/i18n/chunks/ar-1.ts
  • app/src/components/intelligence/GraphCorePanel.tsx
  • app/src/lib/memory/graphCore.ts

📝 Walkthrough

Walkthrough

Adds a deterministic k-core decomposition engine, a small API wrapper, a container tab and presentational panel with RTL tests, page integration, and translation keys across 14 locales.

Changes

Graph Core Analysis Feature

Layer / File(s) Summary
K-core decomposition algorithm and types
app/src/lib/memory/graphCore.ts
Implements Batagelj–Zaversnik-style k-core decomposition; exports CoreNode, CoreShell, CoreResult, computeGraphCore() and kCoreSize(). Handles self-loops, parallel edges, and deterministic ordering.
K-core algorithm test suite
app/src/lib/memory/graphCore.test.ts
Tests basic graph shapes, core/periphery separation, nested k-core sizes, normalization (self-loops, parallel edges), malformed relation handling, case-sensitivity, and input-order determinism.
Graph Core API service
app/src/services/api/graphCoreApi.ts, app/src/services/api/graphCoreApi.test.ts
loadCore(namespace?) queries Tauri RPC and returns computeGraphCore result; loadNamespaces() returns available namespaces. Tests validate namespace passthrough, defaults, error propagation, and public surface.
GraphCorePanel presentational component
app/src/components/intelligence/GraphCorePanel.tsx, app/src/components/intelligence/GraphCorePanel.test.tsx
Presentational UI rendering loading, error (with retry), empty, and results states. Results include metric tiles, degeneracy caption, shell decomposition bars, and ranked deepest-core table with "core" badges; tests cover all states and badge logic.
GraphCoreTab container component
app/src/components/intelligence/GraphCoreTab.tsx, app/src/components/intelligence/GraphCoreTab.test.tsx
Container that loads namespaces and core results, prevents stale responses via monotonic request-id, renders optional namespace selector, and wires retry to reload the current namespace. Tests cover initial load, namespace selection, and error handling.
Page integration and routing
app/src/pages/Intelligence.tsx
Registers new 'core' tab in Intelligence page and conditionally renders <GraphCoreTab /> when active.
Internationalization
app/src/lib/i18n/*.ts
Adds memory.tab.core and graphCore.* keys across English base and 13 locale chunks (ar, bn, de, es, fr, hi, id, it, ko, pt, ru, zh-CN, en-1) for UI labels, statuses, metrics, shell captions, and table headings.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant GraphCoreTab
  participant graphCoreApi
  participant computeGraphCore
  participant MemoryRPC
  User->>GraphCoreTab: open Core tab / select namespace
  GraphCoreTab->>graphCoreApi: loadNamespaces() (on mount)
  GraphCoreTab->>graphCoreApi: loadCore(namespace?)
  graphCoreApi->>MemoryRPC: memoryGraphQuery(namespace?)
  MemoryRPC-->>graphCoreApi: GraphRelation[]
  graphCoreApi->>computeGraphCore: computeGraphCore(relations)
  computeGraphCore-->>graphCoreApi: CoreResult
  graphCoreApi-->>GraphCoreTab: CoreResult
  GraphCoreTab-->>User: render via GraphCorePanel(result)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • graycyrus
  • sanil-23

Poem

🐰 I hopped through nodes and edges today,
Peeling shells of cores in playful array,
Buckets clicked and badges shone bright,
From RPC calls to rendered light,
Now deepest entities dance and stay.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 46.15% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'feat(intelligence): add Graph Core (k-core decomposition)' is specific, concise, and directly describes the primary change—introducing a new Graph Core feature that computes k-core decomposition in the Intelligence view.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot added feature Net-new user-facing capability or product behavior. memory Memory store, memory tree, recall, summarization, and embeddings in src/openhuman/memory/. working A PR that is being worked on by the team. labels May 29, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (1)
app/src/components/intelligence/GraphCorePanel.test.tsx (1)

34-34: ⚡ Quick win

Avoid hardcoding i18n strings in test assertions.

Tests assert against English strings like 'No knowledge graph yet.', 'Entities', 'Connections', 'Shell decomposition', etc. This tightly couples tests to the current i18n implementation. If translation keys or English text change, tests break even though component behavior is correct.

♻️ Use test IDs or semantic queries instead

Option 1 (preferred): Add data-testid attributes to key elements in the component and query by test ID:

 // In GraphCorePanel.tsx metric tiles section
-  <div className="text-[10px] uppercase tracking-wider text-stone-400 dark:text-neutral-500">
+  <div data-testid={`metric-${tile.label}`} className="text-[10px] uppercase tracking-wider text-stone-400 dark:text-neutral-500">

Then in tests:

-expect(screen.getByText('Entities')).toBeInTheDocument();
+expect(screen.getByTestId('metric-graphCore.metricEntities')).toBeInTheDocument();

Option 2: Query by ARIA roles and accessible names (already partially done for headings):

-expect(screen.getByText('Shell decomposition')).toBeInTheDocument();
+expect(screen.getByRole('heading', { name: /shell decomposition/i })).toBeInTheDocument();

Also applies to: 40-40, 47-56

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/src/components/intelligence/GraphCorePanel.test.tsx` at line 34, The
tests in GraphCorePanel.test.tsx hardcode i18n strings (e.g. the assertion using
screen.getByText('No knowledge graph yet.') and other checks for 'Entities',
'Connections', 'Shell decomposition'), making them brittle; update the tests to
avoid textual assertions by replacing screen.getByText usages with semantic
queries or test IDs (e.g. use getByRole/getByLabelText/getByTestId) and, if
necessary, add data-testid attributes to the GraphCorePanel component for the
specific elements being asserted (entities list header, connections header,
empty-state node) so tests assert on stable identifiers like
getByTestId('graph-empty-state') or getByRole('heading', { name: /Entities/i })
instead of English strings. Ensure all occurrences referenced in this diff (the
getByText at startLine 34 and other checks around lines 40 and 47–56) are
updated to use these semantic queries or test IDs.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/src/components/intelligence/GraphCorePanel.test.tsx`:
- Around line 1-6: Tests render GraphCorePanel directly but the component uses
useT() and needs I18nContext; update the tests to wrap renders with an I18n
provider. Import and use the project test helper (e.g. renderWithProviders or
renderWithI18n from app/src/test/test-utils.tsx) or create a small wrapper that
supplies I18nProvider, then replace bare render(...) calls with
renderWithProviders(...) (or renderWithI18n(...)) when mounting GraphCorePanel
so useT() has the required context.

In `@app/src/components/intelligence/GraphCoreTab.test.tsx`:
- Around line 41-45: Tests render GraphCoreTab without providing I18n context
causing useT() to throw; update the three GraphCoreTab tests that call
render(<GraphCoreTab />) (the case that asserts mockLoadCore and the two other
cases) to wrap the component in the existing test i18n provider helper from
app/src/test/ (use the shared test helper that mounts components with
I18nContext) so GraphCoreTab can call useT() during render, and keep assertions
on mockLoadCore and the screen text unchanged.

In `@app/src/components/intelligence/GraphCoreTab.tsx`:
- Around line 40-47: Refactor the useEffect in GraphCoreTab.tsx to an
async/await flow: create and immediately invoke an async function inside
useEffect that awaits loadNamespaces() and calls setNamespaces(...) in the
success path, and catches errors to call setNamespaces([]); also await load('')
and handle its errors. Add diagnostic debug logs around these steps (e.g.,
before/after awaiting loadNamespaces(), on namespace success with the returned
value, on namespace failure including the caught error, before/after calling
load(''), and on load error) using the project logger used elsewhere so failures
are observable. Ensure you keep the behavior that namespace failures do not
block the core view (still setNamespaces([]) on error) and preserve the
dependency array ([load]).

In `@app/src/lib/memory/graphCore.ts`:
- Around line 71-76: The loop that strips self-loops in computeGraphCore
currently returns before registering nodes, so change the relation-handling loop
to always ensure both endpoints are registered via neighbours(subject) and
neighbours(object) (or the method that initializes node entries) before skipping
edge addition when subject === object; keep the continue for not adding
self-loop edges but do not skip node registration. Update logic in the block
that uses isRelation and neighbours to only skip adding edges for self-loops,
not node creation, and add a regression test for computeGraphCore([A→A])
asserting nodeCount === 1 and that the node has degree: 0 and coreness: 0.

---

Nitpick comments:
In `@app/src/components/intelligence/GraphCorePanel.test.tsx`:
- Line 34: The tests in GraphCorePanel.test.tsx hardcode i18n strings (e.g. the
assertion using screen.getByText('No knowledge graph yet.') and other checks for
'Entities', 'Connections', 'Shell decomposition'), making them brittle; update
the tests to avoid textual assertions by replacing screen.getByText usages with
semantic queries or test IDs (e.g. use getByRole/getByLabelText/getByTestId)
and, if necessary, add data-testid attributes to the GraphCorePanel component
for the specific elements being asserted (entities list header, connections
header, empty-state node) so tests assert on stable identifiers like
getByTestId('graph-empty-state') or getByRole('heading', { name: /Entities/i })
instead of English strings. Ensure all occurrences referenced in this diff (the
getByText at startLine 34 and other checks around lines 40 and 47–56) are
updated to use these semantic queries or test IDs.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ebcae14e-36a6-4009-bbba-4da74d8eea71

📥 Commits

Reviewing files that changed from the base of the PR and between 2920e47 and d9f07a4.

📒 Files selected for processing (23)
  • app/src/components/intelligence/GraphCorePanel.test.tsx
  • app/src/components/intelligence/GraphCorePanel.tsx
  • app/src/components/intelligence/GraphCoreTab.test.tsx
  • app/src/components/intelligence/GraphCoreTab.tsx
  • app/src/lib/i18n/chunks/ar-1.ts
  • app/src/lib/i18n/chunks/bn-1.ts
  • app/src/lib/i18n/chunks/de-1.ts
  • app/src/lib/i18n/chunks/en-1.ts
  • app/src/lib/i18n/chunks/es-1.ts
  • app/src/lib/i18n/chunks/fr-1.ts
  • app/src/lib/i18n/chunks/hi-1.ts
  • app/src/lib/i18n/chunks/id-1.ts
  • app/src/lib/i18n/chunks/it-1.ts
  • app/src/lib/i18n/chunks/ko-1.ts
  • app/src/lib/i18n/chunks/pt-1.ts
  • app/src/lib/i18n/chunks/ru-1.ts
  • app/src/lib/i18n/chunks/zh-CN-1.ts
  • app/src/lib/i18n/en.ts
  • app/src/lib/memory/graphCore.test.ts
  • app/src/lib/memory/graphCore.ts
  • app/src/pages/Intelligence.tsx
  • app/src/services/api/graphCoreApi.test.ts
  • app/src/services/api/graphCoreApi.ts

Comment on lines +1 to +6
import { fireEvent, render, screen } from '@testing-library/react';
import { describe, expect, it, vi } from 'vitest';

import { computeGraphCore } from '../../lib/memory/graphCore';
import type { GraphRelation } from '../../utils/tauriCommands/memory';
import GraphCorePanel from './GraphCorePanel';
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.

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Missing I18n context provider for component tests.

GraphCorePanel calls useT() (line 21 of the component), which requires an I18nContext provider, but these tests use bare render() from @testing-library/react without wrapping the component in any provider. The tests will fail at runtime when useT() attempts to access the missing context.

🔧 Wrap renders in I18n provider

Check if app/src/test/test-utils.tsx exports a renderWithProviders helper that includes I18nProvider. If so, import and use it:

-import { fireEvent, render, screen } from '`@testing-library/react`';
+import { fireEvent, screen } from '`@testing-library/react`';
 import { describe, expect, it, vi } from 'vitest';

+import { render } from '../../test/test-utils';
 import { computeGraphCore } from '../../lib/memory/graphCore';

If renderWithProviders does not include I18nProvider, you can create a local wrapper:

+import { I18nProvider } from '../../lib/i18n/I18nContext';
+
+const renderWithI18n = (ui: React.ReactElement) => {
+  return render(<I18nProvider>{ui}</I18nProvider>);
+};

Then replace all render(...) calls with renderWithI18n(...).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/src/components/intelligence/GraphCorePanel.test.tsx` around lines 1 - 6,
Tests render GraphCorePanel directly but the component uses useT() and needs
I18nContext; update the tests to wrap renders with an I18n provider. Import and
use the project test helper (e.g. renderWithProviders or renderWithI18n from
app/src/test/test-utils.tsx) or create a small wrapper that supplies
I18nProvider, then replace bare render(...) calls with renderWithProviders(...)
(or renderWithI18n(...)) when mounting GraphCorePanel so useT() has the required
context.

Comment on lines +41 to +45
it('loads core (all namespaces) on mount and renders the result', async () => {
render(<GraphCoreTab />);
expect(mockLoadCore).toHaveBeenCalledWith(undefined);
await waitFor(() => expect(screen.getByText('Deepest-core entities')).toBeInTheDocument());
});
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.

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Wrap component in I18nContext provider to fix missing context error.

GraphCoreTab uses useT() (line 14 of the component), but the test renders the component without providing the required I18n context. This will cause a runtime error when the component tries to access the context.

🔧 Proposed fix
+import { renderWithProviders } from '../../test/test-utils';
+
 describe('<GraphCoreTab />', () => {
   // ... existing setup ...
   
   it('loads core (all namespaces) on mount and renders the result', async () => {
-    render(<GraphCoreTab />);
+    renderWithProviders(<GraphCoreTab />);
     expect(mockLoadCore).toHaveBeenCalledWith(undefined);
     await waitFor(() => expect(screen.getByText('Deepest-core entities')).toBeInTheDocument());
   });

Apply the same change to the other two test cases (lines 49 and 58).

As per coding guidelines, use existing test helpers from app/src/test/.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/src/components/intelligence/GraphCoreTab.test.tsx` around lines 41 - 45,
Tests render GraphCoreTab without providing I18n context causing useT() to
throw; update the three GraphCoreTab tests that call render(<GraphCoreTab />)
(the case that asserts mockLoadCore and the two other cases) to wrap the
component in the existing test i18n provider helper from app/src/test/ (use the
shared test helper that mounts components with I18nContext) so GraphCoreTab can
call useT() during render, and keep assertions on mockLoadCore and the screen
text unchanged.

Comment on lines +40 to +47
useEffect(() => {
// Namespaces are optional UI sugar; a failure to list them must not block
// the core view, so swallow that error specifically.
loadNamespaces()
.then(setNamespaces)
.catch(() => setNamespaces([]));
void load('');
}, [load]);
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.

🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Refactor namespace loading to use async/await instead of .then() chains.

The .then()/.catch() pattern on lines 44-45 violates the guideline requiring async/await for all promises in TypeScript. Refactor to use async/await with try/catch.

Additionally, verbose debug logging is required for new/changed flows per coding guidelines, but this new async load flow lacks diagnostic logs for namespace fetching.

♻️ Proposed refactor
+import debug from 'debug';
+
+const log = debug('openhuman:intelligence:graph-core');
+
 const GraphCoreTab = () => {
   // ... existing state ...
   
   useEffect(() => {
-    // Namespaces are optional UI sugar; a failure to list them must not block
-    // the core view, so swallow that error specifically.
-    loadNamespaces()
-      .then(setNamespaces)
-      .catch(() => setNamespaces([]));
+    const fetchNamespaces = async () => {
+      try {
+        const ns = await loadNamespaces();
+        log('loaded %d namespaces', ns.length);
+        setNamespaces(ns);
+      } catch (err) {
+        log('namespace load failed (non-blocking): %O', err);
+        setNamespaces([]);
+      }
+    };
+    void fetchNamespaces();
     void load('');
   }, [load]);

As per coding guidelines, use async/await for promises and add namespaced debug logs for new flows.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/src/components/intelligence/GraphCoreTab.tsx` around lines 40 - 47,
Refactor the useEffect in GraphCoreTab.tsx to an async/await flow: create and
immediately invoke an async function inside useEffect that awaits
loadNamespaces() and calls setNamespaces(...) in the success path, and catches
errors to call setNamespaces([]); also await load('') and handle its errors. Add
diagnostic debug logs around these steps (e.g., before/after awaiting
loadNamespaces(), on namespace success with the returned value, on namespace
failure including the caught error, before/after calling load(''), and on load
error) using the project logger used elsewhere so failures are observable.
Ensure you keep the behavior that namespace failures do not block the core view
(still setNamespaces([]) on error) and preserve the dependency array ([load]).

Comment thread app/src/lib/memory/graphCore.ts
aashir-athar added a commit to aashir-athar/openhuman that referenced this pull request May 29, 2026
Address CodeRabbit review on tinyhumansai#2980: previously `computeGraphCore([A→A])`
returned an empty graph (the entire relation was dropped, taking the
endpoint with it), so a user whose only recorded fact was "Alice→Alice"
would vanish into the empty state. Now the self-loop EDGE is still
dropped (a self-loop is not a neighbour and cannot deepen a core), but
the endpoint is REGISTERED as a node with degree 0 and coreness 0 — so
Alice appears in the graph.

Adds a regression test for the self-loop-only case, updates the
buildAdjacency comment, and refines the module header to spell out the
new node-vs-edge distinction.

The "missing I18nContext provider" criticals were verified as false
positives: I18nContext at lib/i18n/I18nContext.tsx:66 ships a fully
functional English default that useT() picks up without a provider, so
the existing test pattern (matching the merged graphCentrality tests)
works correctly — every test passes.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
aashir-athar and others added 2 commits May 30, 2026 06:27
A new read-only "Core" tab for the Intelligence view: k-core decomposition of
the memory knowledge graph. It separates the load-bearing CORE of the user's
knowledge — entities mutually reinforced by many interlinked facts — from the
PERIPHERY of leaves and bridges. A high-degree hub of one-off facts still has
coreness 1; depth, not degree, marks the core — something neither a frequency
count nor PageRank can express.

Engine (pure, deterministic — no React/RPC/clock/RNG):
- coreness per node via the Batagelj-Zaversnik O(V+E) bucket algorithm,
- degeneracy (max coreness) and the shell decomposition,
- kCoreSize(k) for the nested k-core sizes.
Coreness is a graph invariant and the peel is seeded from an id-sorted vertex
list, so output is byte-identical regardless of relation input order.

Adds ZERO new core surface: composes the already-shipped memoryGraphQuery /
memoryListNamespaces JSON-RPC wrappers. Container/presentational split with a
monotonic request-token race guard for load-on-mount; i18n across all 13 locales.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Address CodeRabbit review on tinyhumansai#2980: previously `computeGraphCore([A→A])`
returned an empty graph (the entire relation was dropped, taking the
endpoint with it), so a user whose only recorded fact was "Alice→Alice"
would vanish into the empty state. Now the self-loop EDGE is still
dropped (a self-loop is not a neighbour and cannot deepen a core), but
the endpoint is REGISTERED as a node with degree 0 and coreness 0 — so
Alice appears in the graph.

Adds a regression test for the self-loop-only case, updates the
buildAdjacency comment, and refines the module header to spell out the
new node-vs-edge distinction.

The "missing I18nContext provider" criticals were verified as false
positives: I18nContext at lib/i18n/I18nContext.tsx:66 ships a fully
functional English default that useT() picks up without a provider, so
the existing test pattern (matching the merged graphCentrality tests)
works correctly — every test passes.

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

Labels

feature Net-new user-facing capability or product behavior. memory Memory store, memory tree, recall, summarization, and embeddings in src/openhuman/memory/. working A PR that is being worked on by the team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant