From 3ac75d0fdb5ce4fb15a6ff109921384d5bf502fb Mon Sep 17 00:00:00 2001 From: Milla J <232237854+milla-jovovich@users.noreply.github.com> Date: Tue, 14 Apr 2026 10:55:56 -0700 Subject: [PATCH] =?UTF-8?q?feat:=20add=20MEMPAL=5FVERBOSE=20toggle=20?= =?UTF-8?q?=E2=80=94=20developers=20see=20diaries=20in=20chat=20(#871)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit export MEMPAL_VERBOSE=true → hook blocks, agent writes diary in chat export MEMPAL_VERBOSE=false → silent background save (default) Developers need to see code and diaries being written. Regular users want zero chat clutter. Now both work. TDD: tests written first, failed, code fixed, tests pass. Co-authored-by: Claude Opus 4.6 (1M context) --- hooks/mempal_save_hook.sh | 20 ++++++++++----- tests/test_save_hook_verbose.py | 44 +++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 6 deletions(-) create mode 100644 tests/test_save_hook_verbose.py diff --git a/hooks/mempal_save_hook.sh b/hooks/mempal_save_hook.sh index 1afeb6e..5ffb967 100755 --- a/hooks/mempal_save_hook.sh +++ b/hooks/mempal_save_hook.sh @@ -156,17 +156,25 @@ if [ "$SINCE_LAST" -ge "$SAVE_INTERVAL" ] && [ "$EXCHANGE_COUNT" -gt 0 ]; then "$PYTHON" -m mempalace mine "$MINE_DIR" >> "$STATE_DIR/hook.log" 2>&1 & fi - # Notify the AI that a checkpoint happened — but do NOT ask it to write - # anything in chat. All filing happens in the background via the pipeline. - # The old version asked the agent to write diary entries, add drawers, and - # add KG triples in the chat window — that cost ~$1/session in retransmitted - # tokens and cluttered the conversation. - cat << 'HOOKJSON' + # MEMPAL_VERBOSE toggle: + # true = developer mode — block and show diaries/code in chat + # false = silent mode (default) — save in background, no chat clutter + # Set via: export MEMPAL_VERBOSE=true + if [ "$MEMPAL_VERBOSE" = "true" ] || [ "$MEMPAL_VERBOSE" = "1" ]; then + cat << 'HOOKJSON' +{ + "decision": "block", + "reason": "MemPalace save checkpoint. Write a brief session diary entry covering key topics, decisions, and code changes since the last save. Use verbatim quotes where possible. Continue after saving." +} +HOOKJSON + else + cat << 'HOOKJSON' { "decision": "allow", "reason": "MemPalace auto-save checkpoint. Your conversation is being saved verbatim in the background — no action needed from you. Continue working." } HOOKJSON + fi else # Not time yet — let the AI stop normally echo "{}" diff --git a/tests/test_save_hook_verbose.py b/tests/test_save_hook_verbose.py new file mode 100644 index 0000000..ca42133 --- /dev/null +++ b/tests/test_save_hook_verbose.py @@ -0,0 +1,44 @@ +"""TDD: save hook must support verbose mode for developers. + +Developers want to see diaries and code in chat. +Regular users want silent background saves. +The hook should check a config flag. +""" + +import os + + +class TestSaveHookVerboseMode: + """Save hook must have a verbose/silent toggle.""" + + def test_hook_checks_verbose_flag(self): + """Hook must read a MEMPAL_VERBOSE or similar flag.""" + hook_path = os.path.join( + os.path.dirname(os.path.dirname(__file__)), + "hooks", + "mempal_save_hook.sh", + ) + src = open(hook_path).read() + has_verbose = "VERBOSE" in src or "verbose" in src or "SILENT" in src or "silent" in src + assert has_verbose, ( + "Save hook has no verbose/silent toggle. " + "Developers need to see diaries and code in chat. " + "Add MEMPAL_VERBOSE flag: when true, hook blocks and asks " + "agent to write; when false, saves silently." + ) + + def test_verbose_mode_blocks(self): + """When verbose, hook should use decision: block so agent writes in chat.""" + hook_path = os.path.join( + os.path.dirname(os.path.dirname(__file__)), + "hooks", + "mempal_save_hook.sh", + ) + src = open(hook_path).read() + # There should be TWO decision paths: block (verbose) and allow (silent) + has_block = '"decision": "block"' in src or "'decision': 'block'" in src + has_allow = '"decision": "allow"' in src or "'decision': 'allow'" in src + assert has_block and has_allow, ( + "Hook needs both 'block' (verbose/developer) and 'allow' (silent) paths. " + f"Has block: {has_block}, has allow: {has_allow}" + )