Skip to content

Repair OpenHuman memory source retrieval paths#125

Open
hobertrand-hub wants to merge 5 commits into
tinyhumansai:mainfrom
hobertrand-hub:integration/openhuman-memory-repair
Open

Repair OpenHuman memory source retrieval paths#125
hobertrand-hub wants to merge 5 commits into
tinyhumansai:mainfrom
hobertrand-hub:integration/openhuman-memory-repair

Conversation

@hobertrand-hub

@hobertrand-hub hobertrand-hub commented Jul 27, 2026

Copy link
Copy Markdown

Summary

This is the TinyCortex dependency PR for the OpenHuman source-retrieval repair. It keeps the patch narrow to memory/source retrieval behavior needed by OpenHuman before the host branch is exported.

Changes included:

  • unblock legacy chunk reembedding by preserving readable legacy content paths
  • keep empty legacy content-pointer failures terminal so backfill does not loop forever
  • recognize mem_src:<source_id>:... source scopes during source-scoped retrieval

Why

OpenHuman source-note queries depend on TinyCortex being able to retrieve document-tree scopes and recover usable text from legacy chunk rows. Without these fixes, host-side routing can classify the request correctly but source retrieval still misses or stalls on legacy/indexed source data.

Validation

  • cargo +1.96.1 test store_embed --lib -- --nocapture
  • cargo +1.96.1 test source --lib -- --nocapture
  • cargo +1.96.1 test content::read --lib -- --nocapture
  • cargo +1.96.1 test --lib

Full lib result: 1238 passed; 0 failed.

Summary by CodeRabbit

  • Bug Fixes
    • Improved retrieval source filtering to support mem_src:-based scopes and selector forms when matching hits.
    • Treated mem_src: document scopes as document kind matches during scope filtering.
    • Restored legacy chunk body reads when newer content pointer data is missing or incomplete.
    • Improved re-embedding behavior by clearing outdated “skipped” tombstones after successful embeddings and refining legacy skip-reason handling.
  • Documentation
    • Clarified and updated the TinyCortex vs OpenHuman ownership boundaries for provider pipelines and live sync responsibilities, plus related compatibility/migration guidance.

@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@hobertrand-hub, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 46 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

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.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 9fcd1a3d-8eaf-42e5-a139-87e788c025c6

📥 Commits

Reviewing files that changed from the base of the PR and between 1fd4c1f and b9e4f56.

📒 Files selected for processing (4)
  • src/memory/chunks/embeddings.rs
  • src/memory/chunks/store_embed_tests.rs
  • src/memory/store/content/read.rs
  • src/memory/store/content/read_tests.rs
📝 Walkthrough

Walkthrough

Changes

Memory compatibility and ownership

