# How `get-swarm-forge` Composes Shared Articles with Local Overrides in Swarm Forge

> Learn how get-swarm-forge composes shared articles with local overrides in Swarm Forge. Discover the article composition process and local file merging.

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

---

**`get-swarm-forge` composes the final constitution by copying three shared articles from the main branch first, then adding pack-specific extensions while explicitly blocking any pack override of the shared files, and finally including `local-*.prompt` files that are merged at runtime with their matching shared counterparts.**

The `get-swarm-forge` installer in the [unclebob/swarm-forge](https://github.com/unclebob/swarm-forge) repository implements a strict, three-tier composition model that guarantees canonical shared articles remain authoritative while allowing packs to extend behavior safely. This article explains exactly how the script stitches together base branch files, pack templates, and local overrides.

## The Three-Tier Composition Model

`get-swarm-forge` builds a **forge** by sequencing three distinct sources in a specific priority order:

| Source | Contribution | Handling Mechanism |
|--------|-----------|------------------|
| **Base branch (`main`)** | Canonical shared constitution articles: `engineering.prompt`, `workflow.prompt`, `handoffs.prompt`, plus host scripts and core configuration | Copied verbatim into `swarmforge/constitution/articles/` |
| **Pack branches** (`two-pack`, `four-pack`, `six-pack`) | Pack-specific files: `swarm`, [`swarmforge/swarmforge.conf`](https://github.com/unclebob/swarm-forge/blob/main/swarmforge/swarmforge.conf), role prompts, and local constitution extensions | All files copied **except** the three shared article names |
| **Local overrides** (`local-*.prompt`) | Pack-specific customizations that extend shared articles without replacing them | Copied unchanged; merged at runtime with corresponding shared article |

This design enforces a critical invariant: **shared articles always originate from `main`, never from a pack**.

## Copying Shared Articles from the Base Branch

The installer begins by establishing the canonical foundation. In `get-swarm-forge` at lines 75-82, the script copies the three shared articles directly from the base branch:

```bash

# Inside the installer – copy shared articles from the base branch

for shared_article in engineering.prompt workflow.prompt handoffs.prompt; do
  [[ -f "$base_dir/swarmforge/constitution/articles/$shared_article" ]] &&
    cp "$base_dir/swarmforge/constitution/articles/$shared_article" \
       "swarmforge/constitution/articles/$shared_article"
done

```

These files become the authoritative **shared articles** for the installed forge:

- `swarmforge/constitution/articles/engineering.prompt` — shared engineering rules
- `swarmforge/constitution/articles/workflow.prompt` — shared workflow rules  
- `swarmforge/constitution/articles/handoffs.prompt` — shared handoff rules

## The `copy_pack_template` Function: Selective Pack Copying

The `copy_pack_template` function (lines 53-62) implements the core override-prevention logic. When processing a pack's `constitution/articles/` directory, the script explicitly skips any file matching the three shared article names:

```bash

# Inside the installer – copy pack articles, skipping shared ones

for pack_article in "$src/swarmforge/constitution/articles"/*; do
  [[ -f "$pack_article" ]] || continue
  article_name="${pack_article:t}"
  case "$article_name" in
    engineering.prompt|workflow.prompt|handoffs.prompt) continue ;;
  esac
  cp "$pack_article" "$dest/swarmforge/constitution/articles/$article_name"
done

```

The `case` statement with `continue` ensures that even if a pack contains files named `engineering.prompt`, `workflow.prompt`, or `handoffs.prompt`, they are **never copied**. This hardcoded exclusion guarantees pack authors cannot accidentally or intentionally override the canonical shared rules.

## How Local Overrides Work

Because the shared articles are excluded from pack copying, any file following the `local-*.prompt` naming convention passes through unchanged. These files serve as **extensions** rather than replacements.

For example, a pack might include:

```sh

# Pack-specific local extensions present after install:

ls packs/six-pack/swarmforge/constitution/articles/

# → local-workflow.prompt  local-engineering.prompt  (no engineering.prompt)

```

At runtime, the forge merges each `local-*.prompt` with its corresponding shared article. The README (lines 240-259) clarifies this convention:

> "The `local-*.prompt` naming convention means *add to or specialize* the shared default article for this pack. … Shared article filenames are never taken from the pack."

This creates a clean separation: **packs can only add rules, never modify or remove the shared foundation**.

## Complete Installation Walkthrough

Running the installer produces this deterministic structure:

```sh

# Install the forge (copies shared articles)

./get-swarm-forge

# After install, shared articles are present:

ls swarmforge/constitution/articles/

# → engineering.prompt workflow.prompt handoffs.prompt

```

The resulting constitution combines:

1. **Shared base** — unmodified `main` branch articles
2. **Pack additions** — all non-conflicting files from the selected pack
3. **Local extensions** — `local-*.prompt` files that specialize behavior at runtime

## Why This Design Prevents Accidental Overrides

The composition model eliminates an entire class of configuration errors. Without the explicit exclusion in `copy_pack_template`, a pack maintainer could unknowingly ship an `engineering.prompt` that diverges from the canonical rules, fragmenting the swarm's behavior across different installations.

By centralizing the three shared articles in `main` and enforcing the `local-*.prompt` convention, `unclebob/swarm-forge` ensures:

- **Determinism** — every forge installation receives identical shared articles
- **Extensibility** — packs customize without constraint (via `local-*.prompt`)
- **Safety** — no pack can silently override core constitutional rules

## Summary

- **`get-swarm-forge` copies shared articles first** from `main` to establish canonical rules
- **`copy_pack_template` skips shared filenames** — the `case` statement with `continue` blocks pack overrides of `engineering.prompt`, `workflow.prompt`, and `handoffs.prompt`
- **`local-*.prompt` files extend shared articles** — copied unchanged and merged at runtime
- **The README documents this contract** — packs must use the `local-*.prompt` convention to specialize behavior

## Frequently Asked Questions

### What happens if a pack includes its own `engineering.prompt`?

The `copy_pack_template` function explicitly skips it. The `case` statement at lines 54-61 matches `engineering.prompt|workflow.prompt|handoffs.prompt` and executes `continue`, preventing the file from being copied. The forge always uses the version from `main`.

### How does `local-workflow.prompt` differ from `workflow.prompt` in a pack?

A pack's `local-workflow.prompt` is copied normally (it doesn't match the exclusion pattern), while `workflow.prompt` would be skipped. At runtime, the forge merges `local-workflow.prompt` with the shared `workflow.prompt` from `main`, allowing additive customization without replacement.

### Can a pack completely replace a shared article's behavior?

No — the architecture intentionally prevents this. Complete replacement would require modifying the shared article file directly, which `get-swarm-forge` blocks. Packs must work within the extension model using `local-*.prompt` files.

### Where is the override-prevention logic located?

The critical logic resides in `get-swarm-forge` at lines 53-62 (`copy_pack_template` function) and lines 75-82 (shared article copying). The README at lines 240-259 documents the design rationale.