diff --git a/headroom/learn/plugins/grok.py b/headroom/learn/plugins/grok.py index c274dcf29..898466126 100644 --- a/headroom/learn/plugins/grok.py +++ b/headroom/learn/plugins/grok.py @@ -58,7 +58,15 @@ class GrokPlugin(LearnPlugin, ConversationScanner): continue decoded = unquote(workspace_dir.name) - project_path = Path(decoded) if decoded.startswith("/") else Path.cwd() + # The workspace dir name is a URL-encoded absolute cwd. Use + # Path.is_absolute() rather than a `startswith("/")` check so a + # Windows drive-letter path (e.g. `C:\Users\...`) is recognised as + # absolute instead of silently falling back to cwd (which would + # attribute the learnings to the wrong project and miss its + # GROK.md/AGENTS.md). Mirrors the Windows-aware path handling in + # memory/traffic_learner.py. + decoded_path = Path(decoded) + project_path = decoded_path if decoded_path.is_absolute() else Path.cwd() agents_md = project_path / "AGENTS.md" grok_md = project_path / "GROK.md" diff --git a/tests/test_learn_grok_plugin.py b/tests/test_learn_grok_plugin.py index 3d774b5b7..2bab24cb2 100644 --- a/tests/test_learn_grok_plugin.py +++ b/tests/test_learn_grok_plugin.py @@ -1,6 +1,7 @@ from __future__ import annotations import json +import sys from pathlib import Path from headroom.learn.plugins.grok import GrokPlugin @@ -57,3 +58,26 @@ def test_grok_plugin_scans_tool_calls(tmp_path: Path) -> None: assert len(sessions) == 1 assert len(sessions[0].tool_calls) == 1 assert sessions[0].tool_calls[0].is_error is True + + +def test_grok_plugin_resolves_absolute_workspace_path(tmp_path: Path) -> None: + # The workspace dir name is a URL-encoded absolute cwd. It must resolve to + # that path, not fall back to the process cwd. The Windows branch is the + # real guard for the fix (a drive-letter path does not start with "/"); the + # POSIX branch confirms no regression. Detection uses Path.is_absolute(). + grok_dir = tmp_path / ".grok" + if sys.platform == "win32": + workspace = "C%3A%5Cproj%5Capp" + expected = Path(r"C:\proj\app") + else: + workspace = "%2Ftmp%2Fproj%2Fapp" + expected = Path("/tmp/proj/app") + session_dir = grok_dir / "sessions" / workspace / "session-1" + session_dir.mkdir(parents=True) + (session_dir / "updates.jsonl").write_text("{}\n", encoding="utf-8") + + plugin = GrokPlugin(grok_dir=grok_dir) + projects = plugin.discover_projects() + + assert len(projects) == 1 + assert projects[0].project_path == expected