Skip to content

Commit 81b0f10

Browse files
jcasimirclaude
andcommitted
feat: Add orchestrator support — /ce:run, sync, and /lfg refactor
Orchestrators are pluggable workflow definitions that control which phases to execute, which reviewers to prioritize, and how to synthesize findings. They use the same .md format as reviewers (YAML frontmatter + prose body). - Add /ce:run skill to load and execute named orchestrators - Add orchestrator-registry.yaml as default source config - Generalize sync-reviewers.sh to handle both reviewers and orchestrators via a config-name parameter - Update /ce:refresh to sync orchestrators alongside reviewers - Refactor /lfg to delegate to /ce:run lfg Orchestrator format supports: - phases with gates, skip conditions, and per-phase model overrides - review-preferences (required/preferred categories, min reviewers) - synthesis lens (how to weigh findings) - orchestrator-model vs agent-model for cost control - personality prose in the markdown body Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 81e62ed commit 81b0f10

5 files changed

Lines changed: 208 additions & 66 deletions

File tree

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
---
2+
name: ce:run
3+
description: "Run a named orchestrator to manage a full engineering workflow. Orchestrators define which phases to execute, which reviewers to prioritize, and how to synthesize findings. Use when you want a specific workflow style — e.g., /ce:run erin for full-process PM, /ce:run max for a quick spike."
4+
argument-hint: "<orchestrator-name> [feature description]"
5+
---
6+
7+
# Run Orchestrator
8+
9+
Loads a named orchestrator definition and executes its workflow.
10+
11+
## Step 1: Parse arguments
12+
13+
Split `$ARGUMENTS` into:
14+
- **Orchestrator name** — the first word (e.g., `erin`, `max`, `lfg`)
15+
- **Feature description** — everything after the first word
16+
17+
If no orchestrator name is provided, list available orchestrators and ask which to use.
18+
19+
## Step 2: Locate plugin
20+
21+
Find the plugin's install location:
22+
23+
```bash
24+
PLUGIN_DIR=$(find "$HOME/.claude" "$HOME/.claude-"* -path "*/compound-engineering/*/orchestrators" -type d 2>/dev/null | head -1 | sed 's|/orchestrators$||')
25+
```
26+
27+
Fall back to relative path if not found:
28+
29+
```bash
30+
PLUGIN_DIR="${PLUGIN_DIR:-plugins/compound-engineering}"
31+
```
32+
33+
## Step 3: Load orchestrator
34+
35+
Look for `$PLUGIN_DIR/orchestrators/<name>.md`. If not found:
36+
37+
1. List available orchestrators: `ls $PLUGIN_DIR/orchestrators/*.md`
38+
2. Show the user what's available
39+
3. Suggest running `/ce:refresh` if no orchestrators are found
40+
41+
Read the orchestrator file. Parse the YAML frontmatter for structured data (phases, review-preferences, synthesis) and the markdown body for personality/behavior prose.
42+
43+
## Step 4: Adopt the orchestrator persona
44+
45+
Before executing any phases, adopt the orchestrator's personality from the markdown body. This shapes how you communicate, make judgment calls, and interact with the user throughout the workflow.
46+
47+
If the orchestrator has `skip-when` conditions on optional phases, evaluate them against the feature description and current context to decide which phases to include.
48+
49+
## Step 5: Execute phases
50+
51+
For each phase in the `phases` list from frontmatter:
52+
53+
1. **Check if optional** — If the phase has `optional: true` and `skip-when`, evaluate whether to skip based on the feature description and context. Explain your reasoning to the user.
54+
55+
2. **Invoke the skill** — Run the skill specified in `skill:`, passing `args:` with variable substitution:
56+
- `$ARGUMENTS` → the feature description from step 1
57+
- `$PLAN_PATH` → the path to the plan file created during the plan phase
58+
59+
3. **Evaluate the gate** — If the phase has a `gate:`, verify the gate conditions are met before proceeding to the next phase. If the gate fails, retry or ask the user for guidance (depending on orchestrator personality).
60+
61+
4. **Track state** — Remember the plan file path when created, track which phases have completed, note key decisions.
62+
63+
5. **Handle signals** — If the phase has a `signal:` instead of a `skill:`, output that signal (e.g., `<promise>DONE</promise>`).
64+
65+
### Variable threading
66+
67+
- After the plan phase completes, scan `docs/plans/` for the most recently created plan file and store its path as `$PLAN_PATH`.
68+
- Pass `$PLAN_PATH` to subsequent phases that reference it in their `args:`.
69+
70+
## Step 6: Review preferences
71+
72+
When invoking `/ce:review`, pass the orchestrator's `review-preferences` and `synthesis` configuration as context:
73+
74+
- **min-reviewers** — Minimum number of reviewers to spawn
75+
- **require-categories** — Categories that must be represented (warn if no reviewer available)
76+
- **prefer-categories** — Categories to include if available
77+
- **synthesis.lens** — Pass this to the synthesis reviewer to shape how findings are weighted
78+
79+
These preferences guide reviewer selection but don't override the existing ce:review selection logic — they add constraints on top of it.
80+
81+
## Step 7: Model selection
82+
83+
Orchestrators define two model fields:
84+
85+
- **`orchestrator-model`** — The model for the orchestrator itself (the main conversation thread). `inherit` means use the session model.
86+
- **`agent-model`** — The default model for skills and subagents the orchestrator spawns.
87+
88+
Per-phase `model:` overrides take precedence over `agent-model`. Resolution order:
89+
90+
1. Phase-level `model:` (if specified)
91+
2. Orchestrator-level `agent-model:` (if specified)
92+
3. Session model (inherit)
93+
94+
When spawning Agent subagents, pass the resolved model. When invoking skills in the main conversation (e.g., `/ce:plan`), the orchestrator-model applies since skills run in the main thread.
95+
96+
## Step 8: Completion
97+
98+
When all phases are done, summarize the workflow:
99+
- Which phases ran (and which were skipped, with reasons)
100+
- Key decisions made along the way
101+
- Any learnings captured in the compound phase
102+
103+
Communicate completion in the orchestrator's voice.
104+
105+
## Available Orchestrators
106+
107+
To see what's installed, run:
108+
109+
```bash
110+
ls $PLUGIN_DIR/orchestrators/*.md 2>/dev/null | xargs -I{} basename {} .md
111+
```
112+
113+
If no orchestrators are found, run `/ce:refresh` to sync from configured sources.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Orchestrator Registry
2+
#
3+
# Orchestrator .md files live in external repos and are synced into
4+
# orchestrators/ via /ce:refresh. Each orchestrator's phases, review
5+
# preferences, and personality are defined in its own frontmatter
6+
# and body.
7+
#
8+
# To add a custom orchestrator:
9+
# 1. Add the .md file to your repo (with type: orchestrator in frontmatter)
10+
# 2. Run /ce:refresh to pull it in
11+
# 3. Use /ce:run <name> to invoke it
12+
13+
# === External orchestrator sources ===
14+
15+
sources:
16+
- name: ce-default
17+
repo: JumpstartLab/ce-reviewers-jsl
18+
branch: main
19+
path: orchestrators
Lines changed: 2 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,7 @@
11
---
22
name: lfg
3-
description: Full autonomous engineering workflow
3+
description: "Full autonomous engineering workflow. Shortcut for /ce:run lfg."
44
argument-hint: "[feature description]"
5-
disable-model-invocation: true
65
---
76

