Feature: Consolidated Langgraph Combined scenarios from: langgraph_bridge_coverage, langgraph_dynamic_router_coverage, langgraph_graph_coverage, langgraph_nodes_additional_coverage, langgraph_nodes_coverage, langgraph_nodes_uncovered_lines, langgraph_state_additional_coverage, langgraph_state_branch_coverage, pure_graph_coverage, agent_langgraph_port # ============================================================ # Originally from: langgraph_bridge_coverage.feature # Feature: LangGraph bridge coverage # ============================================================ Scenario: Cover bridge lifecycle and operators Given I set up a langgraph bridge test harness When I create a bridge with mocked graph configuration And I exercise bridge graph and stream creation And I exercise graph executor branches And I exercise state utilities and node operator And I exercise conditional routing helpers And I exercise router node helpers and cleanup Then bridge coverage steps should complete successfully # ============================================================ # Originally from: langgraph_dynamic_router_coverage.feature # Feature: Dynamic Router Coverage # ============================================================ Scenario: Default route when no rules are provided Given a dynamic router with no rules When I route the message """ {"text": "hello"} """ Then the router should return the default end edge Scenario: Route to target when no condition is required Given a dynamic router with a rule targeting "next" and no condition When I route the message """ {"text": "any"} """ Then the router should return a single edge to "next" Scenario: Route to target when condition matches Given a dynamic router with a rule targeting "match_target" when message type is "match" When I route the message """ {"type": "match", "text": "payload"} """ Then the router should return a single edge to "match_target" Scenario: Fall back to end when condition fails Given a dynamic router with a rule targeting "conditional" when message type is "expected" When I route the message """ {"type": "other", "text": "payload"} """ Then the router should return the default end edge # ============================================================ # Originally from: langgraph_graph_coverage.feature # Feature: LangGraph uncovered branches # ============================================================ Scenario: Scheduler falls back when no running loop exists Given a langgraph config with only start and end nodes And asyncio has no running loop When I construct a LangGraph without providing a scheduler Then it should create an AsyncIOScheduler and initialize streams Scenario: Execute dispatches to start stream and returns state Given a langgraph instance with a fresh state manager When I execute the graph with input data Then the start stream should receive the state and execution returns a GraphState Scenario: Start raises when start stream is missing Given a langgraph instance with a removed start stream When I call start on the graph Then a start stream error should be raised Scenario: Parallel groups disabled and cycles detected Given a langgraph config with parallel execution disabled and a cycle When I construct the LangGraph Then the graph should report cycles and empty parallel groups Scenario: Node executor updates state and history Given a langgraph instance with a patched state manager When I invoke the builtin node executor Then it should update state and record execution history Scenario: Topological levels enumerate layered nodes Given a langgraph config with layered nodes When I compute the topological levels Then the levels should list each layer Scenario: Execution history getter returns copy Given a langgraph instance with recorded history When I request execution history Then it should return a copy of the recorded history Scenario: Initialization respects explicit guard nodes Given a langgraph config with explicit start and end nodes When I construct the LangGraph with that config Then initialization should reuse the provided start and end nodes Scenario: Node subscriptions invoke handlers on stream events Given a langgraph instance prepared to observe node streams When the node stream emits next error and completion events Then the subscription handlers should be exercised Scenario: Parallel groups computed for converging branches Given a langgraph config with converging branches When I construct the LangGraph for parallel groups Then parallel groups should reflect staged execution order Scenario: Validation fails when guard nodes missing Given a langgraph instance missing required guard nodes When I validate the graph explicitly Then a guard validation error should be raised Scenario: Start uses default state and stop resets running flag Given a langgraph instance ready to start When I start without input then stop and fetch state Then it should use default state and update running flags # ============================================================ # Originally from: langgraph_nodes_additional_coverage.feature # Feature: Additional LangGraph nodes coverage # ============================================================ Scenario: Conversation history handles empty messages Given a node with default history limits When I prepare the conversation history for empty input Then it should return empty history without truncation Scenario: Conversation history falls back on invalid limits Given a node with invalid history metadata and two messages When I prepare the conversation history with invalid limits Then it should return full history without truncation Scenario: Agent node without configured agent returns failure metadata Given an agent node without an agent configured When I execute the node expecting an agent configuration error Then the result should include failed_node and error text Scenario: Agent receives empty input when no messages exist Given an agent node with no prior messages When I execute the agent node with empty history Then the agent should receive empty input and track node metadata Scenario: Agent merges nested metadata context and flags truncation Given an agent node with nested metadata context and long history When I execute the agent node with nested context Then the agent context should merge nested values and mark truncation Scenario: Agent error path captures processing failures Given an agent node whose handler raises an exception When I execute the failing agent node Then the agent response should contain the error string Scenario: Function node retries and reports missing function Given a function node missing a target with retry policy When I execute the function node with retries Then it should report failure after retries # ============================================================ # Originally from: langgraph_nodes_coverage.feature # Feature: LangGraph nodes coverage # ============================================================ Scenario: Conversation history truncates by message count Given a node with history limit 2 messages And a conversation history of 3 short messages When I prepare the conversation history Then it should return 2 messages and indicate truncation Scenario: Agent node falls back when agent instance is missing Given an agent node referencing a missing agent When I execute the agent node Then it should return a not found assistant message Scenario: Tool agent uses current_message metadata for input Given a tool agent node with a current_message "override" and long history When I execute the tool agent node Then the tool agent should receive input "override" And the response metadata should include last_agent_node Scenario: Function node runs async function Given a function node with an async function When I execute the function node Then the function result message should be "async-result" Scenario: Function node awaits coroutine returned from sync function Given a function node with a sync function that returns a coroutine When I execute the function node Then the function result message should be "sync-inner" Scenario: Conditional node detects assistant field match Given a conditional node looking for field "status" equals "OK" When I execute the conditional node with matching assistant message Then the condition_result should be true and metadata flagged Scenario: Message router selects rule based on field condition Given a message router node with a rule matching field "topic" value "urgent" When I execute the message router with current_message containing topic "urgent" Then it should route to "urgent_node" Scenario: Edge condition checks equals against latest message Given an edge with equals condition on field "content" value "done" When I evaluate the edge condition with matching last message Then the edge condition should be true And evaluating with no messages should also default to true Scenario: Eval condition supports equals and field comparisons Given I evaluate equals condition on message "abc" Then the equals evaluation should return true When I evaluate field condition on message dict with foo value "bar" Then the field evaluation should return true When I evaluate field condition on non-dict message Then it should return false Scenario: Node parallel execution flag reflects configuration Given a node configured for parallel execution Then can_execute_parallel should return true # ============================================================ # Originally from: langgraph_nodes_uncovered_lines.feature # Feature: LangGraph nodes uncovered lines # ============================================================ Scenario: Tool node marks execution Given a tool node configured When I execute the tool node Then it should mark tool executed Scenario: ToolAgent branch uses current_message for input Given a tool agent node using ToolAgent with current_message "override" When I execute the tool agent node with ToolAgent branch Then the ToolAgent should receive input "override" Scenario: Agent falls back to last assistant message when no user entries exist Given an agent node with only assistant history When I execute the agent node for assistant fallback Then the agent should receive the assistant fallback content Scenario: Agent clearing context skips metadata merge Given an agent that clears context during processing When I execute the clearing agent node Then only last_agent_node metadata should remain Scenario: Agent mutation adds metadata updates Given an agent that mutates context to add metadata When I execute the mutating agent node Then the metadata should include the mutated key Scenario: Subgraph node reports invocation Given a subgraph node named "child_subgraph" When I execute the subgraph node Then it should report the invoked subgraph "child_subgraph" Scenario: Start node indicates start Given a start node When I execute the start node Then it should indicate graph start Scenario: End node indicates completion Given an end node When I execute the end node Then it should indicate graph completion Scenario: Non-dict tool result leaves base state updates Given a tool node patched to return non dict When I execute the patched tool node Then the execute result should only include current_node # ============================================================ # Originally from: langgraph_state_additional_coverage.feature # Feature: LangGraph state additional coverage # ============================================================ Scenario: Merge mode trims messages beyond retention limit Given the state management system is available Given I have a GraphState starting with 49 messages And I have merge updates containing 5 new messages When I merge the updates into the state Then the message list should be trimmed to 50 messages And the newest message should be retained after trimming Scenario: Append mode trims messages beyond retention limit Given the state management system is available Given the state management system is available Given I have a GraphState starting with 50 messages And I have append updates containing 5 new messages When I append the updates into the state Then the message list should be trimmed to 50 messages after append And the newest appended message should be retained after trimming Scenario: Time travel history is recorded and trimmed Given the state management system is available Given I have a StateManager with time travel enabled and history size 2 When I perform 4 sequential state updates with time travel Then only the two most recent history snapshots should remain And the earliest snapshots should be discarded Scenario: Automatic checkpoint is saved at interval Given the state management system is available Given I have a StateManager with checkpointing enabled and interval 1 When I perform 2 sequential state updates with checkpointing Then a checkpoint file should exist in the directory And checkpoint saving should have been triggered Scenario: Time travel clamps when steps exceed history Given the state management system is available Given I have a StateManager with time travel history of 2 snapshots When I request time travel 5 steps back Then time travel should return the earliest available snapshot And the returned state should reflect the earliest snapshot # ============================================================ # Originally from: langgraph_state_branch_coverage.feature # Feature: LangGraph state branch coverage # ============================================================ Scenario: Replace mode overwrites existing fields Given the state management system is available Given I have a GraphState with metadata {"original": 1} and current node "old" When I replace the state with updates containing metadata {"new": 2} and current node "new" Then the state's metadata should equal {"new": 2} And the state's current node should equal "new" Scenario: Merge mode merges metadata dictionaries Given the state management system is available Given I have a GraphState with metadata {"alpha": 1} And I have merge metadata updates {"beta": 2} When I merge metadata updates into the state Then the state's metadata should contain keys "alpha" and "beta" Scenario: Append mode appends a single message item Given the state management system is available Given I have a GraphState with 1 message When I append a single message with id 99 into the state Then the state's messages should end with id 99 And the message list length should be 2 Scenario: Save checkpoint without directory is a no-op Given the state management system is available Given I have a StateManager without checkpointing When I invoke checkpoint saving manually Then the update count should remain at 0 Scenario: Load checkpoint restores state and counters Given the state management system is available Given I have a checkpoint file with execution count 7 and metadata {"restored": true} When I load the checkpoint into a StateManager Then the manager state should include metadata {"restored": true} And the manager update count should be 7 Scenario: Latest checkpoint returns None when missing Given the state management system is available Given I have a StateManager without checkpointing When I request the latest checkpoint Then no checkpoint path should be returned Scenario: Latest checkpoint selects the most recent file Given the state management system is available Given I have a StateManager with two checkpoints written at different times When I request the latest checkpoint Then the newest checkpoint path should be returned Scenario: Time travel without history returns None Given the state management system is available Given I have a StateManager with time travel disabled When I request time travel Then the returned time travel state should be None Scenario: Clear history and reset restore initial state Given the state management system is available Given I have a StateManager with time travel history entries When I clear the history and then reset with metadata {"reset": true} Then the history should be empty after reset And the execution count should be zero after reset And the state metadata should include {"reset": true} # ============================================================ # Originally from: pure_graph_coverage.feature # Feature: PureGraph coverage # ============================================================ Scenario: Topological order keeps start and end boundaries Given a pure graph with nodes "alpha" and "beta" When I list its topological order Then the order should be start alpha beta end Scenario: Execute applies registered node functions sequentially Given a pure graph with function nodes "double" and "increment" And registered functions that double then increment When I execute the pure graph starting with 1 Then the final result should be 3 And the functions should run in declaration order Scenario: Execute skips unregistered functions Given a pure graph with a missing function node When I execute the pure graph starting with 5 Then the result should remain 5 Scenario: Nodes without functions do not change value Given a pure graph with non-functional nodes "alpha" and "beta" When I execute the pure graph starting with 7 Then the result should remain 7 # ============================================================ # Originally from: agent_langgraph_port.feature # Feature: Actor-first port of v2 agent and LangGraph suites # ============================================================