@ralph-orchestrator/ralph-cli 2.2.0 → 2.2.1

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.
package/README.md CHANGED
@@ -3,6 +3,7 @@
3
3
  [![License](https://img.shields.io/badge/license-MIT-blue)](LICENSE)
4
4
  [![Rust](https://img.shields.io/badge/rust-1.75+-orange)](https://www.rust-lang.org/)
5
5
  [![Build](https://img.shields.io/github/actions/workflow/status/mikeyobrien/ralph-orchestrator/ci.yml?branch=main&label=CI)](https://github.com/mikeyobrien/ralph-orchestrator/actions)
6
+ [![Coverage](https://img.shields.io/badge/coverage-65%25-yellowgreen)](coverage/index.html)
6
7
  [![Mentioned in Awesome Claude Code](https://awesome.re/mentioned-badge.svg)](https://github.com/hesreallyhim/awesome-claude-code)
7
8
 
8
9
 
@@ -23,8 +24,10 @@ v1.0.0 was ralphed into existence with little oversight and guidance. v2.0.0 is
23
24
  - [Installation](#installation)
24
25
  - [Quick Start](#quick-start)
25
26
  - [Configuration](#configuration)
27
+ - [Custom Backends and Per-Hat Configuration](#custom-backends-and-per-hat-configuration)
26
28
  - [Presets](#presets)
27
29
  - [Key Concepts](#key-concepts)
30
+ - [Orchestration and Coordination Patterns](#orchestration-and-coordination-patterns)
28
31
  - [CLI Reference](#cli-reference)
29
32
  - [Architecture](#architecture)
30
33
  - [Building & Testing](#building--testing)
@@ -325,6 +328,81 @@ hats:
325
328
  ```
326
329
 
327
330
 
331
+ ## Custom Backends and Per-Hat Configuration
332
+
333
+ ### Custom Backends
334
+
335
+ Beyond the built-in backends (Claude, Kiro, Gemini, Codex, Amp, Copilot, OpenCode), you can define custom backends to integrate any CLI-based AI agent:
336
+
337
+ ```yaml
338
+ cli:
339
+ backend: "custom"
340
+ command: "my-agent"
341
+ args: ["--headless", "--auto-approve"]
342
+ prompt_mode: "arg" # "arg" or "stdin"
343
+ prompt_flag: "-p" # Optional: flag for prompt argument
344
+ ```
345
+
346
+ | Field | Description |
347
+ |-------|-------------|
348
+ | `command` | The CLI command to execute |
349
+ | `args` | Arguments inserted before the prompt |
350
+ | `prompt_mode` | How to pass the prompt: `arg` (command-line argument) or `stdin` |
351
+ | `prompt_flag` | Flag preceding the prompt (e.g., `-p`, `--prompt`). If omitted, prompt is positional. |
352
+
353
+ ### Per-Hat Backend Configuration
354
+
355
+ Different hats can use different backends, enabling specialized tools for specialized tasks:
356
+
357
+ ```yaml
358
+ cli:
359
+ backend: "claude" # Default for Ralph and hats without explicit backend
360
+
361
+ hats:
362
+ builder:
363
+ name: "🔨 Builder"
364
+ description: "Implements code"
365
+ triggers: ["build.task"]
366
+ publishes: ["build.done"]
367
+ backend: "claude" # Explicit: Claude for coding
368
+
369
+ researcher:
370
+ name: "🔍 Researcher"
371
+ description: "Researches technical questions"
372
+ triggers: ["research.task"]
373
+ publishes: ["research.done"]
374
+ backend: # Kiro with custom agent (has MCP tools)
375
+ type: "kiro"
376
+ agent: "researcher"
377
+
378
+ reviewer:
379
+ name: "👀 Reviewer"
380
+ description: "Reviews code changes"
381
+ triggers: ["review.task"]
382
+ publishes: ["review.done"]
383
+ backend: "gemini" # Different model for fresh perspective
384
+ ```
385
+
386
+ **Backend Types:**
387
+
388
+ | Type | Syntax | Invocation |
389
+ |------|--------|------------|
390
+ | Named | `backend: "claude"` | Uses standard backend configuration |
391
+ | Kiro Agent | `backend: { type: "kiro", agent: "builder" }` | `kiro-cli --agent builder ...` |
392
+ | Custom | `backend: { command: "...", args: [...] }` | Your custom command |
393
+
394
+ **When to mix backends:**
395
+
396
+ | Scenario | Recommended Backend |
397
+ |----------|---------------------|
398
+ | Complex coding | Claude (best reasoning) |
399
+ | AWS/cloud tasks | Kiro with agent (MCP tools) |
400
+ | Code review | Different model (fresh perspective) |
401
+ | Internal tools | Custom backend |
402
+ | Cost optimization | Faster/cheaper model for simple tasks |
403
+
404
+ Hats without explicit `backend` inherit from `cli.backend`.
405
+
328
406
  ## Presets
329
407
 
330
408
  Presets are pre-configured workflows for common development patterns.
@@ -407,6 +485,410 @@ View event history:
407
485
  ralph events
408
486
  ```
409
487
 
488
+ ## Orchestration and Coordination Patterns
489
+
490
+ Ralph's hat system enables sophisticated multi-agent workflows through event-driven coordination. This section covers the architectural patterns, event routing mechanics, and built-in workflow templates.
491
+
492
+ ### How Hat-Based Orchestration Works
493
+
494
+ #### The Event-Driven Model
495
+
496
+ Hats communicate through a **pub/sub event system**:
497
+
498
+ 1. **Ralph publishes a starting event** (e.g., `task.start`)
499
+ 2. **The matching hat activates** — the hat subscribed to that event takes over
500
+ 3. **The hat does its work** and publishes an event when done
501
+ 4. **The next hat activates** — triggered by the new event
502
+ 5. **The cycle continues** until a termination event or `LOOP_COMPLETE`
503
+
504
+ ```
505
+ ┌─────────────────────────────────────────────────────────────────┐
506
+ │ task.start → [Test Writer] → test.written → [Implementer] → │
507
+ │ test.passing → [Refactorer] → refactor.done ──┐ │
508
+ │ │ │
509
+ │ ┌─────────────────────────────────────────────┘ │
510
+ │ └──→ (loops back to Test Writer for next test) │
511
+ └─────────────────────────────────────────────────────────────────┘
512
+ ```
513
+
514
+ #### Ralph as the Constant Coordinator
515
+
516
+ In hat-based mode, **Ralph is always present**:
517
+
518
+ - Ralph cannot be removed or replaced
519
+ - Custom hats define the **topology** (who triggers whom)
520
+ - Ralph executes with **topology awareness** — knowing which hats exist and their relationships
521
+ - Ralph serves as the **universal fallback** — orphaned events automatically route to Ralph
522
+
523
+ This means custom hats don't execute directly. Instead, Ralph reads all pending events across all hats and decides what to do based on the defined topology. Ralph then either:
524
+ - Delegates to the appropriate hat by publishing an event
525
+ - Handles the work directly if no hat is suited
526
+
527
+ #### Event Routing and Topic Matching
528
+
529
+ Events route to hats using **glob-style pattern matching**:
530
+
531
+ | Pattern | Matches |
532
+ |---------|---------|
533
+ | `task.start` | Exactly `task.start` |
534
+ | `build.*` | `build.done`, `build.blocked`, `build.task`, etc. |
535
+ | `*.done` | `build.done`, `review.done`, `test.done`, etc. |
536
+ | `*` | Everything (global wildcard — used by Ralph as fallback) |
537
+
538
+ **Priority Rules:**
539
+ - Specific patterns take precedence over wildcards
540
+ - If multiple hats have specific subscriptions, that's an error (ambiguous routing)
541
+ - Global wildcard (`*`) only triggers if no specific handler exists
542
+
543
+ ### Coordination Patterns
544
+
545
+ Ralph presets implement several proven coordination patterns:
546
+
547
+ #### 1. Linear Pipeline
548
+
549
+ The simplest pattern — work flows through a sequence of specialists.
550
+
551
+ ```
552
+ Input → Hat A → Event → Hat B → Event → Hat C → Output
553
+ ```
554
+
555
+ **Example: TDD Red-Green-Refactor** (`tdd-red-green.yml`)
556
+
557
+ ```yaml
558
+ hats:
559
+ test_writer:
560
+ triggers: ["tdd.start", "refactor.done"]
561
+ publishes: ["test.written"]
562
+
563
+ implementer:
564
+ triggers: ["test.written"]
565
+ publishes: ["test.passing"]
566
+
567
+ refactorer:
568
+ triggers: ["test.passing"]
569
+ publishes: ["refactor.done", "cycle.complete"]
570
+ ```
571
+
572
+ ```
573
+ tdd.start → 🔴 Test Writer → test.written → 🟢 Implementer →
574
+ test.passing → 🔵 Refactorer → refactor.done ─┐
575
+
576
+ ┌───────────────────────────────┘
577
+ └──→ (back to Test Writer)
578
+ ```
579
+
580
+ **When to use:** Workflows with clear sequential phases where each step builds on the previous.
581
+
582
+ #### 2. Contract-First Pipeline
583
+
584
+ A variant where work must pass validation gates before proceeding.
585
+
586
+ **Example: Spec-Driven Development** (`spec-driven.yml`)
587
+
588
+ ```yaml
589
+ hats:
590
+ spec_writer:
591
+ triggers: ["spec.start", "spec.rejected"]
592
+ publishes: ["spec.ready"]
593
+
594
+ spec_reviewer:
595
+ triggers: ["spec.ready"]
596
+ publishes: ["spec.approved", "spec.rejected"]
597
+
598
+ implementer:
599
+ triggers: ["spec.approved", "spec.violated"]
600
+ publishes: ["implementation.done"]
601
+
602
+ verifier:
603
+ triggers: ["implementation.done"]
604
+ publishes: ["task.complete", "spec.violated"]
605
+ ```
606
+
607
+ ```
608
+ spec.start → 📋 Spec Writer ──→ spec.ready ──→ 🔎 Spec Critic
609
+ ↑ │
610
+ └────── spec.rejected ──────────────┤
611
+
612
+ spec.approved
613
+
614
+
615
+ task.complete ←── ✅ Verifier ←── impl.done ←── ⚙️ Implementer
616
+ │ ↑
617
+ └──── spec.violated ───────────┘
618
+ ```
619
+
620
+ **When to use:** High-stakes changes where the spec must be rock-solid before implementation begins.
621
+
622
+ #### 3. Cyclic Rotation
623
+
624
+ Multiple roles take turns, each bringing a different perspective.
625
+
626
+ **Example: Mob Programming** (`mob-programming.yml`)
627
+
628
+ ```yaml
629
+ hats:
630
+ navigator:
631
+ triggers: ["mob.start", "observation.noted"]
632
+ publishes: ["direction.set", "mob.complete"]
633
+
634
+ driver:
635
+ triggers: ["direction.set"]
636
+ publishes: ["code.written"]
637
+
638
+ observer:
639
+ triggers: ["code.written"]
640
+ publishes: ["observation.noted"]
641
+ ```
642
+
643
+ ```
644
+ mob.start → 🧭 Navigator → direction.set → ⌨️ Driver →
645
+ code.written → 👁️ Observer → observation.noted ─┐
646
+
647
+ ┌─────────────────────────────────┘
648
+ └──→ (back to Navigator)
649
+ ```
650
+
651
+ **When to use:** Complex features that benefit from multiple perspectives and continuous feedback.
652
+
653
+ #### 4. Adversarial Review
654
+
655
+ Two roles with opposing objectives ensure robustness.
656
+
657
+ **Example: Red Team / Blue Team** (`adversarial-review.yml`)
658
+
659
+ ```yaml
660
+ hats:
661
+ builder:
662
+ name: "🔵 Blue Team (Builder)"
663
+ triggers: ["security.review", "fix.applied"]
664
+ publishes: ["build.ready"]
665
+
666
+ red_team:
667
+ name: "🔴 Red Team (Attacker)"
668
+ triggers: ["build.ready"]
669
+ publishes: ["vulnerability.found", "security.approved"]
670
+
671
+ fixer:
672
+ triggers: ["vulnerability.found"]
673
+ publishes: ["fix.applied"]
674
+ ```
675
+
676
+ ```
677
+ security.review → 🔵 Blue Team → build.ready → 🔴 Red Team
678
+ ↑ │
679
+ │ ├─→ security.approved ✓
680
+ │ │
681
+ │ └─→ vulnerability.found
682
+ │ │
683
+ └────── fix.applied ←── 🛡️ Fixer ←──────┘
684
+ ```
685
+
686
+ **When to use:** Security-sensitive code, authentication systems, or any code where adversarial thinking improves quality.
687
+
688
+ #### 5. Hypothesis-Driven Investigation
689
+
690
+ The scientific method applied to debugging.
691
+
692
+ **Example: Scientific Method** (`scientific-method.yml`)
693
+
694
+ ```yaml
695
+ hats:
696
+ observer:
697
+ triggers: ["science.start", "hypothesis.rejected"]
698
+ publishes: ["observation.made"]
699
+
700
+ theorist:
701
+ triggers: ["observation.made"]
702
+ publishes: ["hypothesis.formed"]
703
+
704
+ experimenter:
705
+ triggers: ["hypothesis.formed"]
706
+ publishes: ["hypothesis.confirmed", "hypothesis.rejected"]
707
+
708
+ fixer:
709
+ triggers: ["hypothesis.confirmed"]
710
+ publishes: ["fix.applied"]
711
+ ```
712
+
713
+ ```
714
+ science.start → 🔬 Observer → observation.made → 🧠 Theorist →
715
+ hypothesis.formed → 🧪 Experimenter ──┬─→ hypothesis.confirmed → 🔧 Fixer
716
+
717
+ └─→ hypothesis.rejected ─┐
718
+
719
+ ┌────────────────────────────────────────────────┘
720
+ └──→ (back to Observer with new data)
721
+ ```
722
+
723
+ **When to use:** Complex bugs where the root cause isn't obvious. Forces systematic investigation over random fixes.
724
+
725
+ #### 6. Coordinator-Specialist (Fan-Out)
726
+
727
+ A coordinator delegates to specialists based on the work type.
728
+
729
+ **Example: Gap Analysis** (`gap-analysis.yml`)
730
+
731
+ ```yaml
732
+ hats:
733
+ analyzer:
734
+ triggers: ["gap.start", "verify.complete", "report.complete"]
735
+ publishes: ["analyze.spec", "verify.request", "report.request"]
736
+
737
+ verifier:
738
+ triggers: ["analyze.spec", "verify.request"]
739
+ publishes: ["verify.complete"]
740
+
741
+ reporter:
742
+ triggers: ["report.request"]
743
+ publishes: ["report.complete"]
744
+ ```
745
+
746
+ ```
747
+ ┌─→ analyze.spec ──→ 🔍 Verifier ──┐
748
+ │ │
749
+ gap.start → 📊 Analyzer ←── verify.complete ──────────┘
750
+
751
+ └─→ report.request ──→ 📝 Reporter ──→ report.complete
752
+ ```
753
+
754
+ **When to use:** Work that naturally decomposes into independent specialist tasks (analysis, verification, reporting).
755
+
756
+ #### 7. Adaptive Entry Point
757
+
758
+ A bootstrapping hat detects input type and routes to the appropriate workflow.
759
+
760
+ **Example: Code-Assist** (`code-assist.yml`)
761
+
762
+ ```yaml
763
+ hats:
764
+ planner:
765
+ triggers: ["build.start"]
766
+ publishes: ["tasks.ready"]
767
+ # Detects: PDD directory vs. code task file vs. description
768
+
769
+ builder:
770
+ triggers: ["tasks.ready", "validation.failed", "task.complete"]
771
+ publishes: ["implementation.ready", "task.complete"]
772
+
773
+ validator:
774
+ triggers: ["implementation.ready"]
775
+ publishes: ["validation.passed", "validation.failed"]
776
+
777
+ committer:
778
+ triggers: ["validation.passed"]
779
+ publishes: ["commit.complete"]
780
+ ```
781
+
782
+ ```
783
+ build.start → 📋 Planner ─── (detects input type) ───→ tasks.ready
784
+
785
+ ┌───────────────────────────────────────────────────────┘
786
+
787
+
788
+ ⚙️ Builder ←─────────────── validation.failed ←─────┐
789
+ │ │
790
+ ├── task.complete ──→ (loop for PDD mode) ──────┤
791
+ │ │
792
+ └── implementation.ready ──→ ✅ Validator ──────┤
793
+ │ │
794
+ └─→ validation.passed
795
+
796
+
797
+ 📦 Committer → commit.complete
798
+ ```
799
+
800
+ **When to use:** Workflows that need to handle multiple input formats or adapt their behavior based on context.
801
+
802
+ ### Designing Custom Hat Collections
803
+
804
+ #### Hat Configuration Schema
805
+
806
+ ```yaml
807
+ hats:
808
+ my_hat:
809
+ name: "🎯 Display Name" # Shown in TUI and logs
810
+ description: "What this hat does" # REQUIRED — Ralph uses this for delegation
811
+ triggers: ["event.a", "event.b"] # Events that activate this hat
812
+ publishes: ["event.c", "event.d"] # Events this hat can emit
813
+ default_publishes: "event.c" # Fallback if hat forgets to emit
814
+ max_activations: 10 # Optional cap on activations
815
+ backend: "claude" # Optional backend override
816
+ instructions: |
817
+ Prompt injected when this hat is active.
818
+ Tell the hat what to do, not how to do it.
819
+ ```
820
+
821
+ #### Design Principles
822
+
823
+ 1. **Description is critical** — Ralph uses hat descriptions to decide when to delegate. Make them clear and specific.
824
+
825
+ 2. **One hat, one responsibility** — Each hat should have a clear, focused purpose. If you're writing "and" in the description, consider splitting.
826
+
827
+ 3. **Events are routing signals, not data** — Keep payloads brief. Store detailed output in files and reference them in events.
828
+
829
+ 4. **Design for recovery** — If a hat fails or forgets to publish, Ralph catches the orphaned event. Your topology should handle unexpected states gracefully.
830
+
831
+ 5. **Test with simple prompts first** — Complex topologies can have emergent behavior. Start simple, validate the flow, then add complexity.
832
+
833
+ #### Validation Rules
834
+
835
+ Ralph validates hat configurations:
836
+
837
+ - **Required description**: Every hat must have a description (Ralph needs it for delegation context)
838
+ - **Reserved triggers**: `task.start` and `task.resume` are reserved for Ralph
839
+ - **No ambiguous routing**: Each trigger pattern must map to exactly one hat
840
+
841
+ ```
842
+ ERROR: Ambiguous routing for trigger 'build.done'.
843
+ Both 'planner' and 'reviewer' trigger on 'build.done'.
844
+ ```
845
+
846
+ ### Event Emission
847
+
848
+ Hats emit events to signal completion or hand off work:
849
+
850
+ ```bash
851
+ # Simple event with payload
852
+ ralph emit "build.done" "tests: pass, lint: pass"
853
+
854
+ # Event with JSON payload
855
+ ralph emit "review.done" --json '{"status": "approved", "issues": 0}'
856
+
857
+ # Direct handoff to specific hat (bypasses routing)
858
+ ralph emit "handoff" --target reviewer "Please review the changes"
859
+ ```
860
+
861
+ **In agent output**, events are embedded as XML tags:
862
+
863
+ ```xml
864
+ <event topic="impl.done">Implementation complete</event>
865
+ <event topic="handoff" target="reviewer">Please review</event>
866
+ ```
867
+
868
+ ### Choosing a Pattern
869
+
870
+ | Scenario | Recommended Pattern | Preset |
871
+ |----------|---------------------|--------|
872
+ | Sequential workflow with clear phases | Linear Pipeline | `tdd-red-green` |
873
+ | Spec must be approved before coding | Contract-First | `spec-driven` |
874
+ | Need multiple perspectives | Cyclic Rotation | `mob-programming` |
875
+ | Security review required | Adversarial | `adversarial-review` |
876
+ | Debugging complex issues | Hypothesis-Driven | `scientific-method` |
877
+ | Work decomposes into specialist tasks | Coordinator-Specialist | `gap-analysis` |
878
+ | Multiple input formats | Adaptive Entry | `code-assist` |
879
+ | Standard feature development | Basic delegation | `feature` |
880
+
881
+ ### When Not to Use Hats
882
+
883
+ Hat-based orchestration adds complexity. Use **traditional mode** (no hats) when:
884
+
885
+ - The task is straightforward and single-focused
886
+ - You don't need role separation or handoffs
887
+ - You're prototyping and want minimal configuration
888
+ - The work doesn't naturally decompose into distinct phases
889
+
890
+ Traditional mode is just Ralph in a loop until completion — simpler, faster to set up, and often sufficient.
891
+
410
892
  ### Memories and Tasks
411
893
 
412
894
  Ralph uses two complementary systems for persistent state (both enabled by default):
@@ -23,7 +23,7 @@
23
23
  "hasInstallScript": true,
24
24
  "license": "MIT",
25
25
  "name": "@ralph-orchestrator/ralph-cli",
26
- "version": "2.2.0"
26
+ "version": "2.2.1"
27
27
  },
28
28
  "node_modules/@isaacs/balanced-match": {
29
29
  "engines": {
@@ -515,5 +515,5 @@
515
515
  }
516
516
  },
517
517
  "requires": true,
518
- "version": "2.2.0"
518
+ "version": "2.2.1"
519
519
  }
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "artifactDownloadUrl": "https://github.com/mikeyobrien/ralph-orchestrator/releases/download/v2.2.0",
2
+ "artifactDownloadUrl": "https://github.com/mikeyobrien/ralph-orchestrator/releases/download/v2.2.1",
3
3
  "bin": {
4
4
  "ralph": "run-ralph.js"
5
5
  },
@@ -62,7 +62,7 @@
62
62
  "zipExt": ".tar.xz"
63
63
  }
64
64
  },
65
- "version": "2.2.0",
65
+ "version": "2.2.1",
66
66
  "volta": {
67
67
  "node": "18.14.1",
68
68
  "npm": "9.5.0"