8-
CRITICAL: You MUST execute every step below IN ORDER. Do NOT skip any required step. Do NOT jump ahead to coding or implementation. The plan phase (step 2) MUST be completed and verified BEFORE any work begins. Violating this order produces bad output.
9-
10-
1. **Optional:** If the `ralph-loop` skill is available, run `/ralph-loop:ralph-loop "finish all slash commands" --completion-promise "DONE"`. If not available or it fails, skip and continue to step 2 immediately.
11-
12-
2. `/ce:plan $ARGUMENTS`
13-
14-
GATE: STOP. Verify that the `ce:plan` workflow produced a plan file in `docs/plans/`. If no plan file was created, run `/ce:plan $ARGUMENTS` again. Do NOT proceed to step 3 until a written plan exists. **Record the plan file path** — it will be passed to ce:review in step 4.
15-
16-
3. `/ce:work`
17-
18-
GATE: STOP. Verify that implementation work was performed - files were created or modified beyond the plan. Do NOT proceed to step 4 if no code changes were made.
19-
20-
4. `/ce:review mode:autofix plan:<plan-path-from-step-2>`
21-
22-
Pass the plan file path from step 2 so ce:review can verify requirements completeness.
23-
24-
5. `/compound-engineering:todo-resolve`
25-
26-
6. `/compound-engineering:test-browser`
27-
28-
7. `/compound-engineering:feature-video`
29-
30-
8. Output `<promise>DONE</promise>` when video is in PR
31-
32-
Start with step 2 now (or step 1 if ralph-loop is available). Remember: plan FIRST, then work. Never skip the plan.
7+
Run `/ce:run lfg $ARGUMENTS`

