Stability: stable, tied to acop-orchestration/1.0. This document is
non-normative. It provides reference queries against the OPTIONAL graph
projection described in
acop-orchestration.md ยง graph-friendly projection.
An implementation that does not project orchestration state into a graph is
fully conformant and can ignore this document entirely.
Queries here are illustrative. Where a query and acop-orchestration.md disagree about release semantics, the specification wins.
This document provides a first reusable Cypher query pack for ACOP orchestration state projected into the graph projection layer.
The goal is not to define every future query shape. The goal is to establish the minimum practical queries an orchestration middleware, MCP surface, or lead agent would immediately want:
This assumes the orchestration projection described in:
This pack assumes the following node and edge families exist:
OrchestrationFlowOrchestrationStageOrchestrationLaneOrchestrationGateAcceptanceRecordWorkItemand:
HAS_STAGEHAS_LANEHAS_GATEFLOWS_TORELEASESACCEPTSIMPLEMENTS_FLOW_UNITProperty names are illustrative. Adapt them to the final persisted graph contract.
Question:
MATCH (lane:OrchestrationLane)
MATCH (work:WorkItem)-[:IMPLEMENTS_FLOW_UNIT]->(lane)
WHERE work.status = 'completed'
OPTIONAL MATCH (accept:AcceptanceRecord)-[:ACCEPTS]->(lane)
WITH lane, collect(accept.acceptance_status) AS acceptance_states
WHERE size(acceptance_states) = 0
OR all(state IN acceptance_states WHERE state <> 'accepted' AND state <> 'released')
RETURN
lane.lane_id AS lane_id,
lane.title AS lane_title,
acceptance_states
ORDER BY lane_id;
Question:
MATCH (gate:OrchestrationGate)
OPTIONAL MATCH (accept:AcceptanceRecord)-[:ACCEPTS]->(gate)
WITH gate, collect(accept.acceptance_status) AS acceptance_states
WHERE size(acceptance_states) = 0
OR all(state IN acceptance_states WHERE state <> 'accepted' AND state <> 'released')
RETURN
gate.gate_id AS gate_id,
gate.title AS gate_title,
gate.gate_kind AS gate_kind,
acceptance_states
ORDER BY gate_id;
Question:
MATCH (gate:OrchestrationGate)-[:RELEASES]->(stage:OrchestrationStage)
OPTIONAL MATCH (accept:AcceptanceRecord)-[:ACCEPTS]->(gate)
WITH gate, stage, collect(accept.acceptance_status) AS acceptance_states
WHERE size(acceptance_states) = 0
OR all(state IN acceptance_states WHERE state <> 'accepted' AND state <> 'released')
RETURN
stage.stage_id AS stage_id,
stage.title AS stage_title,
gate.gate_id AS blocking_gate_id,
gate.title AS blocking_gate_title
ORDER BY stage_id, blocking_gate_id;
Question:
MATCH (lane:OrchestrationLane)-[:FLOWS_TO]->(gate:OrchestrationGate)
OPTIONAL MATCH (accept:AcceptanceRecord)-[:ACCEPTS]->(lane)
WITH lane, gate, collect(accept.acceptance_status) AS acceptance_states
WHERE size(acceptance_states) = 0
OR all(state IN acceptance_states WHERE state <> 'accepted' AND state <> 'released')
RETURN
gate.gate_id AS gate_id,
gate.title AS gate_title,
lane.lane_id AS blocking_lane_id,
lane.title AS blocking_lane_title
ORDER BY gate_id, blocking_lane_id;
Question:
This query assumes blocked work items record orchestration blocker codes.
MATCH (work:WorkItem)
WHERE work.status = 'blocked'
AND work.blocker_code IN [
'upstream_gate_pending',
'upstream_stage_unreleased',
'acceptance_pending'
]
RETURN
work.work_item_id AS work_item_id,
work.title AS title,
work.blocker_code AS blocker_code,
work.summary AS summary
ORDER BY work_item_id;
Question:
MATCH (gate:OrchestrationGate)
OPTIONAL MATCH (lane:OrchestrationLane)-[:FLOWS_TO]->(gate)
OPTIONAL MATCH (accept:AcceptanceRecord)-[:ACCEPTS]->(lane)
WITH
gate,
collect(DISTINCT lane.lane_id) AS upstream_lane_ids,
collect(DISTINCT CASE
WHEN accept.acceptance_status IN ['accepted', 'released'] THEN lane.lane_id
ELSE null
END) AS accepted_lane_ids
WITH
gate,
[id IN upstream_lane_ids WHERE id IS NOT NULL] AS upstream_lane_ids,
[id IN accepted_lane_ids WHERE id IS NOT NULL] AS accepted_lane_ids
WHERE size(upstream_lane_ids) > 0
AND size(upstream_lane_ids) = size(accepted_lane_ids)
RETURN
gate.gate_id AS gate_id,
gate.title AS gate_title,
gate.gate_kind AS gate_kind
ORDER BY gate_id;
Question:
MATCH (flow:OrchestrationFlow {flow_id: $flow_id})
OPTIONAL MATCH (flow)-[:HAS_STAGE]->(stage:OrchestrationStage)
OPTIONAL MATCH (stage)-[:HAS_LANE]->(lane:OrchestrationLane)
OPTIONAL MATCH (stage)-[:HAS_GATE]->(gate:OrchestrationGate)
OPTIONAL MATCH (accept:AcceptanceRecord)-[:ACCEPTS]->(lane)
WITH
flow,
count(DISTINCT stage) AS stage_count,
count(DISTINCT lane) AS lane_count,
count(DISTINCT gate) AS gate_count,
count(DISTINCT CASE WHEN accept.acceptance_status IN ['accepted', 'released'] THEN lane END) AS accepted_lane_count
RETURN
flow.flow_id AS flow_id,
flow.title AS title,
stage_count,
lane_count,
gate_count,
accepted_lane_count;
The crucial distinction in orchestration graphs is:
completed work item status is necessaryaccepted orchestration status is what safely releases downstream workIf acceptance state is not written back into the graph projection layer, the graph cannot reliably answer the queries above, and agents will end up reconstructing orchestration truth from ad hoc notes or raw work-item completion events.