Issue #1553: perf: avoid loading all facts for active-task projection/injection

Status: WIP scaffold PR only — implementation pending.

Source Issue

  • Issue: #1553
  • URL: https://github.com/markus-lassfolk/openclaw-hybrid-memory/issues/1553
  • State: OPEN (snapshot: 2026-05-21)
  • Priority label: priority:high
  • Labels: enhancement, priority:high, issue/stage/enriching

Acceptance Criteria / Issue Body

Summary

Active-task projection/injection appears to load all active facts and then filter to project/task facts in memory. With a large facts database, this causes unnecessary SQLite work, JS allocation churn, and memory pressure during every prompt build.

Evidence / suspected code path

The active-task path appears to do a broad fetch before filtering:

const facts = factsDb
  .getAll({ scopeFilter })
  .filter((fact) => fact.category === TASK_LEDGER_CATEGORY)
  .slice(0, factLimit);

On Maeve, the gateway logs reported:

memory-hybrid: injecting 100 active task(s) from category:project facts (87 stale)

The facts.db file is ~421 MB and active fact volume is high. Reading all facts on prompt build is therefore expensive even if only a small subset is needed.

Impact

  • Prompt build performs unnecessary DB reads and allocations.
  • Stale/duplicate active-task rows amplify the cost.
  • In high-concurrency periods, this can add memory churn and latency.
  • It likely interacts badly with the separate duplicate SQLite-handle/native-RSS issue.

Acceptance criteria

  • Active-task selection should query only category='project' / task-ledger rows at the SQL level.
  • Query should select only relevant columns/keys for task reconstruction.
  • Query should apply candidate limits and terminal-status/staleness filters as early as possible.
  • Prompt injection should not require hydrating the entire facts table.
  • Add timing/row-count logs around active-task selection:
    • SQL rows scanned/fetched
    • active candidates
    • stale skipped
    • duplicates collapsed
    • injected count
    • elapsed ms

Suggested fix direction

  • Add FactsDB.getProjectFacts() or getFactsByCategory(category, options) with indexes.
  • Ensure category/key/entity indexes exist and are used.
  • Build active-task rows from latest facts per entity/key rather than all fact history.
  • Consider a materialized active-task table/view updated by active_task_checkpoint.

Stewardship Notes

This placeholder document exists to create a draft PR branch for Issue Stewardship tracking. The implementation work remains pending and should replace or extend this scaffold with the actual fix and verification evidence.


Back to top

OpenClaw Hybrid Memory — durable agent memory

This site uses Just the Docs, a documentation theme for Jekyll.