The Kanban Board
The Kanban Board: a plan rendered as the three columns everyone actually understands - To Do, Doing, Done - reprinted at every state change while the plan runs. No standup, no sync meeting, no PM tool subscription: the orchestrator IS the board.
Scheduling & Concurrency
Round 5
DHH
exit 0
bundle exec ruby examples/kanban_board.rb
a real captured run
KANBAN (12 board states, 303ms wall, 2 people on the team)
at the start:
TO DO DOING DONE
-------------- -------------- --------------
shoot photos write copy
edit photos
layout page
review
publish
mid-flight:
TO DO DOING DONE
-------------- -------------- --------------
review layout page write copy
publish shoot photos
edit photos
at the end:
TO DO DOING DONE
-------------- -------------- --------------
write copy
shoot photos
edit photos
layout page
review
publish
every frame above was captured live from lifecycle hooks - the
board is the plan's actual state, not somebody's memory of it.
source
# frozen_string_literal: true # The Kanban Board: a plan rendered as the three columns everyone # actually understands - To Do, Doing, Done - reprinted at every state # change while the plan runs. No standup, no sync meeting, no PM tool # subscription: the orchestrator IS the board. # # bundle exec ruby examples/kanban_board.rb # # Runs offline; watch the cards move. require class="s">"bundler/setup" require class="s">"agentic" CARDS = { class="s">"write copy" => 0.06, class="s">"shoot photos" => 0.10, class="s">"edit photos" => 0.05, class="s">"layout page" => 0.08, class="s">"review" => 0.04, class="s">"publish" => 0.03 }.freeze DEPS = { class="s">"edit photos" => [class="s">"shoot photos"], class="s">"layout page" => [class="s">"write copy", class="s">"edit photos"], class="s">"review" => [class="s">"layout page"], class="s">"publish" => [class="s">"review"] }.freeze board = {todo: CARDS.keys.dup, doing: [], done: []} frames = [] move = lambda do |card, from, to| board[from].delete(card) board[to] << card columns = [class="y">:todo, class="y">:doing, class="y">:done].map { |col| board[col] } height = columns.map(&class="y">:size).max frame = +class="s">" %-16s %-16s %-16s\n" % [class="s">"TO DO", class="s">"DOING", class="s">"DONE"] frame << class="s">" #{"-class="s">" * 14} #{"-class="s">" * 14} #{"-class="s">" * 14}\n" height.times do |i| frame << (class="s">" %-16s %-16s %-16s\n" % columns.map { |col| col[i] || class="s">"" }) end frames << frame end hooks = { task_slot_acquired: ->(task_id:, task:, waited:) { move.call(task.description, class="y">:todo, class="y">:doing) }, after_task_success: ->(task_id:, task:, result:, duration:) { move.call(task.description, class="y">:doing, class="y">:done) } } orchestrator = Agentic:class="y">:PlanOrchestrator.new(concurrency_limit: 2, lifecycle_hooks: hooks) tasks = {} CARDS.each do |name, duration| tasks[name] = Agentic:class="y">:Task.new( description: name, agent_spec: {class="s">"name" => name, class="s">"instructions" => class="s">"do the work"}, payload: duration ) orchestrator.add_task(tasks[name], (DEPS[name] || []).map { |d| tasks.fetch(d) }, agent: ->(t) { sleep(t.payload) || class="y">:done }) end result = orchestrator.execute_plan puts class="s">"KANBAN (#{frames.size} board states, #{(result.execution_time * 1000).round}ms wall, 2 people on the team)" puts # Show the opening, one mid-flight frame, and the final board [frames.first, frames[frames.size / 2], frames.last].each_with_index do |frame, i| puts [class="s">"at the start:", class="s">"mid-flight:", class="s">"at the end:"][i] puts frame end puts class="s">"every frame above was captured live from lifecycle hooks - the" puts class="s">"board is the plan's actual state, not somebody's memory of it."