# How Back‑One and Back‑All Propagation Tokens Work Without Moving Task Cards in Swarm Forge

> Learn how back-one and back-all propagation tokens work in Swarm Forge without moving task cards. Discover the mechanism behind non-forwarding copies and their impact on UI.

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

---

**The `back-one` and `back-all` propagation tokens queue merge‑only handoff copies to earlier roles, but because these copies are marked non‑forwarding, they never update the board card's `to:` list—so the UI leaves the task card in place until the terminal handoff completes.**

Swarm Forge, an open‑source multi‑agent orchestration framework by Uncle Bob, uses propagation tokens in [`swarmforge.conf`](https://github.com/unclebob/swarm-forge/blob/main/swarmforge.conf) to control how handoffs flow through a pack of roles. This article explains the mechanics of **`back-one`** and **`back-all`**, tracing the implementation from configuration to the Clojure functions that make cards stay put.

## Understanding Propagation Tokens in swarmforge.conf

A window line in [`swarmforge.conf`](https://github.com/unclebob/swarm-forge/blob/main/swarmforge.conf) declares how a role handles incoming and outgoing handoffs. The syntax includes an optional propagation token after the receive mode:

```text
window <role> <agent> <worktree> [task|batch] [forward-only|back-one|back-all] …

```

- **`forward-only`**: Default behavior. The handoff advances to the next role, and the board card moves forward.
- **`back-one`**: Delivers to the next role, **plus** a merge‑only copy to the immediate predecessor.
- **`back-all`**: Delivers to the next role, **plus** merge‑only copies to **all** earlier roles in the pack.

These merge‑only copies let prior roles incorporate changes without re‑triggering the workflow.

## Why Task Cards Don't Move on Back Propagation

The key insight lies in how Swarm Forge distinguishes **forwarding** from **merge‑only** handoffs. According to the hand‑off protocol in the source repository:

> Merge‑only copies are **non‑forwarding**: the receiving role merges the commit but does **not** issue a further handoff.

Because the handoff lacks a `forward` entry for the earlier roles, the UI ignores them for card movement. Only the **terminal handoff**—the one with a complete recipient list reaching the final role—triggers the transition to **Done**.

## The reverse-roles Function in swarm_handoff.bb

The core selection logic lives in `swarmforge/scripts/swarm_handoff.bb`. The `reverse-roles` function determines which earlier roles receive merge‑only copies:

```clojure
(defn reverse-roles [sender]
  (let [roles (pack-role-names)
        idx   (.indexOf roles sender)]
    (if (neg? idx)
      []
      (case (handoff-lib/role-propagation sender)
        "back-one" (if (pos? idx) [(nth roles (dec idx))] [])
        "back-all" (vec (take idx roles))
        []))))

```

### How It Works

1. **`pack-role-names`** returns the ordered list of roles in the current pack.
2. **`handoff-lib/role-propagation`** reads the sender's propagation token from configuration.
3. **For `back-one`**: Returns the single role at index `(dec idx)`—the immediate predecessor, if one exists.
4. **For `back-all`**: Returns `vec (take idx roles)`—every role appearing before the sender.

The returned roles then receive inbox copies marked with `with-non-forwarding`, preventing any downstream handoff generation.

## Code Example: A Three‑Role Pack

Consider a pack with roles `[coder, cleaner, architect]`:

```clojure
;; Architect sends with `back-one` token
(reverse-roles "architect")
;;=> ["cleaner"]  ; only immediate predecessor

;; Architect sends with `back-all` token  
(reverse-roles "architect")
;;=> ["coder" "cleaner"]  ; all earlier roles

```

In both cases, the architect's primary handoff still routes to the next role (or completes if terminal). The merge‑only copies are side deliveries that update earlier worktrees without advancing the board state.

## The Non‑Forwarding Marker

Within `swarm_handoff.bb`, the `with-non-forwarding` wrapper ensures these copies cannot spawn further handoffs. This containment guarantees that:

- Earlier roles see the code changes.
- No infinite loops or redundant forward chains occur.
- The board card's position reflects **only** the terminal handoff's completion status.

## Summary

- **Propagation tokens** in [`swarmforge.conf`](https://github.com/unclebob/swarm-forge/blob/main/swarmforge.conf) (`back-one`, `back-all`) configure retroactive visibility without workflow re‑entry.
- **`reverse-roles`** in `swarm_handoff.bb` implements the selection logic using pack ordering and the sender's token.
- **Merge‑only, non‑forwarding copies** update earlier roles' worktrees but omit `forward` entries, so the UI never moves the task card on these arrivals.
- **Card movement** happens exclusively when the terminal handoff updates the final role's `to:` list.

## Frequently Asked Questions

### What is the default propagation behavior in Swarm Forge?

**`forward-only`** is the default. When omitted, a role's handoffs advance only to the next role in the pack, and the board card moves forward normally. No copies are sent to earlier roles.

### Can a role use both `back-one` and `back-all` simultaneously?

No. The `case` statement in `reverse-roles` evaluates the propagation token as a single value. A role must declare one token—or none—in its [`swarmforge.conf`](https://github.com/unclebob/swarm-forge/blob/main/swarmforge.conf) window line. The implementation does not support combining these modes.

### Why distinguish merge‑only copies from regular handoffs at all?

The separation prevents **re‑forwarding loops** and **spurious card movement**. If earlier roles received standard handoffs, they would issue their own forward handoffs, potentially cycling indefinitely. The non‑forwarding constraint preserves determinism in the pack's state machine.

### Where does the UI check whether to move a card?

Per the [`README.md`](https://github.com/unclebob/swarm-forge/blob/main/README.md) board UI description, the interface examines the `to:` list of the **last role's handoff**. Merge‑only copies lack this entry for their recipients, so the UI ignores them for transition purposes.