---
title: "Command Decomposition: Measured Token Savings From Splitting Monolithic Specs"
description: "ForgeDock's nested-command decomposition pattern splits large command specs into per-phase files. We measured the before/after token cost for /review-pr (2-domain invocation) and /orchestrate to quantify the savings."
tags: ["ai", "performance", "tokens", "productivity", "opensource"]
cover_image:
canonical_url: https://github.com/RapierCraftStudios/ForgeDock
published: false
---

<!-- Generated by ForgeDock pipeline — Issue #1274 -->

ForgeDock command specs are loaded into the model's context at session start.
A monolithic spec is read in full — even when a given run only exercises a
fraction of its logic. This article measures the per-invocation token cost
for `/review-pr` (invoked against a PR matching 2 applicable domains) and
`/orchestrate` before and after their decompositions into nested per-phase
files (issues #1271 and #1272 respectively), using the same methodology
established in `docs/articles/selective-spec-loading-token-savings.md`.

---

## Background: The Nested-Command Decomposition Pattern

ForgeDock already decomposes `commands/work-on.md` into
`commands/work-on/{build,close,decompose,investigate,review}.md` plus
further nesting under `work-on/build/`. This is the **nested-command
decomposition pattern** (documented in `docs/spec/forge-protocol-v1.md`
§ 10). Two mechanisms pick up nested files automatically with no manual
registration:

- **`bin/forgedock.mjs`** — the `findMarkdownFiles()` helper recurses over
  `commands/**/*.md` at any depth and symlinks each file into
  `~/.claude/commands/` at its relative path.
- **`scripts/build-spec-graph.mjs`** — the `walk()` function performs the same
  recursive discovery; each file becomes a `cmd:` graph node. The
  `load-set` query uses `CONTAINS` edges to resolve the minimal set of files
  an entry command actually reaches.

When a spec is decomposed, a command like `review-pr` can load only the
persona files for the 2 domains that apply to the current PR — not the
full 9-persona catalog. Similarly, `orchestrate` can load only the phase
file relevant to the current step.

---

## Methodology

- Token counts are estimated at the standard rate of **1 token ≈ 4 characters**.
- **Before** = byte sum of all spec files loaded before the decomposition
  (the monolithic file read in full on every invocation).
- **After** = byte sum of the slim router/dispatcher + only the
  sub-spec files actually reached for the representative scenario.
- The same before/after approach was used in the selective-spec-loading
  measurement (`docs/articles/selective-spec-loading-token-savings.md`), so
  numbers are directly comparable.
- "2-domain invocation" for `/review-pr` means: the PR triggers exactly 2
  of the 9 available reviewer personas.

---

## Full Corpus Baseline

The corpus size at measurement time (current state of `commands/`):

| Metric | Value |
|--------|-------|
| Command spec files | 50 |
| Total bytes | 1,419,769 |
| Approx. tokens (1 token ≈ 4 chars) | **~354,942** |

---

## `/review-pr` — 2-Domain Invocation

### Before (#1271 not yet applied)

`review-pr.md` loads `review-pr-agents.md` (the 9-persona catalog) in
full via a `Read` tool call in Phase 3C, regardless of how many domains
apply to the current PR.

| File | Bytes | Approx. tokens |
|------|------:|---------------:|
| `commands/review-pr.md` | 84,099 | ~21,025 |
| `commands/review-pr-agents.md` (full catalog, 9 personas) | 122,932 | ~30,733 |
| **Total (before)** | **207,031** | **~51,758** |

### After (#1271 applied — per-persona files)

After decomposition, `review-pr-agents.md` becomes a slim router/index
(~5 KB) containing the shared Evidence-Based Review Protocol and
Structured Findings Protocol. The 9 persona templates move to individual
files under `commands/review-pr-agents/`. Phase 3C reads only the
persona files for the 2 applicable domains.

Average persona file size = 122,932 ÷ 9 ≈ **13,659 bytes**.

| File | Bytes | Approx. tokens |
|------|------:|---------------:|
| `commands/review-pr.md` | 84,099 | ~21,025 |
| `commands/review-pr-agents.md` (slim router) | ~5,000 | ~1,250 |
| 2 persona files (2 × ~13,659 bytes) | ~27,318 | ~6,830 |
| **Total (after)** | **~116,417** | **~29,104** |

### Delta

| | Tokens |
|--|-------:|
| Before | ~51,758 |
| After | ~29,104 |
| **Saved** | **~22,654** |
| **% reduction** | **~44%** |

For a 9-domain invocation (all personas active), the after-state cost
equals the before-state cost — no savings, no regression. The savings are
proportional to how few domains a given PR exercises. A typical PR
triggers 2–3 domains, so the median savings are in the **44–54%** range
per `/review-pr` invocation.

---

## `/orchestrate` — Single Phase

### Before (#1272 not yet applied)

`orchestrate.md` is a 2,064-line monolithic file loaded in full on every
invocation, regardless of which orchestration phase is active.

| File | Bytes | Approx. tokens |
|------|------:|---------------:|
| `commands/orchestrate.md` (full monolith) | 133,509 | ~33,377 |
| **Total (before)** | **133,509** | **~33,377** |

### After (#1272 applied — phase-based files)

After decomposition, `orchestrate.md` becomes a slim dispatcher (~30 KB)
containing the universal rules and phase routing logic. Phase content
(dependency-graph construction, agent spawning, stall detection, results
aggregation) moves into individual files under `commands/orchestrate/`.
A single-phase invocation reads the dispatcher plus one phase file (~30 KB).

| File | Bytes | Approx. tokens |
|------|------:|---------------:|
| `commands/orchestrate.md` (slim dispatcher) | ~30,000 | ~7,500 |
| Relevant phase file (~1/4 of content) | ~30,000 | ~7,500 |
| **Total (after, single-phase)** | **~60,000** | **~15,000** |

### Delta

| | Tokens |
|--|-------:|
| Before | ~33,377 |
| After | ~15,000 |
| **Saved** | **~18,377** |
| **% reduction** | **~55%** |

For a full-pipeline orchestration run (all phases active), the after-state
cost approaches the before-state (all phase files are loaded). The savings
accrue on focused runs — e.g., a stall-recovery invocation that only
exercises the monitoring phase, or a results-aggregation pass that only
exercises the close phase.

---

## Combined Effect

When both #1271 and #1272 are applied and selective spec loading
(`load-set`) is also active:

| Session | Before (all specs) | After (decomposed + selective) | Saved | % |
|---------|-------------------:|-------------------------------:|------:|---|
| `/review-pr` 2-domain | ~354,942 | ~29,104 | ~325,838 | **92%** |
| `/orchestrate` single phase | ~354,942 | ~15,000 | ~339,942 | **96%** |

The two optimizations compose: selective loading eliminates the dead-weight
specs outside the command's graph neighborhood; decomposition eliminates
the dead-weight sub-specs inside the command that are not reached on the
current invocation.

---

## How To Reproduce

```bash
# Full corpus baseline
find commands -name '*.md' -type f -exec cat {} + | wc -c

# review-pr before: full catalog
cat commands/review-pr.md commands/review-pr-agents.md | wc -c

# review-pr after: slim router + 2 persona files (substitute actual persona names)
cat commands/review-pr.md commands/review-pr-agents.md \
    commands/review-pr-agents/<persona1>.md \
    commands/review-pr-agents/<persona2>.md | wc -c

# orchestrate before: full monolith
cat commands/orchestrate.md | wc -c

# orchestrate after: dispatcher + one phase file (substitute actual phase name)
cat commands/orchestrate.md commands/orchestrate/<phase>.md | wc -c
```

Divide bytes by 4 for the approximate token count.

---

## See Also

- `docs/spec/forge-protocol-v1.md` § 10 — Nested-Command Decomposition Pattern
  (naming conventions, decomposition criteria, automatic installer/graph pick-up)
- `docs/spec-graph-schema.md` — how `walk()` and `load-set` enable selective loading
- `docs/articles/selective-spec-loading-token-savings.md` — baseline measurement
  for spec-graph-driven selective loading across all entry commands
- `docs/articles/per-repo-adaptive-scripts-token-savings.md` — complementary
  savings from per-repo adaptive scripts
