# How `ready_for_next.sh` Dispatches to Task vs Batch Helpers in Swarm-Forge

> Discover how ready_for_next.sh dispatches to task or batch helpers in Swarm-Forge by inspecting the role's receive mode for efficient processing.

- Repository: [Robert C. Martin/swarm-forge](https://github.com/unclebob/swarm-forge)
- Tags: internals
- Published: 2026-08-30

---

**[`ready_for_next.sh`](https://github.com/unclebob/swarm-forge/blob/main/ready_for_next.sh) delegates to a Babashka script that inspects the current role's receive mode, then dispatches to either [`ready_for_next_task.sh`](https://github.com/unclebob/swarm-forge/blob/main/ready_for_next_task.sh) for single-task processing or [`ready_for_next_batch.sh`](https://github.com/unclebob/swarm-forge/blob/main/ready_for_next_batch.sh) for batch processing.**

The [`ready_for_next.sh`](https://github.com/unclebob/swarm-forge/blob/main/ready_for_next.sh) dispatcher is a critical orchestration component in the [swarm-forge](https://github.com/unclebob/swarm-forge) project by Uncle Bob. This shell-to-Babashka dispatch pattern enables clean separation between task-oriented and batch-oriented work handoffs, with the routing decision determined dynamically at runtime based on role configuration.

## The Dispatch Chain: From Shell to Helper

The execution flow follows a consistent four-step pattern that keeps the shell layer thin and pushes logic into Clojure-based Babashka scripts.

### Step 1: Shell Entry Point

[`ready_for_next.sh`](https://github.com/unclebob/swarm-forge/blob/main/ready_for_next.sh) performs minimal setup before handing off control. It changes to its directory and executes `ready_for_next.bb` with any arguments passed through.

```bash
#!/bin/bash

# ready_for_next.sh - swarm-forge dispatcher entry point

cd "$(dirname "$0")"
bb ready_for_next.bb "$@"

```

This pattern appears throughout the swarm-forge scripts: shell wrappers provide portability while Babashka scripts contain the actual dispatch logic.

### Step 2: Mode Detection via handoff-lib

Inside `ready_for_next.bb`, the `handoff-lib` library is loaded via `require`. This library exposes two essential functions:

- **`handoff-lib/role`** — returns the current role name
- **`handoff-lib/role-receive-mode`** — returns `"task"`, `"batch"`, or another configured value

The role's receive mode is the single source of truth for dispatch routing.

### Step 3: Case-Based Dispatch

A `case` expression in `ready_for_next.bb` matches the receive mode to the appropriate helper:

```clojure
;; ready_for_next.bb - core dispatch logic
(ns ready-for-next
  (:require [handoff-lib :as h]))

(defn run-helper! [script]
  (babashka.process/exec script))

(let [role-name (h/role)
      mode (h/role-receive-mode role-name)]
  (case mode
    "batch" (run-helper! "ready_for_next_batch.sh")
    "task"  (run-helper! "ready_for_next_task.sh")
    (babashka.core/exit! 2 
      (str "INVALID_RECEIVE_MODE: " mode " for role " role-name))))

```

The dispatch is **exhaustive and strict** — any unrecognized mode triggers an immediate exit with code 2, surfacing configuration errors rather than failing silently.

### Step 4: Helper Execution

Selected helpers are launched via `babashka.process/exec`, which replaces the current process. Both helpers follow the same pattern as the parent:

| Helper Script | Purpose | Underlying Implementation |
|-------------|---------|--------------------------|
| [`ready_for_next_batch.sh`](https://github.com/unclebob/swarm-forge/blob/main/ready_for_next_batch.sh) | Batch work handoffs | `ready_for_next_batch.bb` |
| [`ready_for_next_task.sh`](https://github.com/unclebob/swarm-forge/blob/main/ready_for_next_task.sh) | Single-task handoffs | `ready_for_next_task.bb` |

Each helper is itself a thin wrapper, maintaining architectural consistency across the codebase.

## Key Source Files and Their Responsibilities

Understanding the file structure clarifies where dispatch logic resides versus where execution happens:

- **[`swarmforge/scripts/ready_for_next.sh`](https://github.com/unclebob/swarm-forge/blob/main/swarmforge/scripts/ready_for_next.sh)** — Portable shell entry point
- **`swarmforge/scripts/ready_for_next.bb`** — Core dispatcher with mode-detection and routing
- **`swarmforge/scripts/handoff_lib.bb`** — Reusable role and mode introspection
- **[`swarmforge/scripts/ready_for_next_batch.sh`](https://github.com/unclebob/swarm-forge/blob/main/swarmforge/scripts/ready_for_next_batch.sh)** / **`.bb`** — Batch processing pipeline
- **[`swarmforge/scripts/ready_for_next_task.sh`](https://github.com/unclebob/swarm-forge/blob/main/swarmforge/scripts/ready_for_next_task.sh)** / **`.bb`** — Single-task processing pipeline

## Running the Dispatcher

Invoke the dispatcher directly from the repository root:

```bash

# Execute with default role resolution

./swarmforge/scripts/ready_for_next.sh

# Pass arguments through to the underlying handlers

./swarmforge/scripts/ready_for_next.sh --verbose

```

The actual helper executed depends entirely on the current role's receive mode configuration in `handoff_lib.bb`.

## Design Rationale: Why This Dispatch Pattern?

The swarm-forge architecture separates **dispatch concerns** from **execution concerns** for several maintainability benefits:

- **Role-driven configuration** — Receive modes are data, not code
- **Minimal shell surface area** — Easy to port or wrap
- **Explicit failure modes** — Invalid modes halt immediately with diagnostic output
- **Symmetric helper structure** — Task and batch paths share identical wrapper patterns

This design allows operators to change processing semantics by modifying role configuration rather than shell scripts.

## Summary

- [`ready_for_next.sh`](https://github.com/unclebob/swarm-forge/blob/main/ready_for_next.sh) is a thin shell wrapper that forwards to `ready_for_next.bb`
- Dispatch routing depends on **`handoff-lib/role-receive-mode`**, which returns `"task"` or `"batch"`
- A **`case`** expression in `ready_for_next.bb` selects and executes the appropriate helper
- **Invalid modes** cause immediate termination with exit code 2
- Both task and batch helpers maintain architectural consistency with shell wrappers around Babashka implementations

## Frequently Asked Questions

### How does ready_for_next.sh know which mode to use?

The mode is not passed as an argument or hardcoded. Instead, `ready_for_next.bb` calls `handoff-lib/role` to determine the current role, then queries `handoff-lib/role-receive-mode` with that role name. This function returns a string that drives the `case` dispatch.

### What happens if a role has an invalid receive mode?

The `case` expression includes a fallback clause that calls `babashka.core/exit!` with code 2 and an error message containing the invalid mode and role name. This prevents silent misrouting and surfaces configuration problems immediately.

### Can I run the batch or task helpers directly?

Yes, though this bypasses the role-based dispatch logic. Both [`ready_for_next_batch.sh`](https://github.com/unclebob/swarm-forge/blob/main/ready_for_next_batch.sh) and [`ready_for_next_task.sh`](https://github.com/unclebob/swarm-forge/blob/main/ready_for_next_task.sh) are executable independently. However, direct invocation is generally discouraged in production since it ignores the role's configured receive mode.

### Why use Babashka for dispatch instead of pure Bash?

Babashka provides structured data handling, a `case` expression with exhaustiveness checking, and reusable library code via `require`. The `handoff-lib` abstraction would be significantly more verbose and error-prone to replicate in shell, particularly for role and mode resolution logic.