relay-to-issue
Turn a finished /relay producer↔reviewer thread into a single checklist-style GitHub issue, filed in the repo the relay was actually about. Reviews the relay transcript, summarizes the conclusion (inc
SKILL.mdskills/2-daily/relay-to-issue/SKILL.md
GitHubrelay-to-issue
Convert a closed relay thread into one trackable GitHub issue: a short conclusion plus a markdown checklist of the actionable follow-ups, posted to the right repo.
Split of work: the shipped relay-to-issue.sh does the deterministic plumbing
(locate the thread, resolve which repo, dedup, preflight gh, create the issue,
stamp provenance back). You do the judgment — reading the transcript and writing
the title + body. Don't reimplement the plumbing inline; call the script.
SKILLDIR below = this skill's directory (where this file and relay-to-issue.sh
live). Always call the script by its absolute path so it resolves from any CWD.
Step 1 — Resolve + preflight (always first)
bash "$SKILLDIR/relay-to-issue.sh" resolve # newest thread
bash "$SKILLDIR/relay-to-issue.sh" resolve --thread 2026-06-22/dueling-claudes
Read the printed block and gate on it before reading the thread:
GH_AUTH: missing→ STOP. Tell the operator to rungh auth login; do nothing else.ALREADY_FILED: <url>(notNONE) → STOP. This thread was already filed — report the existing URL. Only proceed if the operator explicitly wants a second issue (then pass--forcein Step 4).TARGET_REPO: AMBIGUOUS→ the thread cites paths in more than one repo. Show theTARGET_CANDIDATESand ask the operator which repo (or to add aTARGET-REPO: owner/nameheader to the thread). Pass the chosen repo as--repo owner/namein Step 4.TARGET_REPO: UNRESOLVED→ ask the operator for--repo owner/name.- Otherwise note
TARGET_REPO+TARGET_SOURCE(explicit / declared / inferred / current-repo). Ifinferred, state which repo you're about to file into so a wrong inference is visible before posting.
Step 2 — Read the thread
Read the resolved THREAD file in full — every block under ## Log. Identify the two
roles (Producer/Reviewer, or Reporter/Maintainer) and every graded finding
([Blocker] / [Should] / [Nit] / [Pass]) and its disposition.
Step 3 — Empty-relay guard (don't file noise)
If the relay closed Approved/Closed with no [Blocker]/[Should] items, no
parked/disagreed items, and nothing actionable left to do → STOP. Do not create an
issue. Report: "Relay closed clean — no actionable items, nothing filed." A hollow
issue is worse than none.
Step 4 — Write the body and file it
Write the issue body to a temp file using the template below, then file:
bash "$SKILLDIR/relay-to-issue.sh" file \
--thread "<abs thread path from resolve>" \
--title "Relay follow-ups: <slug> — <one-line gist>" \
--body-file "$TMPDIR/relay-issue-body.md" \
--labels relay-followup
# [--repo owner/name] only if resolve said AMBIGUOUS/UNRESOLVED
# [--inbox] also drop a PROJECT/1-INBOX/GH-<n> pointer (only when the
# issue lands in THIS repo) — keeps the ledger closed-loop
# [--force] file a second issue for a thread already filed
The script auto-posts, prints the issue URL, and appends a provenance+dedup stamp to
the thread (<!-- relay-to-issue: filed <url> @ <hash> on <date> -->). Report the URL
to the operator.
Issue body template
## Relay follow-ups — <slug>
**Source:** `relay-system/<date>/<slug>.md` @ `<HEAD short hash>` · target repo `<owner/name>`
**Outcome:** <Closed | Approved | Changes requested> after <N> round(s) · Producer `<id>` ↔ Reviewer `<id>`
### Conclusion
<2–4 sentences: what the two agents concluded, and whether they converged.>
**Agreed / dispositioned**
- <finding that was accepted, fixed, or explicitly declined-with-reason>
**Disagreements / parked** (or "None")
- ⚠️ <unresolved point — also appears as a DECIDE box below>
### Actionable checklist
- [ ] <task> — `[Blocker]` _(Round N)_
- [ ] <task> — `[Should]` _(Round N)_
- [ ] ⚠️ DECIDE: <unresolved/disagreed item> _(needs a human call)_
- [ ] <optional cleanup> — `[Nit]` _(Round N)_
<!-- Each box is a spin-off-ready task. Generated by relay-to-issue. -->
Body rules
- One issue, one checklist (the operator's chosen shape). Every box must be a concrete, independently-actionable task — not a restatement of a whole round.
- Keep
[Blocker]and[Should]items; fold[Nit]s in only if genuinely worth doing. - Never drop a disagreement or parked item — surface it as a
⚠️ DECIDEbox. - Preserve grades and cite the source round so each task is traceable.
Cross-repo notes
- The "repo the relay was about" is the repo whose files were under review — often not the harness repo (relays can review a foreign repo; see GH-11 cross-repo targeting).
- Threads don't declare their subject repo in a machine-readable field today, so the script
infers it from the absolute paths cited in the thread. To make it explicit and remove
any ambiguity, add a header line to the thread:
TARGET-REPO: owner/name. That always wins over inference. - The script never auto-posts to a guessed repo: if paths point at more than one repo it
exits ambiguous and asks for
--repo.
Prerequisites
ghinstalled and authenticated (gh auth login), with access to the target repo.- Run un-sandboxed if
ghneeds the keychain.
What this skill does NOT do
- It does not scaffold or run a relay — that's
/relay(portable) or/relay-xyz(this repo's harness). This is the post-relay step. - It does not edit code or the thread's review content — its only writes are the issue, the one-line provenance stamp, and (opt-in) a 1-INBOX pointer.