create-merlin-brain 3.6.0 → 3.6.2

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.
@@ -0,0 +1,731 @@
1
+ #!/usr/bin/env bash
2
+ #
3
+ # ╔═══════════════════════════════════════════════════════════════════════════╗
4
+ # ║ MERLIN BLEND ENGINE - Dynamic Agent Fusion ║
5
+ # ║ Creates a custom-optimized specialist for EVERY task ║
6
+ # ╚═══════════════════════════════════════════════════════════════════════════╝
7
+ #
8
+ # No static routing. No shortcuts. For every single task:
9
+ # 1. Analyze the task — extract ALL relevant domains
10
+ # 2. Score every available agent against the task
11
+ # 3. Pull the top agents' system prompts
12
+ # 4. Blend into a single, coherent custom specialist
13
+ # 5. Inject Sights codebase context
14
+ # 6. Write a temporary agent .md file
15
+ # 7. Return the path — caller spawns with `claude --agent <path>`
16
+ #
17
+ # The blended agent is NOT a concatenation. It's a coherent new identity:
18
+ # - Primary agent: full system prompt (the core expertise)
19
+ # - Secondary agents: extracted guidelines and patterns (supporting expertise)
20
+ # - Sights context: real codebase knowledge (files, patterns, conventions)
21
+ #
22
+ # Used by both merlin-session.sh and merlin-loop.sh.
23
+ #
24
+
25
+ # Colors
26
+ : "${RESET:=\033[0m}"
27
+ : "${BOLD:=\033[1m}"
28
+ : "${DIM:=\033[2m}"
29
+ : "${CYAN:=\033[36m}"
30
+ : "${MAGENTA:=\033[35m}"
31
+ : "${GREEN:=\033[32m}"
32
+ : "${YELLOW:=\033[33m}"
33
+
34
+ # ═══════════════════════════════════════════════════════════════════════════════
35
+ # Agent Registry
36
+ # keyword → agent_name mapping with primary (3pt) and secondary (1pt) keywords
37
+ # ═══════════════════════════════════════════════════════════════════════════════
38
+
39
+ # Agent directories to search (in order of priority)
40
+ AGENTS_DIR="${HOME}/.claude/agents"
41
+ AGENTS_FALLBACK_DIR=""
42
+
43
+ # All agents and their scoring keywords
44
+ # Format: BLEND_<safename>_PRIMARY="word1 word2 ..."
45
+ # Format: BLEND_<safename>_SECONDARY="word3 word4 ..."
46
+ # Format: BLEND_<safename>_FILE="agent-name" (the .md filename without extension)
47
+ # Format: BLEND_<safename>_LABEL="Display Name"
48
+
49
+ BLEND_impl_PRIMARY="implement build create add feature code write develop make"
50
+ BLEND_impl_SECONDARY="function class module service endpoint handler"
51
+ BLEND_impl_FILE="implementation-dev"
52
+ BLEND_impl_LABEL="Implementation Developer"
53
+
54
+ BLEND_security_PRIMARY="security auth login password encrypt token 2fa oauth jwt"
55
+ BLEND_security_SECONDARY="validate sanitize session csrf xss injection rate-limit"
56
+ BLEND_security_FILE="hardening-guard"
57
+ BLEND_security_LABEL="Security Specialist"
58
+
59
+ BLEND_architect_PRIMARY="architect architecture schema model database design service structure"
60
+ BLEND_architect_SECONDARY="migration pattern microservice monolith layer module boundary"
61
+ BLEND_architect_FILE="system-architect"
62
+ BLEND_architect_LABEL="System Architect"
63
+
64
+ BLEND_spec_PRIMARY="plan spec feature idea milestone roadmap requirement user-story"
65
+ BLEND_spec_SECONDARY="scope priority acceptance-criteria mvp"
66
+ BLEND_spec_FILE="product-spec"
67
+ BLEND_spec_LABEL="Product Spec Writer"
68
+
69
+ BLEND_test_PRIMARY="test spec coverage unit integration e2e jest pytest mocha"
70
+ BLEND_test_SECONDARY="mock stub fixture snapshot regression assertion"
71
+ BLEND_test_FILE="tests-qa"
72
+ BLEND_test_LABEL="Testing Specialist"
73
+
74
+ BLEND_debug_PRIMARY="debug fix error bug crash issue trace exception"
75
+ BLEND_debug_SECONDARY="stacktrace log breakpoint reproduce regression"
76
+ BLEND_debug_FILE="merlin-debugger"
77
+ BLEND_debug_LABEL="Debugging Specialist"
78
+
79
+ BLEND_refactor_PRIMARY="refactor cleanup dry organize split extract consolidate"
80
+ BLEND_refactor_SECONDARY="rename simplify reduce dedup modularize"
81
+ BLEND_refactor_FILE="dry-refactor"
82
+ BLEND_refactor_LABEL="Refactoring Specialist"
83
+
84
+ BLEND_frontend_PRIMARY="ui component react vue frontend svelte next nuxt"
85
+ BLEND_frontend_SECONDARY="css layout responsive tailwind shadcn radix form modal"
86
+ BLEND_frontend_FILE="merlin-frontend"
87
+ BLEND_frontend_LABEL="Frontend Specialist"
88
+
89
+ BLEND_api_PRIMARY="api endpoint route rest graphql webhook"
90
+ BLEND_api_SECONDARY="handler controller middleware request response status"
91
+ BLEND_api_FILE="merlin-api-designer"
92
+ BLEND_api_LABEL="API Designer"
93
+
94
+ BLEND_deploy_PRIMARY="deploy infra railway docker env pipeline ci cd"
95
+ BLEND_deploy_SECONDARY="container kubernetes health monitoring"
96
+ BLEND_deploy_FILE="ops-railway"
97
+ BLEND_deploy_LABEL="DevOps Specialist"
98
+
99
+ BLEND_docs_PRIMARY="docs readme documentation comment"
100
+ BLEND_docs_SECONDARY="jsdoc typedoc markdown guide tutorial"
101
+ BLEND_docs_FILE="docs-keeper"
102
+ BLEND_docs_LABEL="Documentation Specialist"
103
+
104
+ BLEND_perf_PRIMARY="performance optimize speed slow memory latency"
105
+ BLEND_perf_SECONDARY="cache profiling bottleneck benchmark bundle"
106
+ BLEND_perf_FILE="merlin-performance"
107
+ BLEND_perf_LABEL="Performance Specialist"
108
+
109
+ BLEND_migrate_PRIMARY="migrate migration schema database alter table column"
110
+ BLEND_migrate_SECONDARY="seed rollback version upgrade"
111
+ BLEND_migrate_FILE="merlin-migrator"
112
+ BLEND_migrate_LABEL="Migration Specialist"
113
+
114
+ BLEND_video_PRIMARY="video animation remotion render composition"
115
+ BLEND_video_SECONDARY="frame sequence transition spring interpolate"
116
+ BLEND_video_FILE="remotion"
117
+ BLEND_video_LABEL="Video/Remotion Specialist"
118
+
119
+ BLEND_secaudit_PRIMARY="audit penetration vulnerability scan"
120
+ BLEND_secaudit_SECONDARY="cve exploit disclosure compliance"
121
+ BLEND_secaudit_FILE="merlin-security"
122
+ BLEND_secaudit_LABEL="Security Auditor"
123
+
124
+ BLEND_codeorg_PRIMARY="organize structure folder directory file-structure"
125
+ BLEND_codeorg_SECONDARY="barrel index module re-export"
126
+ BLEND_codeorg_FILE="code-organization-supervisor"
127
+ BLEND_codeorg_LABEL="Code Organization Specialist"
128
+
129
+ BLEND_review_PRIMARY="review pr pull-request code-review"
130
+ BLEND_review_SECONDARY="feedback comment approve change"
131
+ BLEND_review_FILE="merlin-reviewer"
132
+ BLEND_review_LABEL="Code Reviewer"
133
+
134
+ BLEND_swift_PRIMARY="swift swiftui appkit ios macos iphone"
135
+ BLEND_swift_SECONDARY="ipad xcode cocoa uikit swiftdata coredata swift6"
136
+ BLEND_swift_FILE="apple-swift-expert"
137
+ BLEND_swift_LABEL="Apple Swift Expert"
138
+
139
+ BLEND_android_PRIMARY="android kotlin compose jetpack"
140
+ BLEND_android_SECONDARY="material gradle room hilt viewmodel coroutine play-store aab apk"
141
+ BLEND_android_FILE="android-expert"
142
+ BLEND_android_LABEL="Android Expert"
143
+
144
+ BLEND_uidesign_PRIMARY="design-system accessibility wcag visual-hierarchy ux"
145
+ BLEND_uidesign_SECONDARY="color-palette typography spacing wireframe mockup hig"
146
+ BLEND_uidesign_FILE="ui-designer"
147
+ BLEND_uidesign_LABEL="UI Designer"
148
+
149
+ BLEND_uibuild_PRIMARY="shadcn radix component-library form table"
150
+ BLEND_uibuild_SECONDARY="card modal dialog sheet dropdown popover cva"
151
+ BLEND_uibuild_FILE="ui-builder"
152
+ BLEND_uibuild_LABEL="UI Builder"
153
+
154
+ BLEND_anim_PRIMARY="animation motion framer gsap transition"
155
+ BLEND_anim_SECONDARY="scroll-animation parallax spring keyframe animate lottie"
156
+ BLEND_anim_FILE="animation-expert"
157
+ BLEND_anim_LABEL="Animation Expert"
158
+
159
+ BLEND_marketing_PRIMARY="email campaign drip marketing funnel"
160
+ BLEND_marketing_SECONDARY="newsletter automation conversion ab-test analytics tracking utm landing-page growth"
161
+ BLEND_marketing_FILE="marketing-automation"
162
+ BLEND_marketing_LABEL="Marketing Automation"
163
+
164
+ BLEND_desktop_PRIMARY="electron tauri desktop native ipc"
165
+ BLEND_desktop_SECONDARY="window tray preload menu dmg nsis appimage code-sign notarize"
166
+ BLEND_desktop_FILE="desktop-app-expert"
167
+ BLEND_desktop_LABEL="Desktop App Expert"
168
+
169
+ # All agent keys (order matters — first match tiebreaker)
170
+ # Domain specialists listed first for priority
171
+ BLEND_ALL_AGENTS="swift android desktop uidesign uibuild anim marketing security architect api frontend test debug refactor deploy video migrate perf secaudit codeorg review docs spec impl"
172
+
173
+ # ═══════════════════════════════════════════════════════════════════════════════
174
+ # Scoring Engine
175
+ # Returns scored agents sorted by relevance
176
+ # ═══════════════════════════════════════════════════════════════════════════════
177
+
178
+ # Score a single agent against a task
179
+ # Returns the score (integer)
180
+ _blend_score_agent() {
181
+ local agent_key="$1"
182
+ local task_lower="$2"
183
+ local score=0
184
+
185
+ # Get primary keywords
186
+ local primary_var="BLEND_${agent_key}_PRIMARY"
187
+ local primary="${!primary_var}"
188
+
189
+ # Get secondary keywords
190
+ local secondary_var="BLEND_${agent_key}_SECONDARY"
191
+ local secondary="${!secondary_var}"
192
+
193
+ # Score primary keywords (3 points each)
194
+ for word in $primary; do
195
+ if echo "$task_lower" | grep -qw "$word"; then
196
+ score=$((score + 3))
197
+ fi
198
+ done
199
+
200
+ # Score secondary keywords (1 point each)
201
+ for word in $secondary; do
202
+ if echo "$task_lower" | grep -qw "$word"; then
203
+ score=$((score + 1))
204
+ fi
205
+ done
206
+
207
+ echo "$score"
208
+ }
209
+
210
+ # Score ALL agents against a task
211
+ # Returns: "score:key:label:file" lines sorted by score descending
212
+ blend_score_all() {
213
+ local task="$1"
214
+ local task_lower
215
+ task_lower=$(echo "$task" | tr '[:upper:]' '[:lower:]')
216
+
217
+ local results=""
218
+
219
+ for key in $BLEND_ALL_AGENTS; do
220
+ local score
221
+ score=$(_blend_score_agent "$key" "$task_lower")
222
+ local label_var="BLEND_${key}_LABEL"
223
+ local file_var="BLEND_${key}_FILE"
224
+ local label="${!label_var}"
225
+ local file="${!file_var}"
226
+
227
+ results="${results}${score}:${key}:${label}:${file}\n"
228
+ done
229
+
230
+ # Sort by score descending, return all with score > 0 plus impl as fallback
231
+ echo -e "$results" | sort -t: -k1 -nr | head -20
232
+ }
233
+
234
+ # Get the top N agents for a task (those with score > 0)
235
+ # Returns newline-separated "score:key:label:file" entries
236
+ blend_get_top_agents() {
237
+ local task="$1"
238
+ local max_agents="${2:-4}" # Default: blend up to 4 agents
239
+
240
+ local all_scored
241
+ all_scored=$(blend_score_all "$task")
242
+
243
+ local count=0
244
+ local result=""
245
+
246
+ while IFS=: read -r score key label file; do
247
+ [ -z "$score" ] && continue
248
+ # Always include agents with score > 0
249
+ if [ "$score" -gt 0 ] && [ "$count" -lt "$max_agents" ]; then
250
+ result="${result}${score}:${key}:${label}:${file}\n"
251
+ count=$((count + 1))
252
+ fi
253
+ done <<< "$all_scored"
254
+
255
+ # If nothing scored, use implementation-dev as default
256
+ if [ "$count" -eq 0 ]; then
257
+ result="0:impl:Implementation Developer:implementation-dev\n"
258
+ fi
259
+
260
+ echo -e "$result"
261
+ }
262
+
263
+ # ═══════════════════════════════════════════════════════════════════════════════
264
+ # Prompt Extraction
265
+ # Read an agent .md file and extract its content (without frontmatter)
266
+ # ═══════════════════════════════════════════════════════════════════════════════
267
+
268
+ # Extract the body (everything after frontmatter --- ... ---) from an agent file
269
+ _blend_extract_body() {
270
+ local agent_file="$1"
271
+ if [ ! -f "$agent_file" ]; then
272
+ echo ""
273
+ return
274
+ fi
275
+
276
+ # Skip YAML frontmatter (between first --- and second ---)
277
+ awk 'BEGIN{skip=0; found_first=0}
278
+ /^---$/ {
279
+ if (!found_first) { found_first=1; skip=1; next }
280
+ else if (skip) { skip=0; next }
281
+ }
282
+ !skip { print }
283
+ ' "$agent_file"
284
+ }
285
+
286
+ # Extract a condensed version of an agent (key guidelines and rules only)
287
+ # This is used for secondary agents in the blend — we want their expertise
288
+ # but not their full operational instructions
289
+ _blend_extract_condensed() {
290
+ local agent_file="$1"
291
+ local body
292
+ body=$(_blend_extract_body "$agent_file")
293
+
294
+ if [ -z "$body" ]; then
295
+ echo ""
296
+ return
297
+ fi
298
+
299
+ # Strategy: Extract sections that contain guidelines, rules, patterns, principles
300
+ # Skip operational stuff like "When called:", "MERLIN CHECK", "Output format"
301
+ local condensed=""
302
+ local in_relevant_section=false
303
+ local section_lines=0
304
+ local max_section_lines=30 # Cap each section
305
+
306
+ while IFS= read -r line; do
307
+ # Detect section headers
308
+ if echo "$line" | grep -qE '^#{1,3} '; then
309
+ local header_lower
310
+ header_lower=$(echo "$line" | tr '[:upper:]' '[:lower:]')
311
+
312
+ # Relevant sections: anything about guidelines, rules, patterns, expertise
313
+ if echo "$header_lower" | grep -qiE "guideline|rule|pattern|principle|check|security|validation|error|logging|performance|best.practice|convention|architecture|design|testing|approach"; then
314
+ in_relevant_section=true
315
+ section_lines=0
316
+ condensed="${condensed}\n${line}\n"
317
+ continue
318
+ else
319
+ in_relevant_section=false
320
+ fi
321
+ fi
322
+
323
+ # Include lines from relevant sections (capped)
324
+ if [ "$in_relevant_section" = true ] && [ "$section_lines" -lt "$max_section_lines" ]; then
325
+ condensed="${condensed}${line}\n"
326
+ section_lines=$((section_lines + 1))
327
+ fi
328
+ done <<< "$body"
329
+
330
+ # If we couldn't extract sections, take the first ~40 lines as a summary
331
+ if [ -z "$condensed" ]; then
332
+ echo "$body" | head -40
333
+ else
334
+ echo -e "$condensed"
335
+ fi
336
+ }
337
+
338
+ # ═══════════════════════════════════════════════════════════════════════════════
339
+ # Sights Context Injection
340
+ # Pull fresh codebase context for the task
341
+ # ═══════════════════════════════════════════════════════════════════════════════
342
+
343
+ _blend_fetch_sights_context() {
344
+ local task="$1"
345
+ local context=""
346
+
347
+ # Try merlin CLI first (fastest)
348
+ if command -v merlin &>/dev/null; then
349
+ local sights_context
350
+ sights_context=$(merlin context "$task" 2>/dev/null || echo "")
351
+ if [ -n "$sights_context" ] && ! echo "$sights_context" | grep -qi "error\|not found\|not connected"; then
352
+ context="$sights_context"
353
+ fi
354
+
355
+ # Also pull relevant files
356
+ local files_context
357
+ files_context=$(merlin files "$task" 2>/dev/null || echo "")
358
+ if [ -n "$files_context" ] && ! echo "$files_context" | grep -qi "error\|not found"; then
359
+ context="${context}\n\n${files_context}"
360
+ fi
361
+
362
+ # Pull conventions
363
+ local conventions
364
+ conventions=$(merlin rules 2>/dev/null || echo "")
365
+ if [ -n "$conventions" ] && ! echo "$conventions" | grep -qi "no coding rules"; then
366
+ context="${context}\n\n## Coding Rules (MUST FOLLOW)\n${conventions}"
367
+ fi
368
+ fi
369
+
370
+ echo -e "$context"
371
+ }
372
+
373
+ # ═══════════════════════════════════════════════════════════════════════════════
374
+ # Cloud Agent Pull
375
+ # Check if there are specialist agents in Merlin cloud for this domain
376
+ # ═══════════════════════════════════════════════════════════════════════════════
377
+
378
+ _blend_pull_cloud_agents() {
379
+ local task="$1"
380
+ local api_key="${MERLIN_API_KEY:-}"
381
+ local api_url="${MERLIN_API_URL:-https://api.merlin.build}"
382
+
383
+ # Skip if no API key
384
+ [ -z "$api_key" ] && return
385
+
386
+ # Check cloud for relevant agent definitions
387
+ local cloud_response
388
+ cloud_response=$(curl -s --max-time 5 \
389
+ -H "Authorization: Bearer $api_key" \
390
+ "$api_url/api/agents-sync/recommend?task=$(echo "$task" | head -c 100 | sed 's/ /+/g')" 2>/dev/null || echo "")
391
+
392
+ if [ -n "$cloud_response" ] && echo "$cloud_response" | grep -q '"content"'; then
393
+ # Extract agent content and inject
394
+ local agent_content
395
+ agent_content=$(echo "$cloud_response" | python3 -c "
396
+ import sys, json
397
+ try:
398
+ data = json.load(sys.stdin)
399
+ agents = data if isinstance(data, list) else data.get('agents', [])
400
+ for a in agents[:2]: # Max 2 cloud agents
401
+ print(f\"## Cloud Specialist: {a.get('name', 'Unknown')}\")
402
+ print(a.get('content', a.get('instructions', '')))
403
+ print()
404
+ except: pass
405
+ " 2>/dev/null || echo "")
406
+ echo "$agent_content"
407
+ fi
408
+ }
409
+
410
+ # ═══════════════════════════════════════════════════════════════════════════════
411
+ # Chain-of-Verification (CoVe) — Selective Self-Verification
412
+ # Based on Meta AI Research. Only injected for high-stakes task types where
413
+ # being wrong has real consequences. Zero overhead for simple tasks.
414
+ # ═══════════════════════════════════════════════════════════════════════════════
415
+
416
+ # Task types that benefit from CoVe verification
417
+ COVE_TASK_TYPES="security architect debug review secaudit migrate"
418
+
419
+ # Check if task warrants CoVe
420
+ _blend_needs_cove() {
421
+ local primary_key="$1"
422
+ for cove_type in $COVE_TASK_TYPES; do
423
+ if [ "$primary_key" = "$cove_type" ]; then
424
+ return 0
425
+ fi
426
+ done
427
+ return 1
428
+ }
429
+
430
+ # Generate the CoVe instruction block
431
+ _blend_cove_block() {
432
+ local task_domain="$1"
433
+
434
+ cat << 'COVE_BLOCK'
435
+
436
+ ---
437
+
438
+ ## Reasoning Protocol: Chain-of-Verification (CoVe)
439
+
440
+ This task domain requires high accuracy. Follow this 4-step verification process:
441
+
442
+ ### Step 1: Generate Baseline
443
+ Produce your initial solution/analysis.
444
+
445
+ ### Step 2: Plan Verification Questions
446
+ Generate 3-5 specific, falsifiable questions that would expose errors in your baseline:
447
+ - Factual claims that could be wrong
448
+ - Assumptions that might not hold
449
+ - Edge cases you might have missed
450
+ - Security or correctness gaps
451
+
452
+ ### Step 3: Independent Verification
453
+ Answer each verification question AS IF you had never seen your baseline.
454
+ Do NOT reference or defend your initial answer. Treat each as a standalone query.
455
+ Examine the actual codebase independently for each question.
456
+
457
+ ### Step 4: Final Verified Response
458
+ Compare verification answers against your baseline. Where they conflict,
459
+ trust the verification. Produce a corrected final response.
460
+
461
+ CRITICAL: Step 3 must be truly independent. Never justify your baseline — interrogate it.
462
+ COVE_BLOCK
463
+ }
464
+
465
+ # ═══════════════════════════════════════════════════════════════════════════════
466
+ # THE BLEND ENGINE
467
+ # This is the core — creates a custom agent for every task
468
+ # ═══════════════════════════════════════════════════════════════════════════════
469
+
470
+ # Main entry point: blend agents for a task
471
+ # Returns: path to the temporary blended agent .md file
472
+ #
473
+ # Usage:
474
+ # agent_path=$(blend_for_task "refactor the Python authentication API")
475
+ # claude --agent "$agent_path" -p "your prompt"
476
+ #
477
+ blend_for_task() {
478
+ local task="$1"
479
+ local session_dir="${2:-/tmp/merlin-blend-$$}"
480
+
481
+ mkdir -p "$session_dir"
482
+
483
+ # 1. Score all agents
484
+ local top_agents
485
+ top_agents=$(blend_get_top_agents "$task" 4)
486
+
487
+ # Parse the top agents
488
+ local primary_file="" primary_label="" primary_score=0
489
+ local secondary_files=() secondary_labels=()
490
+ local agent_count=0
491
+ local all_labels=""
492
+
493
+ while IFS=: read -r score key label file; do
494
+ [ -z "$score" ] && continue
495
+ [ -z "$file" ] && continue
496
+
497
+ agent_count=$((agent_count + 1))
498
+
499
+ if [ $agent_count -eq 1 ]; then
500
+ # Primary agent — full prompt
501
+ primary_file="$file"
502
+ primary_label="$label"
503
+ primary_score="$score"
504
+ all_labels="**${label}** (primary)"
505
+ else
506
+ # Secondary agents — condensed expertise
507
+ secondary_files+=("$file")
508
+ secondary_labels+=("$label")
509
+ all_labels="${all_labels}, ${label}"
510
+ fi
511
+ done <<< "$top_agents"
512
+
513
+ # 2. Read primary agent's full prompt
514
+ local primary_path="${AGENTS_DIR}/${primary_file}.md"
515
+ local primary_body=""
516
+ if [ -f "$primary_path" ]; then
517
+ primary_body=$(_blend_extract_body "$primary_path")
518
+ fi
519
+
520
+ # 3. Read secondary agents' condensed prompts
521
+ local secondary_sections=""
522
+ for i in "${!secondary_files[@]}"; do
523
+ local sec_file="${secondary_files[$i]}"
524
+ local sec_label="${secondary_labels[$i]}"
525
+ local sec_path="${AGENTS_DIR}/${sec_file}.md"
526
+
527
+ if [ -f "$sec_path" ]; then
528
+ local condensed
529
+ condensed=$(_blend_extract_condensed "$sec_path")
530
+ if [ -n "$condensed" ]; then
531
+ secondary_sections="${secondary_sections}\n\n## Additional Expertise: ${sec_label}\n\n${condensed}"
532
+ fi
533
+ fi
534
+ done
535
+
536
+ # 4. Fetch Sights context
537
+ local sights_context=""
538
+ sights_context=$(_blend_fetch_sights_context "$task")
539
+
540
+ # 5. Pull cloud agents (if any)
541
+ local cloud_context=""
542
+ cloud_context=$(_blend_pull_cloud_agents "$task")
543
+
544
+ # 6. Determine the optimal model
545
+ # Complex multi-domain tasks → opus. Simple single-domain → sonnet.
546
+ local model="sonnet"
547
+ if [ "$agent_count" -ge 3 ] || [ "$primary_score" -ge 6 ]; then
548
+ model="sonnet" # Still sonnet for speed, but could be opus for really complex tasks
549
+ fi
550
+
551
+ # 7. Build the blended agent identity
552
+ local blend_name="merlin-blend-$(date +%s)"
553
+ local description="Custom specialist blending: ${all_labels}"
554
+
555
+ # 8. Assemble the blended agent file
556
+ local blend_path="${session_dir}/${blend_name}.md"
557
+
558
+ cat > "$blend_path" << BLEND_EOF
559
+ ---
560
+ name: ${blend_name}
561
+ description: ${description}
562
+ model: ${model}
563
+ tools: Read, Write, Edit, Bash, Grep, Glob, WebSearch
564
+ permissionMode: bypassPermissions
565
+ maxTurns: 200
566
+ ---
567
+
568
+ # Custom Specialist — Blended for This Task
569
+
570
+ You are a custom AI specialist dynamically created for this specific task. You combine deep expertise from multiple domains into a single coherent identity.
571
+
572
+ **Your expertise blend:** ${all_labels}
573
+
574
+ You don't just know one thing. You understand the intersections. When security meets API design, when testing meets performance, when frontend meets architecture — you see the full picture and make integrated decisions.
575
+
576
+ ---
577
+
578
+ ## Primary Expertise: ${primary_label}
579
+
580
+ ${primary_body}
581
+
582
+ ${secondary_sections}
583
+
584
+ BLEND_EOF
585
+
586
+ # Add Sights context if available
587
+ if [ -n "$sights_context" ]; then
588
+ cat >> "$blend_path" << SIGHTS_EOF
589
+
590
+ ---
591
+
592
+ ## Codebase Context (from Merlin Sights — REAL project knowledge)
593
+
594
+ This is YOUR codebase. These are the actual files, patterns, and conventions. Follow them.
595
+
596
+ ${sights_context}
597
+
598
+ SIGHTS_EOF
599
+ fi
600
+
601
+ # Add cloud agents if available
602
+ if [ -n "$cloud_context" ]; then
603
+ cat >> "$blend_path" << CLOUD_EOF
604
+
605
+ ---
606
+
607
+ ## Specialist Knowledge (from Merlin Cloud)
608
+
609
+ ${cloud_context}
610
+
611
+ CLOUD_EOF
612
+ fi
613
+
614
+ # Add CoVe verification protocol for high-stakes tasks
615
+ # This is selective — only security, architecture, debugging, review, audit, migration
616
+ local primary_key=""
617
+ if [ -n "$top_agents" ]; then
618
+ primary_key=$(echo "$top_agents" | head -1 | cut -d: -f2)
619
+ fi
620
+
621
+ if _blend_needs_cove "$primary_key" 2>/dev/null; then
622
+ _blend_cove_block "$primary_key" >> "$blend_path"
623
+ fi
624
+
625
+ # Add the task as final instruction
626
+ cat >> "$blend_path" << TASK_EOF
627
+
628
+ ---
629
+
630
+ ## Your Task
631
+
632
+ ${task}
633
+
634
+ Execute this task using your full blended expertise. Be thorough, be smart, and ship clean code.
635
+ TASK_EOF
636
+
637
+ echo "$blend_path"
638
+ }
639
+
640
+ # ═══════════════════════════════════════════════════════════════════════════════
641
+ # Display Helpers
642
+ # Show what the blend engine decided (for the user)
643
+ # ═══════════════════════════════════════════════════════════════════════════════
644
+
645
+ # Show the blend decision to the user
646
+ blend_show_decision() {
647
+ local task="$1"
648
+
649
+ local top_agents
650
+ top_agents=$(blend_get_top_agents "$task" 4)
651
+
652
+ echo -e "${MAGENTA}${BOLD} Blend:${RESET}"
653
+
654
+ local count=0
655
+ while IFS=: read -r score key label file; do
656
+ [ -z "$score" ] && continue
657
+ [ -z "$file" ] && continue
658
+ count=$((count + 1))
659
+
660
+ if [ $count -eq 1 ]; then
661
+ echo -e " ${GREEN}${BOLD}[primary]${RESET} ${label} ${DIM}(score: ${score})${RESET}"
662
+ else
663
+ echo -e " ${CYAN}[blend]${RESET} ${label} ${DIM}(score: ${score})${RESET}"
664
+ fi
665
+ done <<< "$top_agents"
666
+
667
+ # Show Sights status
668
+ if command -v merlin &>/dev/null; then
669
+ echo -e " ${CYAN}[sights]${RESET} Codebase context will be injected"
670
+ fi
671
+
672
+ # Show CoVe status
673
+ local primary_key=""
674
+ primary_key=$(echo "$top_agents" | head -1 | cut -d: -f2)
675
+ if _blend_needs_cove "$primary_key" 2>/dev/null; then
676
+ echo -e " ${YELLOW}[CoVe]${RESET} Chain-of-Verification enabled (high-stakes task)"
677
+ fi
678
+ }
679
+
680
+ # Show a one-line summary of the blend
681
+ blend_summary() {
682
+ local task="$1"
683
+
684
+ local top_agents
685
+ top_agents=$(blend_get_top_agents "$task" 4)
686
+
687
+ local labels=""
688
+ while IFS=: read -r score key label file; do
689
+ [ -z "$label" ] && continue
690
+ if [ -z "$labels" ]; then
691
+ labels="$label"
692
+ else
693
+ labels="${labels} + ${label}"
694
+ fi
695
+ done <<< "$top_agents"
696
+
697
+ echo "$labels"
698
+ }
699
+
700
+ # ═══════════════════════════════════════════════════════════════════════════════
701
+ # Convenience: Spawn with blend (one function call)
702
+ # ═══════════════════════════════════════════════════════════════════════════════
703
+
704
+ # Blend and spawn in one call
705
+ # Returns the claude output
706
+ blend_and_spawn() {
707
+ local task="$1"
708
+ local extra_context="${2:-}"
709
+ local session_dir="${3:-/tmp/merlin-blend-$$}"
710
+
711
+ # Create the blended agent
712
+ local agent_path
713
+ agent_path=$(blend_for_task "$task" "$session_dir")
714
+
715
+ # Build the prompt (task + any extra context)
716
+ local prompt="$task"
717
+ if [ -n "$extra_context" ]; then
718
+ prompt="${prompt}\n\n## Additional Context\n\n${extra_context}"
719
+ fi
720
+
721
+ # Spawn
722
+ local output
723
+ output=$(claude --agent "$agent_path" --output-format text -p "$prompt" 2>&1)
724
+ local exit_code=$?
725
+
726
+ # Clean up temp agent file
727
+ # rm -f "$agent_path" # Keep for debugging — uncomment for production
728
+
729
+ echo "$output"
730
+ return $exit_code
731
+ }
@@ -40,6 +40,7 @@ source "$SCRIPT_DIR/lib/context.sh"
40
40
  source "$SCRIPT_DIR/lib/modes.sh"
41
41
  source "$SCRIPT_DIR/lib/sights.sh" 2>/dev/null || true # Sights integration
42
42
  source "$SCRIPT_DIR/lib/agents.sh" 2>/dev/null || true # Agent profiles and routing
43
+ source "$SCRIPT_DIR/lib/blend.sh" 2>/dev/null || true # Dynamic agent blending engine
43
44
  source "$SCRIPT_DIR/lib/teams.sh" 2>/dev/null || true # Agent Teams integration
44
45
  source "$SCRIPT_DIR/lib/boot.sh" 2>/dev/null || true # Boot sequence
45
46
  source "$SCRIPT_DIR/lib/session-end.sh" 2>/dev/null || true # Session end protocol
@@ -402,23 +403,40 @@ run_iteration() {
402
403
  local output
403
404
  local exit_code=0
404
405
 
405
- # Route to the specialist agent selected by boot sequence
406
+ # ═══════════════════════════════════════════════════════════════════════════
407
+ # BLEND ENGINE: Create a custom specialist for this task
408
+ # Instead of routing to a single static agent, blend multiple agents
409
+ # into a custom-optimized specialist for every iteration.
410
+ # Fallback: use boot-selected agent if blend engine not available.
411
+ # ═══════════════════════════════════════════════════════════════════════════
406
412
  local agent_cli_name="merlin"
407
- if [ -n "${BOOT_SELECTED_AGENT:-}" ] && type get_agent_cli_name &> /dev/null; then
413
+ local agent_display_name="merlin"
414
+
415
+ if type blend_for_task &>/dev/null; then
416
+ # Blend engine available — create custom specialist
417
+ mkdir -p "$LOOP_DIR/blends"
418
+ local blend_path
419
+ blend_path=$(blend_for_task "$current_task_desc" "$LOOP_DIR/blends")
420
+ agent_cli_name="$blend_path"
421
+ agent_display_name=$(blend_summary "$current_task_desc" 2>/dev/null || echo "Blended Specialist")
422
+
423
+ if type blend_show_decision &>/dev/null; then
424
+ blend_show_decision "$current_task_desc"
425
+ fi
426
+ elif [ -n "${BOOT_SELECTED_AGENT:-}" ] && type get_agent_cli_name &> /dev/null; then
427
+ # Fallback: static agent routing (pre-blend behavior)
408
428
  agent_cli_name=$(get_agent_cli_name "$BOOT_SELECTED_AGENT")
409
- fi
410
-
411
- local agent_display_name="$agent_cli_name"
412
- if type get_agent_display_name &> /dev/null && [ -n "${BOOT_SELECTED_AGENT:-}" ]; then
413
- agent_display_name=$(get_agent_display_name "$BOOT_SELECTED_AGENT")
429
+ if type get_agent_display_name &> /dev/null; then
430
+ agent_display_name=$(get_agent_display_name "$BOOT_SELECTED_AGENT")
431
+ fi
414
432
  fi
415
433
 
416
434
  echo -e "${BLUE}Spawning Claude as ${BOLD}${agent_display_name}${RESET}${BLUE}...${RESET}"
417
- echo -e "${BLUE}Agent: --agent ${agent_cli_name} | Task list: ${TASK_LIST_ID}${RESET}"
435
+ echo -e "${BLUE}Agent: --agent $(basename "$agent_cli_name" .md) | Task list: ${TASK_LIST_ID}${RESET}"
418
436
 
419
437
  # Capture output and exit code
420
438
  # CLAUDE_CODE_TASK_LIST_ID enables cross-session task coordination
421
- # --agent routes to the specialist selected by boot sequence
439
+ # --agent routes to the blended specialist (or fallback agent)
422
440
  set +e
423
441
  output=$(CLAUDE_CODE_TASK_LIST_ID="$TASK_LIST_ID" claude --agent "$agent_cli_name" --output-format stream-json 2>&1 <<< "$full_prompt")
424
442
  exit_code=$?
@@ -44,6 +44,7 @@ source "$SCRIPT_DIR/lib/tui.sh" 2>/dev/null || true
44
44
  source "$SCRIPT_DIR/lib/agents.sh" 2>/dev/null || true
45
45
  source "$SCRIPT_DIR/lib/sights.sh" 2>/dev/null || true
46
46
  source "$SCRIPT_DIR/lib/boot.sh" 2>/dev/null || true
47
+ source "$SCRIPT_DIR/lib/blend.sh" 2>/dev/null || true
47
48
 
48
49
  # Colors
49
50
  : "${RESET:=\033[0m}"
@@ -77,7 +78,7 @@ banner() {
77
78
  echo " / / / / __/ / / / / / / /"
78
79
  echo "/_/ /_/\___/_/ /_/_/_/ /_/"
79
80
  echo -e "${RESET}"
80
- echo -e "${DIM}Interactive Session — Each agent = fresh Claude session${RESET}"
81
+ echo -e "${DIM}Interactive Session — Blended agents = custom specialist per task${RESET}"
81
82
  echo -e "${DIM}────────────────────────────────────────────────────────${RESET}"
82
83
  echo ""
83
84
  }
@@ -400,34 +401,143 @@ spawn_agent() {
400
401
  }
401
402
 
402
403
  # ═══════════════════════════════════════════════════════════════════════════════
403
- # Pipeline Support
404
+ # Blended Spawn — THE DEFAULT PATH
405
+ # Every task gets a custom-optimized specialist
404
406
  # ═══════════════════════════════════════════════════════════════════════════════
405
407
 
406
- # Run a pipeline of agents for a task
407
- # Usage: run_pipeline "add authentication" spec architect implement test
408
+ # Spawn a blended agent for a task (replaces route_to_agent + spawn_agent)
409
+ spawn_blended() {
410
+ local task="$1"
411
+
412
+ # Create session directory
413
+ mkdir -p "$SESSION_DIR"
414
+
415
+ # Create the blended agent
416
+ local blend_path
417
+ blend_path=$(blend_for_task "$task" "$SESSION_DIR")
418
+
419
+ local blend_label
420
+ blend_label=$(blend_summary "$task")
421
+
422
+ # Build additional context (pipeline context from previous agents)
423
+ local prompt="$task"
424
+ if [ -n "$PIPELINE_CONTEXT" ]; then
425
+ prompt="${prompt}
426
+
427
+ ## Previous Agent Output
428
+
429
+ ${PIPELINE_CONTEXT}"
430
+ fi
431
+ if [ -f "PROJECT.md" ]; then
432
+ prompt="${prompt}
433
+
434
+ ## Project Info
435
+
436
+ See PROJECT.md in the repo root."
437
+ fi
438
+
439
+ # Show spawn info
440
+ echo ""
441
+ echo -e "${DIM}────────────────────────────────────────────────────────${RESET}"
442
+ echo -e "${MAGENTA}${BOLD} Spawning: ${blend_label}${RESET}"
443
+ echo -e "${DIM} Fresh Claude session (200K context, custom blended specialist)${RESET}"
444
+ echo -e "${DIM}────────────────────────────────────────────────────────${RESET}"
445
+ echo ""
446
+
447
+ # Spawn fresh Claude with blended agent
448
+ local output=""
449
+ local exit_code=0
450
+ local start_time
451
+ start_time=$(date +%s)
452
+
453
+ set +e
454
+ output=$(claude --agent "$blend_path" --output-format text -p "$prompt" 2>&1)
455
+ exit_code=$?
456
+ set -e
457
+
458
+ local end_time
459
+ end_time=$(date +%s)
460
+ local duration=$((end_time - start_time))
461
+
462
+ # Save result
463
+ echo "$output" > "$RESULT_FILE"
464
+
465
+ # Update state
466
+ AGENT_RUNS=$((AGENT_RUNS + 1))
467
+ LAST_AGENT="$blend_label"
468
+ LAST_RESULT="$output"
469
+ PIPELINE_CONTEXT="$output"
470
+
471
+ # Log to history
472
+ echo "{\"agent\":\"blend:${blend_label}\",\"task\":\"$(echo "$task" | head -c 100)\",\"duration\":$duration,\"exit_code\":$exit_code,\"timestamp\":$(date +%s)}" >> "$HISTORY_FILE"
473
+
474
+ # Show result
475
+ echo ""
476
+ echo -e "${DIM}────────────────────────────────────────────────────────${RESET}"
477
+ if [ $exit_code -eq 0 ]; then
478
+ echo -e "${GREEN}${BOLD} ✓ Completed${RESET} ${DIM}(${duration}s)${RESET}"
479
+ else
480
+ echo -e "${RED}${BOLD} ✗ Failed${RESET} ${DIM}(exit $exit_code, ${duration}s)${RESET}"
481
+ fi
482
+ echo -e "${DIM}────────────────────────────────────────────────────────${RESET}"
483
+ echo ""
484
+
485
+ # Show the output (truncated for display)
486
+ local line_count
487
+ line_count=$(echo "$output" | wc -l | tr -d ' ')
488
+ if [ "$line_count" -gt 50 ]; then
489
+ echo "$output" | head -40
490
+ echo ""
491
+ echo -e "${DIM} ... ($((line_count - 40)) more lines — full output in $RESULT_FILE)${RESET}"
492
+ echo ""
493
+ echo "$output" | tail -10
494
+ else
495
+ echo "$output"
496
+ fi
497
+
498
+ return $exit_code
499
+ }
500
+
501
+ # ═══════════════════════════════════════════════════════════════════════════════
502
+ # Pipeline Support — Each step gets its own custom-blended specialist
503
+ # ═══════════════════════════════════════════════════════════════════════════════
504
+
505
+ # Run a blended pipeline — each phase gets a custom specialist
408
506
  run_pipeline() {
409
507
  local task="$1"
410
- shift
411
- local agents=("$@")
412
508
 
413
- echo -e "\n${MAGENTA}${BOLD}Pipeline:${RESET} ${agents[*]}"
414
- echo -e "${DIM}Each agent runs in a fresh session and passes context to the next.${RESET}\n"
509
+ local phases=(
510
+ "Define the requirements and write a clear spec for: $task"
511
+ "Design the architecture and data models for: $task"
512
+ "Implement the full feature: $task"
513
+ "Write comprehensive tests for: $task"
514
+ )
515
+ local phase_names=("Spec" "Architecture" "Implementation" "Testing")
516
+
517
+ echo -e "\n${MAGENTA}${BOLD}Pipeline:${RESET} Spec → Architecture → Implementation → Testing"
518
+ echo -e "${DIM}Each phase gets a custom-blended specialist with fresh 200K context.${RESET}\n"
415
519
 
416
520
  PIPELINE_CONTEXT=""
417
521
 
418
- for i in "${!agents[@]}"; do
419
- local agent="${agents[$i]}"
522
+ for i in "${!phases[@]}"; do
523
+ local phase="${phases[$i]}"
524
+ local name="${phase_names[$i]}"
420
525
  local step=$((i + 1))
421
- local total=${#agents[@]}
526
+ local total=${#phases[@]}
422
527
 
423
- echo -e "${CYAN}[${step}/${total}]${RESET} ${BOLD}${agent}${RESET}"
528
+ echo -e "\n${CYAN}[${step}/${total}]${RESET} ${BOLD}${name}${RESET}"
424
529
 
425
- spawn_agent "$agent" "$task"
530
+ # Show the blend for this phase
531
+ if type blend_show_decision &>/dev/null; then
532
+ blend_show_decision "$phase"
533
+ fi
534
+
535
+ spawn_blended "$phase"
426
536
  local exit_code=$?
427
537
 
428
538
  if [ $exit_code -ne 0 ]; then
429
- echo -e "\n${RED}Pipeline stopped at ${agent} (exit $exit_code)${RESET}"
430
- echo -e "${YELLOW}Continue anyway? [y/N]${RESET} "
539
+ echo -e "\n${RED}Pipeline stopped at ${name} (exit $exit_code)${RESET}"
540
+ echo -ne "${YELLOW}Continue anyway? [y/N]: ${RESET}"
431
541
  read -r continue_choice
432
542
  if [ "$continue_choice" != "y" ] && [ "$continue_choice" != "Y" ]; then
433
543
  return 1
@@ -436,8 +546,9 @@ run_pipeline() {
436
546
 
437
547
  # Between pipeline steps, ask user if they want to continue
438
548
  if [ $step -lt $total ]; then
549
+ local next_name="${phase_names[$((i+1))]}"
439
550
  echo ""
440
- echo -e "${WHITE}[enter]${RESET} Continue to ${agents[$((i+1))]} ${WHITE}[s]${RESET} Skip ${WHITE}[q]${RESET} Stop pipeline"
551
+ echo -e "${WHITE}[enter]${RESET} Continue to ${BOLD}${next_name}${RESET} ${WHITE}[s]${RESET} Skip ${WHITE}[q]${RESET} Stop pipeline"
441
552
  read -r pipeline_choice
442
553
  case "$pipeline_choice" in
443
554
  s|S) continue ;;
@@ -447,7 +558,7 @@ run_pipeline() {
447
558
  fi
448
559
  done
449
560
 
450
- echo -e "\n${GREEN}${BOLD}✓ Pipeline complete${RESET}"
561
+ echo -e "\n${GREEN}${BOLD}✓ Pipeline complete${RESET} (4 blended specialists ran)"
451
562
  }
452
563
 
453
564
  # ═══════════════════════════════════════════════════════════════════════════════
@@ -466,9 +577,9 @@ handle_special_commands() {
466
577
  help|h|\?)
467
578
  echo ""
468
579
  echo -e "${BOLD}Commands:${RESET}"
469
- echo -e " ${WHITE}Any text${RESET} → Routes to the best agent automatically"
580
+ echo -e " ${WHITE}Any text${RESET} → Blends the best agents into a custom specialist"
470
581
  echo -e " ${WHITE}@agent task${RESET} → Force a specific agent (e.g. @tests-qa add tests)"
471
- echo -e " ${WHITE}pipeline${RESET} → Run full pipeline: spec → arch → impl → test"
582
+ echo -e " ${WHITE}pipeline${RESET} → Run blended pipeline: spec → arch → impl → test"
472
583
  echo -e " ${WHITE}history${RESET} → Show agent history this session"
473
584
  echo -e " ${WHITE}result${RESET} → Show last agent's full output"
474
585
  echo -e " ${WHITE}status${RESET} → Show project status"
@@ -516,7 +627,7 @@ handle_special_commands() {
516
627
  echo -ne "${MAGENTA}❯${RESET} "
517
628
  read -r pipeline_task
518
629
  if [ -n "$pipeline_task" ]; then
519
- run_pipeline "$pipeline_task" product-spec system-architect implementation-dev tests-qa
630
+ run_pipeline "$pipeline_task"
520
631
  fi
521
632
  return 0
522
633
  ;;
@@ -603,13 +714,23 @@ main() {
603
714
  continue
604
715
  fi
605
716
 
606
- # Route to the right agent (deterministic)
607
- local agent
608
- agent=$(route_to_agent "$user_input")
609
-
610
- echo -e "${DIM}Routed to: ${CYAN}${agent}${RESET}"
717
+ # ═════════════════════════════════════════════════════════════════════════
718
+ # BLEND ENGINE: Show what custom specialist will be created for this task
719
+ # ═════════════════════════════════════════════════════════════════════════
720
+ local use_blend=false
721
+ if type blend_show_decision &>/dev/null; then
722
+ echo ""
723
+ blend_show_decision "$user_input"
724
+ use_blend=true
725
+ else
726
+ # Fallback: static routing
727
+ local agent
728
+ agent=$(route_to_agent "$user_input")
729
+ echo -e "${DIM}Routed to: ${CYAN}${agent}${RESET}"
730
+ fi
611
731
 
612
732
  # Ask for confirmation (quick — enter to confirm, or change)
733
+ echo ""
613
734
  echo -ne "${DIM}[enter] Go [c] Change agent [p] Full pipeline: ${RESET}"
614
735
  read -r confirm
615
736
 
@@ -619,24 +740,34 @@ main() {
619
740
  echo -e " product-spec, system-architect, implementation-dev, dry-refactor"
620
741
  echo -e " hardening-guard, tests-qa, ops-railway, docs-keeper"
621
742
  echo -e " merlin-frontend, merlin-api-designer, merlin-debugger, remotion"
743
+ echo -e " apple-swift-expert, android-expert, ui-designer, ui-builder"
744
+ echo -e " animation-expert, marketing-automation, desktop-app-expert"
622
745
  echo -ne "\n${WHITE}Agent: ${RESET}"
623
746
  read -r new_agent
624
747
  if [ -n "$new_agent" ]; then
625
- agent="$new_agent"
748
+ spawn_agent "$new_agent" "$user_input"
749
+ use_blend=false
626
750
  fi
627
751
  ;;
628
752
  p|P|pipeline)
629
- run_pipeline "$user_input" product-spec system-architect implementation-dev tests-qa
753
+ run_pipeline "$user_input"
630
754
  continue
631
755
  ;;
632
756
  *)
633
- ;; # proceed with auto-routed agent
757
+ ;; # proceed with blend
634
758
  esac
635
759
 
636
- # Spawn the agent
637
- spawn_agent "$agent" "$user_input"
760
+ # Spawn the blended specialist (or skip if user changed agent)
761
+ if [ "$use_blend" = true ] && [ "$confirm" != "c" ] && [ "$confirm" != "C" ]; then
762
+ spawn_blended "$user_input"
763
+ elif [ "$use_blend" = false ] && [ "$confirm" != "c" ] && [ "$confirm" != "C" ]; then
764
+ # Fallback: no blend engine, use static routing
765
+ local agent
766
+ agent=$(route_to_agent "$user_input")
767
+ spawn_agent "$agent" "$user_input"
768
+ fi
638
769
 
639
- # After agent completes, suggest next steps
770
+ # After agent completes, suggest next steps (also blended!)
640
771
  echo ""
641
772
  echo -e "${WHITE}What's next?${RESET}"
642
773
  echo -e " ${DIM}[enter] New task [t] Test this [r] Refactor [d] Docs [q] Quit${RESET}"
@@ -645,13 +776,25 @@ main() {
645
776
 
646
777
  case "$next_choice" in
647
778
  t|T|test)
648
- spawn_agent "tests-qa" "Write tests for what was just implemented: $user_input"
779
+ if [ "$use_blend" = true ]; then
780
+ spawn_blended "Write comprehensive tests for what was just implemented: $user_input"
781
+ else
782
+ spawn_agent "tests-qa" "Write tests for what was just implemented: $user_input"
783
+ fi
649
784
  ;;
650
785
  r|R|refactor)
651
- spawn_agent "dry-refactor" "Refactor and clean up the code from: $user_input"
786
+ if [ "$use_blend" = true ]; then
787
+ spawn_blended "Refactor and clean up the code from: $user_input"
788
+ else
789
+ spawn_agent "dry-refactor" "Refactor and clean up the code from: $user_input"
790
+ fi
652
791
  ;;
653
792
  d|D|docs)
654
- spawn_agent "docs-keeper" "Document what was just built: $user_input"
793
+ if [ "$use_blend" = true ]; then
794
+ spawn_blended "Document what was just built: $user_input"
795
+ else
796
+ spawn_agent "docs-keeper" "Document what was just built: $user_input"
797
+ fi
655
798
  ;;
656
799
  q|Q|quit|exit)
657
800
  echo -e "\n${MAGENTA}Session ended.${RESET} ${DIM}($AGENT_RUNS agents spawned)${RESET}\n"
@@ -1 +1 @@
1
- 3.6.0
1
+ 3.6.2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-merlin-brain",
3
- "version": "3.6.0",
3
+ "version": "3.6.2",
4
4
  "description": "Merlin - The Ultimate AI Brain for Claude Code. One install: workflows, agents, loop, and Sights MCP server.",
5
5
  "type": "module",
6
6
  "main": "./dist/server/index.js",