@@ -2541,16 +2541,10 @@ def _has_exception_event(span: Any) -> bool:
25412541
25422542async def _run_fixture_008_case (case : Mapping [str , Any ]) -> None :
25432543 case_name = case ["name" ]
2544- # v0.73.1 added the detached fan-out INSTANCE error-status case
2545- # (proposal 0061 §4.2, the fan-out-instance counterpart to the
2546- # subgraph case). Proposal 0061 IS implemented (the instance raise
2547- # propagates exactly like the subgraph raise), but this runner does
2548- # not yet wire the fan-out-instance raise path (expect_raise + the
2549- # both-spans error-status assertions); defer the single case until the
2550- # harness wires it, keeping the other 008 cases running.
2551- if case_name == "detached_fan_out_instance_raises_error_status_on_both_spans" :
2552- return
2553- expect_raise = case_name == "detached_subgraph_raises_error_status_on_both_spans"
2544+ expect_raise = case_name in (
2545+ "detached_subgraph_raises_error_status_on_both_spans" ,
2546+ "detached_fan_out_instance_raises_error_status_on_both_spans" ,
2547+ )
25542548 spans = await _run_detached_case_graph (case , expect_raise = expect_raise )
25552549
25562550 if case_name == "detached_subgraph_two_traces_one_link" :
@@ -2683,6 +2677,49 @@ async def _run_fixture_008_case(case: Mapping[str, Any]) -> None:
26832677 )
26842678 return
26852679
2680+ if case_name == "detached_fan_out_instance_raises_error_status_on_both_spans" :
2681+ # Proposal 0061 §4.2, fan-out-instance variant: a raising detached
2682+ # fan-out instance surfaces ERROR on BOTH the parent's fan-out node
2683+ # span (parent trace, carrying the Link) and the per-instance detached
2684+ # invocation span (its own trace), each with the §4 category + an OTel
2685+ # exception event, sharing the parent invocation_id. The single-element
2686+ # fan-out (items [1]) means exactly one instance runs and raises.
2687+ fan_out_node_spans = [s for s in spans if s .name == "per_document_scoring" ]
2688+ parent_fan_out = next ((s for s in fan_out_node_spans if s .links ), None )
2689+ assert parent_fan_out is not None , "expected a fan-out node span with a Link in the parent trace"
2690+ assert parent_fan_out .status .status_code .name == "ERROR" , (
2691+ "parent fan-out node span MUST carry ERROR for a raising detached instance"
2692+ )
2693+ assert _has_exception_event (parent_fan_out ), "parent fan-out node span MUST record the exception"
2694+ assert dict (parent_fan_out .attributes or {}).get ("openarmature.error.category" ) == "node_exception"
2695+ assert len (parent_fan_out .links ) == 1 , (
2696+ f"fan-out node span MUST carry exactly one Link; got { len (parent_fan_out .links )} "
2697+ )
2698+ parent_trace_id = cast ("Any" , parent_fan_out .context ).trace_id
2699+ detached_trace_id = parent_fan_out .links [0 ].context .trace_id
2700+ assert detached_trace_id != parent_trace_id , "detached instance + parent traces MUST be distinct"
2701+ inv_spans = [s for s in spans if s .name == "openarmature.invocation" ]
2702+ detached_inv = next (
2703+ (s for s in inv_spans if cast ("Any" , s .context ).trace_id == detached_trace_id ), None
2704+ )
2705+ parent_inv = next ((s for s in inv_spans if cast ("Any" , s .context ).trace_id == parent_trace_id ), None )
2706+ assert detached_inv is not None , (
2707+ "detached instance trace MUST root in an openarmature.invocation span"
2708+ )
2709+ assert parent_inv is not None
2710+ assert detached_inv .status .status_code .name == "ERROR" , (
2711+ "detached instance invocation span MUST carry the instance's ERROR status (§4.2)"
2712+ )
2713+ assert _has_exception_event (detached_inv ), (
2714+ "detached instance invocation span MUST record the exception"
2715+ )
2716+ assert dict (detached_inv .attributes or {}).get ("openarmature.error.category" ) == "node_exception"
2717+ parent_iid = _invocation_id_of (parent_inv )
2718+ assert parent_iid is not None and _invocation_id_of (detached_inv ) == parent_iid , (
2719+ "detached instance invocation span MUST share the parent's invocation_id"
2720+ )
2721+ return
2722+
26862723 raise AssertionError (f"unknown sub-case { case_name !r} " )
26872724
26882725
0 commit comments