The Plan Diagrammer
The Plan Diagrammer: any orchestrator's graph, emitted as Mermaid - paste it into a README, GitHub renders it, and the diagram can never drift from the plan because it is generated FROM the plan.
Developer Experience
Round 5
Xavier Noria
exit 0
bundle exec ruby examples/plan_diagram.rb
a real captured run
```mermaid graph TD T0["research topic"] T1["draft outline"] T2["verify sources"] T3["write draft"] T4["publish"] T0 --> T1 T0 --> T2 T1 -- skeleton --> T3 T2 -- citations --> T3 T3 --> T4 ``` paste the block above into any GitHub markdown file. the arrows labeled 'skeleton' and 'citations' are the named dependencies - the diagram documents not just THAT draft waits, but WHY.
source
# frozen_string_literal: true # The Plan Diagrammer: any orchestrator's graph, emitted as Mermaid - # paste it into a README, GitHub renders it, and the diagram can never # drift from the plan because it is generated FROM the plan. # # bundle exec ruby examples/plan_diagram.rb # # Runs offline; prints Mermaid source. Named dependencies become # labeled edges; plain dependencies become arrows. require class="s">"bundler/setup" require class="s">"agentic" # A representative plan: the editorial pipeline with a named fan-in orchestrator = Agentic:class="y">:PlanOrchestrator.new def step(name) Agentic:class="y">:Task.new(description: name, agent_spec: {class="s">"name" => name, class="s">"instructions" => class="s">"work"}) end research = step(class="s">"research topic") outline = step(class="s">"draft outline") sources = step(class="s">"verify sources") draft = step(class="s">"write draft") publish = step(class="s">"publish") orchestrator.add_task(research) orchestrator.add_task(outline, [research]) orchestrator.add_task(sources, [research]) orchestrator.add_task(draft, needs: {skeleton: outline, citations: sources}) orchestrator.add_task(publish, [draft]) # --- the diagrammer: graph in, mermaid out ----------------------------------- # graph[:edges] arrives pre-merged with labels and graph[:order] gives # stable, topological node numbering - both were this example's asks. def to_mermaid(graph) names = graph[class="y">:tasks].transform_values(&class="y">:description) ids = graph[class="y">:order].each_with_index.to_h { |task_id, i| [task_id, class="s">"T#{i}"] } lines = [class="s">"graph TD"] graph[class="y">:order].each { |task_id| lines << class="s">" #{ids[task_id]}[\"#{names[task_id]}\class="s">"]" } graph[class="y">:edges].each do |edge| arrow = edge[class="y">:label] ? class="s">"-- #{edge[class="y">:label]} -->" : class="s">"-->" lines << class="s">" #{ids[edge[class="y">:from]]} #{arrow} #{ids[edge[class="y">:to]]}" end lines.join(class="s">"\n") end mermaid = to_mermaid(orchestrator.graph) puts class="s">"```mermaid" puts mermaid puts class="s">"```" puts puts class="s">"paste the block above into any GitHub markdown file. the arrows" puts class="s">"labeled 'skeleton' and 'citations' are the named dependencies -" puts class="s">"the diagram documents not just THAT draft waits, but WHY."