robot_lab 0.0.6 → 0.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +86 -3
- data/README.md +99 -23
- data/Rakefile +39 -1
- data/docs/api/core/robot.md +130 -7
- data/docs/api/core/tool.md +28 -2
- data/docs/concepts.md +7 -3
- data/docs/examples/index.md +1 -1
- data/docs/examples/rails-application.md +1 -1
- data/docs/guides/building-robots.md +227 -11
- data/docs/guides/rails-integration.md +145 -17
- data/docs/guides/using-tools.md +45 -4
- data/docs/index.md +62 -6
- data/examples/05_streaming.rb +113 -94
- data/examples/16_writers_room/display.rb +2 -2
- data/examples/16_writers_room/output/.gitignore +2 -0
- data/examples/16_writers_room/output/README.md +69 -0
- data/examples/16_writers_room/output/opus_002.md +245 -0
- data/examples/16_writers_room/output/opus_002_notes.log +546 -0
- data/examples/16_writers_room/output/opus_002_screenplay.md +7989 -0
- data/examples/16_writers_room/output/opus_002_screenplay_notes.md +993 -0
- data/examples/16_writers_room/prompts/screenplay_writer.md +66 -0
- data/examples/16_writers_room/room.rb +72 -36
- data/examples/16_writers_room/tools.rb +19 -8
- data/examples/16_writers_room/writer.rb +1 -1
- data/examples/16_writers_room/writers_room.rb +120 -26
- data/examples/17_skills.rb +242 -0
- data/examples/18_rails/.envrc +3 -0
- data/examples/18_rails/.gitignore +5 -0
- data/examples/18_rails/Gemfile +10 -0
- data/examples/18_rails/README.md +48 -0
- data/examples/18_rails/Rakefile +4 -0
- data/examples/18_rails/app/controllers/application_controller.rb +4 -0
- data/examples/18_rails/app/controllers/chat_controller.rb +46 -0
- data/examples/18_rails/app/jobs/application_job.rb +4 -0
- data/examples/18_rails/app/jobs/robot_run_job.rb +79 -0
- data/examples/18_rails/app/models/application_record.rb +5 -0
- data/examples/18_rails/app/models/robot_lab_result.rb +36 -0
- data/examples/18_rails/app/models/robot_lab_thread.rb +23 -0
- data/examples/18_rails/app/robots/chat_robot.rb +14 -0
- data/examples/18_rails/app/tools/time_tool.rb +9 -0
- data/examples/18_rails/app/views/chat/_user_message.html.erb +1 -0
- data/examples/18_rails/app/views/chat/index.html.erb +67 -0
- data/examples/18_rails/app/views/layouts/application.html.erb +49 -0
- data/examples/18_rails/bin/dev +7 -0
- data/examples/18_rails/bin/rails +6 -0
- data/examples/18_rails/bin/setup +15 -0
- data/examples/18_rails/config/application.rb +33 -0
- data/examples/18_rails/config/cable.yml +2 -0
- data/examples/18_rails/config/database.yml +5 -0
- data/examples/18_rails/config/environment.rb +4 -0
- data/examples/18_rails/config/initializers/robot_lab.rb +3 -0
- data/examples/18_rails/config/routes.rb +6 -0
- data/examples/18_rails/config.ru +4 -0
- data/examples/18_rails/db/migrate/001_create_robot_lab_tables.rb +32 -0
- data/examples/README.md +30 -0
- data/examples/prompts/audit_trail.md +8 -0
- data/examples/prompts/incident_responder.md +18 -0
- data/examples/prompts/parameterized_main_test.md +6 -0
- data/examples/prompts/pii_redactor.md +7 -0
- data/examples/prompts/runbook_protocol.md +12 -0
- data/examples/prompts/skill_a_test.md +4 -0
- data/examples/prompts/skill_b_test.md +4 -0
- data/examples/prompts/skill_config_test.md +5 -0
- data/examples/prompts/skill_cycle_a_test.md +6 -0
- data/examples/prompts/skill_cycle_b_test.md +6 -0
- data/examples/prompts/skill_description_test.md +4 -0
- data/examples/prompts/skill_leaf_test.md +4 -0
- data/examples/prompts/skill_nested_test.md +6 -0
- data/examples/prompts/skill_refs_main_test.md +6 -0
- data/examples/prompts/skill_self_ref_test.md +6 -0
- data/examples/prompts/skill_with_params_test.md +6 -0
- data/examples/prompts/sre_compliance.md +10 -0
- data/examples/prompts/structured_output.md +7 -0
- data/examples/prompts/template_with_skills_test.md +6 -0
- data/lib/generators/robot_lab/install_generator.rb +12 -0
- data/lib/generators/robot_lab/templates/initializer.rb.tt +36 -22
- data/lib/generators/robot_lab/templates/job.rb.tt +92 -0
- data/lib/generators/robot_lab/templates/robot.rb.tt +6 -21
- data/lib/generators/robot_lab/templates/robot_test.rb.tt +5 -3
- data/lib/generators/robot_lab/templates/routing_robot.rb.tt +41 -35
- data/lib/robot_lab/{rails → rails_integration}/engine.rb +1 -1
- data/lib/robot_lab/{rails → rails_integration}/railtie.rb +1 -1
- data/lib/robot_lab/rails_integration/turbo_stream_callbacks.rb +72 -0
- data/lib/robot_lab/robot/template_rendering.rb +181 -4
- data/lib/robot_lab/robot.rb +72 -32
- data/lib/robot_lab/run_config.rb +1 -1
- data/lib/robot_lab/tool.rb +26 -0
- data/lib/robot_lab/version.rb +1 -1
- data/lib/robot_lab.rb +6 -4
- metadata +59 -18
- data/examples/14_rusty_circuit/scout_notes.md +0 -89
data/lib/robot_lab.rb
CHANGED
|
@@ -50,7 +50,7 @@ end
|
|
|
50
50
|
|
|
51
51
|
loader = Zeitwerk::Loader.for_gem(warn_on_extra_files: false)
|
|
52
52
|
loader.ignore("#{__dir__}/generators")
|
|
53
|
-
loader.ignore("#{__dir__}/robot_lab/
|
|
53
|
+
loader.ignore("#{__dir__}/robot_lab/rails_integration")
|
|
54
54
|
loader.ignore("#{__dir__}/robot_lab/robot")
|
|
55
55
|
|
|
56
56
|
# Custom inflections for classes that don't follow Zeitwerk naming conventions
|
|
@@ -152,7 +152,7 @@ module RobotLab
|
|
|
152
152
|
# name: "helper",
|
|
153
153
|
# system_prompt: "You are a helpful assistant."
|
|
154
154
|
# )
|
|
155
|
-
def build(name: "robot", template: nil, system_prompt: nil, context: {}, enable_cache: true, bus: nil, config: nil, **options)
|
|
155
|
+
def build(name: "robot", template: nil, system_prompt: nil, context: {}, enable_cache: true, bus: nil, skills: nil, config: nil, **options)
|
|
156
156
|
Robot.new(
|
|
157
157
|
name: name,
|
|
158
158
|
template: template,
|
|
@@ -160,6 +160,7 @@ module RobotLab
|
|
|
160
160
|
context: context,
|
|
161
161
|
enable_cache: enable_cache,
|
|
162
162
|
bus: bus,
|
|
163
|
+
skills: skills,
|
|
163
164
|
config: config,
|
|
164
165
|
**options
|
|
165
166
|
)
|
|
@@ -222,6 +223,7 @@ end
|
|
|
222
223
|
|
|
223
224
|
# Load Rails integration if Rails is defined
|
|
224
225
|
if defined?(Rails::Engine)
|
|
225
|
-
require 'robot_lab/
|
|
226
|
-
require 'robot_lab/
|
|
226
|
+
require 'robot_lab/rails_integration/engine'
|
|
227
|
+
require 'robot_lab/rails_integration/railtie'
|
|
228
|
+
require 'robot_lab/rails_integration/turbo_stream_callbacks'
|
|
227
229
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: robot_lab
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.8
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Dewayne VanHoozer
|
|
@@ -37,20 +37,6 @@ dependencies:
|
|
|
37
37
|
- - "~>"
|
|
38
38
|
- !ruby/object:Gem::Version
|
|
39
39
|
version: '2.6'
|
|
40
|
-
- !ruby/object:Gem::Dependency
|
|
41
|
-
name: activesupport
|
|
42
|
-
requirement: !ruby/object:Gem::Requirement
|
|
43
|
-
requirements:
|
|
44
|
-
- - ">="
|
|
45
|
-
- !ruby/object:Gem::Version
|
|
46
|
-
version: '7.0'
|
|
47
|
-
type: :runtime
|
|
48
|
-
prerelease: false
|
|
49
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
-
requirements:
|
|
51
|
-
- - ">="
|
|
52
|
-
- !ruby/object:Gem::Version
|
|
53
|
-
version: '7.0'
|
|
54
40
|
- !ruby/object:Gem::Dependency
|
|
55
41
|
name: ruby_llm
|
|
56
42
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -295,7 +281,6 @@ files:
|
|
|
295
281
|
- examples/14_rusty_circuit/prompts/open_mic_heckler.md
|
|
296
282
|
- examples/14_rusty_circuit/prompts/open_mic_scout.md
|
|
297
283
|
- examples/14_rusty_circuit/scout.rb
|
|
298
|
-
- examples/14_rusty_circuit/scout_notes.md
|
|
299
284
|
- examples/14_rusty_circuit/show.log
|
|
300
285
|
- examples/15_memory_network_and_bus/editor_in_chief.rb
|
|
301
286
|
- examples/15_memory_network_and_bus/editorial_pipeline.rb
|
|
@@ -315,15 +300,51 @@ files:
|
|
|
315
300
|
- examples/15_memory_network_and_bus/prompts/os_editor.md
|
|
316
301
|
- examples/16_writers_room/display.rb
|
|
317
302
|
- examples/16_writers_room/output/.gitignore
|
|
303
|
+
- examples/16_writers_room/output/README.md
|
|
318
304
|
- examples/16_writers_room/output/opus_001.md
|
|
319
305
|
- examples/16_writers_room/output/opus_001_notes.log
|
|
306
|
+
- examples/16_writers_room/output/opus_002.md
|
|
307
|
+
- examples/16_writers_room/output/opus_002_notes.log
|
|
308
|
+
- examples/16_writers_room/output/opus_002_screenplay.md
|
|
309
|
+
- examples/16_writers_room/output/opus_002_screenplay_notes.md
|
|
310
|
+
- examples/16_writers_room/prompts/screenplay_writer.md
|
|
320
311
|
- examples/16_writers_room/prompts/writer.md
|
|
321
312
|
- examples/16_writers_room/room.rb
|
|
322
313
|
- examples/16_writers_room/tools.rb
|
|
323
314
|
- examples/16_writers_room/writer.rb
|
|
324
315
|
- examples/16_writers_room/writers_room.rb
|
|
316
|
+
- examples/17_skills.rb
|
|
317
|
+
- examples/18_rails/.envrc
|
|
318
|
+
- examples/18_rails/.gitignore
|
|
319
|
+
- examples/18_rails/Gemfile
|
|
320
|
+
- examples/18_rails/README.md
|
|
321
|
+
- examples/18_rails/Rakefile
|
|
322
|
+
- examples/18_rails/app/controllers/application_controller.rb
|
|
323
|
+
- examples/18_rails/app/controllers/chat_controller.rb
|
|
324
|
+
- examples/18_rails/app/jobs/application_job.rb
|
|
325
|
+
- examples/18_rails/app/jobs/robot_run_job.rb
|
|
326
|
+
- examples/18_rails/app/models/application_record.rb
|
|
327
|
+
- examples/18_rails/app/models/robot_lab_result.rb
|
|
328
|
+
- examples/18_rails/app/models/robot_lab_thread.rb
|
|
329
|
+
- examples/18_rails/app/robots/chat_robot.rb
|
|
330
|
+
- examples/18_rails/app/tools/time_tool.rb
|
|
331
|
+
- examples/18_rails/app/views/chat/_user_message.html.erb
|
|
332
|
+
- examples/18_rails/app/views/chat/index.html.erb
|
|
333
|
+
- examples/18_rails/app/views/layouts/application.html.erb
|
|
334
|
+
- examples/18_rails/bin/dev
|
|
335
|
+
- examples/18_rails/bin/rails
|
|
336
|
+
- examples/18_rails/bin/setup
|
|
337
|
+
- examples/18_rails/config.ru
|
|
338
|
+
- examples/18_rails/config/application.rb
|
|
339
|
+
- examples/18_rails/config/cable.yml
|
|
340
|
+
- examples/18_rails/config/database.yml
|
|
341
|
+
- examples/18_rails/config/environment.rb
|
|
342
|
+
- examples/18_rails/config/initializers/robot_lab.rb
|
|
343
|
+
- examples/18_rails/config/routes.rb
|
|
344
|
+
- examples/18_rails/db/migrate/001_create_robot_lab_tables.rb
|
|
325
345
|
- examples/README.md
|
|
326
346
|
- examples/prompts/assistant.md
|
|
347
|
+
- examples/prompts/audit_trail.md
|
|
327
348
|
- examples/prompts/billing.md
|
|
328
349
|
- examples/prompts/classifier.md
|
|
329
350
|
- examples/prompts/comedian.md
|
|
@@ -338,20 +359,39 @@ files:
|
|
|
338
359
|
- examples/prompts/general.md
|
|
339
360
|
- examples/prompts/github_assistant.md
|
|
340
361
|
- examples/prompts/helper.md
|
|
362
|
+
- examples/prompts/incident_responder.md
|
|
341
363
|
- examples/prompts/keyword_extractor.md
|
|
342
364
|
- examples/prompts/llm_config_demo.md
|
|
343
365
|
- examples/prompts/order_support.md
|
|
344
366
|
- examples/prompts/os_advocate.md
|
|
345
367
|
- examples/prompts/os_chief.md
|
|
346
368
|
- examples/prompts/os_editor.md
|
|
369
|
+
- examples/prompts/parameterized_main_test.md
|
|
370
|
+
- examples/prompts/pii_redactor.md
|
|
347
371
|
- examples/prompts/product_support.md
|
|
372
|
+
- examples/prompts/runbook_protocol.md
|
|
348
373
|
- examples/prompts/sentiment_analyzer.md
|
|
374
|
+
- examples/prompts/skill_a_test.md
|
|
375
|
+
- examples/prompts/skill_b_test.md
|
|
376
|
+
- examples/prompts/skill_config_test.md
|
|
377
|
+
- examples/prompts/skill_cycle_a_test.md
|
|
378
|
+
- examples/prompts/skill_cycle_b_test.md
|
|
379
|
+
- examples/prompts/skill_description_test.md
|
|
380
|
+
- examples/prompts/skill_leaf_test.md
|
|
381
|
+
- examples/prompts/skill_nested_test.md
|
|
382
|
+
- examples/prompts/skill_refs_main_test.md
|
|
383
|
+
- examples/prompts/skill_self_ref_test.md
|
|
384
|
+
- examples/prompts/skill_with_params_test.md
|
|
385
|
+
- examples/prompts/sre_compliance.md
|
|
386
|
+
- examples/prompts/structured_output.md
|
|
349
387
|
- examples/prompts/synthesizer.md
|
|
350
388
|
- examples/prompts/technical.md
|
|
389
|
+
- examples/prompts/template_with_skills_test.md
|
|
351
390
|
- examples/prompts/triage.md
|
|
352
391
|
- lib/generators/robot_lab/install_generator.rb
|
|
353
392
|
- lib/generators/robot_lab/robot_generator.rb
|
|
354
393
|
- lib/generators/robot_lab/templates/initializer.rb.tt
|
|
394
|
+
- lib/generators/robot_lab/templates/job.rb.tt
|
|
355
395
|
- lib/generators/robot_lab/templates/migration.rb.tt
|
|
356
396
|
- lib/generators/robot_lab/templates/result_model.rb.tt
|
|
357
397
|
- lib/generators/robot_lab/templates/robot.rb.tt
|
|
@@ -374,8 +414,9 @@ files:
|
|
|
374
414
|
- lib/robot_lab/memory_change.rb
|
|
375
415
|
- lib/robot_lab/message.rb
|
|
376
416
|
- lib/robot_lab/network.rb
|
|
377
|
-
- lib/robot_lab/
|
|
378
|
-
- lib/robot_lab/
|
|
417
|
+
- lib/robot_lab/rails_integration/engine.rb
|
|
418
|
+
- lib/robot_lab/rails_integration/railtie.rb
|
|
419
|
+
- lib/robot_lab/rails_integration/turbo_stream_callbacks.rb
|
|
379
420
|
- lib/robot_lab/robot.rb
|
|
380
421
|
- lib/robot_lab/robot/bus_messaging.rb
|
|
381
422
|
- lib/robot_lab/robot/mcp_management.rb
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
# Scout Notes — The Rusty Circuit
|
|
2
|
-
|
|
3
|
-
## Round 1
|
|
4
|
-
|
|
5
|
-
NOTES: Standard opener - relatable premise (self-checkout frustration) but execution feels safe and predictable. The "incompetence" callback shows some self-awareness, and the credit score punchline lands adequately. However, the material feels very "first draft" - like observations everyone has but hasn't been elevated beyond the obvious.
|
|
6
|
-
|
|
7
|
-
Delivery seems tentative - that expectant look at the crowd suggests they're fishing for validation rather than confidently driving the room. The mic adjustment and setup felt a bit nervous. Too early to judge adaptability or crowd-handling since this is scripted opener material.
|
|
8
|
-
|
|
9
|
-
Withholding judgment on star potential - need to see how they handle the next few minutes when they move beyond their safest material. Looking for signs of unique voice, risk-taking, and whether they can build momentum from this foundation.
|
|
10
|
-
|
|
11
|
-
The premise has potential but needs sharper writing and more confident delivery. Watching for evolution as the set progresses.
|
|
12
|
-
|
|
13
|
-
### Analyst: crowd_work
|
|
14
|
-
|
|
15
|
-
**Opening Analysis:** Solid relatable premise with good escalation from simple frustration to self-deprecating punchline about credit scores. The personification of the machine as "lady" adds character, but the expectant pause suggests uncertainty about audience reception.
|
|
16
|
-
|
|
17
|
-
**Crowd Work Analysis:** Excellent recovery that flips the heckle into material while maintaining control. The callback to "unexpected item" creates a cohesive thread and the broader life metaphor lands with philosophical weight that elevates the bit beyond just grocery store humor.
|
|
18
|
-
|
|
19
|
-
## Round 2
|
|
20
|
-
|
|
21
|
-
The analyst confirms what I'm seeing - this comedian has the instinct to turn disruption into opportunity. That crowd work wasn't just damage control, it was material creation in real time. Watching closely for how they build from here.
|
|
22
|
-
|
|
23
|
-
### Analyst: adaptability
|
|
24
|
-
|
|
25
|
-
Strong adaptive instincts on display here. The comedian skillfully transforms heckling into collaborative energy, using the "unexpected item" callback to create a unifying metaphor that includes the entire audience in the struggle. The venue-specific self-deprecation in Round 2 shows excellent room-reading skills, turning potential weakness into relatable strength while maintaining momentum through the disruption.
|
|
26
|
-
|
|
27
|
-
## Round 3
|
|
28
|
-
|
|
29
|
-
The analyst confirms my assessment - this is someone who thrives on chaos. Three rounds in and they're not just surviving interruptions, they're using them as fuel. This adaptability under fire is exactly what network executives look for in potential stars.
|
|
30
|
-
|
|
31
|
-
## Round 4
|
|
32
|
-
|
|
33
|
-
NOTES: This comedian just demonstrated something crucial - they know when to pivot. After three rounds of crowd/venue work, they smoothly transitioned back to prepared material without losing momentum. That's professional-level set management.
|
|
34
|
-
|
|
35
|
-
The "Michelin star for a gas station hot dog" line is genuinely clever writing - unexpected comparison that works on multiple levels. Shows they can craft material, not just react to situations. The credit score callback maintains continuity while moving the set forward.
|
|
36
|
-
|
|
37
|
-
But here's what's really impressive: that pause before the parking spot bit. They're reading the room's energy, letting the moment breathe, then shifting gears entirely. The mom hanging up punchline is relatable without being hacky - everyone knows that feeling of getting excited about mundane adult things.
|
|
38
|
-
|
|
39
|
-
Pattern solidified: This comedian has both reactive instincts AND structured material. They can work a crowd, handle disruption, acknowledge the venue's vibe, then seamlessly return to their prepared set. That's the mark of someone who understands comedy as both art and craft.
|
|
40
|
-
|
|
41
|
-
The genuine smile suggests they're actually enjoying this chaos rather than just surviving it. That joy is infectious - the room energy has completely shifted from skeptical to engaged.
|
|
42
|
-
|
|
43
|
-
Star potential is becoming clear. This is someone who could handle late-night TV, corporate gigs, or hostile crowds with equal skill.
|
|
44
|
-
|
|
45
|
-
### Analyst: stage_presence
|
|
46
|
-
|
|
47
|
-
**Opening:** Solid relatable premise with good energy, but the delivery feels a bit rehearsed and the expectant pause telegraphs insecurity. The crowd interaction attempt comes off as needy rather than confident.
|
|
48
|
-
|
|
49
|
-
**Round 1:** Excellent heckler handling - you flipped the dynamic by making them part of the bit rather than fighting them. The "unexpected item in the bagging area of life" callback is clever and shows real comedic instincts.
|
|
50
|
-
|
|
51
|
-
**Rounds 2-4:** You found your rhythm by embracing the room's energy and building genuine rapport with both heckler and audience. The self-deprecating humor feels authentic now, and you're working WITH the room instead of AT it - that's when comedy magic happens.
|
|
52
|
-
|
|
53
|
-
## Round 5
|
|
54
|
-
|
|
55
|
-
The analyst nails it - this comedian's stage presence evolved dramatically over the set. Started nervous, ended commanding. That transformation under fire is exactly what separates working comics from stars. This is someone I'd book tomorrow.
|
|
56
|
-
|
|
57
|
-
---
|
|
58
|
-
|
|
59
|
-
## Final Verdict
|
|
60
|
-
|
|
61
|
-
**FINAL TALENT ASSESSMENT - THE RUSTY CIRCUIT**
|
|
62
|
-
|
|
63
|
-
**RECOMMENDATION: IMMEDIATE CALLBACK - HIGH PRIORITY**
|
|
64
|
-
|
|
65
|
-
**What Worked:**
|
|
66
|
-
This comedian demonstrated the rarest quality in stand-up: they get BETTER under pressure. What started as a tentative, safe opener transformed into a masterclass in crowd control and comedic instincts. Key strengths:
|
|
67
|
-
|
|
68
|
-
- **Exceptional Adaptability**: Turned multiple heckles into material gold, showing they can handle any room
|
|
69
|
-
- **Crowd Work Mastery**: The "Stockholm syndrome with punchlines" callback was sophisticated writing in real-time
|
|
70
|
-
- **Venue Intelligence**: Used The Rusty Circuit's gritty reputation as material rather than apologizing for it
|
|
71
|
-
- **Quotable Writing**: "Navy SEALs of entertainment" and "unexpected item in the bagging area of life" are lines that stick
|
|
72
|
-
- **Authentic Voice**: Found the sweet spot between vulnerability and confidence
|
|
73
|
-
|
|
74
|
-
**What Didn't Work:**
|
|
75
|
-
- Opening material felt generic and over-rehearsed
|
|
76
|
-
- Initial delivery showed nerves and validation-seeking
|
|
77
|
-
- Took 2-3 minutes to find their authentic voice
|
|
78
|
-
|
|
79
|
-
**Star Potential:**
|
|
80
|
-
This comedian has the complete package for network success:
|
|
81
|
-
1. **Resilience**: Thrives on chaos rather than crumbling
|
|
82
|
-
2. **Versatility**: Can handle prepared material, crowd work, and venue-specific content seamlessly
|
|
83
|
-
3. **Growth Mindset**: Visibly improved throughout the 5-round set
|
|
84
|
-
4. **Professional Instincts**: Knows when to engage hecklers vs. when to pivot back to material
|
|
85
|
-
|
|
86
|
-
**Bottom Line:**
|
|
87
|
-
I've seen three headliners come from this room. This comedian has that same "it" factor - the ability to turn any situation into comedy gold. They're not just surviving difficult rooms, they're conquering them. That's exactly what we need for late-night spots, corporate gigs, and hostile festival crowds.
|
|
88
|
-
|
|
89
|
-
**Next Steps:** Book them for a showcase set immediately. This is someone who could be headlining within 18 months with proper development.
|