fix(recall): allow exact filtering of untagged/global observations (#2295)#2364
Merged
Conversation
…2295) An empty tag set with tags_match="exact" now selects only untagged (global-scope) observations — the scope that observation_scopes="shared" consolidation writes to. Previously empty/absent tags meant "no filter" in every mode, so there was no way to recall only global observations when mixing shared and tagged scopes. - tags.py: in exact mode, empty/absent tags emit an untagged-only clause (tags IS NULL OR tags = '{}') with no bind param, across the flat SQL builders, Python post-filter, and compound tag-group leaves. All other modes keep treating empty/absent tags as "no filtering". - link_expansion_retrieval.py: always run filter_results_by_tags so the exact-empty/global scope is applied (it's a no-op otherwise). - http.py + regenerated clients/docs: document the exact-empty scope. - Tests: SQL builders (flat + compound, param-offset preserved), Python post-filter, and a recall API test asserting only untagged memories return for tags=[] + tags_match="exact".
Contributor
|
Thanks for mentioning #2322 and keeping the regression test. If appropriate, would it be possible to add me as a co-author for the root-cause investigation and the parameter-offset regression test contribution? |
Regenerated skills/hindsight-docs/references via generate-docs-skill.sh so the docs-skill mirror matches the updated recall/observations docs (and the canonical configuration table). Unblocks verify-generated-files.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #2295. Supersedes #2322.
Allow recall to select only untagged/global observations by passing an empty tag
set (
[]or omitted) together withtags_match="exact". This lets users switchbetween shared and tagged observation scopes without a synthetic "global" tag or
a hand-maintained negative filter.
Root cause
The centralized tag filters treated
None/[]as "no filter" in every mode,returning every scope. There was no way to recall only the global/untagged scope —
the one that
observation_scopes="shared"consolidation writes to.Fix
In
exactmode, an empty/absent tag set now means the global/untagged scope andemits an untagged-only clause (
tags IS NULL OR tags = '{}', matching bothhistorical NULLs and current empty-array storage). Applied consistently across:
build_tags_where_clause,build_tags_where_clause_simple)filter_results_by_tags)_build_group_clause,_match_group)No bind parameter is consumed for the empty-scope clause, so following parameter
indexes stay aligned. All other modes (
any,all,any_strict,all_strict)still treat empty/absent tags as "no filtering" — unchanged.
http.pyfield descriptions and the regenerated clients/OpenAPI/docs document thenew exact-empty scope.
Relationship to #2322
This implements the same fix as #2322 but additionally updates the
RecallRequestAPI descriptions and regenerates the client SDKs (Go/Python/TypeScript), OpenAPI
spec, and docs — so the user-facing surface is complete. It also adds the
parameter-offset regression test from #2322. Opening this to supersede #2322.
Tests
Noneand[], param-offset preservedtags=[]+tags_match="exact"returns the untagged memory andexcludes the tagged one
Verification
tests/test_tags_visibility.pytag-filtering tests pass (34 passed for theexact/untagged/empty/global subset incl. the recall API test)
ty checkpassed;ruff check+ruff formatclean; generated files in sync