Layer / File(s) Summary
OpenHuman sync ownership documentation
docs/openhuman-memory-migration.md, docs/openhuman-memory/README.md, docs/openhuman-memory/sources-registry-sync.md, docs/plan/05-openhuman-compat-matrix.md
Documentation assigns reusable provider fetch, pagination, and canonicalization mechanics to TinyCortex while retaining live sync execution and product concerns in OpenHuman.
Legacy content and re-embedding handling
src/memory/store/content/*, src/memory/chunks/embeddings.rs, src/memory/chunks/store_embed_tests.rs
Chunk reads fall back to legacy content, embedding writes clear matching skip tombstones, and legacy skip reasons receive coverage.
Memory source-scope matching
src/memory/retrieval/fast.rs, src/memory/retrieval/source.rs, src/memory/retrieval/*_tests.rs
Retrieval filtering and document classification support mem_src: scopes, including bare and prefixed source identifiers.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

Suggested reviewers: senamakel

Poem

I hop through scopes where memories gleam,
Old chunks return from a legacy stream.
Tombstones fade when embeddings land,
Sync duties split with a clearer hand.
Thump, thump—docs and code agree!

🚥 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 is concise and accurately reflects the main fix to OpenHuman memory source retrieval paths.
Docstring Coverage ✅ Passed Docstring coverage is 91.30% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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.

@hobertrand-hub
hobertrand-hub marked this pull request as ready for review July 27, 2026 02:16
@greptile-apps

greptile-apps Bot commented Jul 27, 2026

Copy link
Copy Markdown

Greptile Summary

This PR patches three narrow but tightly coupled memory-retrieval behaviors needed by OpenHuman source-note queries before the host branch is exported.

  • read_chunk_body now falls back to the legacy inline content column when no staged content pointer exists, and the has_uncovered_reembed_work SQL is updated to treat the two historical "content-pointer missing/empty" skip reasons as retryable so the backfill loop can recover them once the fallback is live.
  • Successful embedding upserts now delete any matching skip tombstone so previously-blocked legacy chunks re-enter the normal embedded state.
  • source_scope_allows (fast retrieval) and scope_matches_kind (source retrieval) now recognize mem_src:<source_id>:<path> tree scopes, letting OpenHuman document-source queries filter and classify per-file trees correctly.

Confidence Score: 5/5

The change is safe to merge; all three code paths are narrow, well-tested, and their cross-module coupling is explicitly documented and covered by new unit tests.

Each fix is isolated: the legacy content fallback adds a new code path that only fires when neither raw refs nor a staged pointer exist; the backfill SQL change only relaxes which skip reasons count as terminal; and the scope helpers are additive filters. All altered paths have direct unit tests verifying the before/after behavior. No data-destructive changes and no schema alterations are present.

Files Needing Attention: No files require special attention. The implicit coupling between the skip-reason text constants in read.rs and the LIKE patterns in the embeddings SQL is the only fragile seam, and it is guarded by the new store_embed_tests.

Important Files Changed

Filename Overview
src/memory/store/content/read.rs Changed read_chunk_body to fall back to a new read_legacy_chunk_preview helper when no content pointer exists, restoring usable text from the inline content column for legacy chunk rows. Added three public constants that anchor the reembed-backfill skip-reason contract.
src/memory/chunks/embeddings.rs upsert_chunk_embedding_conn now deletes matching skip tombstones on successful embedding, and has_uncovered_reembed_work excludes chunks whose only skip reason matches the two legacy-content-pointer retryable prefixes.
src/memory/retrieval/fast.rs Replaced raw HashSet::contains scope checks with source_scope_allows, and added three helper functions to handle mem_src: prefix extraction and case-insensitive matching.
src/memory/retrieval/source.rs Added mem_src: → document kind classification arm in scope_matches_kind with case-insensitive lowercased guard.
src/memory/chunks/store_embed_tests.rs Added four new targeted tests covering skip-marker cleanup on embedding upsert, retryable skip reason transparency for has_uncovered_reembed_work, and terminal empty-content behavior.
src/memory/retrieval/fast_tests.rs Added mem_src scope filter test covering bare-ID, collection-prefix, and exact tree-scope forms, plus negative case.
src/memory/retrieval/source_tests.rs Extended scope_prefix_matching_known_platforms test with mem_src: cases in both lowercase and mixed case.
src/memory/store/content/read_tests.rs Added two tests verifying legacy-content-column fallback reads and the terminal error path for empty inline content.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["read_chunk_body(chunk_id)"] --> B{raw refs present?}
    B -- yes --> C["read_chunk_body_from_raw"]
    B -- no --> D{content pointer exists?}
    D -- yes --> E["resolve path + read file\n(repair checksum if stale)"]
    D -- no --> F["read_legacy_chunk_preview"]
    F --> G{get_chunk returns Some?}
    G -- no --> H["bail: LEGACY_NO_CONTENT_POINTER_REASON_PREFIX\n(retryable skip reason)"]
    G -- yes --> I{chunk.content empty?}
    I -- yes --> J["bail: LEGACY_EMPTY_CHUNK_CONTENT_REASON_PREFIX\n(terminal skip reason)"]
    I -- no --> K["return chunk.content (legacy inline column)"]

    subgraph reembed_backfill
        L["has_uncovered_reembed_work"] -->|"chunk has no embedding AND no terminal skip row"| M["chunk in worklist"]
        N["upsert_chunk_embedding_conn"] -->|success| O["DELETE matching skip tombstone"]
    end

    K --> N
    E --> N
    H -->|"wraps to body read failed: no content pointer"| P["mark_chunk_reembed_skipped (retryable)"]
    J -->|"wraps to body read failed: legacy chunk content empty"| Q["mark_chunk_reembed_skipped (terminal)"]
Loading

Reviews (3): Last reviewed commit: "Document legacy reembed skip reasons" | Re-trigger Greptile

Comment thread src/memory/retrieval/fast.rs
Comment thread src/memory/retrieval/fast.rs
Comment thread src/memory/retrieval/source.rs

@coderabbitai coderabbitai 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.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/memory/store/content/read.rs (1)

1-1: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Fragile string contract between legacy bail! messages and SQL LIKE classification.

read_legacy_chunk_preview in read.rs authors the exact error text that has_uncovered_reembed_work in embeddings.rs pattern-matches via LIKE to decide whether a skip record is retryable (legacy) or terminal. This coupling is undocumented and only enforced by tests — an innocuous wording tweak in one file silently changes re-embed retry semantics in the other, including a pattern in embeddings.rs that intentionally targets only pre-existing (pre-fix) skip rows no longer produced by current code.

  • src/memory/store/content/read.rs#L159-168: add a doc comment on read_legacy_chunk_preview noting that its bail! message text is matched verbatim by LIKE patterns in embeddings.rs::has_uncovered_reembed_work, or extract the strings into shared constants used by both sites.
  • src/memory/chunks/embeddings.rs#L393-395: add a comment on the two NOT LIKE clauses explaining that the second pattern targets legacy (pre-fix) skip rows only and is no longer generated by current read.rs code, to avoid future removal as "dead."
🤖 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/memory/store/content/read.rs` at line 1, Document the error-message
contract in read_legacy_chunk_preview, noting that its bail! text is matched by
LIKE patterns in embeddings.rs::has_uncovered_reembed_work. Also comment the two
NOT LIKE clauses there, clarifying that the second preserves handling for legacy
pre-fix skip rows no longer produced by current read.rs code; prefer shared
constants only if already appropriate.
🧹 Nitpick comments (1)
src/memory/store/content/read.rs (1)

140-145: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Likely unreachable rel_path.is_empty() branch.

get_chunk_content_pointers already filters out empty paths before returning Some: "Ok(row.and_then(|(p, s)| p.zip(s).filter(|(path, _)| !path.is_empty())))". Given that contract, once Some((rel_path, expected_sha256)) is destructured, rel_path cannot be empty, so this check appears to be dead code.

If this is intentional defense against a future contract change, a short comment noting that would help; otherwise consider removing it to avoid confusing readers about when the legacy-preview path triggers.

🤖 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/memory/store/content/read.rs` around lines 140 - 145, Remove the
redundant rel_path.is_empty() check in the read content flow after
get_chunk_content_pointers returns Some, since that function already filters
empty paths. Keep the existing read_legacy_chunk_preview fallback for the None
case and preserve normal processing for valid pointers.
🤖 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/memory/chunks/embeddings.rs`:
- Around line 393-395: Add a concise comment beside the legacy “empty content
pointer and no raw refs” LIKE filter explaining that it preserves retries for
pre-existing skip rows from older read.rs behavior, even though current code no
longer emits that message. Leave both retry filters and their matching patterns
unchanged.

In `@src/memory/store/content/read.rs`:
- Around line 159-168: The legacy chunk bail messages in
read_legacy_chunk_preview are coupled to hardcoded SQL LIKE prefixes in
has_uncovered_reembed_work. Extract shared reason-prefix constants and use them
both when constructing these errors and in the embedding query, preserving the
existing message text and matching behavior.

---

Outside diff comments:
In `@src/memory/store/content/read.rs`:
- Line 1: Document the error-message contract in read_legacy_chunk_preview,
noting that its bail! text is matched by LIKE patterns in
embeddings.rs::has_uncovered_reembed_work. Also comment the two NOT LIKE clauses
there, clarifying that the second preserves handling for legacy pre-fix skip
rows no longer produced by current read.rs code; prefer shared constants only if
already appropriate.

---

Nitpick comments:
In `@src/memory/store/content/read.rs`:
- Around line 140-145: Remove the redundant rel_path.is_empty() check in the
read content flow after get_chunk_content_pointers returns Some, since that
function already filters empty paths. Keep the existing
read_legacy_chunk_preview fallback for the None case and preserve normal
processing for valid pointers.
🪄 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 Plus

Run ID: 6280690f-7089-4d73-a594-a00a77433bf2

📥 Commits

Reviewing files that changed from the base of the PR and between 108b8e0 and b47bf89.

📒 Files selected for processing (11)
  • docs/openhuman-memory-migration.md
  • docs/openhuman-memory/README.md
  • docs/openhuman-memory/sources-registry-sync.md
  • docs/plan/05-openhuman-compat-matrix.md
  • src/memory/chunks/embeddings.rs
  • src/memory/chunks/store_embed_tests.rs
  • src/memory/retrieval/fast.rs
  • src/memory/retrieval/source.rs
  • src/memory/retrieval/source_tests.rs
  • src/memory/store/content/read.rs
  • src/memory/store/content/read_tests.rs

Comment thread src/memory/chunks/embeddings.rs Outdated
Comment thread src/memory/store/content/read.rs
@hobertrand-hub

Copy link
Copy Markdown
Author

Addressed the Greptile P2 notes in follow-up commit 1fd4c1f:

  • mem_src: extraction in fast retrieval is now ASCII case-insensitive.
  • source_scope matching now accepts exact tree scopes, bare source IDs, and mem_src:<source_id> collection-prefix selectors.
  • Added focused coverage for those accepted selector shapes.
  • Documented why mem_src:<source_id>:<path> scopes classify as document source trees.

Validation after the follow-up:

  • cargo +1.96.1 test source --lib -- --nocapture
  • cargo +1.96.1 test fast --lib -- --nocapture
  • cargo +1.96.1 test --lib (1239 passed; 0 failed)

@hobertrand-hub

Copy link
Copy Markdown
Author

Addressed the CodeRabbit maintainability comments in follow-up commit b9e4f56:

  • Extracted the legacy chunk-read failure prefixes into shared constants.
  • has_uncovered_reembed_work now builds its retryable LIKE patterns from those constants instead of duplicating message text.
  • Documented why the old empty-content-pointer skip prefix remains retryable even though current readers no longer emit it.
  • Removed the redundant rel_path.is_empty() branch after get_chunk_content_pointers, since that API already filters empty paths.

Validation after this follow-up:

  • cargo +1.96.1 test content::read --lib -- --nocapture
  • cargo +1.96.1 test store_embed --lib -- --nocapture
  • cargo +1.96.1 test fast --lib -- --nocapture
  • cargo +1.96.1 test --lib (1239 passed; 0 failed)

@hobertrand-hub

Copy link
Copy Markdown
Author

@senamakel PR #125 is ready from my side for maintainer squash-merge.

Current visible status:

  • Greptile Review: success on latest commit.
  • CodeRabbit: approved/latest status success.
  • Local validation after the latest follow-up commit: cargo +1.96.1 test --lib (1239 passed; 0 failed).

Please squash-merge into main when you are satisfied with the repo merge-state / required-review status. I am keeping the OpenHuman host branch parked until this lands upstream.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant