feat(display): document and test memory_notifications setting

Follow-up to salvaged PR #4684:
- Add display.memory_notifications to DEFAULT_CONFIG (off|on|verbose, default on)
- Document the setting in docs/user-guide/features/memory.md
- Add resolver tests for off/on/verbose memory + skill paths
This commit is contained in:
teknium 2026-06-16 05:33:56 -07:00 committed by Teknium
parent 4cf9d80fba
commit 98ae28657f
3 changed files with 141 additions and 0 deletions

View file

@ -1428,6 +1428,12 @@ DEFAULT_CONFIG = {
"tui_agents_nudge": True,
"bell_on_complete": False,
"show_reasoning": False,
# Background self-improvement review notifications surfaced in chat.
# "off" — no chat notification (the review still runs and writes)
# "on" — generic "💾 Memory updated" line (default)
# "verbose" — include a compact content preview of what changed
# Per-platform overrides via display.platforms.<platform>.memory_notifications.
"memory_notifications": "on",
"streaming": False,
"timestamps": False, # Show [HH:MM] on user and assistant labels
"final_response_markdown": "strip", # render | strip | raw

View file

@ -315,3 +315,117 @@ def test_background_review_fork_skips_external_memory_plugins(monkeypatch):
"the fork leaks harness prompts into the user's real memory "
"namespace via on_turn_start / prefetch_all / sync_all."
)
# ---------------------------------------------------------------------------
# memory_notifications mode: off | on | verbose
# ---------------------------------------------------------------------------
import json as _json
from agent.background_review import summarize_background_review_actions
def _memory_add_review():
"""A minimal review transcript: one memory add (assistant call + tool result)."""
return [
{
"role": "assistant",
"tool_calls": [
{
"id": "call_mem1",
"function": {
"name": "memory",
"arguments": _json.dumps(
{
"action": "add",
"target": "memory",
"content": "User prefers terse replies",
}
),
},
}
],
},
{
"role": "tool",
"tool_call_id": "call_mem1",
"content": _json.dumps(
{"success": True, "message": "Entry added.", "target": "memory"}
),
},
]
def _skill_patch_review():
return [
{
"role": "assistant",
"tool_calls": [
{
"id": "call_skill1",
"function": {
"name": "skill_manage",
"arguments": _json.dumps(
{"action": "patch", "name": "demo", "old_string": "a", "new_string": "b"}
),
},
}
],
},
{
"role": "tool",
"tool_call_id": "call_skill1",
"content": _json.dumps(
{
"success": True,
"message": "Patched SKILL.md in skill 'demo' (1 replacement).",
"_change": {"old": "a", "new": "b"},
}
),
},
]
def test_memory_notifications_off_returns_nothing():
actions = summarize_background_review_actions(
_memory_add_review(), [], notification_mode="off"
)
assert actions == []
def test_memory_notifications_on_returns_generic_line():
actions = summarize_background_review_actions(
_memory_add_review(), [], notification_mode="on"
)
assert actions == ["Memory updated"]
def test_memory_notifications_verbose_includes_content_preview():
actions = summarize_background_review_actions(
_memory_add_review(), [], notification_mode="verbose"
)
assert len(actions) == 1
# Verbose surfaces the actual content that was saved.
assert "User prefers terse replies" in actions[0]
assert actions[0] != "Memory updated"
def test_memory_notifications_default_is_on():
"""No mode passed → behaves like 'on' (generic line, not empty/verbose)."""
actions = summarize_background_review_actions(_memory_add_review(), [])
assert actions == ["Memory updated"]
def test_skill_patch_off_silent_verbose_shows_diff():
assert (
summarize_background_review_actions(
_skill_patch_review(), [], notification_mode="off"
)
== []
)
verbose = summarize_background_review_actions(
_skill_patch_review(), [], notification_mode="verbose"
)
assert len(verbose) == 1
assert "demo" in verbose[0] and "" in verbose[0]

View file

@ -245,6 +245,27 @@ This is the answer to "the agent saved a wrong assumption about me": set
`write_approval: true`, and every save — especially the unprompted background
ones — waits for your yes/no before it ever enters your profile.
## Background review notifications (`display.memory_notifications`)
After a turn, the background self-improvement review may quietly save a memory
or update a skill. By default it surfaces a short `💾 Memory updated` line in
chat so you know it happened. Control how chatty that is:
```yaml
display:
memory_notifications: on # off | on (default) | verbose
```
| Value | Behaviour |
|-------|-----------|
| `off` | No chat notification. The review still runs and still writes — you just don't see a line for it. |
| `on` (default) | Generic line, e.g. `💾 Memory updated`, `💾 Skill 'foo' patched`. |
| `verbose` | Includes a compact preview of what changed, e.g. `💾 Memory User prefers terse replies` or a `"old" → "new"` skill diff snippet. |
> This only governs the **gateway** chat notification. The review itself, and
> writes to your memory/skill stores, are unaffected by this setting. Set it
> per-platform via `display.platforms.<platform>.memory_notifications`.
## Controlling skill writes (`skills.write_approval`)
Skills use the same on/off gate, but the review UX differs because a