@@ -330,6 +330,86 @@ def test_global_gates_preserves_shared_route_with_supported_owner(monkeypatch, t
330330 assert gate ["owner" ] != "user_or_controller"
331331
332332
333+ def test_global_gates_agent_scope_drops_goal_controller_route_when_quota_is_runnable (
334+ monkeypatch , tmp_path
335+ ) -> None :
336+ agent_id = "codex-runnable"
337+ status_payload = {
338+ "ok" : True ,
339+ "attention_queue" : {
340+ "items" : [
341+ {
342+ "goal_id" : "runnable-goal" ,
343+ "waiting_on" : "controller" ,
344+ "operator_question" : "Resolve another lane's gate?" ,
345+ }
346+ ]
347+ },
348+ }
349+ quota_payload = {
350+ "ok" : True ,
351+ "goal_id" : "runnable-goal" ,
352+ "state" : "eligible" ,
353+ "agent_identity" : {"agent_id" : agent_id , "registered" : True },
354+ "selected_todo" : {"todo_id" : "runnable-todo" , "status" : "open" },
355+ "agent_lane_next_action" : {
356+ "todo_id" : "runnable-todo" ,
357+ "status" : "open" ,
358+ },
359+ "user_todo_summary" : {"open_count" : 0 , "gate_open_items" : []},
360+ "interaction_contract" : {"user_channel" : {"action_required" : False }},
361+ }
362+ patch_manager_reads (
363+ monkeypatch ,
364+ status_payload = status_payload ,
365+ quota_payloads = {"runnable-goal" : quota_payload },
366+ )
367+
368+ payload = build_global_gates (tmp_path , agent_id = agent_id )
369+
370+ assert payload ["gates" ] == []
371+ assert payload ["lanes" ] == []
372+ assert payload ["groups" ]["blocked_work" ] == []
373+ assert payload ["summary" ]["open_gate_count" ] == 0
374+ assert payload ["summary" ]["blocked_lane_count" ] == 0
375+
376+
377+ def test_global_gates_agent_scope_preserves_scoped_controller_gate (
378+ monkeypatch , tmp_path
379+ ) -> None :
380+ agent_id = "codex-controller-gated"
381+ status_payload = {
382+ "ok" : True ,
383+ "attention_queue" : {
384+ "items" : [
385+ {
386+ "goal_id" : "controller-gated-goal" ,
387+ "waiting_on" : "controller" ,
388+ "operator_question" : "Resolve this scoped controller gate?" ,
389+ }
390+ ]
391+ },
392+ }
393+ patch_manager_reads (
394+ monkeypatch ,
395+ status_payload = status_payload ,
396+ quota_payloads = {
397+ "controller-gated-goal" : controller_quota (
398+ "controller-gated-goal" , agent_id = agent_id
399+ )
400+ },
401+ )
402+
403+ payload = build_global_gates (tmp_path , agent_id = agent_id )
404+
405+ assert [gate ["goal_id" ] for gate in payload ["gates" ]] == [
406+ "controller-gated-goal"
407+ ]
408+ assert payload ["gates" ][0 ]["owner" ] == "controller"
409+ assert payload ["lanes" ][0 ]["status" ] == "operator_gate"
410+ assert payload ["groups" ]["blocked_work" ] == payload ["lanes" ]
411+
412+
333413def test_global_gates_filters_every_group_to_requested_agent (monkeypatch , tmp_path ) -> None :
334414 status_payload = {
335415 "ok" : True ,
0 commit comments