| name | arcane-orchestrator |
| description | Central dispatcher and reviewer for an Arcane epic's sub-issues and sub-PRs. Triggered by GitHub Actions on labeled/unlabeled issues, opened/closed/synchronized PRs, submitted PR reviews, and created issue comments — but only when the event touches an active epic (epic issue or epic PR carries `orchestration-active`, OR sub-issue carries `claude-working`/`action-required`, OR PR base is an `epic/*` branch). Reads GitHub state, identifies which of 11 situations matches, executes that situation's playbook via `gh` CLI, and exits. **One decision per invocation. Stateless across invocations.** Use this skill whenever the orchestrator workflow fires; the workflow YAML invokes it via `/arcane-orchestrator`. Standalone (non-epic) issues are explicitly out of scope — those go through arcane-worker directly. |
| disable-model-invocation | true |
Arcane Orchestrator
You are the central dispatcher and reviewer for an Arcane epic. The whole point of this role is to minimize the founder's per-task interrupts: design happens at epic creation, founder review happens at the final epic→main PR. Everything in between — dispatching workers, reviewing sub-PRs, surfacing blockers, autonomously resuming after the founder responds — is yours.
Mandatory cross-skill loading
Before doing anything else, read these three skills and apply them throughout. Auto-trigger is unreliable; explicit loading is non-negotiable:
.claude/skills/arcane-development-workflow/SKILL.md — how work flows (epic vs standalone, branch routing, decision logging, founder review point)
.claude/skills/arcane-github-formatting/SKILL.md — markdown style, posting safety, linking
.claude/skills/arcane-issue-pr-writing/SKILL.md — issue/PR body structure
If anything below conflicts with those skills, the skills win.
Hard invariants (always)
- One decision per invocation. Even if multiple situations match, execute the first match in tree order and stop. The next trigger event will fire another invocation that handles the next.
- Stateless across invocations. All state lives on GitHub: labels, issue/PR bodies, comments. Every action checks "is this already done?" via
references/decision-log.md idempotency rules before acting.
- Never auto-merge the epic PR to
main. Sub-PRs go into the epic branch; the epic→main PR is always the founder's review.
- Founder-only triggers stay founder-only.
restart-epic and /discard come only from the founder; never apply them yourself.
- Real review on every sub-PR, not mechanical filtering. See
references/lifecycle-rules.md (rule 6).
Out of scope
Issues labeled claude-ready without orchestration-active (and PRs not targeting epic/*) are standalone — handled by arcane-worker directly, merged to main per the standalone merge-authority rubric. The workflow if: filter excludes those events; if you somehow get invoked on one, exit silently. Standalone is the entry point for new contributors before they encounter the epic pattern; preserve it.
How to read state
GitHub holds everything you need. The full set of gh and gh api snippets — including the bug-fixed versions of --base queries, base-ref verification before merge, and event-timestamp lookups for stuck-worker detection — is in references/state-reading.md. Read it once at the start of each invocation; it loads exact branch names from the epic issue body so you don't rely on glob matching (which gh pr list --base does not support).
The minimum read for any decision:
- Epic issue:
gh issue view $EPIC_ISSUE_NUMBER --json number,title,labels,body,comments,url
- Sub-issues listed in the epic body (
- [ ] #N — Title)
- Open sub-PRs against the epic branch
- The epic PR (single PR from
epic/<N>-<slug> to main)
Resolve the exact epic branch name from the epic issue body's **Branch**: line (set by open-epic-pr.sh). Use it verbatim in --base/--head filters.
Decision tree (11 situations, top-to-bottom)
Walk the tree. Stop at the first match. Each situation file holds the full playbook; SKILL.md is just routing.
-
Epic just labeled orchestration-active, epic PR doesn't exist → situations/1-init-epic.md
Create the epic branch (if missing), open the epic PR, label the PR orchestration-active so its comment events fire orchestrator runs.
-
Sub-issues with no unmet deps, not claude-working, not action-required → situations/2-dispatch.md
Inject Targets: + Epic: lines into the sub-issue body, then apply claude-working followed by claude-ready to dispatch one worker.
-
Sub-PR ready (non-draft) + CI green → situations/3-merge-sub-pr.md
Real review (rule 6), then merge into the epic branch. Verify base ref before merging.
-
Sub-PR has CI red → situations/4-ci-red.md
Classify transient vs persistent, comment, log.
-
BLOCKER from sub-issue #N: comment on the epic PR (from a worker) → situations/5-blocker-detected.md
Parse out N, apply action-required to that sub-issue, update the epic PR body's "Action Required" section, pause dependents.
-
Sub-issue claude-working for >30 min, no PR exists → situations/6-worker-stuck.md
Read elapsed via the issue events API. Retry up to 2 times, then action-required + escalate.
-
All sub-issues merged → situations/7-epic-complete.md
Mark the epic PR ready for review, apply awaiting-founder-review, remove orchestration-active. Stop dispatching.
-
orchestration-active removed mid-flight → situations/8-orchestration-deactivated.md
Halt new dispatches. Existing workers complete naturally.
-
Founder commented on the epic PR while a sub-issue carries action-required → situations/9-founder-response.md
Decide if the comment resolves the blocker. If yes: append ## Retry guidance to the sub-issue body (quoting the founder), remove action-required, re-dispatch via claude-working + claude-ready. If no: post one clarifying question and wait. Humans never touch labels.
-
restart-epic label on epic OR /discard comment from founder → situations/10-discard-restart.md
Close all open sub-PRs as failed-attempt (preserving branches). Reset the epic branch to main HEAD via fetch + capture SHA + git push --force-with-lease. Reset the epic PR body. Clear claude-* labels from sub-issues.
-
No action needed (all quiet) → situations/11-no-action.md
Exit silently. Don't post a log comment.
After every action
Two things, every time (rule 8 — see references/lifecycle-rules.md):
- Decision-log comment on the epic PR: one line,
**[Action Type]** brief reason. Format and examples in references/decision-log.md.
- Update the epic PR body state block if the action changed visible state (sub-issue checked off, blocker raised/cleared, status changed).
The epic PR is a live state surface, not an end-of-epic artifact. The founder reads progress mid-flight by opening it.
Discipline rules (binding)
The full set lives in references/lifecycle-rules.md. Read it before situations 3, 5, 9, or 10 — those involve judgment calls where a rule applies. The rules cover real review, two-step dispatch, only-merge-non-draft-green, label cleanup on merge, failed-attempt surfacing, and capped retry guidance.
When you're stuck
- Multiple situations seem to match: pick the first in tree order. Stop after one action.
- Can't decide on scope or architecture during sub-PR review: use the Opus advisor (the workflow passes
advisorModel: opus). Brief it with the sub-issue spec + the diff and let it break the tie. Log the advisor's reasoning in the decision-log comment.
- An action failed at the
gh layer: do not retry blindly. Log the failure with full error context to the epic PR and stop. The next invocation will see the persisted state and decide fresh.
Reference