plugins/compound-engineering/skills/refresh/SKILL.md

Lines changed: 50 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
---
22
name: ce:refresh
3-
description: "Sync reviewer personas from external Git repos into the local plugin. Reads sources from reviewer-registry.yaml, fetches .md files, and places them in agents/review/. Use when setting up the plugin for the first time, after updating your reviewer repo, or to pull in new reviewer personas."
3+
description: "Sync reviewer personas and orchestrator definitions from external Git repos into the local plugin. Use when setting up the plugin for the first time, after updating your repos, or to pull in new reviewers or orchestrators."
44
---
55

6-
# Refresh Reviewers
6+
# Refresh Reviewers & Orchestrators
77

8-
Syncs reviewer persona files from external Git repositories into the plugin's `agents/review/` directory.
8+
Syncs reviewer persona files and orchestrator definitions from external Git repositories into the plugin.
99

1010
## Step 1: Locate plugin
1111

@@ -21,56 +21,87 @@ Fall back to relative path if not found (e.g., running from source repo):
2121
PLUGIN_DIR="${PLUGIN_DIR:-plugins/compound-engineering}"
2222
```
2323

24+
Ensure the orchestrators directory exists:
25+
26+
```bash
27+
mkdir -p "$PLUGIN_DIR/orchestrators"
28+
```
29+
2430
## Step 2: Interactive source configuration
2531

26-
Read the user's source config at `~/.config/compound-engineering/reviewer-sources.yaml`. If it doesn't exist, the sync script will create it on first run — skip this step and go directly to Step 3.
32+
Read the user's reviewer source config at `~/.config/compound-engineering/reviewer-sources.yaml`. If it doesn't exist, the sync script will create it on first run — skip this step and go directly to Step 3.
2733

2834
If the file exists, parse it and present the current sources to the user like this:
2935

3036
List the current sources, then present three options using AskUserQuestion:
3137

3238
```
33-
Current sources:
34-
- jsl-reviewers (JumpstartLab/ce-reviewers-jsl@main)
35-
- ce-default (JumpstartLab/ce-reviewers@main)
39+
Current reviewer sources:
40+
- jsl-reviewers (JumpstartLab/ce-reviewers-jsl@main, path: reviewers)
41+
- ce-default (JumpstartLab/ce-reviewers@main, path: reviewers)
42+
43+
Current orchestrator sources:
44+
- jsl-orchestrators (JumpstartLab/ce-reviewers-jsl@main, path: orchestrators)
3645
3746
1. Sync now
38-
2. Edit config file
47+
2. Edit config files
3948
3. Or type a request (e.g., "add owner/repo", "remove ce-default")
4049
```
4150

4251
Handle the response:
4352
- **1 / Sync now** — proceed to Step 3.
44-
- **2 / Edit config file** — open `~/.config/compound-engineering/reviewer-sources.yaml` via Bash: `${EDITOR:-$(command -v code 2>/dev/null || echo nano)} ~/.config/compound-engineering/reviewer-sources.yaml`. After the editor, re-read the file and present the menu again.
45-
- **Anything else** — interpret as a natural language request to modify the config (add a source, remove one, change a branch, add an except entry, etc.). Edit the YAML accordingly, then present the menu again.
53+
- **2 / Edit config files** — open both config files in editor. After editing, re-read and present the menu again.
54+
- **Anything else** — interpret as a natural language request to modify one or both configs. Edit accordingly, then present the menu again.
4655

47-
## Step 3: Sync
56+
## Step 3: Sync reviewers
4857

49-
Run the sync script:
58+
Run the sync script for reviewers:
5059

5160
```bash
5261
bash "$PLUGIN_DIR/skills/refresh/sync-reviewers.sh" \
5362
"$PLUGIN_DIR/skills/ce-review/references/reviewer-registry.yaml" \
5463
"$PLUGIN_DIR/agents/review"
5564
```
5665

57-
## Step 4: Show results
66+
## Step 4: Sync orchestrators
5867

59-
The script writes a summary to `~/.config/compound-engineering/last-refresh-summary.md`. Read that file and **output its contents to the user exactly as written**. The summary is already formatted as markdown — do not summarize, paraphrase, or reformat it. Just show it.
68+
Run the same sync script for orchestrators, using the orchestrator registry and output directory:
69+
70+
```bash
71+
bash "$PLUGIN_DIR/skills/refresh/sync-reviewers.sh" \
72+
"$PLUGIN_DIR/skills/ce-run/references/orchestrator-registry.yaml" \
73+
"$PLUGIN_DIR/orchestrators" \
74+
orchestrator
75+
```
76+
77+
**Note:** The sync script's third argument (`orchestrator`) tells it to use `orchestrator-sources.yaml` as the user config instead of `reviewer-sources.yaml`. It fetches `.md` files from configured sources regardless of content type.
78+
79+
## Step 5: Show results
80+
81+
The sync script writes summaries to `~/.config/compound-engineering/`:
82+
- `last-reviewer-refresh-summary.md` — reviewer sync results
83+
- `last-orchestrator-refresh-summary.md` — orchestrator sync results
84+
85+
Read both files and **output their contents to the user exactly as written**. The summaries are already formatted as markdown — do not summarize, paraphrase, or reformat them.
86+
87+
If only one summary file exists (e.g., no orchestrator sources configured yet), show just the one that exists.
6088

6189
## Source YAML Format
6290

91+
Both reviewer and orchestrator source configs use the same format:
92+
6393
```yaml
6494
sources:
65-
- name: my-reviewers
95+
- name: my-source
6696
repo: username/repo-name
6797
branch: main
68-
path: .
98+
path: reviewers
6999

