fix(memory.get): surface sort_by downgrades for agent_skill#272
Open
Fearvox wants to merge 1 commit into
Open
Conversation
Two related silent-data-loss defects in the /api/v1/memory/get path:
1. The agent_skill branch of GetManager (manager.py:115-148) hard-codes
sort_by='updated_at' and discards the caller's sort_by='timestamp'
(the default). The override is invisible: no log line, no DTO field,
no metric. A caller iterating skills by recency gets them ordered by
last-modification time and has no way to tell.
- Add effective_sort: str | None to GetData (dto.py) so all four
listing paths (episode / profile / agent_case / agent_skill)
surface the column actually applied.
- In the agent_skill arm, set effective_sort='updated_at' and emit
a structlog warning ('get.sort_by.downgraded') only when the
override actually fires, with kwargs
memory_type / requested_sort_by / effective_sort_by / owner_id /
request_id. Callers diff response.data.effective_sort against
request.sort_by to detect the override.
- Update the GetRequest.sort_by docstring to describe the new
contract (no more 'silently falls back').
2. GetRequest DTO accepts page / page_size / sort_by / sort_order /
filters for memory_type='profile', but the manager profile arm
(manager.py:96-102) is a single-row KV fetch and never threads
those fields into the lookup. Five request fields are silently
dropped at once: a paginated/filtered request always returns
0-or-1 row with no signal.
- Add _validate_profile_has_no_paging (dto.py) that raises
ValueError (→ 422 at the route) when memory_type='profile' and
any of page != 1, page_size != 20, or filters is set. sort_by is
allowed because effective_sort already makes the override
observable.
3. Documentation co-evolution:
- docs/api.md sort_by description (around line 890) flips from
'silently falls back to updated_at' to the new contract
(downgrade + effective_sort echo + structlog warning).
- docs/api.md response-body table (around line 918) gains an
effective_sort row.
- docs/openapi.json regenerated via scripts/dump_openapi.py
(--check passes) so the OpenAPI schema carries the new field.
b007012 to
310720d
Compare
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
Two related silent-data-loss defects in the
/api/v1/memory/getpath are fixed by making the override observable in three ways (DTO echo, structlog warning, request diff) and by rejecting impossible request shapes up front.src/everos/memory/get/manager.py— theagent_skillarm hard-codessort_by='updated_at'and discards the caller'ssort_by='timestamp'(the default). No log, no DTO field, no metric. A caller iterating skills by recency gets them ordered by last-modification time and has no way to tell. Fix: addeffective_sort: str | NonetoGetData, surface it from all four listing paths, and emit aget.sort_by.downgradedstructlog warning only when the override actually fires.src/everos/memory/get/dto.py—GetRequestacceptspage,page_size, andfiltersformemory_type='profile', but the manager profile branch is a single-row KV-by-owner lookup and never threads those fields into the profile path. Five request fields are silently dropped at once. Fix: add_validate_profile_has_no_pagingthat raisesValueError(→ 422 at the route) whenmemory_type='profile'and any ofpage != 1,page_size != 20, orfilters is not None.docs/api.md— thesort_bydescription still says 'the server silently falls back toupdated_at'; flips to the new contract (downgrade +effective_sortecho + structlog warning) and the response-body table gains aneffective_sortrow.docs/openapi.json— regenerated viascripts/dump_openapi.pyso the OpenAPI schema carries the neweffective_sortfield (--checkpasses).Fixes #270, #271.
Area
Verification
Checklist
main..envfiles, dependency folders, or generated output.Notes for Reviewers
fix(memory)PR was staged in the round-1 hunt as a held survivor because it was a source-code change requiring pytest verification, separate from round-1's docs-only PR (fix(docs): repair dead xrefs in api.md, runbook, skill #269). After round-1's docs PR was merged, the source-code fix lands here on top.GetData.effective_sortis a new optional field; existing clients ignore it. (b)memory_type='profile'with non-defaultpage,page_size, orfiltersnow returns 422 instead of silently degrading. Default-argument clients are unaffected.By submitting this pull request, I agree that my contribution is licensed under the Apache License 2.0.