Skip to content

feat(onboarding): guided memory & vault setup with health checklist (#2910)#3160

Merged
senamakel merged 13 commits into
tinyhumansai:mainfrom
oxoxDev:feat/2910-vault-onboarding
Jun 2, 2026
Merged

feat(onboarding): guided memory & vault setup with health checklist (#2910)#3160
senamakel merged 13 commits into
tinyhumansai:mainfrom
oxoxDev:feat/2910-vault-onboarding

Conversation

@oxoxDev
Copy link
Copy Markdown
Contributor

@oxoxDev oxoxDev commented Jun 1, 2026

Summary

  • Add a guided Memory & Vault Setup step to onboarding (/onboarding/custom/vault) explaining what OpenHuman reads, what it writes, and where generated notes live.
  • New reusable VaultHealthChecklist component (also surfaced in Settings → Memory) showing path-exists / writable / Obsidian-registered / pipeline-healthy with recovery actions (reveal folder, open/register in Obsidian, install Obsidian).
  • New core RPC openhuman.memory_tree_vault_health_check returning { exists, readable, writable, obsidian_registered, pipeline_healthy, last_sync_ms, content_root_abs } with a real write probe (create-temp → remove under the content root).
  • Single structured read/write explainer (Workspace vault·write / Connected sources·read / internal memory-tree files) shared by onboarding + Settings.

Problem

New users hit dead ends setting up vaults and memory: it is unclear what is read-only vs writable, where generated notes are stored, whether the workspace vault opens, or whether the sync pipeline is healthy. Without onboarding they cannot tell read sources from the write vault, and silent setup failures erode confidence before the upgrade prompt.

Solution

  • Add VaultSetupStep to the custom onboarding wizard (CUSTOM_WIZARD_STEPS + routes), with a Default (OpenHuman-managed) vs Configure (review + tune now) choice; local-only sessions are forced to Configure.
  • Configure embeds MemoryDataPanel (read/write explainer + health checklist + memory-window control + workspace), so the same surface backs both onboarding and Settings → Memory — no duplicated panels.
  • Back the checklist with a real Rust health probe (vault_health_check_rpc in memory/read_rpc.rs), reusing existing workspace-path resolution + Obsidian-status + pipeline-status logic; failed checks render explicit recovery guidance (no silent failures).

Submission Checklist

If a section does not apply to this change, mark the item as N/A with a one-line reason. Do not delete items.

  • Tests added or updated (happy path + at least one failure / edge case) — Rust vault_health_check_* tests (read_rpc_tests.rs) cover fresh/missing-root and writable/registered states; Vitest VaultHealthChecklist.test.tsx + VaultSetupStep.test.tsx cover loaded, error, and local-session states.
  • Diff coverage ≥ 80% — pending CI verification (pr-ci.yml diff-cover); focused Vitest + cargo test memory::read_rpc pass locally.
  • Coverage matrix updated — N/A: feature surfaces a new RPC + UI step but adds no feature-ID row tracked in the matrix.
  • All affected feature IDs from the matrix are listed under ## Related — N/A: no matrix feature IDs affected.
  • No new external network dependencies introduced — health check is local FS + existing RPC; no new backend calls.
  • Manual smoke checklist updated if this touches release-cut surfaces — N/A: additive onboarding step, no release-cut surface changed.
  • Linked issue closed via Closes #NNN in the ## Related section.

Impact

  • Desktop only (onboarding wizard + Settings → Memory). No mobile/web/CLI surface change.
  • Additive: new RPC + new onboarding step; no migrations, no schema changes, no change to existing memory read/write behavior. The write probe creates then removes a temp file under the content root.

Related


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

Linear Issue

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

Commit & Branch

  • Branch: feat/2910-vault-onboarding
  • Commit SHA: e882aa5ddda15a8735e2ce3190357b8cdd1461ae

Validation Run

  • pnpm --filter openhuman-app format:check — prettier clean on changed files
  • pnpm typecheck — passes
  • Focused tests: pnpm test:unit VaultHealthChecklist.test.tsx VaultSetupStep.test.tsx (6 passed); cargo test --lib openhuman::memory::read_rpc (36 passed, incl. 2 new vault_health_check tests)
  • Rust fmt/check (if changed): cargo fmt --check clean, cargo check -p openhuman clean
  • Tauri fmt/check (if changed): pnpm rust:check clean (warnings pre-existing)

Validation Blocked

  • command: N/A
  • error: N/A
  • impact: N/A

Behavior Changes

  • Intended behavior change: adds a guided vault/memory onboarding step + a reusable vault health checklist + a new health-probe RPC.
  • User-visible effect: new "Memory & Vault Setup" onboarding step and a "Vault setup health" panel in Settings → Memory.

Parity Contract

  • Legacy behavior preserved: existing onboarding steps, memory read/write behavior, and the Settings → Memory panel are unchanged aside from the added sections.
  • Guard/fallback/dispatch parity checks: local-only sessions are forced to Configure (managed default disabled); checklist degrades to an error card if the RPC fails.

Duplicate / Superseded PR Handling

  • Duplicate PR(s): none
  • Canonical PR: this PR
  • Resolution: N/A

Verification

  • Live-verified on staging build: onboarding vault step renders both choice cards; Configure shows the structured storage explainer + a single health checklist matching the live RPC (exists/writable pass, Obsidian/pipeline need-attention) with working Reveal Folder / Open in Obsidian actions.

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • New Features

    • Added vault health status monitoring in the Memory Data settings panel, displaying disk accessibility, Obsidian registration, and sync information
    • Introduced new "Vault Setup" step in the onboarding wizard with configuration guidance for local and managed sessions
    • Added action buttons to reveal vault folders and open vaults directly in Obsidian
  • Tests

    • Added comprehensive test coverage for vault health monitoring and setup components

oxoxDev added 7 commits June 1, 2026 18:16
…surface

The MemoryWindowControl h3 had no text-color class, so it inherited the
onboarding flow's dark default and rendered near-invisible when the panel is
embedded in the vault setup step. Pin it to text-stone-900 dark:text-neutral-100
to match the sibling section headings.
…e explainer

The vault step rendered the read/write explainer and the health checklist
twice — once inline in VaultSetupContent and again via the embedded
MemoryDataPanel. Render only MemoryDataPanel embedded so each appears once,
and rework its prose explainer into a structured write/read/internal
definition list matching the checklist card style.
Collapse multi-line object literals and rewrap per the repo prettier config so
`format:check` passes on the vault-health checklist, its test, and the memory
data panel.
@oxoxDev oxoxDev requested a review from a team June 1, 2026 16:06
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 1, 2026

Review Change Stack

Warning

Review limit reached

@senamakel, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 31 minutes and 4 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c1dff829-c85e-45d8-90b1-5aa95de65c2a

📥 Commits

Reviewing files that changed from the base of the PR and between e882aa5 and e4e9ab3.

📒 Files selected for processing (22)
  • app/src/components/intelligence/VaultHealthChecklist.tsx
  • app/src/components/settings/panels/MemoryDataPanel.tsx
  • app/src/lib/i18n/ar.ts
  • app/src/lib/i18n/bn.ts
  • app/src/lib/i18n/de.ts
  • app/src/lib/i18n/en.ts
  • app/src/lib/i18n/es.ts
  • app/src/lib/i18n/fr.ts
  • app/src/lib/i18n/hi.ts
  • app/src/lib/i18n/id.ts
  • app/src/lib/i18n/it.ts
  • app/src/lib/i18n/ko.ts
  • app/src/lib/i18n/pl.ts
  • app/src/lib/i18n/pt.ts
  • app/src/lib/i18n/ru.ts
  • app/src/lib/i18n/zh-CN.ts
  • app/src/pages/onboarding/Onboarding.tsx
  • app/src/pages/onboarding/OnboardingContext.tsx
  • app/src/pages/onboarding/customWizardSteps.ts
  • app/src/pages/onboarding/pages/VaultSetupStep.tsx
  • app/src/pages/onboarding/steps/CustomWizardStep.tsx
  • src/openhuman/memory/read_rpc.rs
📝 Walkthrough

Walkthrough

This PR introduces vault health monitoring and guided onboarding for the Memory and vault setup. A new backend RPC probes directory accessibility, Obsidian registration, and pipeline health; a React component displays status with recovery actions; and a wizard step integrates the checklist into onboarding with conditional UI for local vs managed sessions.

Changes

Vault Health Monitoring and Onboarding Setup

Layer / File(s) Summary
Backend vault health RPC and probing
src/openhuman/memory/read_rpc.rs, src/openhuman/memory/schema.rs, src/openhuman/memory/read_rpc_tests.rs
vault_health_check_rpc probes memory_tree/content for existence, readability, and writeability via temporary file creation; verifies Obsidian vault registration; and reports pipeline health and last sync timestamp. Two test cases cover fresh workspaces and seeded content with Obsidian registration.
Frontend Tauri API wrapper for vault health
app/src/utils/tauriCommands/memoryTree.ts
VaultHealthCheck interface and memoryTreeVaultHealthCheck() function wrap the backend RPC, unwrap the single-log envelope, and emit structured debug logs for vault health snapshots.
VaultHealthChecklist component and settings integration
app/src/components/intelligence/VaultHealthChecklist.tsx, app/src/components/intelligence/VaultHealthChecklist.test.tsx, app/src/components/settings/panels/MemoryDataPanel.tsx
React component fetches vault health on mount, manages loading/refreshing/error state, displays a checklist of status items (path exists, writable, Obsidian-registered, pipeline health), exposes Refresh button, and provides actions to reveal the vault folder, open in Obsidian via custom URL, or install Obsidian. Integrated into settings panel with informational guidance. Four test cases verify fully healthy state, missing folder, non-writable vault, and Obsidian-unregistered recovery flows.
VaultSetupStep onboarding page and router integration
app/src/pages/onboarding/pages/VaultSetupStep.tsx, app/src/pages/onboarding/pages/VaultSetupStep.test.tsx, app/src/pages/onboarding/Onboarding.tsx, app/src/pages/onboarding/customWizardSteps.ts, app/src/pages/onboarding/steps/CustomWizardStep.tsx, app/src/pages/onboarding/OnboardingContext.tsx
New wizard step determines initial choice (default/configure) based on local vs managed session, forces "configure" in local mode, memoizes embedded MemoryDataPanel with health checklist, disables default path in local mode with specific guidance, navigates on back, and tracks analytics on continue. Router wired to /onboarding/custom/vault with deep-link to /settings/memory-data. Stepper label updated to "Vault". Tests verify conditional UI across session types.
Type formatting and heading styling updates
app/src/pages/onboarding/OnboardingContext.tsx, app/src/components/settings/components/MemoryWindowControl.tsx
CustomStepKey union type reformatted to multi-line for readability; memory window heading given explicit light/dark text colors via Tailwind classes.

Sequence Diagram(s)

sequenceDiagram
  participant Browser as User / Browser
  participant Component as VaultHealthChecklist
  participant Tauri as memoryTreeVaultHealthCheck
  participant Backend as vault_health_check RPC
  participant FS as Filesystem<br/> + Registry
  
  Browser->>Component: Mount / Click Refresh
  Component->>Tauri: memoryTreeVaultHealthCheck()
  Tauri->>Backend: invoke RPC
  Backend->>FS: Probe memory_tree/content
  FS-->>Backend: Health status
  Backend-->>Tauri: VaultHealthCheckResponse
  Tauri-->>Component: Unwrapped data + debug log
  Component->>Component: Render checklist
  
  Browser->>Component: Click Reveal / Open / Install
  Component->>Tauri: openUrl() or revealPath()
  Tauri->>FS: Navigate / reveal
  FS-->>Browser: File manager / URL handler
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • tinyhumansai/openhuman#2349: Direct code-level integration — frontend VaultHealthChecklist wires to memoryTreeVaultHealthCheck RPC implemented in that PR.
  • tinyhumansai/openhuman#2950: Overlapping Memory Timeline modifications that affect the same memoryTimeline API surface and Memory core utilities.
  • tinyhumansai/openhuman#2720: Related vault health RPC and memory-tree subsystem changes that this PR depends on.

Suggested labels

feature, memory, rust-core, working

Suggested reviewers

  • sanil-23
  • graycyrus
  • senamakel

Poem

🐰 A vault so healthy, checklist in hand,
Users guided through onboarding land,
From Rust to React, the flow runs true,
Obsidian opens with paths bright and new!
No more silent fails, just clarity—phew!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: adding a guided memory & vault setup step with health checklist in the onboarding flow.
Linked Issues check ✅ Passed The PR implements all core objectives from #2910: guided onboarding flow [#2910], read/write model explanation [#2910], vault health checks [#2910], recovery paths [#2910], and test coverage [#2910].
Out of Scope Changes check ✅ Passed All changes are scoped to objectives in #2910: onboarding flow, health checklist component, RPC implementation, settings integration, and corresponding tests.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

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


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. rust-core Core Rust runtime in src/: CLI, core_server, shared infrastructure. 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 Jun 1, 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 (2)
app/src/pages/onboarding/steps/CustomWizardStep.tsx (1)

117-117: 💤 Low value

Consider simplifying the nested t() fallback pattern.

Line 117 uses a nested t() call: t('onboarding.custom.stepperVault', t('onboarding.custom.stepperMemory', 'Vault')). While technically valid, this pattern is unconventional and may confuse future maintainers. The inner t() call resolves to either the stepperMemory translation or 'Vault', which is then passed as the default value for the outer t() call.

♻️ Simpler alternative

If the intent is to use stepperVault with a fallback to 'Vault', simplify to:

-    t('onboarding.custom.stepperVault', t('onboarding.custom.stepperMemory', 'Vault')),
+    t('onboarding.custom.stepperVault', 'Vault'),

If both keys should be checked in sequence (first try stepperVault, then stepperMemory, then literal 'Vault'), document the intent or extract to a helper:

const getVaultLabel = () => {
  // Try new key first, fall back to legacy key, then literal
  return t('onboarding.custom.stepperVault') 
    || t('onboarding.custom.stepperMemory') 
    || 'Vault';
};

(Note: this assumes your useT() returns empty string for missing keys; adjust based on actual behavior.)

🤖 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/pages/onboarding/steps/CustomWizardStep.tsx` at line 117, The nested
t() fallback is confusing: inside the component or file replace the expression
t('onboarding.custom.stepperVault', t('onboarding.custom.stepperMemory',
'Vault')) with a clearer fallback strategy such as either calling
t('onboarding.custom.stepperVault', 'Vault') if you only want a literal
fallback, or implement a small helper (e.g., getVaultLabel) that returns
t('onboarding.custom.stepperVault') || t('onboarding.custom.stepperMemory') ||
'Vault' and use that helper where the current nested t() is used; update the
reference where the label is computed so maintainers see intent clearly.
app/src/pages/onboarding/customWizardSteps.ts (1)

20-20: 💤 Low value

Reassess the “memory” custom-wizard route (currently unreachable in the active flow).

  • CustomStepKey still includes 'memory' and CustomMemoryPage.tsx exists (STEP_KEY = 'memory').
  • app/src/pages/onboarding/customWizardSteps.ts still maps memory: '/onboarding/custom/memory', but CUSTOM_WIZARD_STEPS no longer includes 'memory' (it goes from embeddingsvault).
  • The routed onboarding flow in app/src/pages/onboarding/Onboarding.tsx mounts custom/vault and has no custom/memory route; there are no navigations to /onboarding/custom/memory.

If the “memory” step was truly replaced by “vault”, remove 'memory' from CustomStepKey and prune CustomMemoryPage + the memory entries in CUSTOM_WIZARD_ROUTES/CUSTOM_WIZARD_SETTINGS_ROUTES (can’t drop only the route string without adjusting the Record<CustomStepKey, ...> types).

🤖 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/pages/onboarding/customWizardSteps.ts` at line 20, Custom "memory"
step is orphaned: remove all references or restore it consistently. If "vault"
replaced "memory", delete the CustomMemoryPage (and its STEP_KEY = 'memory'),
remove 'memory' from the CustomStepKey union, and remove the 'memory' entries
from CUSTOM_WIZARD_ROUTES and CUSTOM_WIZARD_SETTINGS_ROUTES in
customWizardSteps.ts; then update any Record<CustomStepKey, ...> maps and
imports so types line up (no leftover keys) and ensure Onboarding.tsx only
references the remaining steps (e.g., 'embeddings' -> 'vault'). If you intend to
keep memory instead, add it back into CUSTOM_WIZARD_STEPS and mount a route in
Onboarding.tsx to /onboarding/custom/memory and restore navigation.
🤖 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/VaultHealthChecklist.tsx`:
- Around line 14-26: The function formatRelativeTime currently returns
hard-coded English strings; update it to use the i18n hook useT() from
app/src/lib/i18n/I18nContext and replace every literal ("Never", "just now",
"min ago", "hr ago", "day(s) ago") with translation keys (e.g., 'vault.never',
'vault.justNow', 'vault.minutesAgo', 'vault.hoursAgo', 'vault.daysAgo') and
proper pluralization where needed, by calling useT() in the VaultHealthChecklist
component (or surrounding module) and passing the translated strings into
formatRelativeTime or refactor formatRelativeTime to accept the translator
function (t) as an argument; apply the same localization pattern to other
user-visible strings in this component (lines ~37-225) so all UI text flows
through useT().

In `@app/src/components/settings/panels/MemoryDataPanel.tsx`:
- Around line 57-91: The hardcoded UI strings in MemoryDataPanel.tsx must be
changed to use the i18n hook: import and call useT() from I18nContext and
replace the literal strings ("How memory storage works", "Workspace vault ·
write", the three descriptions, and title="Vault setup health") with t(...)
lookups; add corresponding keys under a sensible namespace (e.g.,
memory.howItWorks.title, memory.howItWorks.workspaceVault.label,
memory.howItWorks.workspaceVault.description,
memory.howItWorks.connectedSources.label,
memory.howItWorks.connectedSources.description,
memory.howItWorks.internalFiles.label,
memory.howItWorks.internalFiles.description, memory.vaultHealthTitle) to
app/src/lib/i18n/en.ts and mirror them in other locale files so
VaultHealthChecklist onToast={addToast} uses
title={t('memory.vaultHealthTitle')}.

In `@app/src/pages/onboarding/pages/VaultSetupStep.tsx`:
- Around line 14-15: Replace hardcoded user strings with i18n keys using useT()
from I18nContext: remove the constant LOCAL_DEFAULT_DISABLED_REASON and stop
passing literal strings to CustomWizardStep props (title, subtitle,
defaultDescription, configureDescription); instead call useT() in VaultSetupStep
and reference translation keys (e.g., onboarding.custom.vault.title, subtitle,
defaultDescription, configureDescription, localDisabledReason), add those keys
and English values to app/src/lib/i18n/en.ts and update other locale files
accordingly so all user-visible text is localized.
- Around line 29-36: The effect is synchronously calling setChoice and setDraft
when isLocalSession becomes true, which triggers the
react-hooks/set-state-in-effect lint; refactor by deriving the forced choice at
render or guarding the update with a ref so no state setter is called
synchronously in the effect: e.g., compute choice = isLocalSession ? 'configure'
: choiceState (and initialize choiceState accordingly) or add a ref like
appliedLocalSessionRef used inside the effect to only perform setDraft
asynchronously/once (or better, move the draft update into the code path that
sets isLocalSession) — update references to setChoice, setDraft, isLocalSession
and STEP_KEY in VaultSetupStep to implement one of these patterns.

---

Nitpick comments:
In `@app/src/pages/onboarding/customWizardSteps.ts`:
- Line 20: Custom "memory" step is orphaned: remove all references or restore it
consistently. If "vault" replaced "memory", delete the CustomMemoryPage (and its
STEP_KEY = 'memory'), remove 'memory' from the CustomStepKey union, and remove
the 'memory' entries from CUSTOM_WIZARD_ROUTES and CUSTOM_WIZARD_SETTINGS_ROUTES
in customWizardSteps.ts; then update any Record<CustomStepKey, ...> maps and
imports so types line up (no leftover keys) and ensure Onboarding.tsx only
references the remaining steps (e.g., 'embeddings' -> 'vault'). If you intend to
keep memory instead, add it back into CUSTOM_WIZARD_STEPS and mount a route in
Onboarding.tsx to /onboarding/custom/memory and restore navigation.

In `@app/src/pages/onboarding/steps/CustomWizardStep.tsx`:
- Line 117: The nested t() fallback is confusing: inside the component or file
replace the expression t('onboarding.custom.stepperVault',
t('onboarding.custom.stepperMemory', 'Vault')) with a clearer fallback strategy
such as either calling t('onboarding.custom.stepperVault', 'Vault') if you only
want a literal fallback, or implement a small helper (e.g., getVaultLabel) that
returns t('onboarding.custom.stepperVault') ||
t('onboarding.custom.stepperMemory') || 'Vault' and use that helper where the
current nested t() is used; update the reference where the label is computed so
maintainers see intent clearly.
🪄 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: ef49f7ac-9440-497f-a2fc-961a46ea9018

📥 Commits

Reviewing files that changed from the base of the PR and between 4187561 and e882aa5.

📒 Files selected for processing (14)
  • app/src/components/intelligence/VaultHealthChecklist.test.tsx
  • app/src/components/intelligence/VaultHealthChecklist.tsx
  • app/src/components/settings/components/MemoryWindowControl.tsx
  • app/src/components/settings/panels/MemoryDataPanel.tsx
  • app/src/pages/onboarding/Onboarding.tsx
  • app/src/pages/onboarding/OnboardingContext.tsx
  • app/src/pages/onboarding/customWizardSteps.ts
  • app/src/pages/onboarding/pages/VaultSetupStep.test.tsx
  • app/src/pages/onboarding/pages/VaultSetupStep.tsx
  • app/src/pages/onboarding/steps/CustomWizardStep.tsx
  • app/src/utils/tauriCommands/memoryTree.ts
  • src/openhuman/memory/read_rpc.rs
  • src/openhuman/memory/read_rpc_tests.rs
  • src/openhuman/memory/schema.rs

Comment thread app/src/components/intelligence/VaultHealthChecklist.tsx Outdated
Comment thread app/src/components/settings/panels/MemoryDataPanel.tsx Outdated
Comment thread app/src/pages/onboarding/pages/VaultSetupStep.tsx Outdated
Comment thread app/src/pages/onboarding/pages/VaultSetupStep.tsx Outdated
Copy link
Copy Markdown
Contributor

@graycyrus graycyrus left a comment

Choose a reason for hiding this comment

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

@oxoxDev heads up — CI is failing (PR Submission Checklist) and several coverage + E2E checks are still pending, so I'll hold off on approval until those are green. I did a pass through the diff and found a few things beyond what CodeRabbit caught:

The stepper label fallback in CustomWizardStep.tsx is going to show the wrong text. t('onboarding.custom.stepperVault', t('onboarding.custom.stepperMemory', 'Vault')) — if stepperVault is missing from the locale files (which it almost certainly is, since there's no corresponding key added to en.ts in this diff), the t() call falls back to the second argument. That second argument is another t() call for stepperMemory, which is an existing key and will resolve to whatever the Memory step label currently says — probably "Memory". So the vault step in the stepper will read "Memory". You want t('onboarding.custom.stepperVault', 'Vault') with a string fallback, and you need to add stepperVault to the locale files.

The completeAndExit failure in VaultSetupStep.tsx is swallowed silently. The try/catch around it logs to console.error and then... nothing. If completeAndExit throws, the user is stuck on the final onboarding step with no feedback and no way to proceed. This needs a toast or an inline error state so the user knows something went wrong and can retry.

CodeRabbit already caught the i18n gaps (hardcoded strings in VaultHealthChecklist, MemoryDataPanel, and VaultSetupStep) and the useEffect/setState lint violation — those are all blocking too and need to be addressed before this is ready.

Smaller things: the memory key is still in CUSTOM_WIZARD_ROUTES and CUSTOM_WIZARD_SETTINGS_ROUTES in customWizardSteps.ts even though memory was removed from CUSTOM_WIZARD_STEPS. It's inert but it's dead config that should be cleaned up. In probe_directory_writable, the remove_file failure is silently ignored — a leak of .openhuman-vault-writecheck-*.tmp in the user's vault is unlikely but Obsidian would surface it as an unexpected file if it ever stuck around. Worth at least logging the failure at debug level.

The core RPC logic itself is solid — the spawn_blocking pattern is correct, path redaction in the log is good, and the Rust tests cover the states that matter. The component structure and the way VaultHealthChecklist is shared between onboarding and Settings is the right call.

Fix the stepper key, the completeAndExit error path, and the i18n/lint issues CodeRabbit flagged, get CI green, and this is ready.

t('onboarding.custom.stepperSearch'),
t('onboarding.custom.stepperEmbeddings'),
t('onboarding.custom.stepperMemory'),
t('onboarding.custom.stepperVault', t('onboarding.custom.stepperMemory', 'Vault')),
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.

[major] Nested t() as fallback resolves to the wrong label. If stepperVault is not in the locale files (no entry is added in this PR), this falls back to t('onboarding.custom.stepperMemory', 'Vault') — which is an existing key that returns the Memory step label, not "Vault".

Change to:

t('onboarding.custom.stepperVault', 'Vault')

And add stepperVault to en.ts (and other locale files).

}
}}
continueLabel={t('onboarding.custom.finish')}
/>
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.

[major] Error from completeAndExit is logged to console but otherwise swallowed. The user has no feedback that onboarding failed to complete and no way to retry. Need to surface this — a toast, an inline error state on the button, anything. As written, a failed exit leaves the user stuck.

Copy link
Copy Markdown
Contributor

@sanil-23 sanil-23 left a comment

Choose a reason for hiding this comment

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

@oxoxDev nice work on this — the read/write explainer plus the health checklist with concrete recovery actions is exactly what the issue was asking for, and I appreciate that you backed it with both Rust (vault_health_check_*) and Vitest coverage rather than leaving it UI-only. The shared MemoryDataPanel between onboarding and Settings is the right call too.

The code itself looks clean on my read — the new RPC avoids .unwrap() in the request path, the log line redacts the content-root path so no filesystem PII leaks, and the write probe (create-temp then remove under content-root) is a sensible way to detect writability without side effects.

A couple of things to sort before I can come back and approve:

  • CI isn't green yet — Rust Core Coverage, the two failing E2E lanes, and PR Submission Checklist (the diff-coverage box is still unchecked) all need to pass. Worth confirming the new lines clear the >= 80% diff-cover gate.
  • CodeRabbit has open threads on localizing the user-visible strings in the new components (they should flow through useT() like the rest of app/src/**). Those are the main code change left — once they're addressed and CI is green, ping me and I'll do the approval pass.

One small optional note: the readable field is computed in the RPC and carried through the TS type, but the checklist UI only surfaces exists/writable/obsidian/pipeline — so readable is effectively dead on the wire right now. Either surface it or drop it, your call.

@senamakel senamakel self-assigned this Jun 2, 2026
senamakel added 5 commits June 2, 2026 01:20
# Conflicts:
#	app/src/pages/onboarding/Onboarding.tsx
#	app/src/pages/onboarding/OnboardingContext.tsx
#	app/src/pages/onboarding/customWizardSteps.ts
#	app/src/pages/onboarding/steps/CustomWizardStep.tsx
- VaultHealthChecklist: replace all hardcoded strings with useT() i18n keys
- MemoryDataPanel: replace hardcoded strings with useT() i18n keys
- VaultSetupStep: replace hardcoded strings with useT() i18n keys,
  surface completeAndExit errors via inline error banner instead of
  swallowing them, refactor useEffect setState to render-time ref guard

Addresses @coderabbitai and @graycyrus review comments.
Add stepperVault, onboarding.custom.vault.*, vaultHealth.*, and
memoryData.* translation keys for the new vault onboarding step
and health checklist components.
Add real translations for stepperVault, onboarding.custom.vault.*,
vaultHealth.*, and memoryData.* keys across ar, bn, de, es, fr, hi,
id, it, ko, pl, pt, ru, zh-CN locale files.
The remove_file call after the vault writability probe was silently
discarding errors, which could leave .openhuman-vault-writecheck-*.tmp
files in the user's vault. Log at debug level so the failure is
traceable.

Addresses @graycyrus review comment.
@senamakel senamakel merged commit 9683653 into tinyhumansai:main Jun 2, 2026
17 of 19 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. memory Memory store, memory tree, recall, summarization, and embeddings in src/openhuman/memory/. rust-core Core Rust runtime in src/: CLI, core_server, shared infrastructure. working A PR that is being worked on by the team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add guided onboarding for memory and vault setup

4 participants