Shameless Green
Shameless Green: the 99 Bottles discipline applied to a plan. Step zero is one god task that does everything - and it's GREEN, and we are not ashamed, because green output pinned as a golden master is what buys every move after it. Then the refactoring loop: extract ONE responsibility per step, re-run the whole plan, and compare output byte-for-byte. A step that "improves the design" while changing the answer is not a refactoring - it's a bug with good posture, and the …
Testing & Verification
Round 17
Sandi Metz
exit 0
bundle exec ruby examples/shameless_green.rb
a real captured run
SHAMELESS GREEN (first make it work, then make it right - PROVABLY right)
tasks max ops/task depth referee
step 0 shameless green 1 4 2 output pinned as GOLDEN
step 1 extract the I/O edge 2 3 3 identical output - refactoring, certified
step 2 extract calculation 3 2 4 REJECTED: output changed ("7 tickets, 2 bugs, busiest: wed") - rolled back
step 2' extract calculation 3 2 4 identical output - refactoring, certified
step 3 one job per task 4 1 5 identical output - refactoring, certified
the arc is 99 Bottles, one abstraction up: step 0 is unashamed -
a god task, but GREEN, and pinned as the golden master that funds
every later move. each extraction removes exactly one
responsibility (watch max ops/task fall 4, 3, 2, 1 while depth
grows - the design metrics are computed from the shape, not
asserted by the author). and step 2 is the whole sermon: an
extraction that 'cleaned up' the counting changed the bug count,
the golden master caught it, the step was rejected, the rope
held. refactoring is changing the arrangement of code while
PROVING the behavior stands still; without the proof it's just
editing with confidence.
source
# frozen_string_literal: true # Shameless Green: the 99 Bottles discipline applied to a plan. Step # zero is one god task that does everything - and it's GREEN, and we # are not ashamed, because green output pinned as a golden master is # what buys every move after it. Then the refactoring loop: extract # ONE responsibility per step, re-run the whole plan, and compare # output byte-for-byte. A step that "improves the design" while # changing the answer is not a refactoring - it's a bug with good # posture, and the referee rejects it. Design metrics (tasks, max # responsibilities per task, graph depth) are computed, not asserted. # # bundle exec ruby examples/shameless_green.rb # # Runs offline; one extraction is deliberately botched to prove the # rope holds. Exit 1 unless the final shape is single-responsibility # AND the output never changed. require class="s">"bundler/setup" require class="s">"agentic" Agentic.logger.level = class="y">:fatal TICKETS = [ {id: 1, kind: class="y">:bug, day: class="s">"wed"}, {id: 2, kind: class="y">:feature, day: class="s">"mon"}, {id: 3, kind: class="y">:bug, day: class="s">"wed"}, {id: 4, kind: class="y">:chore, day: class="s">"fri"}, {id: 5, kind: class="y">:bug, day: class="s">"wed"}, {id: 6, kind: class="y">:feature, day: class="s">"tue"}, {id: 7, kind: class="y">:chore, day: class="s">"wed"} ].freeze # The four responsibilities, as sharable lambdas - each version of # the plan differs only in how many live in one task FETCH = ->(_) { TICKETS } COUNT = ->(tickets) { {total: tickets.size, bugs: tickets.count { |t| t[class="y">:kind] == class="y">:bug }, busiest: tickets.group_by { |t| t[class="y">:day] }.max_by { |_, v| v.size }.first} } BUGGY_COUNT = ->(tickets) { {total: tickets.size, bugs: tickets.count { |t| t[class="y">:kind] == class="y">:bug } - 1, busiest: class="s">"wed"} } # the botched extraction FORMAT = ->(stats) { class="s">"#{stats[class="y">:total]} tickets, #{stats[class="y">:bugs]} bugs, busiest: #{stats[class="y">:busiest]}" } RENDER = ->(line) { class="s">"== WEEKLY REPORT ==\n#{line}" } # Each step: stages, where a stage is {name:, ops: [lambdas]} - a # task per stage, responsibilities per task COUNTED from the data STEPS = [ {label: class="s">"step 0 shameless green", stages: [{name: class="s">"do everything", ops: [FETCH, COUNT, FORMAT, RENDER]}]}, {label: class="s">"step 1 extract the I/O edge", stages: [{name: class="s">"fetch", ops: [FETCH]}, {name: class="s">"the rest", ops: [COUNT, FORMAT, RENDER]}]}, {label: class="s">"step 2 extract calculation", stages: [{name: class="s">"fetch", ops: [FETCH]}, {name: class="s">"count", ops: [BUGGY_COUNT]}, {name: class="s">"present", ops: [FORMAT, RENDER]}]}, {label: class="s">"step 2' extract calculation", stages: [{name: class="s">"fetch", ops: [FETCH]}, {name: class="s">"count", ops: [COUNT]}, {name: class="s">"present", ops: [FORMAT, RENDER]}]}, {label: class="s">"step 3 one job per task", stages: [{name: class="s">"fetch", ops: [FETCH]}, {name: class="s">"count", ops: [COUNT]}, {name: class="s">"format", ops: [FORMAT]}, {name: class="s">"render", ops: [RENDER]}]} ].freeze def run_shape(stages) orchestrator = Agentic:class="y">:PlanOrchestrator.new(concurrency_limit: 2) previous = nil last = nil stages.each do |stage| task = Agentic:class="y">:Task.new(description: stage[class="y">:name], agent_spec: {class="s">"name" => stage[class="y">:name], class="s">"instructions" => class="s">"w"}) orchestrator.add_task(task, previous ? [previous] : [], agent: ->(t) { stage[class="y">:ops].inject(t.previous_output) { |acc, op| op.call(acc) } }) previous = task last = task end result = orchestrator.execute_plan [result.task_result(last.id).output, orchestrator.graph[class="y">:stats]] end puts class="s">"SHAMELESS GREEN (first make it work, then make it right - PROVABLY right)" puts puts format(class="s">" %-30s %-7s %-14s %-7s %s", class="s">"", class="s">"tasks", class="s">"max ops/task", class="s">"depth", class="s">"referee") golden = nil rejected = 0 final_output = nil final_max_ops = nil STEPS.each do |step| output, stats = run_shape(step[class="y">:stages]) max_ops = step[class="y">:stages].map { |s| s[class="y">:ops].size }.max verdict = if golden.nil? golden = output class="s">"output pinned as GOLDEN" elsif output == golden final_output = output final_max_ops = max_ops class="s">"identical output - refactoring, certified" else rejected += 1 class="s">"REJECTED: output changed (#{output.lines.last.strip.inspect}) - rolled back" end puts format(class="s">" %-30s %-7d %-14d %-7d %s", step[class="y">:label], step[class="y">:stages].size, max_ops, stats[class="y">:max_depth] + 1, verdict) end puts puts class="s">" the arc is 99 Bottles, one abstraction up: step 0 is unashamed -" puts class="s">" a god task, but GREEN, and pinned as the golden master that funds" puts class="s">" every later move. each extraction removes exactly one" puts class="s">" responsibility (watch max ops/task fall 4, 3, 2, 1 while depth" puts class="s">" grows - the design metrics are computed from the shape, not" puts class="s">" asserted by the author). and step 2 is the whole sermon: an" puts class="s">" extraction that 'cleaned up' the counting changed the bug count," puts class="s">" the golden master caught it, the step was rejected, the rope" puts class="s">" held. refactoring is changing the arrangement of code while" puts class="s">" PROVING the behavior stands still; without the proof it's just" puts class="s">" editing with confidence." exit((final_output == golden && final_max_ops == 1 && rejected == 1) ? 0 : 1)