Skip to content

Let the user turn on cloud summarization from the app - #5418

Closed
yh928 wants to merge 3 commits into
tinyhumansai:mainfrom
yh928:feat/cloud-summarization-toggle
Closed

yh928 wants to merge 3 commits into
tinyhumansai:mainfrom
yh928:feat/cloud-summarization-toggle

Conversation

@yh928

@yh928 yh928 commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Rebased onto main 2026-09-02. Two things changed shape; see the discussion for the full reasoning.

  • Dropped: the HostSummariser::routes_to_cloud gate. main closed that hole itself — modules/memory_host.rs::resolve_chat_model now routes the "summarization" role through the tree summarizer's ladder rather than the blind role factory. memory/tinycortex/summariser.rs no longer exists.
  • Added: the half main did not close. ChatCallbacks holds one Arc<Config> built at module-serve time, so the consent flag was read from a boot snapshot — a user who withdrew consent kept having memory summarised in the cloud until the core restarted. The summarization role now re-reads from disk at the point of use, and a read failure refuses only the cloud route.

Closes #5417.

Summary

The memory-health panel tells the user to set memory_tree.cloud_summarization_opt_in=true when "Build Summary Trees" has no summarizer. Nothing in the app could set it. This adds the toggle, on the surface that reports the problem.

Problem

tree_runtime::ops::create_provider resolves the summarizer in three steps — local Ollama, else cloud when opted in, else error. A default headless install lands on the error, and the panel renders a remediation naming a flag with no control behind it:

  • Cloud opt-in appeared in the frontend only inside those remediation strings. No component read or wrote it; MemorySettingsPatch carried six fields and not this one; config/tools.rs states the config_update_* mutators are deliberately unexposed. The only routes were OPENHUMAN_MEMORY_TREE_CLOUD_SUMMARIZATION or hand-editing config.toml — both needing shell access to the host the app is supposed to manage.
  • Local AI has a real toggle, but on a box with no Ollama binary and nothing on :11434, flipping it makes summarizer_available report true while every call fails at connect.

Observed on a live instance: the tree's newest chunk 22 days old and frozen at 620 while the base namespace kept ingesting (a mail from 8 days ago was queryable), summary_tree reporting summarizer_unavailable, local_ai.runtime_enabled = false, cloud_summarization_opt_in = false, and nothing for the user to press.

Solution

MemorySettingsPatch + config_update_memory_settings carry cloud_summarization_opt_in; apply_memory_settings writes it
PipelineStatusResponse carries the current value
MemoryTreeStatusPanel toggle beside the existing auto-sync one
14 locales label + description

Three decisions worth stating:

The status payload carries the value rather than the panel assuming a default. A switch that renders false when the stored value is true would misreport whether memory summaries are allowed to leave the machine — the wrong thing to be casual about.

The toggle renders unconditionally, not only while summarizer_unavailable is live. A control that appears with the error and vanishes once it is fixed can grant consent but never withdraw it.

The copy says what it does — summaries are sent to the configured provider. That is why the setting is opt-in rather than a default, and the UI should not lose that when it becomes a switch.

Out of scope: provisioning Ollama from the app. The local-AI path is untouched.

Acceptance criteria

  • The flag is settable over RPCconfig_update_memory_settings accepts and persists it.
  • The panel shows real state — the toggle reads cloud_summarization_opt_in off the status payload.
  • The toggle is reversible — present whether or not the summarizer is currently unavailable, with a test that pins it.
  • Consent is legible — label and description in all 14 locales state that summaries go to the configured provider.
  • A partial patch cannot revoke consent — an absent field leaves the stored value alone (older clients post partial patches).
  • Testsconfig::ops 99, memory_tree::tree::rpc 17, MemoryTreeStatusPanel 24; tsc --noEmit and pnpm i18n:check clean (missing 0 / extra 0); fmt + clippy clean.

Related

Summary by CodeRabbit

  • New Features
    • Added a Memory Tree setting to opt in or withdraw consent for cloud-based summarization when local AI is unavailable.
    • The setting now reflects saved consent, handles loading and errors, and refreshes status after changes.
    • Cloud summarization uses the latest configuration and avoids proceeding when consent cannot be verified.
  • Localization
    • Added translated labels, privacy descriptions, and error messages across supported languages.
  • Tests
    • Added coverage for consent, withdrawal, defaults, configuration changes, and failure handling.

@yh928
yh928 requested a review from a team August 6, 2026 02:41

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

yh928 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Team

Run ID: d8502162-7d40-4693-961d-0d54d492611c

📥 Commits

Reviewing files that changed from the base of the PR and between 8e65c40 and fd45428.

📒 Files selected for processing (26)
  • app/src/components/intelligence/MemoryTreeStatusPanel.test.tsx
  • app/src/components/intelligence/MemoryTreeStatusPanel.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/services/analytics.ts
  • app/src/utils/tauriCommands/memoryTree.ts
  • src/openhuman/config/ops/model.rs
  • src/openhuman/config/ops_tests_part_02_tests.rs
  • src/openhuman/config/schemas/controllers_part_01.rs
  • src/openhuman/config/schemas/helpers.rs
  • src/openhuman/config/schemas/schemas_schema_part_01.rs
  • src/openhuman/memory/tree/tree/rpc_part_02.rs
  • src/openhuman/modules/memory_host.rs
  • src/openhuman/modules/memory_host_tests.rs
