-
Validate N. Parse the positional argument. Reject if missing, non-integer, <= 0, or > 8 — ask the user rather than silently capping. Never default to a value the user did not provide.
-
Resolve the current GitHub user: USER=$(gh api user -q .login). Use that login as the assignee filter and never hardcode a username.
-
Fetch open curation issues assigned to the user.
gh issue list \
--assignee @me \
--state open \
--label curation \
--json number,title,assignees,body,createdAt \
--limit 100
The --label curation filter is what restricts to "new disease curation requests" — issues filed by /claim-disease carry the curation,enhancement labels and the title pattern Curate <label> (<MONDO_ID>). If a contributor opens curation issues with a different label, document it in this skill rather than relaxing the filter.
-
Filter to sole-assignee issues. Drop any issue whose assignees array has more than one entry. The user explicitly wants solo work — an issue assigned to both alice and bob is a team task, even if the current user is alice. Do this filter in jq, not by hand:
jq '[.[] | select((.assignees | length) == 1)]'
-
Filter out issues with an existing PR. For each remaining issue number ISSUE_NUM, check the authoritative GitHub linkage on the issue itself:
gh issue view "${ISSUE_NUM}" --json closedByPullRequestsReferences \
-q '.closedByPullRequestsReferences | length'
Skip the issue if the count is non-zero. A merged PR usually means the issue should already be closed, but stale links happen — be conservative.
Do NOT use gh pr list --search "closes #${ISSUE_NUM}" as a forward check. GitHub's free-text search matches the literal string #${ISSUE_NUM} anywhere in PR body or commits, including unrelated occurrences like ORPHA:${ISSUE_NUM}. This produced a false positive in production on issue #2704 (Orphanet ID ORPHA:2704 in PR #1992's body matched #2704). closedByPullRequestsReferences is structured GitHub linkage and avoids the trap.
If closedByPullRequestsReferences is rejected as an unknown field by the local gh version, upgrade gh rather than falling back to the lossy text search.
-
Sort and pick. Sort the survivors by number ascending (oldest issue first — that's the conventional FIFO for a curation queue) and take the first N. If fewer than N survive, do not pad — report the shortfall in step 8.
-
Extract the disease label and MONDO ID from each title. Issue titles follow Curate <label> (<MONDO_ID>). Parse with a regex; if a title does not match (e.g. an old hand-filed issue), skip it and note it in the final report rather than passing a garbled label to /curate.
-
Dispatch /curate in parallel. In a single message, launch N Agent tool calls — one per disease — using subagent_type: general-purpose so each agent has full tool access (Tools: *). claude works too on harnesses that register it as a catch-all type, but general-purpose is the canonical name across harnesses; prefer it for portability. Each agent's prompt MUST:
-
State the disease label and MONDO ID verbatim.
-
Quote any deep-research provider hints from the issue body (e.g. "using falcon", "using deep-research"). Default to falcon when none are mentioned.
-
Reference the GitHub issue number so the agent links the resulting PR back to it.
-
Instruct the agent to consult the initiate-new-disorder-creation skill for the full curation workflow (this is what /curate does — sub-agents cannot invoke slash commands directly, so this skill must be named in the prompt).
-
For CURATE_ROOT_WITH_SUBTYPES issues, note that subtypes should be modelled with has_subtypes.
-
MUST tell the agent to create a git worktree of its own and cd into it, then root every Read/Edit/Write/Bash file operation in the worktree's path — never in the parent checkout's path. Never give the agent the parent checkout's absolute path as its working directory. In a real production incident, two of three agents took an absolute parent path from the prompt (/Users/.../dismech-1) and wrote kb/disorders/<disease>.yaml plus dozens of references_cache/*.md files into the parent checkout instead of their own worktree — branches were left empty and recovery required surgery. The agent prompt should include something like:
Create your own git worktree (use the `superpowers:using-git-worktrees` skill) on a fresh branch off `origin/main`, then `cd` into that worktree. After `cd`, run `pwd` and confirm the printed path is the worktree's path and is NOT the parent checkout's path BEFORE any file write. For Read/Edit/Write tool calls (which require absolute paths), use absolute paths rooted in the worktree — never an absolute path that contains the parent checkout's location. For Bash calls, prefer relative paths after `cd`-ing into the worktree. Commit and push from inside the worktree.
Dispatching all N in one message is the whole point — sequential dispatch defeats the skill. See superpowers:dispatching-parallel-agents if you need a refresher on parallel sub-agent semantics. Run the agents in the background (run_in_background: true) so the orchestrator regains control immediately and can report; you will be notified as each finishes.
After every agent finishes (or stalls), verify each branch has at least one commit: git log origin/main..<branch> --oneline. If empty, the agent's work is likely uncommitted in its worktree's working tree — or worse, leaked into the parent checkout. Check git status in the parent before dispatching another batch.
-
Report. After all agents finish, list:
- Issues processed (number + label + agent result summary)
- Issues skipped and why (already has PR / co-assigned / unparseable title)
- The shortfall, if you delivered fewer than N curations