Skip to content

Commit 49704af

Browse files
jpheinclaude
andcommitted
fix: wing_ prefix + agent filter on diary_read
Addresses bensig's 2-issue review on this PR. 1. _wing_from_transcript_path() was returning bare project names (e.g. "myproject") while all existing wings follow the wing_* convention from AAAK_SPEC. Entries landed in wing="myproject" while diary_read defaulted to wing="wing_<agent_name>" — orphaning every diary entry written by the stop hook. Now returns "wing_<project>" and falls back to "wing_sessions". 2. tool_diary_read() did not include agent_name in the ChromaDB where filter when a custom wing was provided — any caller with a shared wing could read entries written by other agents. Add {"agent": agent_name} to the $and clause. Also flagged by Qudo and left unresolved until now. Tests updated to expect the wing_ prefix (6 tests). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent ca5b357 commit 49704af

3 files changed

Lines changed: 19 additions & 10 deletions

File tree

mempalace/hooks_cli.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -207,14 +207,17 @@ def _wing_from_transcript_path(transcript_path: str) -> str:
207207
208208
Claude Code stores transcripts at:
209209
~/.claude/projects/-home-<user>-Projects-<project>/session.jsonl
210-
We extract <project> as the wing name. Falls back to "sessions".
210+
We extract <project> and return ``wing_<project>`` to match the
211+
AAAK_SPEC convention (``wing_user``, ``wing_agent``, ``wing_code``,
212+
``wing_<project>``…). Falls back to ``wing_sessions``.
211213
"""
212214
# Normalize path separators for cross-platform (Windows backslashes)
213215
normalized = transcript_path.replace("\\", "/")
214216
match = re.search(r"-Projects-([^/]+?)(?:/|$)", normalized)
215217
if match:
216-
return match.group(1).lower().replace(" ", "_")
217-
return "sessions"
218+
project = match.group(1).lower().replace(" ", "_")
219+
return f"wing_{project}"
220+
return "wing_sessions"
218221

219222

220223
def hook_stop(data: dict, harness: str):

mempalace/mcp_server.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1011,7 +1011,13 @@ def tool_diary_read(agent_name: str, last_n: int = 10, wing: str = ""):
10111011

10121012
try:
10131013
results = col.get(
1014-
where={"$and": [{"wing": wing}, {"room": "diary"}]},
1014+
where={
1015+
"$and": [
1016+
{"wing": wing},
1017+
{"room": "diary"},
1018+
{"agent": agent_name},
1019+
]
1020+
},
10151021
include=["documents", "metadatas"],
10161022
limit=10000,
10171023
)

tests/test_hooks_cli.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ def test_stop_hook_blocks_at_interval(tmp_path):
174174
assert result["decision"] == "block"
175175
assert result["reason"].startswith(STOP_BLOCK_REASON)
176176
# Default wing when transcript path doesn't match Claude Code pattern
177-
assert "wing=sessions" in result["reason"]
177+
assert "wing=wing_sessions" in result["reason"]
178178

179179

180180
def test_stop_hook_derives_wing_from_transcript_path(tmp_path):
@@ -192,7 +192,7 @@ def test_stop_hook_derives_wing_from_transcript_path(tmp_path):
192192
state_dir=tmp_path,
193193
)
194194
assert result["decision"] == "block"
195-
assert "wing=myproject" in result["reason"]
195+
assert "wing=wing_myproject" in result["reason"]
196196

197197

198198
def test_stop_hook_tracks_save_point(tmp_path):
@@ -241,21 +241,21 @@ def test_precompact_allows(tmp_path):
241241

242242
def test_wing_from_transcript_path_extracts_project():
243243
path = "/home/jp/.claude/projects/-home-jp-Projects-memorypalace/session.jsonl"
244-
assert _wing_from_transcript_path(path) == "memorypalace"
244+
assert _wing_from_transcript_path(path) == "wing_memorypalace"
245245

246246

247247
def test_wing_from_transcript_path_fallback():
248-
assert _wing_from_transcript_path("/some/random/path.jsonl") == "sessions"
248+
assert _wing_from_transcript_path("/some/random/path.jsonl") == "wing_sessions"
249249

250250

251251
def test_wing_from_transcript_path_windows_backslashes():
252252
path = "C:\\Users\\jp\\.claude\\projects\\-home-jp-Projects-myapp\\session.jsonl"
253-
assert _wing_from_transcript_path(path) == "myapp"
253+
assert _wing_from_transcript_path(path) == "wing_myapp"
254254

255255

256256
def test_wing_from_transcript_path_lowercases():
257257
path = "/home/jp/.claude/projects/-home-jp-Projects-MyProject/session.jsonl"
258-
assert _wing_from_transcript_path(path) == "myproject"
258+
assert _wing_from_transcript_path(path) == "wing_myproject"
259259

260260

261261
# --- _log ---

0 commit comments

Comments
 (0)