Files
openhuman/src/openhuman/tools/impl/memory/tree
227f534e2c fix(memory): translate time_window_days for memory_tree query_global
## Summary

Fix the schema/backend impedance mismatch reported in #2252. The consolidated `memory_tree` tool advertises `time_window_days` as the look-back field for both `query_source` and `query_global`, but the underlying `QueryGlobalRequest` deserializes from `window_days`. Any LLM call that followed the consolidated contract with `mode = "query_global"` failed with `missing field 'window_days'`.

## Problem

```jsonc
// LLM sends, per the consolidated schema in
// src/openhuman/tools/impl/memory/tree/mod.rs:
{ "mode": "query_global", "time_window_days": 7 }

// Dispatch hands `args` straight through:
//   "query_global" => MemoryTreeQueryGlobalTool.execute(args).await,

// `MemoryTreeQueryGlobalTool` (src/openhuman/tools/impl/memory/tree/query_global.rs)
// deserializes into:
//   pub struct QueryGlobalRequest { pub window_days: u32 }
//
// -> serde error: missing field `window_days`
```

`query_source` natively uses `time_window_days` (its `QuerySourceRequest` matches the consolidated schema verbatim), so the bug is isolated to the `query_global` arm.

## Solution

Translate `time_window_days` → `window_days` in the consolidated dispatch arm for `query_global`, mirroring the existing thin-adapter pattern used in `src/openhuman/mcp_server/tools.rs` (where `tree.read_chunk` maps MCP `chunk_id` → controller `id`).

- Schema stays as advertised — LLMs already calling the consolidated tool aren't asked to relearn a field name.
- Standalone `MemoryTreeQueryGlobalTool` (which advertises `window_days` natively) is unchanged.
- Explicit `window_days` always wins, so callers using the underlying contract directly aren't surprised when both fields are present.

## Submission Checklist

- [x] Tests added or updated (happy path + at least one failure / edge case) per [Testing Strategy](../gitbooks/developing/testing-strategy.md#failure-path-requirement) — four new tests cover: the rename (happy path), passthrough when `window_days` is already set, explicit `window_days` winning over a stale `time_window_days`, and the no-field case being untouched.
- [x] **Diff coverage ≥ 80%** — `cargo test --lib memory_tree_dispatcher_tests::` runs 9/9 locally; the new translator helper has a dedicated test per branch.
- [x] Coverage matrix updated — `N/A: behaviour-only fix on an existing consolidated tool path.`
- [x] All affected feature IDs from the matrix are listed in the PR description under `## Related`
- [x] No new external network dependencies introduced
- [x] Manual smoke checklist — `N/A: backend-only fix, not on a release-cut surface.`
- [x] Linked issue closed via `Closes #NNN` — `Closes #2252` (commit message + this PR description).

## Impact

- **Runtime**: agent-facing `memory_tree` consolidated tool only. The standalone `memory_tree_query_global` tool path is unchanged.
- **Compatibility**: backward compatible. Callers that were passing `window_days` (the only callers that worked before this fix) continue to work. Callers that were passing `time_window_days` (which previously errored) now succeed.
- **Performance**: negligible — one `Map::contains_key` + at most one `remove` + one `insert` per `query_global` call.
- **Security**: no policy change.

## Related

- Closes #2252
- Touches: `src/openhuman/tools/impl/memory/tree/mod.rs`
- Backend reference: `src/openhuman/memory/tree/retrieval/rpc.rs` (`QueryGlobalRequest`, `QuerySourceRequest`)
- Pattern reference: `src/openhuman/mcp_server/tools.rs` — same thin-adapter translation idiom used for `tree.read_chunk`'s `chunk_id → id` mapping.


<!-- This is an auto-generated comment: release notes by coderabbit.ai -->

## Summary by CodeRabbit

* **Bug Fixes**
  * Fixed global memory query handling to properly process field parameters, improving compatibility and reliability of memory tree queries.

* **Tests**
  * Extended test coverage for memory query parameter handling, including edge cases and field precedence validation.

<!-- review_stack_entry_start -->

[![Review Change Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/tinyhumansai/openhuman/pull/2273?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: justin <justin80605@gmail.com>
Co-authored-by: Steven Enamakel <enamakel@tinyhumans.ai>
2026-05-20 16:49:42 -07:00
..