{"id":"schedule-critical-path","version":"1.0.0","description":"Compute CPM zero-slack critical nodes and tight edges on a DAG, plus one representative critical path.","supported_operations":["schedule critical path","cpm zero-slack critical path","critical nodes edges and representative path"],"unsupported_operations":["multiple enumerated critical paths","probabilistic PERT","crashing","calendar dates and working hours"],"semantics":["Input is a directed simple graph plus durations whose own keys are exactly the node ids, each a canonical non-negative integer string of at most 18 digits.","Edge from→to is finish-to-start with lag 0: to cannot start before from finishes.","The graph must be a DAG under Kahn order (smallest remaining indegree-0 declared index); a cycle including a self-loop throws invalid_input with a message containing cycle.","ES[v] is 0 if v has no predecessors, else the maximum EF of its predecessors. EF[v] is ES[v] plus duration[v]. Times that exceed 18 digits throw.","makespan is the maximum EF, or 0 when there are no nodes.","Latest times walk the Kahn sequence backwards: LF[v] is makespan if v has no successors, else the minimum LS of its successors. LS[v] is LF[v] minus duration[v].","Slack is LS minus ES (equal to LF minus EF). A node is critical iff its slack is 0.","critical_nodes lists slack-0 ids in declared nodes order.","critical_edges lists original edges in original edge order whose both ends are critical and EF[from] equals ES[to].","The representative path is empty on the empty graph. Otherwise it starts at the smallest-index critical node with no incoming critical tight edge, then repeatedly appends the smallest-index successor reached by a critical tight edge."],"limits":{"max_nodes":2000,"max_edges":10000,"max_node_id_bytes":256,"max_duration_digits":18},"pricing":{"status":"unpriced","charge_usd":null},"input_schema":{"type":"object","additionalProperties":false,"required":["nodes","edges","durations"],"properties":{"nodes":{"type":"array","maxItems":2000,"items":{"type":"string","minLength":1,"maxLength":256}},"edges":{"type":"array","maxItems":10000,"items":{"type":"object","additionalProperties":false,"required":["from","to"],"properties":{"from":{"type":"string","minLength":1,"maxLength":256},"to":{"type":"string","minLength":1,"maxLength":256}}}},"durations":{"type":"object","additionalProperties":{"type":"string","pattern":"^(0|[1-9][0-9]*)$","maxLength":18}}}},"output_schema":{"type":"object","additionalProperties":false,"required":["makespan","critical_nodes","critical_edges","path"],"properties":{"makespan":{"type":"string","pattern":"^(0|[1-9][0-9]*)$","maxLength":18},"critical_nodes":{"type":"array","maxItems":2000,"items":{"type":"string","minLength":1,"maxLength":256}},"critical_edges":{"type":"array","maxItems":10000,"items":{"type":"object","additionalProperties":false,"required":["from","to"],"properties":{"from":{"type":"string","minLength":1,"maxLength":256},"to":{"type":"string","minLength":1,"maxLength":256}}}},"path":{"type":"array","maxItems":2000,"items":{"type":"string","minLength":1,"maxLength":256}}}},"examples":[{"input":{"nodes":["spec","api","ui","integ","ship"],"edges":[{"from":"spec","to":"api"},{"from":"spec","to":"ui"},{"from":"api","to":"integ"},{"from":"ui","to":"integ"},{"from":"integ","to":"ship"}],"durations":{"spec":"2","api":"5","ui":"3","integ":"4","ship":"1"}},"output":{"makespan":"12","critical_nodes":["spec","api","integ","ship"],"critical_edges":[{"from":"spec","to":"api"},{"from":"api","to":"integ"},{"from":"integ","to":"ship"}],"path":["spec","api","integ","ship"]}}],"execute_url":"/v1/tools/schedule-critical-path/versions/1.0.0/execute"}