Skip to content

feat(memory): route summaries through workspace paths#2527

Merged
senamakel merged 5 commits into
tinyhumansai:mainfrom
YOMXXX:feat/2492-memory-workspace-links
May 25, 2026
Merged

feat(memory): route summaries through workspace paths#2527
senamakel merged 5 commits into
tinyhumansai:mainfrom
YOMXXX:feat/2492-memory-workspace-links

Conversation

@YOMXXX
Copy link
Copy Markdown
Contributor

@YOMXXX YOMXXX commented May 23, 2026

Summary

  • Routes Memory graph summary clicks through the shared workspace path command instead of raw Obsidian deep links.
  • Adds a guarded summary preview action that uses the same workspace preview surface as chat file links.
  • Routes the Memory workspace "Reveal Folder" toast action through revealWorkspacePath.
  • Mirrors the Rust summary path rules in a small frontend helper, including Gmail source scope prefix stripping and non-Gmail source prefix preservation.

Problem

  • Memory graph summary actions were building absolute Obsidian paths locally, bypassing the shared workspace link contract added for chat paths.
  • That left Memory surfaces without the same preview/reveal/open guardrails and made source summary path correctness easy to drift from Rust's canonical summary_rel_path logic.

Solution

  • Added memoryWorkspacePaths.ts to derive memory_tree/content/... paths from graph summary nodes using the Rust path conventions.
  • Replaced direct Obsidian opening for summary nodes with openWorkspacePath.
  • Added hover-time preview via previewWorkspaceText, keeping the preview button reachable after leaving the SVG node.
  • Kept the explicit "Open in Obsidian" vault action as-is, but moved its fallback reveal action onto revealWorkspacePath.

Submission Checklist

  • Tests added or updated (happy path + at least one failure / edge case) per Testing Strategy
  • Diff coverage ≥ 80% — local targeted lcov passed; diff-cover reports no coverage-relevant lines in the current test-only follow-up diff; CI coverage gate remains authoritative.
  • Coverage matrix updated — N/A: behaviour-only change to existing Memory graph/workspace surfaces; no feature row added/removed/renamed.
  • All affected feature IDs from the matrix are listed in the PR description under ## Related — N/A: no matrix feature ID change.
  • No new external network dependencies introduced (mock backend used per Testing Strategy)
  • Manual smoke checklist updated if this touches release-cut surfaces (docs/RELEASE-MANUAL-SMOKE.md) — N/A: no release smoke surface change.
  • Linked issue closed via Closes #NNN in the ## Related section

Impact

  • Desktop UI: Memory graph summary nodes now use guarded workspace-relative file operations.
  • Compatibility: existing explicit Obsidian vault open flow is preserved.
  • Security: avoids constructing local absolute file opens in the graph click path; uses existing workspace path validation surface.

Related


AI Authored PR Metadata (required for Codex/Linear PRs)

Linear Issue

  • Key: N/A
  • URL: N/A

Commit & Branch

  • Branch: feat/2492-memory-workspace-links
  • Commit SHA: c38d11f4a8f3e3f6624fc98bdcc421c60812a4ca

Validation Run

  • pnpm --filter openhuman-app test:unit src/components/intelligence/MemoryGraph.test.tsx src/components/intelligence/memoryWorkspacePaths.test.ts src/components/intelligence/__tests__/MemoryWorkspace.test.tsx — 3 files, 33 tests passed
  • pnpm --filter openhuman-app exec vitest run --coverage --config test/vitest.config.ts src/components/intelligence/MemoryGraph.test.tsx src/components/intelligence/memoryWorkspacePaths.test.ts src/components/intelligence/__tests__/MemoryWorkspace.test.tsx — 3 files, 33 tests passed, lcov generated
  • /tmp/openhuman-diff-cover-venv/bin/diff-cover app/coverage/lcov.info --compare-branch=upstream/main --fail-under=80 — passed; no coverage-relevant lines in the current diff after the test-only review follow-up
  • pnpm typecheck — passed
  • pnpm i18n:check — passed with 0 missing/extra/drifted keys
  • git diff --check — passed
  • pnpm format:check — passed
  • pnpm lint — passed with existing warnings only
  • GGML_NATIVE=OFF pnpm rust:check — passed with existing warnings only
  • GGML_NATIVE=OFF git push pre-push hook — passed

