plugins/dev/skills/ci-describe-pr/SKILL.md
Generate PR descriptions autonomously for CI/automation (no user interaction). Non-interactive variant of /describe-pr for use in CI pipelines and automated workflows. Auto-detects current PR, generates description, and updates GitHub.
npx skillsauth add coalesce-labs/catalyst ci-describe-prInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Generate or update PR descriptions autonomously without user interaction. Designed for CI pipelines and automated workflows.
/describe_prhumanlayer thoughts sync automatically# Auto-detect PR for current branch
PR_JSON=$(gh pr view --json number,url,title,state,body,headRefName,baseRefName 2>/dev/null)
if [[ -z "$PR_JSON" ]]; then
echo "No PR found for current branch"
exit 1
fi
PR_NUMBER=$(echo "$PR_JSON" | jq -r '.number')
if [[ -f "thoughts/shared/pr_description.md" ]]; then
# Read template
else
echo "No PR template found at thoughts/shared/pr_description.md"
# Generate without template
fi
gh pr diff $PR_NUMBER
gh pr view $PR_NUMBER --json commits,files
gh pr view $PR_NUMBER --json url,title,number,state,baseRefName,headRefName,author
branch=$(echo "$PR_JSON" | jq -r '.headRefName')
if [[ "$branch" =~ ([A-Z]+)-([0-9]+) ]]; then
ticket="${BASH_REMATCH[0]}"
fi
Analyze all commits and changes. Generate a complete PR description following the template.
CRITICAL: NO Claude attribution — remove any "Generated with Claude" or "Co-Authored-By" lines.
CTL-623 — sibling reference format (REQUIRED): When referencing related/sibling
work in prose, reference it by its GitHub PR number (#NNN), never by a bare Linear
token (TEAM-NNN) or a Linear issue URL. A bare sibling TEAM-NNN token is auto-linked
by Linear's GitHub integration and drags that sibling's workflow status (Done → Implement)
on PR open/merge. Do not emit bare sibling Linear tokens in prose. The own ticket's
Fixes https://linear.app/... line is correct and stays. Sibling neutralization is
handled mechanically by the guard block appended at write-back time (step 6).
body_file="thoughts/shared/prs/${PR_NUMBER}_description.md"
# Save to thoughts
cat > "$body_file" <<EOF
[Generated description]
EOF
# CTL-623: append a Linear automation guard block so sibling tickets embedded in
# the branch name or pulled into the body are NOT auto-linked and dragged backward
# in status when this PR opens/merges. Scans the branch AND the assembled body;
# no-op for single-ticket PRs. See https://linear.app/docs/github (skip/ignore
# negative magic word).
# CTL-633: branch and body are scanned in DIFFERENT modes — the branch goes
# through the awk segmenter (legitimate sibling-number recovery); the body
# uses canonical-only regex so prose, dashed dates, and SHAs cannot fabricate
# fake `skip TEAM-NNN` lines. Stays non-interactive — no cache refresh prompt.
# shellcheck source=/dev/null
source "${CLAUDE_PLUGIN_ROOT}/scripts/lib/linear-pr-skip.sh"
body="$(cat "$body_file")"
skip_block="$( {
linear_sibling_skip_block_from_branch "$ticket" "$branch"
linear_sibling_skip_block_from_body "$ticket" "$body"
} | awk '/^skip /{if(!seen[$0]++) print; next} {if(!h){print; h=1}}' )"
[[ -n "$skip_block" ]] && printf '\n%s\n' "$skip_block" >>"$body_file"
# Sync thoughts
humanlayer thoughts sync
# Update PR on GitHub
gh pr edit $PR_NUMBER --title "$new_title"
gh pr edit $PR_NUMBER --body-file "$body_file"
If Linearis CLI is available, update the ticket status to stateMap.inReview from config.
Use linearis issues usage for exact update syntax. Skip silently if CLI not available.
PR description updated: #$PR_NUMBER
URL: $PR_URL
Ticket: $ticket (updated to In Review)
IMPORTANT: Document Storage Rules
thoughts/shared/prs/ for PR descriptionsthoughts/searchable/ — this is a read-only search indextesting
Phase-agent that fixes a failing verify verdict so the pipeline self-heals instead of stalling to needs-human (CTL-653). Reads `${ORCH_DIR}/workers/<ticket>/verify.json`, fixes the `findings[]` (every severity:"high" plus the regression_risk drivers) directly via Edit/Write, commits the remediation, and emits `phase.remediate.complete.<ticket>`. The scheduler's router then re-dispatches `verify` to re-check (the verify⇄remediate cycle, cap 3). Dispatched as a `claude --bg` job by `phase-agent-dispatch`, which invokes it via slash command — hence `user-invocable: true`.
tools
--- name: phase-triage description: Phase agent that triages a Linear ticket — expands acronyms, classifies (feature/bug/docs/refactor/chore), identifies genuine blockers (a semantic second-pass over the backlog — NOT a prose scrape; CTL-838), estimates scope, writes triage.json, and posts a triage analysis comment to Linear. Triage completion is signaled by that comment plus the local triage.json — there is no `triaged` label. Emits phase.triage.complete.<TICKET> on success and phase.triage.fai
tools
Phase agent for the research step of the 9-phase orchestrator pipeline (CTL-450). Wraps /catalyst-dev:research-codebase and produces thoughts/shared/research/<date>-<ticket>.md, then emits phase.research.complete.<ticket>. Reads triage.json from the worker dir as its prior-phase artifact. Spawned via plugins/dev/scripts/phase-agent-dispatch, which invokes it via slash command — hence `user-invocable: true`.
development
Phase-agent wrapper that opens the pull request after implementation completes (CTL-449 Initiative 1 Phase 3). Delegates to `/catalyst-dev:create-pr` (which already auto-runs `describe-pr` and transitions Linear to `inReview`), then writes the PR number + URL into the phase signal file so the downstream `phase-monitor-merge` agent can read it without re-querying GitHub. Dispatched as a `claude --bg` job by `phase-agent-dispatch`, which invokes it via slash command — hence `user-invocable: true`.