SuperAPI AI Directory

shepherd

General & other

View repository

Updated 10-15 22:12

About this skill

Forge owns your open PRs. A singleton daemon converges every open PR toward merge-readiness; you read its verdicts and only step in on escalations. Never merges, never resolves review threads.

Shepherd

shepherd is the PR-ownership utility, not a workflow stage. It has two modes over the single forge shepherd verb:

  • Daemon (default ownership): forge shepherd daemon is a machine-wide singleton for this repo. It heartbeats and converges the whole PR world every ~60s — self-registering hand-opened PRs, restarting killed watchers, reaping verified orphans, converging CI check state into kernel verdicts, retiring merged/closed PRs — then self-retires (releases the lease, kills its children, exits) once no PRs remain open. You do NOT poll by hand; the daemon does.
  • One-shot convergence: forge shepherd <pr> runs the local review preflight, reads one PR's current-head state, takes at most one idempotent Tier-A action, persists bounded deltas/receipts, and exits. Use it for a point-in-time question or one bounded convergence attempt on a single PR.

Which mode? (decision rule)

  • User asks about one PR, right now ("is #212 ready?", "why is this blocked?") → one-shot (forge shepherd <pr> --pull).
  • Anything ongoing — "keep", "until it merges", "watch", "babysit", multiple PRs, or a session that starts with PRs already open → ensure the daemon is running.

Automatic attachment

Forge wakes the singleton after a successful supported session start, every successful push, and every successful non-dry-run ship. Push does not require a locally resolved PR number; the daemon enumerates all open and draft PRs itself. Ordinary commands do not launch it.

The daemon is a repo singleton guarded by an O_EXCL lease, so no liveness check is needed first. Forge prefers a supplied harness background shell; its bare-CLI detached fallback launches from the stable common repository root, not the current disposable worktree. Agents never launch a detached spawn directly. (A forge prime daemon-liveness line remains the separate W-S5 follow-up.)

Reading verdicts (the common case)

forge shepherd <pr> --pull --json          # actionable payload: WHY blocked + exactly what to fix
forge shepherd <pr> --bundle --json        # the COMPLETE read-only PR-state bundle
forge shepherd events <pr> --since <seq>   # only the new events since sequence <seq>

--pull is strictly read-only (dry-run pass: no rerun, no rebase, no merge, no thread resolution). It returns one bounded, actionable-only payload — blockers[], classified requiredChecks, failed-check log failures[] (matrix-deduped), and every unresolved reviewThreads[] — so you get "everything blocking this PR + what to fix" in one call. Passing checks and satisfied policy are omitted.

A plain forge shepherd <pr> also returns a consolidated localPreflight, at most 128 deltas, receiptIds, and one explicit handoff. The preflight probes CodeRabbit and runs strict lint, Sonar parity, structural drift, and affected tests. An unavailable or unauthenticated CodeRabbit CLI is reported as UNAVAILABLE/INCOMPLETE, never as a fabricated pass; deterministic failures or actual review findings make the remote decision read-only for that pass. A checkout that is not the exact PR head is NOT_APPLICABLE, never reviewed as if it were authoritative.

Verdict vocabulary (collapsed, W-S1)

Verdict Meaning
MERGE_READY Required checks green, branch up to date — hand off to a human to merge.
PENDING A Tier-A action was taken, or checks are still running — await the next tick/pass.
INCOMPLETE Exact-head local review or durable convergence evidence is unavailable — fail closed and retry after evidence is restored.
BLOCKED Something actionable blocks merge (failing/missing/skipped required check, conflict, behind, unresolved threads, changes requested). Read blockers[].
CI_DEAD_HEAD The head has no required checks running (e.g. an auto-update authored by GITHUB_TOKEN never re-triggered CI). Recovery is an escalation, not an autonomous Tier-A rerun: it needs a maintainer-provided FORGE_PR_TOKEN (contents + pull-requests + checks) to re-author the push so CI re-triggers.
ESCALATE A Tier-C condition (conflict, unreadable required set, persistent failure, oscillation, budget exhaustion). Context is posted to the PR.
HARD_STOP A permanent auth/scope failure retrying cannot fix — a human must widen token scope.

Trigger scenario → command

Situation Command
PR just opened / shipped automatic singleton wake; read with forge shepherd <pr> --pull
Session starts with open PRs automatic singleton wake
"Why isn't my PR merging / what's blocking it" forge shepherd <pr> --pull
"Is the PR ready?" forge shepherd <pr> --pull (read MERGE_READY)
"A check failed / went red" forge shepherd <pr> --pull --json (read failures[])
"Keep watching / babysit my PRs" ensure forge shepherd daemon running
Read incremental deltas forge shepherd events <pr> --since <seq>

Boundaries (kept — true of both modes)

  • Never merges. No merge action, no server-side auto-merge latch. Terminates at MERGE_READY and hands off — a human merges in the GitHub UI.
  • Never resolves review threads. It refreshes a single sticky status comment; thread resolution is semantic and stays with review.
  • Action ladder. Tier-A (autonomous, idempotent): re-run a flaky required check (rerun-budget capped); refresh the single sticky status comment — an upsert, never an append, so the ~60s daemon loop cannot post duplicate comments. Tier-B (opt-in, default OFF): --auto-rebase rebases onto base and force-pushes with lease — a lease rejection is a hard-stop, never re-armed. Tier-C: everything else escalates (incl. CI_DEAD_HEAD recovery, which needs the maintainer FORGE_PR_TOKEN).
  • Required-check gate. MERGE_READY only when the branch-protection required set is known and all green; if protection is unreadable, it escalates rather than guessing.
  • HEAD-changed abort. Before any mutating action it re-reads the head SHA and aborts if HEAD moved.

Adjacent skills

  • Fixing review feedback (CodeRabbit/Greptile/human comments, resolving threads) → review.
  • Opening or pushing the PR → ship.
  • Post-merge health (CI green on main, close issues) → verify.
  • "Where am I / what's in flight" orientation → status.

Kill-switches

FORGE_SHEPHERD_DISABLE=1              # env: makes automatic firing inert
forge gate disable rail.auto_shepherd # config gate honored by every automatic seam

CI/test (NODE_ENV=test, BUN_ENV=test, CI, GITHUB_ACTIONS, or GITLAB_CI), dry-run, uninitialized repositories, and disabled paths return before lease, Kernel-state, or process work. All leave the manual forge shepherd surface usable; they only stop automatic daemon fire.

State

Public Memory is the durable monitor authority and public Flow reducers restore its bounded event and watcher-process checkpoints after restart. The per-PR journal under .forge/pr-monitor/<repo>-<pr>/ remains a compatibility delivery surface for events --since, not authority. Merged/closed evidence produces one idempotent terminal MonitorReceipt; conflicting or incomplete replay fails closed. For 0.1 no receipt grants continuing lease authority: live ownership is re-probed at consequential boundaries, and canonical LeaseReceipt epoch/scope plus the same-actor/session ABA fix remain explicitly deferred.