|
15 | 15 | _maybe_auto_ingest, |
16 | 16 | _parse_harness_input, |
17 | 17 | _sanitize_session_id, |
| 18 | + _wing_from_transcript_path, |
18 | 19 | hook_stop, |
19 | 20 | hook_session_start, |
20 | 21 | hook_precompact, |
@@ -170,6 +171,26 @@ def test_stop_hook_blocks_at_interval(tmp_path): |
170 | 171 | ) |
171 | 172 | assert result["decision"] == "block" |
172 | 173 | assert result["reason"].startswith(STOP_BLOCK_REASON) |
| 174 | + # Default wing when transcript path doesn't match Claude Code pattern |
| 175 | + assert "wing=sessions" in result["reason"] |
| 176 | + |
| 177 | + |
| 178 | +def test_stop_hook_derives_wing_from_transcript_path(tmp_path): |
| 179 | + """When transcript path looks like a Claude Code path, wing is derived from it.""" |
| 180 | + project_dir = tmp_path / ".claude" / "projects" / "-home-jp-Projects-myproject" |
| 181 | + project_dir.mkdir(parents=True) |
| 182 | + transcript = project_dir / "session.jsonl" |
| 183 | + _write_transcript( |
| 184 | + transcript, |
| 185 | + [{"message": {"role": "user", "content": f"msg {i}"}} for i in range(SAVE_INTERVAL)], |
| 186 | + ) |
| 187 | + result = _capture_hook_output( |
| 188 | + hook_stop, |
| 189 | + {"session_id": "test", "stop_hook_active": False, "transcript_path": str(transcript)}, |
| 190 | + state_dir=tmp_path, |
| 191 | + ) |
| 192 | + assert result["decision"] == "block" |
| 193 | + assert "wing=myproject" in result["reason"] |
173 | 194 |
|
174 | 195 |
|
175 | 196 | def test_stop_hook_tracks_save_point(tmp_path): |
@@ -214,6 +235,28 @@ def test_precompact_always_blocks(tmp_path): |
214 | 235 | assert result["reason"] == PRECOMPACT_BLOCK_REASON |
215 | 236 |
|
216 | 237 |
|
| 238 | +# --- _wing_from_transcript_path --- |
| 239 | + |
| 240 | + |
| 241 | +def test_wing_from_transcript_path_extracts_project(): |
| 242 | + path = "/home/jp/.claude/projects/-home-jp-Projects-memorypalace/session.jsonl" |
| 243 | + assert _wing_from_transcript_path(path) == "memorypalace" |
| 244 | + |
| 245 | + |
| 246 | +def test_wing_from_transcript_path_fallback(): |
| 247 | + assert _wing_from_transcript_path("/some/random/path.jsonl") == "sessions" |
| 248 | + |
| 249 | + |
| 250 | +def test_wing_from_transcript_path_windows_backslashes(): |
| 251 | + path = "C:\\Users\\jp\\.claude\\projects\\-home-jp-Projects-myapp\\session.jsonl" |
| 252 | + assert _wing_from_transcript_path(path) == "myapp" |
| 253 | + |
| 254 | + |
| 255 | +def test_wing_from_transcript_path_lowercases(): |
| 256 | + path = "/home/jp/.claude/projects/-home-jp-Projects-MyProject/session.jsonl" |
| 257 | + assert _wing_from_transcript_path(path) == "myproject" |
| 258 | + |
| 259 | + |
217 | 260 | # --- _log --- |
218 | 261 |
|
219 | 262 |
|
|
0 commit comments