How `swarm_handoff.sh` Validates Hand‑off Draft Files: A Deep Dive into SwarmForge's 7-Step Pipeline

The validation logic in swarm_handoff.sh is actually implemented in the accompanying swarm_handoff.bb Clojure/Babashka script, which runs a deterministic 7-step pipeline checking syntax, semantics, type compatibility, and Git integrity before queuing any hand‑off.

swarm_handoff.sh in the unclebob/swarm-forge repository serves as a thin Bash wrapper that delegates all work to swarm_handoff.bb. Understanding this validation logic is essential for developers creating hand‑off drafts that pass inspection and reach the outbox. Each validation step in swarm_handoff.bb is designed to catch specific categories of errors before malformed files propagate through the SwarmForge system.

Where the Validation Actually Lives

The Bash wrapper at swarmforge/scripts/swarm_handoff.sh contains no validation logic itself—it simply passes arguments to swarm_handoff.bb. All draft validation happens in the Babashka script at swarmforge/scripts/swarm_handoff.bb, specifically within functions parse-draft, validate-recipients, validate, and their helper functions.

Step 1: Parse the Draft File for Syntax Errors

The parse-draft function (lines 93–136) reads the hand‑off draft line‑by‑line and extracts field/value pairs. It collects multiple syntax errors rather than failing on the first:

  • Missing separator: Fields must use ": " (colon space)
  • Empty fields: Neither field names nor values can be blank
  • Duplicate headers: Each header may appear only once
  • Reserved fields: Fields like from, timestamp, and sequence are reserved for system use
  • Unknown fields: Any field not in the allowed set is rejected

This greedy error collection lets users fix multiple issues in one pass.


# Example syntax error caught by parse-draft

$ ./swarm_handoff.sh malformed.handoff
HANDOFF INVALID: malformed.handoff

Errors:
- Line 3: Missing ': ' separator.
- Duplicate header 'priority'.
- Unknown field 'urgency'.

Step 2: Validate Recipients in the to Header

The validate-recipients function (lines 138–156) processes the comma‑separated to field with four specific checks per recipient:

  1. Empty recipient – no blank entries between commas
  2. Underscores – illegal in recipient names
  3. Duplication – no repeated recipients allowed
  4. Unknown role – each recipient must exist in roles.tsv (checked via role-known?)

The roles.tsv file at .swarmforge/roles.tsv provides the canonical list of valid roles.

Step 3: Check Required Fields and Base Constraints

In the validate function (lines 195–202), the base-errors construction ensures:

  • type, to, and priority are all present
  • type matches allowed values: git_handoff or note
  • priority conforms to the two‑digit pattern (e.g., 01, 12)

Step 4: Apply Type‑Specific Header Validation

Depending on the type value, additional validation runs via git-errors (lines 211–222) or note-errors (lines 224–229):

git_handoff requirements:

  • commit header must be present and resolvable to a valid Git object
  • task header required, with length restrictions
  • Commit SHA canonicalized to short‑hash via canonical-commit

note requirements:

  • message header required, with length validation

Step 5: Enforce Field‑Type Compatibility

The field-errors comprehension (lines 181–194) ensures headers only appear when appropriate to their type. For example, task and commit are illegal in a note hand‑off, while message cannot appear in a git_handoff.

This prevents semantic confusion where fields meant for one hand‑off type leak into another.

Step 6: Canonicalize Git Commits

The canonical-commit function (lines 157–172) provides Git integrity validation:

  1. Runs git rev-parse --disambiguate to locate a unique object for the given SHA fragment
  2. Verifies the object is actually a commit (not a tree or blob)
  3. Returns the canonical short‑hash for consistent identification

This ensures hand‑offs reference real, reachable commits in the repository.

Step 7: Aggregate and Report All Errors

The final return of validate (lines 235–236) combines parsing errors, recipient errors, field‑type errors, and type‑specific errors into a single vector. The -main function at the bottom of swarm_handoff.bb orchestrates the flow:

  1. Parse → parse-draft
  2. Validate → validate (with all helper functions)
  3. If errors exist → print error-report and exit with status 2
  4. If clean → write hand‑off to .swarmforge/handoffs/outbox/

Valid vs. Invalid Hand‑off Examples

Valid git_handoff draft:

type: git_handoff
to: reviewer,qa
priority: 05
task: improve-login-flow
commit: a1b2c3d4e5
$ ./swarm_handoff.sh example.handoff
HANDOFF QUEUED: /path/to/.swarmforge/handoffs/outbox/05_20241012T083045Z_000123_from_alice_to_reviewer_qa.handoff

Invalid draft (missing commit, duplicate recipient):

type: git_handoff
to: reviewer,reviewer
priority: 09
task: refactor-auth
$ ./swarm_handoff.sh bad.handoff
HANDOFF INVALID: bad.handoff

Errors:
- Missing required header 'commit' for git_handoff.
- Duplicate recipient 'reviewer'.

Exit status 2 prevents queuing malformed hand‑offs.

Key Source Files for Hand‑off Validation

File Purpose
swarmforge/scripts/swarm_handoff.sh Bash wrapper forwarding to Babashka script
swarmforge/scripts/swarm_handoff.bb Core validation pipeline with all functions above
.swarmforge/roles.tsv Canonical role list for recipient validation
swarmforge/handoff-protocol.md Protocol specification for hand‑off format

Summary

The swarm_handoff.sh validation logic—implemented in swarm_handoff.bb—provides comprehensive draft checking through seven distinct steps:

  • Syntax validation via parse-draft catches formatting errors
  • Recipient validation via validate-recipients enforces role existence and naming rules
  • Base field requirements ensure mandatory headers are present and well‑formed
  • Type‑specific rules apply appropriate constraints for git_handoff vs. note
  • Field‑type compatibility prevents inappropriate header mixing
  • Git integrity checks via canonical-commit validate commit references
  • Aggregated error reporting gives complete feedback before any exit

This pipeline guarantees that only syntactically correct, semantically valid, and type‑appropriate hand‑offs reach the SwarmForge outbox.

Frequently Asked Questions

What exit status does swarm_handoff.sh return for invalid drafts?

Exit status 2. The script explicitly exits with code 2 when validation errors are found, after printing the error-report. Successful validation results in normal exit status 0 and the hand‑off being queued to the outbox.

Can I use underscores in recipient names according to swarm_handoff.sh validation?

No. The validate-recipients function explicitly rejects any recipient containing underscores. This is one of the four checks applied to each comma‑separated entry in the to header, alongside emptiness, duplication, and role existence in roles.tsv.

Why does swarm_handoff.sh delegate to a Babashka script rather than pure Bash?

The validation requirements—structured parsing, error aggregation, Git integration, and type‑dependent logic—are complex enough to benefit from Clojure's data structures and libraries. swarm_handoff.bb handles this elegantly while swarm_handoff.sh provides a familiar CLI entry point and handles environment setup.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →