Skip to content

Commit 095beaa

Browse files
committed
fix: use empty JSON instead of invalid \"allow\" decision value
Claude Code only recognizes \"block\" as a top-level decision value. \"allow\" is a permissionDecision value for PreToolUse hooks, not a valid top-level decision. The correct way to not block is to return empty JSON. Caught by #872.
1 parent 332f7d3 commit 095beaa

2 files changed

Lines changed: 7 additions & 16 deletions

File tree

mempalace/hooks_cli.py

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,6 @@
3636
"Save everything to MemPalace, then allow compaction to proceed."
3737
)
3838

39-
PRECOMPACT_ALLOW_REASON = (
40-
"MemPalace pre-compaction save. Your conversation has been saved "
41-
"in the background. Compaction can proceed safely."
42-
)
43-
4439

4540
def _sanitize_session_id(session_id: str) -> str:
4641
"""Only allow alnum, dash, underscore to prevent path traversal."""
@@ -262,7 +257,7 @@ def hook_precompact(data: dict, harness: str):
262257
# Mine synchronously so data lands before compaction proceeds
263258
_mine_sync(transcript_path)
264259

265-
_output({"decision": "allow", "reason": PRECOMPACT_ALLOW_REASON})
260+
_output({})
266261

267262

268263
def run_hook(hook_name: str, harness: str):

tests/test_hooks_cli.py

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
from mempalace.hooks_cli import (
1111
SAVE_INTERVAL,
1212
STOP_BLOCK_REASON,
13-
PRECOMPACT_ALLOW_REASON,
1413
_count_human_messages,
1514
_get_mine_dir,
1615
_log,
@@ -213,8 +212,7 @@ def test_precompact_allows(tmp_path):
213212
{"session_id": "test"},
214213
state_dir=tmp_path,
215214
)
216-
assert result["decision"] == "allow"
217-
assert result["reason"] == PRECOMPACT_ALLOW_REASON
215+
assert result == {}
218216

219217

220218
# --- _log ---
@@ -383,7 +381,7 @@ def test_precompact_with_mempal_dir(tmp_path):
383381
{"session_id": "test"},
384382
state_dir=tmp_path,
385383
)
386-
assert result["decision"] == "allow"
384+
assert result == {}
387385
mock_run.assert_called_once()
388386

389387

@@ -398,7 +396,7 @@ def test_precompact_with_mempal_dir_oserror(tmp_path):
398396
{"session_id": "test"},
399397
state_dir=tmp_path,
400398
)
401-
assert result["decision"] == "allow"
399+
assert result == {}
402400

403401

404402
def test_precompact_with_timeout(tmp_path):
@@ -413,7 +411,7 @@ def test_precompact_with_timeout(tmp_path):
413411
result = _capture_hook_output(
414412
hook_precompact, {"session_id": "test"}, state_dir=tmp_path
415413
)
416-
assert result["decision"] == "allow"
414+
assert result == {}
417415

418416

419417
def test_precompact_mines_transcript_dir(tmp_path, monkeypatch):
@@ -427,7 +425,7 @@ def test_precompact_mines_transcript_dir(tmp_path, monkeypatch):
427425
{"session_id": "test", "transcript_path": str(transcript)},
428426
state_dir=tmp_path,
429427
)
430-
assert result["decision"] == "allow"
428+
assert result == {}
431429
mock_run.assert_called_once()
432430
# Verify mine dir is the transcript's parent
433431
call_args = mock_run.call_args[0][0]
@@ -472,9 +470,7 @@ def test_run_hook_dispatches_precompact(tmp_path):
472470
with patch("mempalace.hooks_cli.STATE_DIR", tmp_path):
473471
with patch("mempalace.hooks_cli._output") as mock_output:
474472
run_hook("precompact", "claude-code")
475-
mock_output.assert_called_once()
476-
call_args = mock_output.call_args[0][0]
477-
assert call_args["decision"] == "allow"
473+
mock_output.assert_called_once_with({})
478474

479475

480476
def test_run_hook_unknown_hook():

0 commit comments

Comments
 (0)