70-
- name: community-reviewers
100+
- name: another-source
71101
repo: SomeOrg/ce-reviewers
102+
path: orchestrators
72103
except:
73-
- kieran-python-reviewer
104+
- name-to-skip
74105
```
75106
76107
| Field | Required | Default | Description |
@@ -79,7 +110,7 @@ sources:
79110
| `repo` | yes | — | GitHub owner/repo |
80111
| `branch` | no | `main` | Branch to fetch from |
81112
| `path` | no | `.` | Directory in the repo containing .md files |
82-
| `except` | no | `[]` | Reviewer filenames (without .md) to skip |
113+
| `except` | no | `[]` | Filenames (without .md) to skip |
83114

84115
## Conflict Resolution
85116

plugins/compound-engineering/skills/refresh/sync-reviewers.sh

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,46 @@
11
#!/usr/bin/env bash
22
#
3-
# sync-reviewers.sh — Fetch reviewer .md files from configured external repos
3+
# sync-reviewers.sh — Fetch .md files from configured external repos
44
#
5-
# Usage: ./sync-reviewers.sh <default-registry-yaml> <output-dir>
5+
# Usage: ./sync-reviewers.sh <default-registry-yaml> <output-dir> [<config-name>]
66
#
7-
# Checks for a user-level config at ~/.config/compound-engineering/reviewer-sources.yaml.
7+
# config-name defaults to "reviewer" — set to "orchestrator" for orchestrator sync.
8+
# Checks for a user-level config at ~/.config/compound-engineering/<config-name>-sources.yaml.
89
# If it doesn't exist, creates it from the default registry. Then reads sources from
910
# the user config, fetches .md files, and writes them to the output directory.
1011
# First-listed source wins on filename conflicts (processed in reverse order).
1112

1213
set -u
1314

14-
DEFAULT_REGISTRY="${1:?Usage: sync-reviewers.sh <default-registry-yaml> <output-dir>}"
15-
OUTPUT_DIR="${2:?Usage: sync-reviewers.sh <default-registry-yaml> <output-dir>}"
15+
DEFAULT_REGISTRY="${1:?Usage: sync-reviewers.sh <default-registry-yaml> <output-dir> [<config-name>]}"
16+
OUTPUT_DIR="${2:?Usage: sync-reviewers.sh <default-registry-yaml> <output-dir> [<config-name>]}"
17+
CONFIG_NAME="${3:-reviewer}"
1618

1719
USER_CONFIG_DIR="$HOME/.config/compound-engineering"
18-
USER_CONFIG="$USER_CONFIG_DIR/reviewer-sources.yaml"
20+
USER_CONFIG="$USER_CONFIG_DIR/${CONFIG_NAME}-sources.yaml"
1921

2022
# --- First-run: seed user config from default ---
2123
if [ ! -f "$USER_CONFIG" ]; then
2224
mkdir -p "$USER_CONFIG_DIR"
23-
cat > "$USER_CONFIG" << 'YAML'
24-
# Reviewer Sources
25+
CONFIG_LABEL="$(echo "$CONFIG_NAME" | sed 's/.*/\u&/')"
26+
cat > "$USER_CONFIG" << YAML
27+
# ${CONFIG_LABEL} Sources
2528
#
26-
# Configure which repos to pull reviewer personas from.
27-
# Run /ce:refresh to sync reviewers after editing this file.
29+
# Configure which repos to pull ${CONFIG_NAME} definitions from.
30+
# Run /ce:refresh to sync after editing this file.
2831
#
2932
# Sources listed first have higher priority. If two sources have
3033
# a file with the same name, the first source's version is kept.
3134
#
3235
# To add a source, copy this template and uncomment it:
3336
#
34-
# - name: my-reviewers
37+
# - name: my-${CONFIG_NAME}s
3538
# repo: owner/repo-name
3639
# branch: main
37-
# path: reviewers
40+
# path: ${CONFIG_NAME}s
3841
# except:
39-
# - reviewer-to-skip
40-
# - another-reviewer-to-skip
42+
# - name-to-skip
43+
# - another-to-skip
4144
4245
YAML
4346
# Append the sources from the default registry
@@ -54,7 +57,7 @@ for line in lines:
5457
print(line, end='')
5558
" >> "$USER_CONFIG"
5659
echo "Created $USER_CONFIG"
57-
echo "Edit this file to add your own reviewer repos, then run /ce:refresh again."
60+
echo "Edit this file to add your own ${CONFIG_NAME} repos, then run /ce:refresh again."
5861
echo ""
5962
fi
6063

@@ -185,8 +188,8 @@ sources_json=$(parse_sources)
185188
num_sources=$(echo "$sources_json" | python3 -c "import json,sys; print(len(json.load(sys.stdin)))")
186189

187190
if [ "$num_sources" -eq 0 ]; then
188-
echo "No external reviewer sources configured."
189-
echo "Add sources to reviewer-registry.yaml and run again."
191+
echo "No external ${CONFIG_NAME} sources configured."
192+
echo "Add sources to ${CONFIG_NAME}-sources.yaml and run again."
190193
exit 0
191194
fi
192195

@@ -301,10 +304,11 @@ done
301304
total=$((added + updated + unchanged))
302305

303306
# Write summary to a file that Claude can Read and show verbatim
304-
SUMMARY_FILE="${USER_CONFIG_DIR}/last-refresh-summary.md"
307+
CONFIG_LABEL="$(echo "$CONFIG_NAME" | sed 's/.*/\u&/')"
308+
SUMMARY_FILE="${USER_CONFIG_DIR}/last-${CONFIG_NAME}-refresh-summary.md"
305309

306310
{
307-
echo "# Reviewer Refresh Summary"
311+
echo "# ${CONFIG_LABEL} Refresh Summary"
308312
echo ""
309313

310314
# Per-source report — compact comma-separated format
@@ -339,7 +343,7 @@ for (( i=0; i<num_sources; i++ )); do
339343
echo ""
340344
done
341345

342-
echo "${total} reviewers synced. ${added} added, ${updated} updated, ${unchanged} unchanged."
346+
echo "${total} ${CONFIG_NAME}s synced. ${added} added, ${updated} updated, ${unchanged} unchanged."
343347
[ "$skipped" -gt 0 ] && echo "${skipped} excluded by config."
344348
[ "$conflicts" -gt 0 ] && echo "${conflicts} conflicts resolved (first source wins)."
345349
} > "$SUMMARY_FILE"

0 commit comments

Comments
 (0)