agentic examples

The Assembly Doctor

The Assembly Doctor: syntax_suggest for plans. When a 12-step plan won't assemble, "KeyError: task not found" is technically true the way "syntax error, unexpected end" is technically true - it names the symptom and hides the street address. The doctor examines a broken plan spec the way syntax_suggest examines a broken file: find the smallest region that explains the failure, SHOW it with an arrow pointing at the problem, and suggest the one-keystroke fix when the framework …

Developer Experience Round 17 Richard Schneeman exit 0

source on github

bundle exec ruby examples/assembly_doctor.rb

a real captured run

THE ASSEMBLY DOCTOR (error messages are the UI of failure)

  examining the 5pm deploy plan (8 steps): 2 wounds found

  Unmatched dependency, in step 5:
       4  "fetch metadata"
    >  5  "upload assets"  after: "fetch metdata"
                                  ^^^^^^^^^^^^^^^ no step has this name (did you mean fetch metadata?)

  Dependency cycle - the plan can never start:
    >  run migrations -> verify health -> restart app -> run migrations
       every member of the loop waits for another member. one of
       these edges is aspirational, not structural - probably the
       newest one.

  after the two one-line fixes: doctor finds nothing; plan runs: completed

  the doctor's rules are syntax_suggest's rules, one abstraction up:
  don't report the symptom's location, report the SMALLEST REGION
  that explains it (the typo'd edge, the whole loop); show the code,
  not a stack trace; and when the system is holding the list of
  valid names - it always is - spend one Levenshtein pass to turn
  the diagnosis into a one-keystroke fix. the framework's own
  Suggestions module supplied the did-you-mean. people don't quit
  because programming is hard; they quit because failure is rude.

source

# frozen_string_literal: true

# The Assembly Doctor: syntax_suggest for plans. When a 12-step plan
# won't assemble, "KeyError: task not found" is technically true the
# way "syntax error, unexpected end" is technically true - it names
# the symptom and hides the street address. The doctor examines a
# broken plan spec the way syntax_suggest examines a broken file:
# find the smallest region that explains the failure, SHOW it with
# an arrow pointing at the problem, and suggest the one-keystroke
# fix when the framework can see it. Error messages are the UI of
# failure, and failure is most of programming.
#
#   bundle exec ruby examples/assembly_doctor.rb
#
# Runs offline; diagnoses two classic assembly wounds, then proves
# the repaired plan actually runs.

require class="s">"bundler/setup"
require class="s">"agentic"

Agentic.logger.level = class="y">:fatal

# A deploy pipeline, written by a human at 5pm: one typo'd dependency
# name, and one cycle added during a hasty refactor
PLAN = [
  {step: class="s">"checkout code"},
  {step: class="s">"install deps", after: [class="s">"checkout code"]},
  {step: class="s">"compile assets", after: [class="s">"install deps"]},
  {step: class="s">"fetch metadata", after: [class="s">"checkout code"]},
  {step: class="s">"upload assets", after: [class="s">"compile assets", class="s">"fetch metdata"]}, # <- 5pm
  {step: class="s">"run migrations", after: [class="s">"install deps", class="s">"verify health"]},  # <- the refactor
  {step: class="s">"restart app", after: [class="s">"run migrations", class="s">"upload assets"]},
  {step: class="s">"verify health", after: [class="s">"restart app"]}
].freeze

# --- the doctor -------------------------------------------------------------------
def diagnose(plan)
  names = plan.map { |s| s[class="y">:step] }
  findings = []

  # Wound 1: dependencies that name no step (with the framework's own
  # did-you-mean pass - the plan is holding the list of valid names)
  plan.each_with_index do |step, i|
    Array(step[class="y">:after]).each do |dep|
      next if names.include?(dep)
      findings << {kind: class="s">"unmatched dependency", snippet: [i, dep],
                   hint: Agentic:class="y">:Suggestions.hint(dep, names)}
    end
  end

  # Wound 2: cycles - shown as the LOOP itself, not as a deadlocked
  # hang. Depth-first search finds a member; walking dependencies that
  # still reach the origin reconstructs the loop for display
  deps_of = ->(name) { Array(plan.find { |s| s[class="y">:step] == name }&.dig(class="y">:after)) }
  reaches = ->(from, target, seen) {
    return false if seen.include?(from)
    deps_of.call(from).include?(target) ||
      deps_of.call(from).any? { |d| reaches.call(d, target, seen + [from]) }
  }
  cycle_member = names.find { |n| reaches.call(n, n, []) }
  if cycle_member
    loop_path = [cycle_member]
    until loop_path.size > 1 && loop_path.last == cycle_member
      loop_path << deps_of.call(loop_path.last).find { |d| d == cycle_member || reaches.call(d, cycle_member, []) }
    end
    findings << {kind: class="s">"dependency cycle", snippet: loop_path}
  end

  findings
end

def print_diagnosis(plan, findings)
  findings.each do |f|
    case f[class="y">:kind]
    when class="s">"unmatched dependency"
      i, dep = f[class="y">:snippet]
      line = class="s">"    >  #{i + 1}  #{plan[i][class="y">:step].inspect}  after: #{dep.inspect}"
      puts class="s">"  Unmatched dependency, in step #{i + 1}:"
      puts class="s">"       #{i}  #{plan[i - 1][class="y">:step].inspect}"
      puts line
      puts class="s">"#{" class="s">" * line.index(dep.inspect)}#{"^class="s">" * dep.inspect.size} no step has this name#{f[class="y">:hint]}"
    when class="s">"dependency cycle"
      puts class="s">"  Dependency cycle - the plan can never start:"
      puts class="s">"    >  #{f[class="y">:snippet].join(" -> class="s">")}"
      puts class="s">"       every member of the loop waits for another member. one of"
      puts class="s">"       these edges is aspirational, not structural - probably the"
      puts class="s">"       newest one."
    end
    puts
  end
end

puts class="s">"THE ASSEMBLY DOCTOR (error messages are the UI of failure)"
puts
findings = diagnose(PLAN)
puts class="s">"  examining the 5pm deploy plan (#{PLAN.size} steps): #{findings.size} wounds found"
puts
print_diagnosis(PLAN, findings)

# --- the repaired plan must actually run - doctors get audited too -----------------
fixed = PLAN.map { |s| {step: s[class="y">:step], after: Array(s[class="y">:after]).map { |d| (d == class="s">"fetch metdata") ? class="s">"fetch metadata" : d } - [class="s">"verify health"]} }
fixed[5][class="y">:after] = [class="s">"install deps"] # run migrations no longer waits on verify health
abort(class="s">"  doctor still sees wounds in the fixed plan!") unless diagnose(fixed).empty?

orchestrator = Agentic:class="y">:PlanOrchestrator.new(concurrency_limit: 4)
tasks = {}
fixed.each do |s|
  tasks[s[class="y">:step]] = Agentic:class="y">:Task.new(description: s[class="y">:step], agent_spec: {class="s">"name" => s[class="y">:step], class="s">"instructions" => class="s">"go"})
  orchestrator.add_task(tasks[s[class="y">:step]], s[class="y">:after].map { |d| tasks.fetch(d) }, agent: ->(_t) { class="s">"ok" })
end
result = orchestrator.execute_plan

puts class="s">"  after the two one-line fixes: doctor finds nothing; plan runs: #{result.status}"
puts
puts class="s">"  the doctor's rules are syntax_suggest's rules, one abstraction up:"
puts class="s">"  don't report the symptom's location, report the SMALLEST REGION"
puts class="s">"  that explains it (the typo'd edge, the whole loop); show the code,"
puts class="s">"  not a stack trace; and when the system is holding the list of"
puts class="s">"  valid names - it always is - spend one Levenshtein pass to turn"
puts class="s">"  the diagnosis into a one-keystroke fix. the framework's own"
puts class="s">"  Suggestions module supplied the did-you-mean. people don't quit"
puts class="s">"  because programming is hard; they quit because failure is rude."
exit((findings.size == 2 && result.status == class="y">:completed) ? 0 : 1)