Add a State Hub workplan/wait graph as a Fabric explorer mode.
All checks were successful
CI Smoke / host-smoke (push) Successful in 1s
CI Smoke / container-smoke (push) Successful in 3s

Coordination is a view, not topology. Open workplans and wait tasks
project into graph-explorer; citation edges recover depends_on from
task prose. UI: /ui/graph-explorer?mode=coordination.

Assistant: grok
Assistant-Session: 01a09dc1-b21e-77e1-919e-fcad2f82b267
This commit is contained in:
codex 2026-09-14 13:07:42 +02:00
parent 18fabb37ce
commit b7724dedea
8 changed files with 366 additions and 2 deletions

View file

@ -25,6 +25,8 @@ LAYER_ORDER = (
"dependency",
"binding",
"library",
"workplan",
"task",
)
_KIND_LAYER = {
@ -41,6 +43,8 @@ _KIND_LAYER = {
"DependencyDeclaration": "dependency",
"BindingAssertion": "binding",
"Library": "library",
"Workplan": "workplan",
"Task": "task",
}
_LAYER_COLORS = {
@ -57,6 +61,8 @@ _LAYER_COLORS = {
"dependency": "#b45309",
"binding": "#be123c",
"library": "#0891b2",
"workplan": "#1d4ed8",
"task": "#c026d3",
}
_EDGE_STRENGTH = {
@ -303,6 +309,11 @@ def fabric_graph_explorer_manifest(base_url: str = "") -> dict[str, Any]:
"label": "Unresolved",
"description": "Highlight dependencies that have no accepted provider binding.",
},
{
"id": "coordination",
"label": "Workplan coordination",
"description": "State Hub open workplans and wait/human tasks. Not Fabric topology.",
},
],
"profile_persistence": "local",
"shareable_state": {
@ -486,6 +497,12 @@ def fabric_graph_explorer_payload(
for edge in source_edges:
source = source_repository_node_ids.get(str(edge.get("from", "")), str(edge.get("from", "")))
target = source_repository_node_ids.get(str(edge.get("to", "")), str(edge.get("to", "")))
for endpoint in (source, target):
if endpoint and endpoint not in node_layers:
elements.append(_unknown_node_element(endpoint))
node_layers[endpoint] = "unknown"
node_repos[endpoint] = ""
node_kinds[endpoint] = "Unknown"
edge_type = _presentation_edge_type(str(edge.get("type", "")), source, target, node_kinds)
if not source or not target:
continue
@ -1155,6 +1172,37 @@ def _node_description(kind: str, attributes: object) -> str:
return ""
def _unknown_node_element(node_id: str) -> dict[str, Any]:
"""Represent an unresolved edge endpoint without dropping the edge."""
return {
"data": {
"id": node_id,
"stableKey": f"unknown:{node_id}",
"kind": "Unknown",
"layer": "unknown",
"label": f"Unknown: {node_id}",
"name": node_id,
"description": "Referenced by a graph edge but not present in the accepted node set.",
"repo": "",
"domain": "",
"lifecycle": "unresolved",
"reviewState": "needs_review",
"freshnessState": "missing",
"unresolved": True,
"confidence": 0.0,
"visualSize": 38,
"ownership": "unknown",
"displayState": "show",
"visibilitySource": "default",
"visibilityReason": "unresolved edge endpoint",
"sourceReferences": [],
"deepLinks": {},
},
"classes": "unknown unresolved needs_review",
}
def _source_references(node: dict[str, Any]) -> list[dict[str, str]]:
attributes = node.get("attributes")
references: list[dict[str, str]] = []