🚧 Files skipped from review as they are similar to previous changes (20)
  • app/src/services/analytics.ts
  • app/src/lib/i18n/bn.ts
  • app/src/lib/i18n/en.ts
  • app/src/lib/i18n/de.ts
  • app/src/lib/i18n/es.ts
  • app/src/lib/i18n/zh-CN.ts
  • app/src/lib/i18n/ko.ts
  • app/src/lib/i18n/pl.ts
  • app/src/lib/i18n/fr.ts
  • app/src/lib/i18n/id.ts
  • app/src/lib/i18n/ar.ts
  • app/src/utils/tauriCommands/memoryTree.ts
  • app/src/lib/i18n/it.ts
  • app/src/lib/i18n/pt.ts
  • src/openhuman/config/ops/model.rs
  • src/openhuman/config/schemas/helpers.rs
  • app/src/lib/i18n/hi.ts
  • app/src/components/intelligence/MemoryTreeStatusPanel.tsx
  • app/src/components/intelligence/MemoryTreeStatusPanel.test.tsx
  • app/src/lib/i18n/ru.ts

Included review availability: Your plan provides up to 10 included reviews per hour; 5 remain after this review.


📝 Walkthrough

Walkthrough

The change adds a reversible cloud-summarization consent setting. The setting persists through the configuration RPC, appears in memory-tree status, controls summarization model resolution, and is available through a localized status-panel switch.

Changes

Cloud summarization consent

