The Terminal Band
The Terminal Band: a one-computer band where every instrument is a task. Four players compose their parts IN PARALLEL (they've played together for years; the chord chart is the only coordination), a mixer task fans them in by name, and then the part every real band needs: a harmony referee that checks every tick for dissonance and names the player responsible. This band once had a theremin. Once.
Fun & Strange
Round 18
Aaron Patterson
exit 0
bundle exec ruby examples/terminal_band.rb
a real captured run
THE TERMINAL BAND (four players, one chart, zero rehearsals)
set one, with the full lineup:
tick bass melody harmony theremin
0 C C E .
1 C E G .
2 C G C .
3 C C E F#
4 F A C .
5 F C F .
6 F F A .
7 F A C B
8 G D G .
9 G G B .
10 G B D .
11 G D G C#
12 C C E .
13 C E G .
14 C G C .
15 C C E F#
referee: dissonance at ticks 3, 7, 11, 15 - and removing only
"theremin" resolves every one of them. it's not you, theremin,
it's your tritones. (it's also you.)
set two, as a trio:
tick bass melody harmony
0 C C E
1 C E G
2 C G C
3 C C E
4 F A C
5 F C F
6 F F A
7 F A C
8 G D G
9 G G B
10 G B D
11 G D G
12 C C E
13 C E G
14 C G C
15 C C E
referee: sixteen ticks, zero dissonance - the band is TIGHT
the joke is load-bearing: the players composed in PARALLEL with
no shared state but the chord chart - the same trick as any
fan-out plan, where the contract (I-IV-V-I) replaces coordination.
the mixer read every part BY NAME (needs:), and the referee is a
falsifiable claim about the combined output, per tick, with BLAME
ATTRIBUTION - remove one input at a time until the property
holds, which is bisection wearing a bow tie. also we fired a
theremin over math. extremely our band.
source
# frozen_string_literal: true # The Terminal Band: a one-computer band where every instrument is a # task. Four players compose their parts IN PARALLEL (they've played # together for years; the chord chart is the only coordination), a # mixer task fans them in by name, and then the part every real band # needs: a harmony referee that checks every tick for dissonance and # names the player responsible. This band once had a theremin. Once. # # bundle exec ruby examples/terminal_band.rb # # Runs offline; exits 1 unless the final mix is consonant AND the # referee correctly identified whom to fire. require class="s">"bundler/setup" require class="s">"agentic" Agentic.logger.level = class="y">:fatal NOTE_NAMES = %w[C C# D D# E F F# G G# A A# B].freeze CHART = [[0, 4, 7], [5, 9, 0], [7, 11, 2], [0, 4, 7]].freeze # I-IV-V-I in C, as pitch classes TICKS = 16 DISSONANT = [1, 2, 6, 10, 11].freeze # the intervals that get you fired def name_of(pitch) = pitch ? NOTE_NAMES[pitch % 12] : class="s">"." def chord_at(tick) = CHART[tick / 4] # --- the players (each composes alone; the chart keeps them honest) ---------------- PLAYERS = { class="s">"bass" => ->(_t) { TICKS.times.map { |i| chord_at(i)[0] } }, # roots, always roots class="s">"melody" => ->(_t) { TICKS.times.map { |i| chord_at(i)[i % 3] } }, # arpeggios, feeling fancy class="s">"harmony" => ->(_t) { TICKS.times.map { |i| chord_at(i)[(i + 1) % 3] } }, # a chord tone above class="s">"theremin" => ->(_t) { TICKS.times.map { |i| (i % 4 == 3) ? chord_at(i)[0] + 6 : nil } } # class="s">"it's called ART" }.freeze def band_plays(roster) orchestrator = Agentic:class="y">:PlanOrchestrator.new(concurrency_limit: 4) tracks = roster.to_h do |name| task = Agentic:class="y">:Task.new(description: name, agent_spec: {class="s">"name" => name, class="s">"instructions" => class="s">"play"}) orchestrator.add_task(task, agent: PLAYERS[name]) [name, task] end mixer = Agentic:class="y">:Task.new(description: class="s">"mixer", agent_spec: {class="s">"name" => class="s">"mixer", class="s">"instructions" => class="s">"mix"}) orchestrator.add_task(mixer, needs: tracks.transform_values(&class="y">:itself), agent: ->(t) { roster.to_h { |name| [name, t.needs.public_send(name)] } }) orchestrator.execute_plan.task_result(mixer.id).output end # The referee: flag every dissonant tick, then find the one player # whose silence resolves ALL of them - that's who gets the phone call def referee(mix) clashes = TICKS.times.select do |i| sounding = mix.values.map { |part| part[i] }.compact.map { |p| p % 12 }.uniq sounding.combination(2).any? { |a, b| DISSONANT.include?((a - b) % 12) || DISSONANT.include?((b - a) % 12) } end return [clashes, nil] if clashes.empty? culprit = mix.keys.find do |name| rest = mix.reject { |k, _| k == name } clashes.none? do |i| sounding = rest.values.map { |part| part[i] }.compact.map { |p| p % 12 }.uniq sounding.combination(2).any? { |a, b| DISSONANT.include?((a - b) % 12) || DISSONANT.include?((b - a) % 12) } end end [clashes, culprit] end def print_tracker(mix) puts class="s">" tick #{mix.keys.map { |k| k[0, 8].ljust(8) }.join}" TICKS.times do |i| puts class="s">" %4d %s" % [i, mix.keys.map { |k| name_of(mix[k][i]).ljust(8) }.join] end end puts class="s">"THE TERMINAL BAND (four players, one chart, zero rehearsals)" puts mix = band_plays(PLAYERS.keys) clashes, culprit = referee(mix) puts class="s">" set one, with the full lineup:" print_tracker(mix) puts puts class="s">" referee: dissonance at ticks #{clashes.join(", class="s">")} - and removing only" puts class="s">" #{culprit.inspect} resolves every one of them. it's not you, theremin," puts class="s">" it's your tritones. (it's also you.)" puts fired_correctly = (culprit == class="s">"theremin") mix2 = band_plays(PLAYERS.keys - [culprit]) clashes2, = referee(mix2) puts class="s">" set two, as a trio:" print_tracker(mix2) puts puts class="s">" referee: #{clashes2.empty? ? "sixteen ticks, zero dissonance - the band is TIGHTclass="s">" : "STILL dissonant at #{clashes2.join(class="s">", ")}class="s">"}" puts puts class="s">" the joke is load-bearing: the players composed in PARALLEL with" puts class="s">" no shared state but the chord chart - the same trick as any" puts class="s">" fan-out plan, where the contract (I-IV-V-I) replaces coordination." puts class="s">" the mixer read every part BY NAME (needs:), and the referee is a" puts class="s">" falsifiable claim about the combined output, per tick, with BLAME" puts class="s">" ATTRIBUTION - remove one input at a time until the property" puts class="s">" holds, which is bisection wearing a bow tie. also we fired a" puts class="s">" theremin over math. extremely our band." exit((fired_correctly && clashes2.empty? && clashes.any?) ? 0 : 1)