@@ -22,6 +22,7 @@ def run_check_version_with_mock_claude(
2222 mock_version : str | None ,
2323 cwd : Path | None = None ,
2424 mock_deepwork : bool = True ,
25+ stdin_json : str | None = None ,
2526) -> tuple [str , str , int ]:
2627 """
2728 Run check_version.sh with a mocked claude command.
@@ -32,6 +33,7 @@ def run_check_version_with_mock_claude(
3233 cwd: Working directory
3334 mock_deepwork: If True, create a mock deepwork command that succeeds.
3435 If False, do not create mock deepwork (simulates not installed).
36+ stdin_json: Optional JSON string to pass via stdin (simulates hook input)
3537
3638 Returns:
3739 Tuple of (stdout, stderr, return_code)
@@ -66,6 +68,7 @@ def run_check_version_with_mock_claude(
6668 text = True ,
6769 cwd = cwd or tmpdir ,
6870 env = env ,
71+ input = stdin_json ,
6972 )
7073
7174 return result .stdout , result .stderr , result .returncode
@@ -290,3 +293,120 @@ def test_deepwork_check_happens_before_version_check(self, check_version_script:
290293 assert "DEEPWORK NOT INSTALLED" in stderr
291294 # Should NOT show version warning
292295 assert "CLAUDE CODE VERSION WARNING" not in stderr
296+
297+
298+ class TestSessionSourceDetection :
299+ """Tests for skipping non-initial sessions based on source field."""
300+
301+ def test_startup_source_runs_normally (self , check_version_script : Path ) -> None :
302+ """Test that source='startup' runs the full check."""
303+ import json
304+
305+ stdin_json = json .dumps ({"source" : "startup" , "session_id" : "test123" })
306+ stdout , stderr , code = run_check_version_with_mock_claude (
307+ check_version_script , "3.0.0" , stdin_json = stdin_json
308+ )
309+
310+ # Should run normally and output empty JSON (version OK)
311+ assert code == 0
312+ assert stdout .strip () == "{}"
313+
314+ def test_resume_source_skips_check (self , check_version_script : Path ) -> None :
315+ """Test that source='resume' skips all checks and returns empty JSON."""
316+ import json
317+
318+ stdin_json = json .dumps ({"source" : "resume" , "session_id" : "test123" })
319+ stdout , stderr , code = run_check_version_with_mock_claude (
320+ check_version_script ,
321+ "1.0.0" ,
322+ stdin_json = stdin_json , # Low version that would trigger warning
323+ )
324+
325+ # Should skip and return empty JSON without warnings
326+ assert code == 0
327+ assert stdout .strip () == "{}"
328+ assert "WARNING" not in stderr
329+ assert "DEEPWORK" not in stderr
330+
331+ def test_clear_source_skips_check (self , check_version_script : Path ) -> None :
332+ """Test that source='clear' (compact) skips all checks."""
333+ import json
334+
335+ stdin_json = json .dumps ({"source" : "clear" , "session_id" : "test123" })
336+ stdout , stderr , code = run_check_version_with_mock_claude (
337+ check_version_script , "1.0.0" , stdin_json = stdin_json
338+ )
339+
340+ # Should skip and return empty JSON
341+ assert code == 0
342+ assert stdout .strip () == "{}"
343+ assert "WARNING" not in stderr
344+
345+ def test_no_source_field_runs_normally (self , check_version_script : Path ) -> None :
346+ """Test backwards compatibility: missing source field runs full check."""
347+ import json
348+
349+ # JSON without source field (older Claude Code version)
350+ stdin_json = json .dumps ({"session_id" : "test123" })
351+ stdout , stderr , code = run_check_version_with_mock_claude (
352+ check_version_script ,
353+ "2.0.0" ,
354+ stdin_json = stdin_json , # Low version
355+ )
356+
357+ # Should run normally and show warning (backwards compat)
358+ assert code == 0
359+ assert "WARNING" in stderr
360+
361+ def test_empty_stdin_runs_normally (self , check_version_script : Path ) -> None :
362+ """Test that empty stdin runs full check (backwards compat)."""
363+ stdout , stderr , code = run_check_version_with_mock_claude (
364+ check_version_script , "2.0.0" , stdin_json = ""
365+ )
366+
367+ # Should run normally and show warning
368+ assert code == 0
369+ assert "WARNING" in stderr
370+
371+ def test_resume_skips_even_with_missing_deepwork (self , check_version_script : Path ) -> None :
372+ """Test that resume sessions skip before deepwork check."""
373+ import json
374+
375+ stdin_json = json .dumps ({"source" : "resume" })
376+ stdout , stderr , code = run_check_version_with_mock_claude (
377+ check_version_script , "3.0.0" , mock_deepwork = False , stdin_json = stdin_json
378+ )
379+
380+ # Should skip immediately, NOT block on deepwork
381+ assert code == 0
382+ assert stdout .strip () == "{}"
383+ assert "DEEPWORK NOT INSTALLED" not in stderr
384+
385+ def test_startup_with_low_version_shows_warning (self , check_version_script : Path ) -> None :
386+ """Test that startup sessions with low version show warning."""
387+ import json
388+
389+ stdin_json = json .dumps ({"source" : "startup" })
390+ stdout , stderr , code = run_check_version_with_mock_claude (
391+ check_version_script , "2.0.0" , stdin_json = stdin_json
392+ )
393+
394+ # Should run full check and show warning
395+ assert code == 0
396+ assert "WARNING" in stderr
397+ assert "hookSpecificOutput" in stdout
398+
399+ def test_unknown_source_skips_check (self , check_version_script : Path ) -> None :
400+ """Test that unknown source values skip the check."""
401+ import json
402+
403+ # Future-proofing: unknown source values should be treated as non-startup
404+ stdin_json = json .dumps ({"source" : "unknown_future_value" })
405+ stdout , stderr , code = run_check_version_with_mock_claude (
406+ check_version_script , "1.0.0" , stdin_json = stdin_json
407+ )
408+
409+ # Should skip and return empty JSON
410+ assert code == 0
411+ assert stdout .strip () == "{}"
412+ assert "WARNING" not in stderr
0 commit comments