Feature: Bridge remaining coverage gaps
  As a developer
  I want targeted tests for remaining missed lines and branches in bridge.py
  So that coverage approaches 100%

  # Targets: line 35 (cancellation_reasons init), line 68 (task.cancel in async cleanup),
  # lines 201-204 (string content branch in execute_graph),
  # branches 39→38, 67→68, 182→184, 260→258

  Scenario: Cancellation reason is recorded when cancelling a tracked task
    Given a bridge instance prepared for cancellation reason tracking
    When I cancel a tracked task providing reason "user requested abort"
    Then the bridge cancellation_reasons mapping should contain the task
    And the stored reason should equal "user requested abort"

  Scenario: Cancelling a None task raises a ValueError
    Given a bridge instance prepared for cancellation reason tracking
    When I try cancelling a None task with reason "some reason"
    Then a ValueError mentioning "task must not be None" should be raised

  Scenario: Cancelling a task with empty reason raises a ValueError
    Given a bridge instance prepared for cancellation reason tracking
    When I try cancelling a valid task with an empty reason string
    Then a ValueError mentioning "reason must be a non-empty string" should be raised

  Scenario: Async cleanup cancels a not-yet-done task on the bridge
    Given a bridge holding a deliberately stalled coroutine task
    When I perform async cleanup with a 200ms timeout on stalled tasks
    Then every stalled task should have been cancelled or finished
    And the bridge task tracking set should be empty after async cleanup

  Scenario: Async cleanup handles already-completed tasks without error
    Given a bridge holding an already-finished async task
    When I perform async cleanup with a 200ms timeout on stalled tasks
    Then the bridge task tracking set should be empty after async cleanup

  Scenario: Graph executor inner coroutine processes string content directly
    Given a bridge with a mock graph wired for direct coroutine invocation
    When I invoke the executor coroutine with a plain string message body
    Then the mock graph execute should have received a messages list with the string
    And the executor coroutine should return a StreamMessage with graph metadata

  Scenario: Graph executor inner coroutine processes list content as fallback
    Given a bridge with a mock graph wired for direct coroutine invocation
    When I invoke the executor coroutine with a list payload as message body
    Then the mock graph execute should have received a content key wrapping the list

  Scenario: Graph stream config includes correct type and publication fields
    Given a bridge with a registered graph called "stream_verify"
    When I obtain the stream configuration for graph "stream_verify"
    Then the stream config name should equal "graph_stream_verify"
    And the stream config publications should include "__output__"

  Scenario: State checkpointer operator applies to a message for a valid graph
    Given a bridge with a registered graph called "ckpt_valid"
    And the graph "ckpt_valid" has a checkpoint directory configured
    When I construct and apply the checkpointer operator for "ckpt_valid"
    Then the checkpointer should have invoked _save_checkpoint on the state manager

  Scenario: The __del__ method completes normally when cleanup_tasks succeeds
    Given a fully functional bridge for destructor testing
    When __del__ is called on the fully functional bridge
    Then the __del__ call should complete without any error