Validation Blocked

  • command: N/A
  • error: N/A; local macOS/Tahoe rust:check needs the documented GGML_NATIVE=OFF workaround for whisper-rs -mcpu=native.
  • impact: None; the workaround check passed.

Behavior Changes

  • Intended behavior change: Memory summary file actions now go through shared workspace open/preview/reveal commands.
  • User-visible effect: summary hover can preview content; summary clicks still open the corresponding markdown file through the guarded workspace path flow.

Parity Contract

  • Legacy behavior preserved: explicit Obsidian vault launch remains backed by obsidian://open?path=....
  • Guard/fallback/dispatch parity checks: summary open, preview, failure, truncation, path construction, and reveal paths are covered in focused Vitest tests.

Duplicate / Superseded PR Handling

  • Duplicate PR(s): N/A
  • Canonical PR: this PR
  • Resolution (closed/superseded/updated): N/A

Summary by CodeRabbit

  • New Features

    • Tooltip preview button for memory summaries that loads content asynchronously, shows errors, and indicates truncation.
  • Refactor

    • Open/reveal actions now use workspace-path based navigation for summaries and folder reveal behavior.
  • Bug Fixes

    • Preview stays accessible after mouse leave; tooltip/hover clears correctly; summary vs non-summary clicks behave reliably; deterministic legend/node counting.
  • Tests

    • Expanded coverage for preview flows, path resolution, hover/click interactions, and edge cases.

Review Change Stack

@YOMXXX YOMXXX requested a review from a team May 23, 2026 09:53
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 23, 2026

📝 Walkthrough

Walkthrough

This PR routes Memory open/reveal/preview through shared workspace-path utilities, removes MemoryGraph's contentRootAbs prop, adds hover-driven summary preview UI with truncation/error handling, updates MemoryWorkspace to reveal the workspace base, and revises tests to assert the new workspace-path interactions.

Changes

Memory workspace-path migration

Layer / File(s) Summary
Workspace path construction utilities
app/src/components/intelligence/memoryWorkspacePaths.ts
New MEMORY_CONTENT_WORKSPACE_PATH, summaryWorkspacePath(node), and helpers to slugify scopes, format timestamps, and build workspace-relative wiki summary paths (handles gmail: scopes and global date dirs).
MemoryGraph component refactor
app/src/components/intelligence/MemoryGraph.tsx
Removes contentRootAbs prop. Adds SummaryPreviewState, hover-derived workspace path, openWorkspacePath opener, previewWorkspaceText preview fetch with error/truncation handling, tooltip preview button, and preview panel rendering.
MemoryGraph test updates
app/src/components/intelligence/MemoryGraph.test.tsx
Hoists shared mocks for openUrl, openWorkspacePath, previewWorkspaceText; resets defaults in beforeEach; removes contentRootAbs from renders; updates/adds tests for workspace-path opens, preview flows (including truncation and errors), non-summary negative interactions, and deterministic node counting.
MemoryWorkspace integration
app/src/components/intelligence/MemoryWorkspace.tsx
Imports workspace-path helpers, changes "View Vault" reveal to revealWorkspacePath(MEMORY_CONTENT_WORKSPACE_PATH), and renders MemoryGraph without contentRootAbs.
MemoryWorkspace test updates
app/src/components/intelligence/__tests__/MemoryWorkspace.test.tsx
Mocks openWorkspacePath, revealWorkspacePath, previewWorkspaceText; sets beforeEach defaults; updates reveal-success and reveal-error tests to use revealWorkspacePath('memory_tree/content'); updates summary click test to expect openWorkspacePath with constructed memory_tree/content/${relativePath}.
Path utilities tests
app/src/components/intelligence/memoryWorkspacePaths.test.ts
Adds tests validating summaryWorkspacePath null case, trimming behavior preserving internal underscores, Gmail-prefix stripping, date formatting, and global-unknown-date fallback.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant MemoryGraph
  participant summaryWorkspacePath
  participant previewWorkspaceText
  participant openWorkspacePath

  User->>MemoryGraph: hover summary node
  MemoryGraph->>summaryWorkspacePath: compute workspace path
  MemoryGraph->>User: show tooltip with path + preview button
  User->>MemoryGraph: click preview
  MemoryGraph->>previewWorkspaceText: fetch preview for path
  previewWorkspaceText-->>MemoryGraph: preview content / error / truncation
  MemoryGraph->>User: render preview panel
  User->>MemoryGraph: click node (open)
  MemoryGraph->>openWorkspacePath: open workspace path
