Skip to content

test: +1.69% coverage on src/runtime via 7 targeted test files#14

Closed
aksOps wants to merge 1 commit into
fix/sonar-gate-greenfrom
test/coverage-uplift
Closed

test: +1.69% coverage on src/runtime via 7 targeted test files#14
aksOps wants to merge 1 commit into
fix/sonar-gate-greenfrom
test/coverage-uplift

Conversation

@aksOps

@aksOps aksOps commented May 15, 2026

Copy link
Copy Markdown
Contributor

Summary

Phase 2 of the Sonar gate-green effort. Where PR #13 syncs exclusions to flip the gate, this PR actually closes coverage gaps with new tests.

Stacks on top of #13 (base = fix/sonar-gate-green). Once #13 merges, this PR will rebase onto main cleanly.

Coverage delta

Metric Before After
Tests passing 1,265 1,310 (+45)
src/runtime/ line coverage 87.21% 88.90% (+1.69%)
Uncovered lines 733 636 (-97)

What's covered

File Test file Target
llm.py:141-160, 171-177 test_llm_stub_structured_output.py StubChatModel.with_structured_output happy path
graph.py:583-610 test_envelope_recovery.py _try_recover_envelope_from_raw (table-driven across raw / fenced / greedy strategies)
orchestrator.py:945-998 test_orchestrator_extract_last_error.py _extract_last_error exception-class mapping (table-driven)
graph.py:613-644 test_handle_agent_failure.py Happy path + FileNotFoundError fallback + partial-tool-write preservation
orchestrator.py:1552-1587 test_retry_session_locked_post_policy.py _retry_session_locked post-policy execution path (filter, thread-id pin, pause/finalize fork)
service.py:541-568 test_service_run_exception_branches.py _run exception branches: CancelledError / GraphInterrupt / generic
api.py:879-890 test_sse_tail_loop.py SSE tail-poll loop + CancelledError re-raise (pins PR #13's bug fix)

What's intentionally NOT covered

StubChatModel.with_structured_output permissive model_validate fallback (llm.py:161-169) — pydantic v2's model_validate ultimately calls __init__, so any constructor-failing schema also fails the fallback. The branch exists for hypothetical schemas with custom __pydantic_validator__ overrides; it can't be cleanly unit-tested without monkey-patching pydantic internals. Documented in the test file.

Test plan

  • uv run ruff check src/ tests/ — passed
  • uv run pyright src/runtime — 0 errors / 0 warnings
  • uv run pytest -x — 1,310 passed / 8 skipped
  • uv run pytest --cov=src/runtime --cov-fail-under=85 -x — 88.90%
  • No src/runtime/ changes → dist/* unchanged → bundle staleness gate (HARD-08) is a no-op
  • CI green on PR
  • SonarCloud new_coverage rises further on the merged main

🤖 Generated with Claude Code

Targeted coverage uplift across the framework core's pure helpers and
two integration boundaries. Local src/runtime coverage rises from
87.21% to 88.90% (+1.69%); 97 previously-uncovered lines now exercised.

New test files (7):

  * tests/test_llm_stub_structured_output.py
      StubChatModel.with_structured_output happy path
      (llm.py:141-160, 171-177). The defensive model_validate fallback
      (lines 161-169) is excluded with a documented justification:
      pydantic v2's model_validate calls __init__, so any schema whose
      constructor raises also fails the fallback.

  * tests/test_envelope_recovery.py
      _try_recover_envelope_from_raw (graph.py:583-610). Table-driven
      across the three candidate-substring strategies (raw, fenced,
      greedy first-{...-last-}) and every failure path.

  * tests/test_orchestrator_extract_last_error.py
      Orchestrator._extract_last_error (orchestrator.py:945-998).
      Pure mapping from a failed-AgentRun summary string to a
      representative typed exception. Table-driven across
      EnvelopeMissingError, ValidationError, TimeoutError,
      OSError, RuntimeError fallback, plus reversed-iteration ordering.

  * tests/test_handle_agent_failure.py
      _handle_agent_failure (graph.py:613-644). Both the happy path
      (reload + append + status='error') and the FileNotFoundError
      fallback path (use caller's in-memory session). Plus a
      partial-tool-write preservation regression test.

  * tests/test_retry_session_locked_post_policy.py
      Orchestrator._retry_session_locked post-policy execution path
      (orchestrator.py:1552-1587). Stub orchestrator pulls in the
      real method body and substitutes the surrounding integration
      points (graph, finalize, pause). Covers the failed-AgentRun
      filter, retry_count + active_thread_id pinning, and the
      pause-vs-finalize fork.

  * tests/test_service_run_exception_branches.py
      OrchestratorService.start_session._run exception branches
      (service.py:541-568). Three classes get distinct treatment:
      CancelledError (propagate as-is), GraphInterrupt (propagate
      WITHOUT marking registry status='error' -- HITL pause is not a
      failure), generic Exception (mark error then propagate).

  * tests/test_sse_tail_loop.py
      SSE _stream tail-poll loop (api.py:879-890), including the
      CancelledError re-raise from PR #13. Two tests: one drives the
      tail to deliver a post-drain event, one forces sleep to raise
      CancelledError and asserts it propagates (pinning the bug fix).

Verification:
  ruff check src/ tests/                         passed
  pyright src/runtime                            0 errors / 0 warnings
  pytest -x                                      1310 passed / 8 skipped (was 1265/8)
  pytest --cov=src/runtime --cov-fail-under=85   88.90% (was 87.21%)
  build_single_file.py                           dist unchanged (tests only)

Projected SonarCloud impact (after the Phase 1 PR #13 exclusion sync):
  new_coverage   ~87.2% -> ~89-90%
@aksOps aksOps force-pushed the test/coverage-uplift branch from e18d8e7 to 373451f Compare May 15, 2026 08:53
@aksOps aksOps deleted the branch fix/sonar-gate-green May 15, 2026 08:57
@aksOps aksOps closed this May 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant