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