Skip to content

fix(memory): refresh system version facts on upgrade#1390

Open
kovtcharov-amd wants to merge 1 commit into
mainfrom
worktree-fix-stale-memory-versions
Open

fix(memory): refresh system version facts on upgrade#1390
kovtcharov-amd wants to merge 1 commit into
mainfrom
worktree-fix-stale-memory-versions

Conversation

@kovtcharov-amd
Copy link
Copy Markdown
Collaborator

Why this matters

After upgrading GAIA (or Lemonade), the memory system kept reporting the old versions — the Knowledge Browser showed GAIA version: 0.17.6 and Lemonade Server version: 10.2.0 long after the install was upgraded, so any agent that reads system facts into its prompt reasoned about a stale environment. The cause: system-context refresh was a pure 7-day age check with no trigger tied to an actual version change, and a version bump produced a duplicate fact rather than replacing the old one (version strings overlap ~0.75, below the 0.8 dedup threshold).

After this change, system facts refresh as soon as the stored GAIA/Lemonade version differs from the live value — so versions correct themselves on the next agent startup instead of lagging up to a week — and a refresh replaces the old fact instead of leaving two contradictory rows.

Fixes #1384.

Test plan

  • pytest tests/unit/test_memory_mixin.py — 177 pass (10 new: version-mismatch detection, age trigger, no-duplicate after simulated bump, force-refresh no-duplicate, meta-fact rename)
  • python util/lint.py --black --isort — pass
  • Manual: enable system context (gaia memory bootstrap --system), bump __version__/LEMONADE_VERSION, restart an agent → memory shows the new version with exactly one GAIA-version and one Lemonade-version row

Memory kept reporting the pre-upgrade GAIA/Lemonade versions: refresh was
purely a 7-day age check with no trigger when a version actually changed, so
facts could stay stale for up to a week — and a bump produced a duplicate row
because version strings overlap below the dedup threshold.

System context now refreshes as soon as a stored GAIA/Lemonade version differs
from the live value, clears the old `system` entries before re-collecting so
values are replaced rather than duplicated, and uses delete_by_category across
the startup, CLI, and UI refresh paths (previously the startup path used
delete_by_source while the others used delete_by_category). The meta fact is
renamed to "last collected on" to match its actual regenerate-every-run
behaviour, and the `--system` / `--reset-system` flags and the opt-in
`system_context_enabled` setting are now documented.
@github-actions github-actions Bot added documentation Documentation changes tests Test changes agents labels Jun 3, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 3, 2026

Review: fix(memory): refresh system version facts on upgrade

Approve with suggestions. This is a clean, well-scoped, well-tested fix for a real bug — stale version facts lingering after an upgrade because refresh was a pure 7-day age check and a version bump produced a duplicate (version strings fall below the 0.8 dedup threshold). The new version-aware trigger plus delete-before-recollect is the right shape, and the test coverage is genuinely good. One thing worth a second look: the broad except Exception around the clear step can silently reintroduce the exact duplicate this PR fixes.

I verified the supporting facts: gaia.version exposes __version__ (0.20.0) and LEMONADE_VERSION (10.2.0); every category="system" write in the codebase also uses source="system", so the delete_by_source → delete_by_category switch deletes the same row set while matching the bootstrap/CLI paths; and get_by_category orders confidence DESC, updated_at DESC, so existing[0] is reliably the newest fact (all system facts are confidence 1.0). I could not run pytest in this sandbox (no numpy, read-only FS) — relying on CI for execution; logic checks out on read.

Issues

🟢 Swallowed clear failure can re-introduce duplicates (src/gaia/agents/base/memory.py:513)

The clear-before-recollect is best-effort:

if existing:
    try:
        self._memory_store.delete_by_category("system")
    except Exception as e:
        logger.debug("[MemoryMixin] failed to clear system context: %s", e)
# ...falls through and re-stores every fact

If the delete raises and is swallowed at debug level, the code still proceeds to re-store all facts — recreating the duplicate version rows this PR exists to prevent, with only a debug-level trace to explain it. In practice delete_by_category only raises on a SQLite error that would likely break store() too, so the real-world risk is low. Still, per CLAUDE.md's "No Silent Fallbacks — Fail Loudly," this is the kind of silent degradation worth tightening: at minimum log at warning, and consider letting it raise (or returning early) so a failed clear doesn't silently undo the fix.

🟢 Broad except hides import errors (src/gaia/agents/base/memory.py:55)

    except Exception:
        pass

_live_software_versions() swallows any failure from from gaia.version import ... and returns {}, which is a reasonable fallback to the age-based path — but gaia.version is a core module whose import realistically only fails as ImportError. Narrowing to except ImportError (or adding a logger.debug) keeps a genuine breakage from being invisible, consistent with the fail-loudly guidance. Minor.

Strengths

  • Root cause, not symptom. The PR correctly identifies why refresh lagged (age-only trigger) and why bumps duplicated (sub-threshold dedup on version strings) and fixes both. The _changed_software_versions "compare only labels present in BOTH stored and live" guard is a nice touch — it avoids churning on a transient collection gap.
  • Test coverage maps to the bug. Mismatch detection, equal-version no-op, missing-label no-churn, age trigger, no-duplicate-after-bump, and force-refresh-no-duplicate together pin the exact regression. Good use of _live_software_versions patching to simulate an upgrade without touching gaia.version.
  • Consistency cleanup. Aligning the startup path, UI router, and bootstrap CLI all on delete_by_category("system") removes a real divergence, and the docstring/comment updates (source=category=, "first captured" → "last collected") keep the prose honest. Docs in memory.mdx were updated alongside the code.

Verdict

Approve with suggestions — no blocking issues. Both notes are minor hardening around exception handling; neither needs to gate merge. Nice, surgical fix.

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

Labels

agents documentation Documentation changes tests Test changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Memory system reports stale GAIA/Lemonade versions after upgrade

1 participant