Size coordination workplans by chokepoint in-degree (RAIL-FAB-WP-0029-T01).
Coordination nodes and edges now carry visualSize and edgeWidth, which the explorer styles already read. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 7458@bnt-lap001 Assistant-Session: 62534cdf-8348-48a7-9c0d-46e0f74c8eae
This commit is contained in:
parent
a9e677986a
commit
7dd4b062a8
2 changed files with 27 additions and 2 deletions
|
|
@ -66,6 +66,18 @@ def _indexed_depends_targets(workplan: dict[str, Any]) -> list[str]:
|
||||||
return targets
|
return targets
|
||||||
|
|
||||||
|
|
||||||
|
TASK_NODE_SIZE = 26
|
||||||
|
WORKPLAN_BASE_SIZE = 44
|
||||||
|
WORKPLAN_SIZE_STEP = 10
|
||||||
|
WORKPLAN_SIZE_CAP = 8
|
||||||
|
|
||||||
|
|
||||||
|
def chokepoint_size(in_degree: int) -> int:
|
||||||
|
"""Grow workplan nodes with the number of open items waiting on them."""
|
||||||
|
|
||||||
|
return WORKPLAN_BASE_SIZE + WORKPLAN_SIZE_STEP * min(max(in_degree, 0), WORKPLAN_SIZE_CAP)
|
||||||
|
|
||||||
|
|
||||||
def coordination_graph_payload(
|
def coordination_graph_payload(
|
||||||
workplans: list[dict[str, Any]],
|
workplans: list[dict[str, Any]],
|
||||||
tasks: list[dict[str, Any]],
|
tasks: list[dict[str, Any]],
|
||||||
|
|
@ -153,6 +165,7 @@ def coordination_graph_payload(
|
||||||
"needsHuman": human,
|
"needsHuman": human,
|
||||||
"displayState": "highlight" if status == "wait" or human else "show",
|
"displayState": "highlight" if status == "wait" or human else "show",
|
||||||
"unresolved": status == "wait" or human,
|
"unresolved": status == "wait" or human,
|
||||||
|
"visualSize": TASK_NODE_SIZE,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
@ -254,11 +267,16 @@ def coordination_graph_payload(
|
||||||
indexed_pairs.add((src_wp, dst))
|
indexed_pairs.add((src_wp, dst))
|
||||||
|
|
||||||
for el in elements:
|
for el in elements:
|
||||||
node_id = el["data"]["id"]
|
data = el["data"]
|
||||||
|
if data.get("kind") == "Edge":
|
||||||
|
data.setdefault("edgeWidth", 3 if data.get("edgeType") in {"depends_on", "waits_on"} else 1.5)
|
||||||
|
continue
|
||||||
|
node_id = data["id"]
|
||||||
if not node_id.startswith("workplan:"):
|
if not node_id.startswith("workplan:"):
|
||||||
continue
|
continue
|
||||||
wp_id = node_id.split(":", 1)[1]
|
wp_id = node_id.split(":", 1)[1]
|
||||||
el["data"]["chokepoint"] = int(chokepoint.get(wp_id) or 0)
|
data["chokepoint"] = int(chokepoint.get(wp_id) or 0)
|
||||||
|
data["visualSize"] = chokepoint_size(data["chokepoint"])
|
||||||
|
|
||||||
generated = datetime.now(timezone.utc).isoformat()
|
generated = datetime.now(timezone.utc).isoformat()
|
||||||
return {
|
return {
|
||||||
|
|
|
||||||
|
|
@ -158,6 +158,13 @@ def test_indexed_depends_on_outranks_citation_fallback() -> None:
|
||||||
if el["data"]["id"] == "workplan:wp-b"
|
if el["data"]["id"] == "workplan:wp-b"
|
||||||
)
|
)
|
||||||
assert chokepoint == 1
|
assert chokepoint == 1
|
||||||
|
sizes = {
|
||||||
|
el["data"]["id"]: el["data"]["visualSize"]
|
||||||
|
for el in payload["elements"]
|
||||||
|
if el["data"]["id"].startswith("workplan:")
|
||||||
|
}
|
||||||
|
assert sizes["workplan:wp-b"] > sizes["workplan:wp-a"]
|
||||||
|
assert all(e["edgeWidth"] > 0 for e in edges)
|
||||||
|
|
||||||
|
|
||||||
def test_canonical_id_depends_on_resolves_to_hub_uuid() -> None:
|
def test_canonical_id_depends_on_resolves_to_hub_uuid() -> None:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue