anduin
Use when the user runs /anduin <tracker> <project> [--filter <id-or-query>] [--max N] [--ready] [--dry-run] [--confirm]. The council→forge pipeline as one composite sweep — it rides /glorfindel (plan
SKILL.mdskills/anduin/SKILL.md
GitHubAnduin — The Great River
Anduin, the Great River, ran the length of the land from the Misty Mountains to the Sea, carrying all things downstream on one current. So this skill: it carries a project's tickets down the one channel from council to forge — Glorfindel rides the plan stage, then Aulë rides the skeleton-and-forge stage — in a single pass, on one current, never two boats jostling.
Ethos
- One channel, two stages, in order. Anduin runs the council sweep first, the forge sweep second, within one invocation. Because they take turns under one call, they never run concurrently and never contend — the cure for "two watches fighting" is sequence, not merger.
- Anduin conducts; the riders still ride. Anduin posts nothing and forges nothing of its own. Every comment, verdict, state change, and PR is Glorfindel's or Aulë's doing, gated exactly as those skills gate them. Anduin only orders the two and sums their reports.
- The decider sorts the tickets. Both stages sweep the same scope; the skeleton-rung decider gives each ticket exactly one action, so Glorfindel acts on plan-rung tickets and Aulë on skeleton/forge-rung tickets. No ticket is claimed twice in one pass.
- A single pass, not a loop. Anduin sweeps once and reports. The adaptive
cadence is
/amon-sul's to provide —/amon-sul anduin …rides Anduin on the back-off ladder with one wakeup slot, so the whole pipeline watches itself without two schedules colliding.
Argument parsing
/anduin <tracker> <project> [--filter <filter>] [--max N] [--ready] [--dry-run] [--confirm]
| Argument | Required | Meaning | Stage |
|---|---|---|---|
<tracker> |
yes | youtrack (alias yt) or jira |
both |
<project> |
yes | Project shortName / key (e.g. URD, MET) |
both |
--filter <filter> |
no* | Tracker-aware scope, same semantics as /glorfindel |
both |
--max N |
no | Forge cap per pass. Default 3 (≤10). | forge only |
--ready |
no | Open PRs ready-for-review (default draft). | forge only |
--dry-run |
no | Plan/report only; post nothing, forge nothing. Opts the forge out of auto. | both |
--confirm |
no | Prompt before each council post and each PR-open. Opts the forge out of auto. | both |
The forge runs unattended by default. Anduin gives the forge stage
--auto --max 3unless you pass a gate flag. So bare/anduin youtrack URD(or/amon-sul anduin youtrack URD) opens real PRs with no further prompt, up to 3 per pass. To watch without forging, pass--dry-run; to forge with a per-PR prompt, pass--confirm. There is no--autoflag to type — it is the default; the gate flags are how you turn it off.
Anduin parses these once and routes them to the two riders:
Council (
/glorfindel) receives<tracker> <project> --filter <filter>, plus:- No gate flag given → append
--auto. On Jira this skips Glorfindel's post-safety prompt so the council ride runs unattended; on YouTrack it is a harmless no-op (no such gate). This is what keeps the Jira pipeline hands-off — without it, the council stage would halt at its post-safety prompt every tick. --dry-rungiven → append--dry-run. Plans, posts nothing.--confirmgiven → append--confirm. Prompts before each post.- It ignores
--max/--ready(forge-only).
- No gate flag given → append
Forge (
/aule) receives<tracker> <project> --filter <filter>, plus:- No gate flag given → append
--auto --max <N, default 3>and--readyif set. The forge runs unattended. --dry-rungiven → append--dry-run(and--max/--readyif set). No--auto. Nothing forges.--confirmgiven → append--confirm(and--max/--readyif set). No--auto. Each PR-open prompts.
--dry-runand--confirmare mutually exclusive with the default auto, and with each other (--dry-runwins if both somehow appear). They are the only way to disable unattended operation on either stage.- No gate flag given → append
*Filter resolution follows /glorfindel's rule — explicit --filter wins; else
default_filters.md keyed by <tracker>:<project>; else stop with that skill's
missing-filter error.
The filter must straddle Open and In Progress
This is the one trap of the pipeline. Council transitions an approved ticket to
its forth state (for URD, In Progress) — which drops it out of a
state:Open filter. If both stages share --filter state:Open, the forge stage
never sees the ticket the council just approved, and the pipeline stalls at the
skeleton rung.
Use a filter that includes both, so the same scope feeds both stages and the decider sorts each ticket to its rung:
- YouTrack:
--filter "#Unresolved"(every non-resolved state), or an explicit--filter "state: Open, {In Progress}". - Jira:
--filter "statusCategory != Done"(or an explicitstatus in (Open, "In Progress")).
If the resolved filter is state:Open (or any single-state scope that excludes the
forth state), warn the user once that the forge stage will not see council-advanced
tickets, and suggest the broad filter above. Proceed if they confirm; the council
stage still works, only the hand-off stalls.
On Jira
Both stages support Jira — Anduin passes <tracker> straight through. Two
differences from YouTrack to know:
- Two rungs by default, three on request. On Jira the default flow is council →
forge directly: Glorfindel drafts
[COUNSEL vN], the human posts[FORTH], and Aulë forges on[COUNSEL]+[FORTH]. The skeleton rung is opt-in there — started by/celebrimbor jira <project> --ticket <id> --skeleton, never by a sweep — and once a[SKELETON]stands, Aulë routes the ticket byjira-skeleton-rung.pyand forges only after the skeleton's own[FORTH]. Anduin sequences the stages the same way. - Unattended is smoothed by
--auto. Glorfindel and Aulë each guard Jira with a post-safety prompt; Anduin's default appends--autoto both stages, so an unattended/anduin jira PSG(or/amon-sul anduin jira PSG) runs hands-off rather than halting at those prompts each tick. Pass--dry-run/--confirmto put the guards back. State mapping and filters use Jira's vocabulary (numeric transition IDs forforth/forged; JQL for the filter).
Workflow
1. Ride the council (Glorfindel)
Invoke /glorfindel through the Skill tool with the gate flag resolved per the
defaulting rule above:
- No gate flag →
/glorfindel <tracker> <project> --filter <filter> --auto— unattended (the--autoskips Jira's post-safety prompt; no-op on YouTrack). --dry-run→/glorfindel <tracker> <project> --filter <filter> --dry-run.--confirm→/glorfindel <tracker> <project> --filter <filter> --confirm.
Let it do its whole job — list, per-ticket council machinery, post [PLAN] /
[COUNSEL] / refine, transition on [FORTH], and its own aggregate report. Hold
that report.
2. Ride the forge (Aulë)
Then invoke /aule through the Skill tool with the forge flags resolved per the
defaulting rule above:
- No gate flag →
/aule <tracker> <project> --filter <filter> --auto --max <N|3> [--ready]— unattended forging, the default. --dry-run→/aule <tracker> <project> --filter <filter> --dry-run [--max N] [--ready].--confirm→/aule <tracker> <project> --filter <filter> --confirm [--max N] [--ready].
Let it do its whole job — list, rung-dispatch each qualifier to /celebrimbor
(skeleton or forge), close any already-forged ticket whose PR/MR has merged (step
5b — move to the merged= state, thread a [METTA] note), its gate, and its
aggregate report. Hold that report.
Council first is deliberate: a plan or skeleton approved earlier this pass is transitioned and ready, so the forge stage can pick it up in the same pass rather than waiting for the next.
3. Combined report and verdict
Print one block carrying both stages' summaries verbatim-in-spirit (do not re-run either), then a final plain verdict line the watcher can read:
**Anduin — pipeline pass of <tracker>:<project>**
— Council (Glorfindel): <one-line tally from its report>
— Forge (Aulë): <one-line tally from its report>
Anduin — STIRRED (or) Anduin — QUIET
Decide the verdict:
- STIRRED if either stage produced anything beyond its quiescent outcomes:
- Council stirred if any ticket read
drafted,answered,dry-run,forth,forged,nay,farewell,talked-out, orerror— i.e. anything other thanquiet/untouched. (answeredis real movement — Erestor posted a[PEDO]reply — even though the plan itself did not redraft.) - Forge moved if any ticket read
forged,closed,aborted,answered,dry-run, orerror, or qualifiers remain for the next forge pass. Aulë's outcome vocabulary carries noskeleton-draftedstate — a skeleton-rung dispatch that succeeds reportsforgedlike any other;abortedcounts as movement too, since it is retryable work still waiting, not silence. Aclosedoutcome — Aulë laying a merged ticket to rest — is movement as much as a forge is.
- Council stirred if any ticket read
- QUIET only when neither of the above held — council reported nothing but
quiet/untouched(or swept nothing), and forge reported none offorged,closed,aborted,answered,dry-run, orerror, with zero qualifiers remaining.
The verdict line is the contract /amon-sul reads to set its streak. Always emit
exactly one of the two tokens.
Rules
- Anduin never posts, transitions, or forges of its own. It only orders the two riders and sums their reports. Every write is Glorfindel's or Aulë's.
- Sequential, always. The forge sweep begins only after the council sweep returns. Never dispatch them in parallel — the sequence is the whole point.
- Forge blast radius is the default, by design. Unlike
/aule— where--automust be typed — Anduin forges unattended unless gated. Bare/anduinopens up to--max(default 3) real PRs per pass, and/amon-sul anduin …does so every tick the road stirs, with no flag in the invocation to signal it. This is the chosen default; the brakes are--dry-run(forge nothing) and--confirm(prompt per PR). Prefer a--dry-runpass first to see what would forge before arming an unattended watch. - One pass per invocation. Anduin does not self-schedule. For a loop, wrap it
in
/amon-sul anduin …; the watcher owns the cadence and the single wakeup. - A stage error does not sink the other. If the council sweep errors, still ride the forge (it reads the tracker afresh); if the forge errors, the council's posts already stand. Record both outcomes in the combined report.
- Do not surface tracker or forge tokens in logs, responses, or saved files.