plugins/pm-ops/skills/sync-prs/SKILL.md
Sync GitHub PRs with Linear issues and identify correlation gaps
npx skillsauth add coalesce-labs/catalyst sync-prsInstall 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.
Analyzes the relationship between GitHub pull requests and Linear issues to identify:
# 1. Validate thoughts system (REQUIRED)
if [[ -f "scripts/validate-thoughts-setup.sh" ]]; then
./scripts/validate-thoughts-setup.sh || exit 1
else
# Inline validation if script not found
if [[ ! -d "thoughts/shared" ]]; then
echo "❌ ERROR: Thoughts system not configured"
echo "Run: ./scripts/humanlayer/init-project.sh . {project-name}"
exit 1
fi
fi
# 2. Determine script directory with fallback
if [[ -n "${CLAUDE_PLUGIN_ROOT}" ]]; then
SCRIPT_DIR="${CLAUDE_PLUGIN_ROOT}/scripts"
else
# Fallback: resolve relative to this command file
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)/scripts"
fi
# 3. Check PM plugin prerequisites
if [[ -f "${SCRIPT_DIR}/check-prerequisites.sh" ]]; then
"${SCRIPT_DIR}/check-prerequisites.sh" || exit 1
else
echo "⚠️ Prerequisites check skipped (script not found at: ${SCRIPT_DIR})"
fi
# Determine script directory with fallback
if [[ -n "${CLAUDE_PLUGIN_ROOT}" ]]; then
SCRIPT_DIR="${CLAUDE_PLUGIN_ROOT}/scripts"
else
# Fallback: resolve relative to this command file
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)/scripts"
fi
source "${SCRIPT_DIR}/pm-utils.sh"
TEAM_KEY=$(get_team_key)
Task 1 - Get GitHub PRs: Use catalyst-dev:github-research agent (if exists) or inline gh
commands:
Get open and recently merged PRs (last 7 days)
Task 2 - Get Linear Issues: Use Task tool with catalyst-dev:linear-research agent:
Prompt: "Get all in-review and in-progress issues for team ${TEAM_KEY}"
Model: haiku
Wait for both tasks to complete
Use Task tool with github-linear-analyzer agent:
Input:
Output:
# PR-Linear Sync Report
**Generated**: 2025-01-27 **Repository**: user/repo **Linear Team**: TEAM
## 📊 Summary
- Open PRs: 12 (8 linked, 4 orphaned)
- Merged PRs (7d): 15 (13 linked, 2 orphaned)
- Linear issues in review: 10 (8 with PRs, 2 without)
## 🔗 Linked PRs (Healthy)
| PR | Linear Issue | Status | Author |
| ---- | ------------ | ------ | ------ |
| #123 | TEAM-456 | Open | Alice |
| #124 | TEAM-457 | Merged | Bob |
## ⚠️ Orphaned PRs (No Linear Issue)
| PR | Title | Branch | Author | Action |
| ---- | ------------- | ----------- | ------ | ------------------------------------ |
| #125 | "Fix bug" | fix-bug | Alice | Create Linear issue or link existing |
| #126 | "Update docs" | docs-update | Bob | Create Linear issue or link existing |
**Recommended Actions**:
Create a Linear issue for the orphaned PR using Linearis CLI (run `linearis issues usage` for
create syntax). Include the PR URL in the description.
| Issue | Title | Status | Assignee | Action | | -------- | ------------------- | ----------- | -------- | ----------------------------------------- | | TEAM-789 | "Implement feature" | In Progress | Alice | Create PR or update status | | TEAM-790 | "Refactor code" | In Review | Bob | PR might exist with different branch name |
| Issue | PR | Merged | Action | | -------- | ---- | ---------- | ----------- | | TEAM-456 | #123 | 2025-01-25 | Close issue | | TEAM-457 | #124 | 2025-01-26 | Close issue |
Auto-close commands: For each issue with a merged PR, update ticket status to stateMap.done
from config and add a comment with the PR link. Use linearis issues usage and
linearis comments usage for exact syntax.
| PR | Issue | Days Open | Author | Action | | ---- | -------- | --------- | ------ | ------------------------- | | #120 | TEAM-450 | 18 days | Alice | Review and merge or close |
### Step 4: Save Report
**IMPORTANT: Document Storage Rules**
- ALWAYS write to `thoughts/shared/pm/reports/`
- NEVER write to `thoughts/searchable/` — this is a read-only search index
```bash
REPORT_DIR="thoughts/shared/pm/reports"
mkdir -p "$REPORT_DIR"
REPORT_FILE="$REPORT_DIR/$(date +%Y-%m-%d)-pr-sync.md"
# Write formatted report to file
cat > "$REPORT_FILE" << EOF
# PR-Linear Sync Report - $(date +%Y-%m-%d)
[... formatted report content ...]
EOF
echo "✅ Report saved: $REPORT_FILE"
# Update workflow context
if [[ -f "${SCRIPT_DIR}/workflow-context.sh" ]]; then
"${SCRIPT_DIR}/workflow-context.sh" add reports "$REPORT_FILE" null
fi
🔗 PR-Linear Sync Report
Health Score: 75/100
✅ 8 properly linked PRs
⚠️ 4 orphaned PRs need Linear issues
⚠️ 2 orphaned issues need PRs
✅ 2 ready to close
Actions available:
1. Auto-close merged issues (generates commands)
2. Create Linear issues for orphaned PRs
3. View full report
Full report: thoughts/shared/pm/reports/2025-01-27-pr-sync.md
development
Migrate a single-harness repo to the dual-harness layout so both Claude Code and Codex load the same instructions and skills — AGENTS.md as the portable canonical doc, a thin CLAUDE.md `@AGENTS.md` bridge, and a `.agents/skills` dir with a `.claude/skills` symlink onto it. Use when asked to migrate to dual-harness, make this repo work in both Claude and Codex, or for agent metadata cleanup.
tools
Goal-driven senior-engineer pipeline-unstick sweep (CTL-1176 rung 3). Given the stuck/failed/needs-human set (or ONE ticket handed by the recovery router), its GOAL is to get the pipeline MOVING again — not to fix one ticket's review findings (that is phase-remediate). It runs AFTER the eyes (diagnostician evidence) and the hands (deterministic unstuck-sweep seams) have already tried, and it CONSUMES their output from a recovery-pass.json brief rather than re-diagnosing or redoing their narrow work. It acts like a senior engineer with full tool access — it resolves merge conflicts, rebases, force-pushes, merges green PRs, and re-dispatches stalled phases AUTONOMOUSLY — and escalates to the operator ONLY for a genuine value judgment / something that degrades other functionality / a real cost-benefit trade-off / a serious architecture change / an ADR conflict. On escalation it AUTHORS the operator inbox row + the push notification (executive-voiced). Dispatched as a `claude --bg` job by phase-agent-dispatch via slash command, AND invocable bare by the operator as a sweep — hence `user-invocable: true`. Ships behind CATALYST_RECOVERY_PASS (off by default — no live behavior change until shadow/enforce).
tools
Diagnose and fix Catalyst setup issues. Validates tools, database, config, OTel, direnv, and thoughts. Automatically fixes what it can — creates directories, initializes the database, sets WAL mode, runs migrations. Use for new installs, upgrades, or when something isn't working.
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