Loading

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • tinyhumansai/openhuman#2064: Prior changes touching MemoryGraph tests around deep-link/open behavior; this PR replaces that behavior with workspace-path calls and preview support.

Poem

🐰 I hopped through graph nodes, sniffed each path anew,
Replaced obsidian echoes with workspace trails true.
Hover for a whisper, click for a small reveal,
Errors and truncations now shown with gentle zeal.
A tiny rabbit cheers—preview, open, and feel!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 18.18% 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
Title check ✅ Passed The title 'feat(memory): route summaries through workspace paths' directly summarizes the main change: routing memory summary operations through the shared workspace path layer instead of direct Obsidian URLs.
Linked Issues check ✅ Passed All key objectives from #2492 are met: MemoryGraph and MemoryWorkspace route through workspace paths [#2492], Obsidian behavior is preserved intentionally [#2492], and comprehensive tests cover open/reveal/preview with edge cases [#2492].
Out of Scope Changes check ✅ Passed All changes directly support the linked objective (#2492): routing Memory surfaces through shared workspace paths, adding the memoryWorkspacePaths helper, updating MemoryGraph/MemoryWorkspace, and adding comprehensive tests.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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


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 the working A PR that is being worked on by the team. label May 23, 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.

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

134-157: ⚡ Quick win

Add a preview-failure test for the new error surface.

MemoryGraph now renders preview errors, but this suite only asserts the success path. Add one rejection-path test for previewWorkspaceText and assert the error text is shown in memory-graph-preview.

Proposed test addition
+  it('shows preview error text when workspace preview fails', async () => {
+    mocks.previewWorkspaceText.mockRejectedValueOnce(new Error('preview failed'));
+    const nodes = [
+      makeSummaryNode({
+        id: 'sum-A',
+        tree_kind: 'topic',
+        tree_scope: 'workspace one',
+        level: 2,
+        file_basename: 'summary-A',
+      }),
+    ];
+    render(<MemoryGraph nodes={nodes} edges={[]} mode="tree" />);
+
+    fireEvent.mouseEnter(screen.getByTestId('memory-graph-node-sum-A'));
+    fireEvent.click(screen.getByTestId('memory-graph-preview-sum-A'));
+
+    expect(await screen.findByTestId('memory-graph-preview')).toHaveTextContent('preview failed');
+  });
🤖 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/MemoryGraph.test.tsx` around lines 134 - 157,
Add a rejection-path test for MemoryGraph that mocks mocks.previewWorkspaceText
to return a rejected Promise (e.g., Promise.reject(new Error('boom'))), then
render MemoryGraph with the same makeSummaryNode, fire mouseEnter on
memory-graph-node-sum-A and click memory-graph-preview-sum-A, await the mock
call (using waitFor) and finally assert that
screen.findByTestId('memory-graph-preview') contains the error text (e.g.,
'boom' or the expected error message) to verify the error surface is rendered;
reference MemoryGraph, mocks.previewWorkspaceText, memory-graph-node-sum-A,
memory-graph-preview-sum-A, and memory-graph-preview when locating code to
modify.
🤖 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.

Nitpick comments:
In `@app/src/components/intelligence/MemoryGraph.test.tsx`:
- Around line 134-157: Add a rejection-path test for MemoryGraph that mocks
mocks.previewWorkspaceText to return a rejected Promise (e.g.,
Promise.reject(new Error('boom'))), then render MemoryGraph with the same
makeSummaryNode, fire mouseEnter on memory-graph-node-sum-A and click
memory-graph-preview-sum-A, await the mock call (using waitFor) and finally
assert that screen.findByTestId('memory-graph-preview') contains the error text
(e.g., 'boom' or the expected error message) to verify the error surface is
rendered; reference MemoryGraph, mocks.previewWorkspaceText,
memory-graph-node-sum-A, memory-graph-preview-sum-A, and memory-graph-preview
when locating code to modify.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1ed3a6e9-47c1-4319-b715-43d5ef9d5c39

📥 Commits

Reviewing files that changed from the base of the PR and between 7745d58 and 0a8c641.

📒 Files selected for processing (5)
  • app/src/components/intelligence/MemoryGraph.test.tsx
  • app/src/components/intelligence/MemoryGraph.tsx
  • app/src/components/intelligence/MemoryWorkspace.tsx
  • app/src/components/intelligence/__tests__/MemoryWorkspace.test.tsx
  • app/src/components/intelligence/memoryWorkspacePaths.ts

coderabbitai[bot]
coderabbitai Bot previously approved these changes May 23, 2026
@coderabbitai coderabbitai Bot added the feature Net-new user-facing capability or product behavior. label May 23, 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: 1

🧹 Nitpick comments (1)
app/src/components/intelligence/memoryWorkspacePaths.test.ts (1)

22-48: ⚡ Quick win

Consider adding tests for additional edge cases.

The suite provides good baseline coverage but is missing tests for:

  1. Gmail scope handling: tree_kind: 'source' with tree_scope: 'gmail:user@example.com' should strip the gmail: prefix and slugify only the remainder.
  2. Valid timestamp formatting: A realistic time_range_start_ms (e.g., new Date('2024-06-15').getTime()) should produce a formatted date like global-2024-06-15 in the path.

These cases exercise important branches in summaryScopeSlug and the happy path of dateFromMs.

📋 Suggested additional tests
it('strips gmail: prefix from source scopes', () => {
  expect(
    summaryWorkspacePath(
      summaryNode({ tree_kind: 'source', tree_scope: 'gmail:user@example.com' })
    )
  ).toBe(`${MEMORY_CONTENT_WORKSPACE_PATH}/wiki/summaries/source-user-example-com/L1/summary-file.md`);
});

it('formats valid timestamps as ISO dates for global summaries', () => {
  const ms = new Date('2024-06-15T12:00:00Z').getTime();
  expect(
    summaryWorkspacePath(summaryNode({ tree_kind: 'global', time_range_start_ms: ms }))
  ).toBe(`${MEMORY_CONTENT_WORKSPACE_PATH}/wiki/summaries/global-2024-06-15/L1/summary-file.md`);
});

Based on learnings from the upstream contract in memoryWorkspacePaths.ts:47-56, which shows the gmail: prefix stripping logic in summaryScopeSlug.

🤖 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/memoryWorkspacePaths.test.ts` around lines 22
- 48, Add two unit tests to cover the missing branches: one that verifies
summaryWorkspacePath(summaryNode({ tree_kind: 'source', tree_scope:
'gmail:user@example.com' })) strips the "gmail:" prefix and slugifies the
remainder (exercise summaryScopeSlug), and another that passes a realistic
timestamp (e.g., new Date('2024-06-15T12:00:00Z').getTime()) to
summaryWorkspacePath(summaryNode({ tree_kind: 'global', time_range_start_ms: ms
})) and asserts the path contains the formatted date segment (exercise
dateFromMs/ISO formatting); use the same MEMORY_CONTENT_WORKSPACE_PATH and
summaryNode helper so the new tests match existing patterns.
🤖 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/memoryWorkspacePaths.test.ts`:
- Around line 23-26: Add tests to cover the remaining null-return cases for
summaryWorkspacePath: create summary nodes where tree_kind is null/undefined and
where level is null/undefined (use the existing summaryNode helper to build
these variants) and assert summaryWorkspacePath(...) returns null for each; keep
them alongside the existing test that checks kind !== 'summary' and missing
file_basename so all four contract conditions (!node.tree_kind, node.level ==
null, missing file_basename, kind !== 'summary') are asserted.

---

Nitpick comments:
In `@app/src/components/intelligence/memoryWorkspacePaths.test.ts`:
- Around line 22-48: Add two unit tests to cover the missing branches: one that
verifies summaryWorkspacePath(summaryNode({ tree_kind: 'source', tree_scope:
'gmail:user@example.com' })) strips the "gmail:" prefix and slugifies the
remainder (exercise summaryScopeSlug), and another that passes a realistic
timestamp (e.g., new Date('2024-06-15T12:00:00Z').getTime()) to
summaryWorkspacePath(summaryNode({ tree_kind: 'global', time_range_start_ms: ms
})) and asserts the path contains the formatted date segment (exercise
dateFromMs/ISO formatting); use the same MEMORY_CONTENT_WORKSPACE_PATH and
summaryNode helper so the new tests match existing patterns.
🪄 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: 3a287136-4df7-4f80-9f57-a631d257b68a

📥 Commits

Reviewing files that changed from the base of the PR and between 0a8c641 and 134f387.

📒 Files selected for processing (2)
  • app/src/components/intelligence/MemoryGraph.test.tsx
  • app/src/components/intelligence/memoryWorkspacePaths.test.ts

Comment thread app/src/components/intelligence/memoryWorkspacePaths.test.ts
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.

🧹 Nitpick comments (2)
app/src/components/intelligence/memoryWorkspacePaths.test.ts (2)

42-50: ⚡ Quick win

Incomplete coverage of gmail-prefix conditional logic.

The test validates that gmail: is stripped for source scopes, but doesn't verify the conditional behavior: the upstream contract strips gmail: only when tree_kind === 'source' AND the scope starts with gmail:. Add negative cases to confirm:

  • A non-gmail source scope (e.g., dropbox:foo) is not stripped
  • A gmail-prefixed non-source scope (e.g., tree_kind: 'topic', tree_scope: 'gmail:foo') is not stripped
📋 Suggested additional test cases
  it('strips gmail prefixes from source scopes before slugifying', () => {
    expect(
      summaryWorkspacePath(
        summaryNode({ tree_kind: 'source', tree_scope: 'gmail:user@example.com' })
      )
    ).toBe(
      `${MEMORY_CONTENT_WORKSPACE_PATH}/wiki/summaries/source-user-example-com/L1/summary-file.md`
    );
+   // Non-gmail source scope should preserve the prefix
+   expect(
+     summaryWorkspacePath(
+       summaryNode({ tree_kind: 'source', tree_scope: 'dropbox:Documents' })
+     )
+   ).toBe(
+     `${MEMORY_CONTENT_WORKSPACE_PATH}/wiki/summaries/source-dropbox-documents/L1/summary-file.md`
+   );
+   // Gmail prefix on non-source should NOT be stripped
+   expect(
+     summaryWorkspacePath(
+       summaryNode({ tree_kind: 'topic', tree_scope: 'gmail:work' })
+     )
+   ).toBe(
+     `${MEMORY_CONTENT_WORKSPACE_PATH}/wiki/summaries/topic-gmail-work/L1/summary-file.md`
+   );
  });
🤖 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/memoryWorkspacePaths.test.ts` around lines 42
- 50, Add two negative tests to cover the conditional gmail-prefix stripping:
one where tree_kind is 'source' but tree_scope is a non-gmail prefix (e.g.,
'dropbox:foo') and one where tree_scope starts with 'gmail:' but tree_kind is
not 'source' (e.g., tree_kind: 'topic', tree_scope: 'gmail:foo'); in both cases
assert that summaryWorkspacePath(summaryNode(...)) produces a path that
preserves the original scope (i.e., no removal of 'dropbox:' or 'gmail:') and
matches the expected string built from MEMORY_CONTENT_WORKSPACE_PATH and the
slugified scope used in the existing test pattern, reusing the same helpers
summaryWorkspacePath and summaryNode to locate the behavior.

67-72: ⚡ Quick win

Non-obvious edge case could use a comment.

The test correctly expects Number.MAX_SAFE_INTEGER to produce 'unknown-date', but this is non-obvious because MAX_SAFE_INTEGER appears to be a valid number. It fails because it exceeds JavaScript's Date valid range (±8.64×10¹⁵ ms), creating an Invalid Date. Adding a brief comment would help future readers understand this edge case.

📝 Suggested clarifying comment
    expect(
      summaryWorkspacePath(
+       // MAX_SAFE_INTEGER exceeds Date valid range (±8.64e15 ms), producing Invalid Date
        summaryNode({ tree_kind: 'global', time_range_start_ms: Number.MAX_SAFE_INTEGER })
      )
    ).toBe(
      `${MEMORY_CONTENT_WORKSPACE_PATH}/wiki/summaries/global-unknown-date/L1/summary-file.md`
    );
🤖 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/memoryWorkspacePaths.test.ts` around lines 67
- 72, Add a brief clarifying comment above the assertion that uses
Number.MAX_SAFE_INTEGER in memoryWorkspacePaths.test.ts to explain why
MAX_SAFE_INTEGER maps to 'unknown-date' despite being a number: note that
Date(Number.MAX_SAFE_INTEGER) is out of JS Date valid range (±8.64×10^15 ms) and
becomes Invalid Date, so summaryWorkspacePath(summaryNode({...
time_range_start_ms: Number.MAX_SAFE_INTEGER })) should produce the
'unknown-date' path; place this comment near the summaryWorkspacePath and
summaryNode usage to help future readers.
🤖 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.

Nitpick comments:
In `@app/src/components/intelligence/memoryWorkspacePaths.test.ts`:
- Around line 42-50: Add two negative tests to cover the conditional
gmail-prefix stripping: one where tree_kind is 'source' but tree_scope is a
non-gmail prefix (e.g., 'dropbox:foo') and one where tree_scope starts with
'gmail:' but tree_kind is not 'source' (e.g., tree_kind: 'topic', tree_scope:
'gmail:foo'); in both cases assert that summaryWorkspacePath(summaryNode(...))
produces a path that preserves the original scope (i.e., no removal of
'dropbox:' or 'gmail:') and matches the expected string built from
MEMORY_CONTENT_WORKSPACE_PATH and the slugified scope used in the existing test
pattern, reusing the same helpers summaryWorkspacePath and summaryNode to locate
the behavior.
- Around line 67-72: Add a brief clarifying comment above the assertion that
uses Number.MAX_SAFE_INTEGER in memoryWorkspacePaths.test.ts to explain why
MAX_SAFE_INTEGER maps to 'unknown-date' despite being a number: note that
Date(Number.MAX_SAFE_INTEGER) is out of JS Date valid range (±8.64×10^15 ms) and
becomes Invalid Date, so summaryWorkspacePath(summaryNode({...
time_range_start_ms: Number.MAX_SAFE_INTEGER })) should produce the
'unknown-date' path; place this comment near the summaryWorkspacePath and
summaryNode usage to help future readers.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 7578dcc8-9080-454f-8fa1-2a722d91ccac

📥 Commits

Reviewing files that changed from the base of the PR and between 134f387 and bfa4810.

📒 Files selected for processing (1)
  • app/src/components/intelligence/memoryWorkspacePaths.test.ts

@YOMXXX
Copy link
Copy Markdown
Contributor Author

YOMXXX commented May 23, 2026

@graycyrus @senamakel Ready for review.

Latest state for #2527 (feat(memory): route summaries through workspace paths):

  • all required checks are green
  • no unresolved review threads
  • CodeRabbit has no actionable comments on the latest head

@senamakel senamakel merged commit 8ba259c into tinyhumansai:main May 25, 2026
28 checks passed
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. working A PR that is being worked on by the team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Migrate Memory surfaces to shared workspace file links

2 participants