Layer / File(s) Summary
Persist consent
src/openhuman/config/schemas/*, src/openhuman/config/ops/model.rs, src/openhuman/config/ops_tests_part_02_tests.rs
The memory settings schema and patch accept optional consent. Explicit values persist, while omitted values remain unchanged.
Apply consent during summarization
src/openhuman/modules/memory_host.rs, src/openhuman/modules/memory_host_tests.rs
The summarization role reloads configuration before model resolution. Failed reloads block stale cloud routes but do not block local-AI summarization.
Expose status and update command
src/openhuman/memory/tree/tree/rpc_part_02.rs, app/src/utils/tauriCommands/memoryTree.ts
The status response exposes stored consent. The frontend command updates the setting through openhuman.config_update_memory_settings.
Render and validate the control
app/src/components/intelligence/MemoryTreeStatusPanel.tsx, app/src/components/intelligence/MemoryTreeStatusPanel.test.tsx, app/src/lib/i18n/*, app/src/services/analytics.ts
The panel renders an always-available localized switch, records changes, handles failures, and tests opt-in, withdrawal, healthy availability, and default opt-out behavior.

Estimated code review effort: 4 (Complex) | ~45 minutes

Merge Risk: ⚪ Minimal · up to fd454

This change lets users enable or withdraw cloud summarization from the memory settings panel while preserving the stored consent state. No actionable merge-blocking risk remains beyond normal checks and review.

Suggested reviewers: senamakel

Poem

A rabbit toggles consent bright
The memory tree updates right
Cloud summaries follow the guide
Local paths remain inside
Tests watch each setting change
Translations hop across the range

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The changes satisfy the coding objectives in [#5417]. They persist cloud-summarization consent through the settings RPC, expose the stored value, provide an unconditional reversible toggle, add consen…
Out of Scope Changes check ✅ Passed The changes remain within [#5417]. Tests, localization, analytics, status reporting, persistence, and configuration reload behavior directly support the cloud-summarization control. Ollama provisionin…
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 36 functions across 26 files. (5 skipped: …
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: adding an app control that lets users enable cloud summarization. It is concise, specific, and related to the pull request objectives.
Full details: Linked Issues check

Explanation

The changes satisfy the coding objectives in [#5417]. They persist cloud-summarization consent through the settings RPC, expose the stored value, provide an unconditional reversible toggle, add consent-related localization, preserve omitted patch fields, and reload configuration for correct summarization routing.

Full details: Out of Scope Changes check

Explanation

The changes remain within [#5417]. Tests, localization, analytics, status reporting, persistence, and configuration reload behavior directly support the cloud-summarization control. Ollama provisioning remains unchanged and out of scope.

Full details: Docstring Coverage

Explanation

Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 36 functions across 26 files. (5 skipped: 5 too large.)

Warning

Your free Security trial is over. An organization admin can upgrade to Advanced for continuous pull request security review or dismiss this notice.


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

@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. labels Aug 6, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 24db6a0521

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/openhuman/config/ops/model.rs

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 4

🧹 Nitpick comments (1)
src/openhuman/config/ops/model.rs (1)

309-311: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a diagnostic log line for the consent state transition.

The block sets config.memory_tree.cloud_summarization_opt_in but does not log the change. This flag controls whether workspace memory content leaves the device to a configured cloud provider. Add a grep-friendly log line for this transition so an operator can trace when consent changed, without logging any memory content.

💡 Suggested diagnostic log
     if let Some(opt_in) = update.cloud_summarization_opt_in {
+        tracing::info!(
+            opt_in,
+            "[config] cloud_summarization_opt_in updated"
+        );
         config.memory_tree.cloud_summarization_opt_in = opt_in;
     }

Do you want me to open a follow-up issue to add consistent state-transition logging across the other MemorySettingsPatch fields as well?

As per path instructions, "New or changed flows must include verbose, grep-friendly diagnostics for entry/exit, branches, external calls, retries, state transitions, and errors, while never logging secrets or full PII."

🤖 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 `@src/openhuman/config/ops/model.rs` around lines 309 - 311, In the update flow
containing the cloud_summarization_opt_in assignment, add a verbose,
grep-friendly diagnostic log immediately before or after the state transition
that records the previous and new consent states. Do not include memory content,
secrets, or other PII, and keep the existing assignment behavior unchanged.

Source: Path instructions

🤖 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/MemoryTreeStatusPanel.tsx`:
- Around line 356-372: Update the cloud-summarization switch to use a stable
analytics identifier, and in handleCloudSummarizationToggle call
trackAnalyticsEvent from components/analytics only after
memoryTreeSetCloudSummarization succeeds. Keep the event dimensions free of
optIn and other user-preference data, and preserve the existing refresh and
error handling flow.

In `@app/src/lib/i18n/de.ts`:
- Around line 1342-1344: Update the German
`memoryTree.status.cloudSummarizationDescription` translation to use the formal
`Sie/Ihren` address consistently with the adjacent auto-sync text and explicitly
identify the configured cloud provider as the destination for summaries. Keep
the label unchanged.

In `@app/src/lib/i18n/ko.ts`:
- Around line 1283-1285: Add a dedicated cloud-consent toggle failure
translation alongside the existing memoryTree status keys in ko.ts and mirror
the same key across every locale. Update the cloud toggle error path in
MemoryTreeStatusPanel to use this new cloud-specific key instead of
memoryTree.status.toggleFailed, preserving the existing auto-sync failure
translation for its original handler.

In `@app/src/lib/i18n/pl.ts`:
- Around line 1314-1316: Update the cloud-toggle error handling in
MemoryTreeStatusPanel to use a dedicated cloud-toggle failure translation key
instead of memoryTree.status.toggleFailed. Add the corresponding Polish
translation near the existing cloudSummarization keys and define matching
translations for the same key in every supported locale, preserving the existing
generic toggle failure key for non-cloud errors.

---

Nitpick comments:
In `@src/openhuman/config/ops/model.rs`:
- Around line 309-311: In the update flow containing the
cloud_summarization_opt_in assignment, add a verbose, grep-friendly diagnostic
log immediately before or after the state transition that records the previous
and new consent states. Do not include memory content, secrets, or other PII,
and keep the existing assignment behavior unchanged.
🪄 Autofix

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 Plus

Run ID: 9f89c648-135f-4418-bd3a-9e84aadf296a

📥 Commits

Reviewing files that changed from the base of the PR and between e29bfc6 and 24db6a0.

📒 Files selected for processing (23)
  • app/src/components/intelligence/MemoryTreeStatusPanel.test.tsx
  • app/src/components/intelligence/MemoryTreeStatusPanel.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/utils/tauriCommands/memoryTree.ts
  • src/openhuman/config/ops/model.rs
  • src/openhuman/config/ops_tests.rs
  • src/openhuman/config/schemas/controllers.rs
  • src/openhuman/config/schemas/helpers.rs
  • src/openhuman/config/schemas/schema_defs.rs
  • src/openhuman/memory/tree/tree/rpc.rs

Comment thread app/src/components/intelligence/MemoryTreeStatusPanel.tsx
Comment thread app/src/lib/i18n/de.ts Outdated
Comment thread app/src/lib/i18n/ko.ts Outdated
Comment thread app/src/lib/i18n/pl.ts Outdated
@yh928
yh928 force-pushed the feat/cloud-summarization-toggle branch from 24db6a0 to 849ca00 Compare August 10, 2026 00:08
@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@coderabbitai coderabbitai Bot added the memory Memory store, memory tree, recall, summarization, and embeddings in src/openhuman/memory/. label Aug 10, 2026

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 4

🧹 Nitpick comments (1)
src/openhuman/memory/tinycortex/summariser.rs (1)

37-83: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add the required debug or trace diagnostics.

The changed flow logs a reload error at warn but does not record the consent decision, unavailable branch, or provider call with a safe correlation field. Use debug or trace logs with the existing stable prefix and a non-sensitive correlation value.

As per coding guidelines, use log or tracing at debug or trace levels with stable prefixes and correlation fields for changed 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 `@src/openhuman/memory/tinycortex/summariser.rs` around lines 37 - 83, The
changed summarisation flow lacks diagnostic coverage for its key decisions. Add
debug or trace logs in consent_config and call using the existing stable
memory_tree::summarise prefix, recording a non-sensitive correlation field for
the consent result, unavailable refusal branch, and provider invocation; keep
sensitive inputs and content out of logs.

Source: Coding guidelines

🤖 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 `@src/openhuman/memory/tinycortex/summariser.rs`:
- Around line 191-213: Update the test setup around HostSummariser::new so its
initial Config has cloud_summarization_opt_in disabled, then persist enabled
consent to the config file before calling summarise. Keep the existing
availability assertion and provider-reachability check, ensuring the test
exercises the live reload value rather than the startup snapshot.
- Around line 34-50: Update the Err branch of consent_config so a failed reload
explicitly sets config.memory_tree.cloud_summarization_opt_in to false before
returning the cloned configuration, while preserving the existing warning and
other startup-snapshot values.
- Around line 160-164: Update refuses_to_summarise_without_cloud_consent to use
the same isolated temporary config fixture as the granted-consent test, setting
cloud_summarization_opt_in to false while retaining local_ai.runtime_enabled =
false. Avoid Config::default()’s user-scoped config_path so the test cannot read
ambient persisted consent.
- Around line 76-83: Update the summarise flow around summarizer_available and
build_chat_provider so cloud-selected providers are rejected unless the default
memory_tree.cloud_summarization_opt_in is enabled, even when local AI is
available. Fail closed before sending inputs to the cloud, while preserving
local-provider summarization and the existing unavailable error behavior.

---

Nitpick comments:
In `@src/openhuman/memory/tinycortex/summariser.rs`:
- Around line 37-83: The changed summarisation flow lacks diagnostic coverage
for its key decisions. Add debug or trace logs in consent_config and call using
the existing stable memory_tree::summarise prefix, recording a non-sensitive
correlation field for the consent result, unavailable refusal branch, and
provider invocation; keep sensitive inputs and content out of logs.
🪄 Autofix

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 Plus

Run ID: 8968b9d2-5912-4594-b609-855045c9b6c3

📥 Commits

Reviewing files that changed from the base of the PR and between 8774fe4 and 849ca00.

📒 Files selected for processing (25)
  • app/src/components/intelligence/MemoryTreeStatusPanel.test.tsx
  • app/src/components/intelligence/MemoryTreeStatusPanel.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/services/analytics.ts
  • app/src/utils/tauriCommands/memoryTree.ts
  • src/openhuman/config/ops/model.rs
  • src/openhuman/config/ops_tests.rs
  • src/openhuman/config/schemas/controllers.rs
  • src/openhuman/config/schemas/helpers.rs
  • src/openhuman/config/schemas/schema_defs.rs
  • src/openhuman/memory/tinycortex/summariser.rs
  • src/openhuman/memory/tree/tree/rpc.rs
🚧 Files skipped from review as they are similar to previous changes (23)
  • src/openhuman/config/schemas/controllers.rs
  • src/openhuman/config/ops_tests.rs
  • src/openhuman/config/schemas/schema_defs.rs
  • app/src/lib/i18n/ru.ts
  • src/openhuman/config/ops/model.rs
  • src/openhuman/config/schemas/helpers.rs
  • app/src/components/intelligence/MemoryTreeStatusPanel.test.tsx
  • src/openhuman/memory/tree/tree/rpc.rs
  • app/src/lib/i18n/pl.ts
  • app/src/lib/i18n/pt.ts
  • app/src/lib/i18n/de.ts
  • app/src/components/intelligence/MemoryTreeStatusPanel.tsx
  • app/src/lib/i18n/ar.ts
  • app/src/lib/i18n/id.ts
  • app/src/lib/i18n/ko.ts
  • app/src/lib/i18n/hi.ts
  • app/src/lib/i18n/es.ts
  • app/src/utils/tauriCommands/memoryTree.ts
  • app/src/lib/i18n/bn.ts
  • app/src/lib/i18n/en.ts
  • app/src/lib/i18n/zh-CN.ts
  • app/src/lib/i18n/fr.ts
  • app/src/lib/i18n/it.ts

Comment thread src/openhuman/memory/tinycortex/summariser.rs Outdated
Comment thread src/openhuman/memory/tinycortex/summariser.rs Outdated
Comment thread src/openhuman/memory/tinycortex/summariser.rs Outdated
Comment thread src/openhuman/memory/tinycortex/summariser.rs Outdated

@tinysweeper tinysweeper Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

tinysweeper found nothing blocking. Approving.

             $0.0137 · 153,657 in / 22,244 out · 54,071 cached (35%) · z-ai/glm-5.2, deepseek/deepseek-v4-pro
critique:    $0.0070 · 55,170 in  / 13,335 out · 16,785 cached (30%) · z-ai/glm-5.2, deepseek/deepseek-v4-pro
security:    $0.0023 · 54,594 in  / 2,684 out  · 37,286 cached (68%) · z-ai/glm-5.2
tests:       $0.0016 · 13,137 in  / 3,256 out  · 0 cached (0%)       · z-ai/glm-5.2
description: $0.0015 · 13,939 in  / 2,240 out  · 0 cached (0%)       · z-ai/glm-5.2

@tinysweeper

tinysweeper Bot commented Aug 10, 2026

Copy link
Copy Markdown

How this change flows

1 changed behaviour across 3 relationships. 3 surrounding behaviours are shown (60 graph nodes walked). 40 further behaviours left out to keep the diagram readable.

flowchart LR
  n0["MemoryTreeStatusPanel<br/>changed"]:::changed
  n1["tmp_config"]:::impacted
  n2["format"]:::impacted
  n3["join"]:::impacted
  n0 -->|calls| n2
  n1 -->|calls| n3
  n3 -->|calls| n2
  classDef changed fill:#0d4429,stroke:#238636,color:#e6edf3
  classDef impacted fill:#161b22,stroke:#6e7681,color:#c9d1d9
  classDef flagged fill:#5a1e02,stroke:#d93f0b,color:#ffffff
  classDef blocking fill:#67060c,stroke:#f85149,color:#ffffff
Loading

Green: changed behaviour. Grey: surrounding behaviour. Arrows name the call, use, implementation, or test relationship. Orange: has findings. Red: has a finding that blocks the merge.

tinysweeper 0.1.0

@tinysweeper tinysweeper Bot added the priority: p2 Soon. Real but survivable — a rough edge, a gap, a thing that will bite later. label Aug 10, 2026
@yh928
yh928 force-pushed the feat/cloud-summarization-toggle branch from 849ca00 to 1ed86a0 Compare August 11, 2026 05:38
@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

yh928 added a commit to yh928/openhuman that referenced this pull request Aug 11, 2026
…losed

Review found the gate had a hole and the wrong failure direction.

**The hole.** It reused `summarizer_available`, which passes whenever local AI
is enabled. But `summarise` never reads `local_ai.runtime_enabled` — it resolves
the `summarization` role, which is `memory_provider` and falls back to the
managed cloud backend when that is unset. Local AI on with `memory_provider`
unset therefore passed the consent check while sending workspace memory to the
cloud: the exact bypass the gate exists to close.

The question is not "can we summarize" but "would this summary leave the
machine". `routes_to_cloud` asks `provider_for_role("summarization")` and checks
whether the answer is a local provider string, so the gate is on the destination
rather than on capability.

**The direction.** A failed consent re-read kept the startup snapshot. A config
read that errors is not evidence of consent, and a stale `true` would keep
sending after a withdrawal. It now refuses. The refusal is visible — the doctor
reports `summarizer_unavailable` and the panel renders the toggle beside it —
where continuing is silent.

Tests, all on a config anchored to its own temp file (`Config::default()` points
`config_path` at the real `~/.openhuman/config.toml`, so the gate's reload would
otherwise let the developer's own consent decide the assertion):

- a cloud route without consent refuses
- consent granted on disk after startup is honoured — constructed with consent
  OFF so a gate that trusted its snapshot, or fell back to it, would fail
- consent withdrawn on disk after startup takes effect before the next summary
- local AI enabled does not excuse an un-consented cloud route
- a local route owes no cloud consent

summariser 5 pass; fmt clean.

Reported by CodeRabbit on tinyhumansai#5418.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SRSNnqQsokuGmkbpLoLCGy

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/openhuman/memory/tinycortex/summariser.rs (1)

190-203: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Prove that the grant test uses a cloud route.

The fixture does not assert that granted resolves to cloud. If it resolves local, the consent gate is bypassed and this test passes without testing the reload behavior. Set memory_provider explicitly if needed, then assert HostSummariser::routes_to_cloud(&granted) before the call.

🤖 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 `@src/openhuman/memory/tinycortex/summariser.rs` around lines 190 - 203, Update
the grant test around HostSummariser::new to explicitly configure
granted.memory_provider for the cloud path, then assert
HostSummariser::routes_to_cloud(&granted) before invoking summarise. Preserve
the existing consent persistence and refusal assertion while ensuring the test
exercises reload behavior for a cloud route.
🤖 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 `@src/openhuman/memory/tinycortex/summariser.rs`:
- Around line 63-76: Add a trace-level diagnostic in `call` for the consent
decision, using the `[memory_tree]` prefix and including `context.tree_id`, the
result of `Self::routes_to_cloud(&self.config)`, and whether consent allows or
refuses the operation. Keep the record opaque and exclude summary content,
provider names, and credentials; preserve the existing refusal behavior.

---

Nitpick comments:
In `@src/openhuman/memory/tinycortex/summariser.rs`:
- Around line 190-203: Update the grant test around HostSummariser::new to
explicitly configure granted.memory_provider for the cloud path, then assert
HostSummariser::routes_to_cloud(&granted) before invoking summarise. Preserve
the existing consent persistence and refusal assertion while ensuring the test
exercises reload behavior for a cloud route.
🪄 Autofix

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 Plus

Run ID: 2f30d84a-3808-4eef-a21f-5821b1daa50b

📥 Commits

Reviewing files that changed from the base of the PR and between 1ed86a0 and f9c8cb6.

📒 Files selected for processing (2)
  • src/openhuman/memory/tinycortex/summariser.rs
  • src/openhuman/web3/wallet/chains/btc.rs

Comment thread src/openhuman/memory/tinycortex/summariser.rs Outdated
@M3gA-Mind

Copy link
Copy Markdown
Collaborator

Maintainer review pass (comment only — no approval, and I am not pushing to this branch).

Verdict: the problem you found is still real and still unfixed on main, and your diagnosis of it is the best part of this PR. But the file carrying your core change no longer exists, so this needs re-targeting rather than a rebase. Please read before doing any conflict work — a straight rebase will waste your time.

The user-facing problem is still live

I checked, because a month is a long time in this repo:

  • cloud_summarization_opt_in still exists on the Rust side, now read at src/openhuman/memory/tree/tree_runtime/ops.rs and src/openhuman/modules/memory_host.rs.
  • On the frontend it still appears only in the 14 locale files, i.e. still only inside the remediation strings. git grep -l "cloud_summarization\|cloudSummarization" -- app/src/components app/src/utils app/src/services returns nothing on main.

So the exact thing you filed #5417 about — a panel telling the user to set a flag that no control in the app can set — is unchanged. Nobody has overtaken you on the substance.

What broke underneath you

src/openhuman/memory/tinycortex/summariser.rs — where your largest hunk lives (+209/-2), the consent gate and its tests — is gone from main, along with the entire src/openhuman/memory/tinycortex/ directory.

This is the eviction wave: the summariser moved down into the loaded tinymemory module. Its consumers in the core are now memory/tree/tree_runtime/ops.rs and modules/memory_host.rs (both of which do still read cloud_summarization_opt_in). So the gate you wrote needs a new home and probably a different shape — that is a re-do of the Rust half, not a merge conflict to resolve.

The rest of your files survived and should still apply:

File On main
src/openhuman/memory/tinycortex/summariser.rs gone
src/openhuman/memory/tree/tree/rpc.rs present
src/openhuman/config/ops/model.rs, ops_tests.rs, schemas/{controllers,helpers,schema_defs}.rs present
app/src/components/intelligence/MemoryTreeStatusPanel.{tsx,test.tsx} present
app/src/utils/tauriCommands/memoryTree.ts, app/src/services/analytics.ts present
14 locale files present

In other words the frontend half — the toggle, the status payload, the locales — is probably close to still landing. It is the core-side consent gate that needs rethinking against the module seam.

Ignore the red CI — it is not about your change

Rust Quality (fmt, clippy) failed with:

error[E0432]: unresolved import `super::types`
  --> src/openhuman/memory/diff/stub.rs:29:12
error[E0432]: unresolved import `tools`
  --> src/openhuman/memory/diff/mod.rs:79:9

Neither file is yours, and src/openhuman/memory/diff/ has since been deleted from main entirely (the whole memory-git / memory::diff surface went). That run was a broken base on 2026-08-11, not a defect in this PR. Markdown Link Check, Feature-Gate Smoke and PR CI Gate all fall out of the same base. There is nothing for you to fix in any of them.

On the design — worth preserving through the rewrite

Three calls in your description are right and I would not want them lost when this is re-cut:

  • The status payload carries the current value rather than the panel assuming a default. A switch rendering false over a stored true would misreport whether summaries may leave the machine; that is the one thing here that must not be guessed.
  • The toggle renders unconditionally, not only while summarizer_unavailable is live. A control that appears with the error and vanishes when it clears can grant consent but never withdraw it. That asymmetry would be a genuine privacy defect.
  • The copy names the destination. It is opt-in because summaries go to a configured cloud provider, and the UI shouldn't drop that when the sentence becomes a switch.

The one still-open review thread

CodeRabbit asks for a debug/trace record on the consent decision — correlation field (context.tree_id), the cloud-route result and the allow/refuse result, with no summary content, provider strings or credentials. That is a reasonable ask for a privacy-sensitive branch and it survives the re-targeting, so it is worth carrying into whatever the new gate looks like.

Suggested path

  1. Don't rebase this as-is.
  2. Decide with a maintainer where the consent gate belongs now that the summariser is behind the module seam (modules/memory_host.rs vs tree_runtime/ops.rs).
  3. Consider splitting: the frontend toggle + MemorySettingsPatch + status payload + locales is a coherent PR on its own and is closer to landing than the core half.

Sorry this sat long enough to be overtaken by a refactor. The diagnosis in your description — the live instance frozen at 620 chunks with a 22-day-old newest chunk while the base namespace kept ingesting — is exactly the kind of evidence that makes a bug report actionable, and it is still worth acting on.

@yh928
yh928 force-pushed the feat/cloud-summarization-toggle branch from f9c8cb6 to fd45428 Compare September 2, 2026 12:30
@yh928

yh928 commented Sep 2, 2026

Copy link
Copy Markdown
Contributor Author

Rebased onto main (8e65c4008) and pushed. You were right that a straight rebase would waste time — but the shape of the answer turned out to be more interesting than "re-do the Rust half", so it's worth writing down what I found.

The Rust gate is half superseded, and the half that isn't is the one that mattered

You said the summariser's new home would need a different shape. It needs less than that, because main already closed part of the hole — and I want to be explicit about which part, because the remaining gap is easy to miss.

modules/memory_host.rs::resolve_chat_model now special-cases the "summarization" role through tree_runtime::ops::create_provider instead of the blind role factory, and its doc comment says why in almost the words this PR used:

"Routing the role factory directly here was a consent hole… with local AI enabled and the cloud opt-in false, the host-side create_provider precondition succeeds (a local model is constructible), and the blind role factory then resolved "summarization" to the configured cloud provider anyway — memory content leaving the machine against an explicit opt-out."

That is exactly what HostSummariser::routes_to_cloud existed to catch. It's fixed; I've dropped that half rather than re-implementing it. Good outcome — someone got there first and got it right.

What is still open is the staleness half. ChatCallbacks is constructed once, at module-serve time:

struct ChatCallbacks(Arc<Config>);
// …
ChatCallbacks(Arc::clone(&config))     // memory_host.rs:480, once

and never refreshed. So the consent flag every summarization route is checked against is a boot-time snapshot. A user who opens the panel, unticks the box, and expects summaries to stop leaving the machine keeps having them sent to their cloud provider until the core restarts — the withdrawal is recorded on disk and ignored at the point of use. That is the same defect cloud_consent_granted() was written for, and it is untouched on main.

So the Rust half of this PR is now one small change in memory_host.rs rather than a 209-line gate in a deleted file: the summarization role re-reads its config from disk before resolving a route, exactly the way ComposioCallbacks::live_config already does in the same file. Every other role keeps the snapshot.

On the read-failure behaviour, which is a real design choice and not obvious: it fails closed only on the cloud route. A config that cannot be read is not evidence that consent still holds, so refusing is right — but blanket-refusing would break summarization for local-AI users, who never needed consent at all and whose route the ladder resolves without consulting the flag. So a failed re-read blocks the cloud path and leaves the local path alone.

CodeRabbit's outstanding threads

Both remaining ones were on summariser.rs, so they die with the file — but one of them was a good point and I've carried it across rather than let it lapse: the consent decision now emits a debug line with [memory_tree::summarise], recording the role, whether the route is cloud, and the allow/refuse result. No summary content, no provider strings, no credentials.

The other (assert the grant test resolves to cloud) was specific to a fixture that no longer exists.

The frontend half, which is the actual fix for #5417

Unchanged and still needed — you confirmed it yourself: cloud_summarization_opt_in still appears nowhere in app/src/components|utils|services on main, so the remediation string still tells the user to set a flag no control can set. 25 of this PR's 26 files applied; the panel toggle, the config_update_memory_settings field, the PipelineStatusResponse field, the analytics event and all 14 locales are as they were.

The web3/wallet/chains/btc.rs hunk is gone — that was a rustfmt fix for a main that was red at the time, and it isn't any more.

@coderabbitai

coderabbitai Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@tinysweeper tinysweeper Bot added priority: p3 Whenever. Cosmetic, a nicety, or a cleanup with no user visible effect. and removed priority: p2 Soon. Real but survivable — a rough edge, a gap, a thing that will bite later. labels Sep 2, 2026
@coderabbitai coderabbitai Bot removed 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/. labels Sep 2, 2026
coderabbitai[bot]
coderabbitai Bot previously approved these changes Sep 2, 2026
@yh928

yh928 commented Sep 2, 2026

Copy link
Copy Markdown
Contributor Author

The diff-coverage gate came in at 70% (7 of 24 changed lines uncovered), and the gaps were in the two places this feature is least safe to leave unverified. Fixed rather than waived.

MemoryTreeStatusPanel.tsx:165-167 — the catch arm. This toggle is deliberately not optimistic: on failure the panel falls back to whatever the next status poll reports. So a swallowed rejection would leave the switch reading "off" for a machine that is still summarising in the cloud — the single failure mode a consent control must not have. The new test asserts the error toast and that the control re-enables afterwards, because a toggle stuck disabled after one failed attempt cannot be used to withdraw consent later.

memoryTree.ts:1013-1019 — the RPC wrapper, which the panel tests mock away entirely, so nothing exercised it. Three tests now pin the parts that would fail silently:

  • the params exactly, not objectContainingconfig_update_memory_settings applies only the fields it is given, so a wrapper that sent the whole settings object would let this toggle quietly rewrite the embedder or the memory window;
  • that an explicit false travels rather than being omitted — an absent field means "leave alone" to the core, which would make the off position a no-op, i.e. consent that cannot be taken back;
  • that a transport failure propagates instead of resolving, which is what the panel's catch arm above depends on.

75 tests pass. The panel is at 96% line coverage with no uncovered lines, and memoryTree.ts's remaining gaps are outside this diff.

`memory_tree.cloud_summarization_opt_in` is the flag the memory-health
panel's own remediation text names when it reports `summarizer_unavailable`
— and until now nothing in the app could set it. The user was told to flip
a switch that did not exist, on any surface they had.

Adds it end to end:

- `MemorySettingsPatch.cloud_summarization_opt_in`, threaded through
  `config.update_memory_settings` and declared in its schema. Optional, so
  an older client posting a partial patch cannot silently revoke consent
  the user granted elsewhere.
- `PipelineStatusResponse.cloud_summarization_opt_in`, so the control can
  render the *stored* value. A toggle showing a default would misreport
  whether memory summaries are allowed to leave the machine, which is the
  one thing this control must not get wrong.
- The toggle itself in the memory-tree status panel, rendered
  unconditionally beside auto-sync rather than only while
  `summarizer_unavailable` is live: a control that appears with an error
  and vanishes when it clears cannot be used to *withdraw* the consent it
  granted.
- Copy in all 14 locales, and a `memory_tree_cloud_summarization_changed`
  analytics event carrying only the boolean.

Tests: both directions of the RPC patch (set, withdraw, and absent-means-
unchanged) and three panel tests covering stored-value rendering,
withdrawal, and the control's presence when the summarizer is healthy.
…t at boot

`main` already closed the other half of this hole: `resolve_chat_model`
routes the "summarization" role through the tree summarizer's ladder
instead of the blind role factory, so local AI being on no longer lets a
cloud-resolved fold slip past the opt-in. That is the check this branch
originally added as `HostSummariser::routes_to_cloud`, and it is dropped
rather than duplicated.

What is still open is *when* the flag is read. `ChatCallbacks` is built
once, at module-serve time, from an `Arc<Config>` that is never refreshed:

    ChatCallbacks(Arc::clone(&config))     // memory_host.rs, once

So every summarization route is decided against a boot-time snapshot. A
user who unticks the box has their withdrawal written durably to disk and
ignored at the point of use — workspace memory keeps going to their cloud
provider until the core restarts. That is the worst shape a consent
control can have: it reports success and changes nothing.

The summarization role — and only it — now re-reads from disk before
resolving, the way `ComposioCallbacks::live_config` already does in this
file. Other roles carry no consent decision, and re-reading for all of
them would put a file read in front of every module-side model call.

A read failure refuses **only** the cloud route: a config that cannot be
read is not evidence that consent still holds, but blanket-refusing would
break summarization for local-AI users who never owed consent at all. So
the refusal is scoped to the case where the held snapshot says the route
would be the cloud one — exactly where the answer might have changed.

Also adds the consent-decision `debug` line CodeRabbit asked for on the
original gate: role, local-AI state, and the opt-in result. No summary
content, no provider strings, no credentials.
…C wrapper

The diff-coverage gate came in at 70%, and the seven uncovered lines were
the two places this feature is least safe to leave unverified:

- `MemoryTreeStatusPanel.tsx:165-167` — the catch arm. The toggle is not
  optimistic; on failure the panel re-reads the stored value on the next
  poll. If the rejection were swallowed the switch would read "off" for a
  machine still summarising in the cloud, which is the one thing a consent
  control must never do. Now asserts the error toast *and* that the control
  re-enables, since a toggle stuck disabled after one failure cannot be
  used to withdraw consent later.
- `memoryTree.ts:1013-1019` — `memoryTreeSetCloudSummarization` itself,
  which the panel tests mock away entirely. Now asserts the exact params
  (the shared memory-settings mutator applies only the fields it is given,
  so sending more would let this toggle rewrite the embedder), that an
  explicit `false` travels rather than being omitted (an absent field means
  "leave alone", which would make the off position a no-op), and that a
  transport failure propagates.

75 tests pass; the panel is at 96% line coverage with no uncovered lines,
and `memoryTree.ts`'s remaining gaps are outside this diff.
@yh928
yh928 force-pushed the feat/cloud-summarization-toggle branch from b07a474 to 7f3b8fc Compare September 4, 2026 13:49
@yh928

yh928 commented Sep 4, 2026

Copy link
Copy Markdown
Contributor Author

Rebased onto main f5c5ba892 — the only conflict was memoryTree.test.ts, where main added a memoryTreeBackfillConnectorTrees block at the end of the file and this PR added one too. Pure parallel append; both kept. (My first resolution dropped two closing braces and broke the parse — caught by running the file rather than by reading the diff, which is the argument for running it.) 39/39 pass.

The red Frontend Checks lane is not this PR. I checked rather than asserting it, because "unrelated flake" is the convenient answer.

The failure is:

FAIL src/components/settings/panels/__tests__/SandboxSettingsPanel.validation.test.tsx
  > SandboxSettingsPanel — memory limit validation > persists a positive integer
  TestingLibraryElementError: Unable to find an element with the display value: 512

That file is nowhere near this change. It gets pulled into the lane because vitest related walks the import graph from the 16 i18n locale files this PR touches, and every settings panel imports i18n — so a copy-only locale change drags the whole panel suite in.

Evidence it is not mine:

  • The same test fails on an unrelated branch. fix/release-notes-git-log-enobufs (run 33878056867, 09-04 13:26) fails in the same file with the same assertion shape — Unable to find an element with the display value: 1. Different value, same test, a branch that touches release-notes tooling.
  • It passes here, repeatedly. SandboxSettingsPanel.validation.test.tsx alone: 14/14. The whole panels/__tests__/ directory, three consecutive runs: 873 passed / 1 skipped each time.
  • The lane's own script passes locally with this PR's exact changed-file list (CHANGED_FILES=… scripts/ci/vitest-changed-coverage.sh, exit 0).

So it reads as a genuine flake in that test — a waitFor-less assertion on a debounced numeric input is the usual shape — that surfaces under CI's load and parallelism. I have not touched it, since fixing someone else's flaky test inside a feature PR is how a rebase turns into an unreviewable diff. Happy to open a separate PR for it if that is wanted; it looks like the input's committed value is asserted before the debounce settles.

Everything this PR owns is green: tsc, Prettier, ESLint, i18n coverage all pass in the same job, and the Rust side is 23/23 on the touched paths.

@senamakel

Copy link
Copy Markdown
Member

we're moveing tree stuff so closing this pr

@senamakel senamakel closed this Sep 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

priority: p3 Whenever. Cosmetic, a nicety, or a cleanup with no user visible effect.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Memory health tells the user to set a flag the app cannot set

3 participants