agile-workflow

📁 yabasha/agile-workflow 📅 2 days ago
3
总安装量
3
周安装量
#59578
全站排名
安装命令
npx skills add https://github.com/yabasha/agile-workflow --skill agile-workflow

Agent 安装分布

opencode 3
gemini-cli 3
github-copilot 3
codex 3
amp 3
kimi-cli 3

Skill 文档

Agile Development & Repository Management

You are an agile team lead and repository manager. This skill covers the full lifecycle of agile software development — from sprint planning through issue resolution, code review, release management, and repository maintenance. Follow the relevant module based on user intent.

Key Value
Version 2.0.0
Author Bashar Ayyash (Yabasha.dev)
License MIT
Tools Required bash, git, gh (GitHub CLI)
Platforms Claude Code, Cursor, Windsurf, Copilot, Codex, OpenClaw, Aider, any LLM coding assistant with shell access

Module Dispatcher

Route the user’s intent to the correct module:

User Intent Module
“fix issues”, “resolve issues”, “tackle issues”, “batch fix” Part 1: Issue Resolution Pipeline
“plan sprint”, “create sprint”, “sprint planning” Sprint Planning
“groom backlog”, “create issue”, “label issues” Backlog Management
“estimate”, “story points”, “size issues” Story Point Estimation
“triage issues”, “prioritize issues” Issue Triage & Auto-labeling
“retrospective”, “retro”, “sprint review” Sprint Retrospectives
“kanban”, “board”, “project board” Kanban Board Management
“epic”, “milestone”, “roadmap” Epic & Milestone Tracking
“standup”, “status report”, “daily report” Status Reports & Standups
“branch strategy”, “gitflow”, “trunk-based” Branch Strategy
“commit convention”, “conventional commits” Conventional Commits
“release”, “bump version”, “changelog”, “tag” Release Management
“set up repo”, “configure repo”, “repo setup” Repository Setup & Configuration
“repo health”, “stale branches”, “cleanup repo” Repository Health
“monorepo”, “workspaces”, “changesets” Monorepo Management
“git hooks”, “husky”, “lint-staged” Git Hooks & Automation
“rebase”, “cherry-pick”, “bisect”, “worktree” Advanced Git Operations
“CI/CD”, “github actions”, “pipeline” Part 4: CI/CD & Quality
“code review”, “review PR” Part 5: Code Review Standards
“svn to git”, “migrate from svn” SVN-to-Git Migration
“git error”, “undo commit”, “recover branch” Git Error Recovery
“resolve pr comments”, “fix review comments” Phase 3: PR Review Comment Resolution
“merge PRs”, “merge all” Phase 4: Merge All PRs

If intent is unclear, ask the user which module they need.


Part 1: Issue Resolution Pipeline

End-to-end workflow: detect open issues → prioritize → fix in parallel → create PRs → resolve review comments → merge → clean up.

Phase 1: Issue Discovery & Prioritization

1.1 Fetch all open issues

gh issue list --state open --json number,title,labels,body,assignees,milestone

1.2 Auto-categorize by labels

Scan issue titles and bodies for keywords and apply labels automatically:

# Create standard labels if they don't exist
gh label create "priority:critical" --color "B60205" --description "Production blocker" --force
gh label create "priority:high" --color "D93F0B" --description "Must fix this sprint" --force
gh label create "priority:medium" --color "FBCA04" --description "Should fix soon" --force
gh label create "priority:low" --color "0E8A16" --description "Nice to have" --force
gh label create "type:bug" --color "D73A4A" --description "Something isn't working" --force
gh label create "type:feature" --color "0075CA" --description "New functionality" --force
gh label create "type:chore" --color "CFD3D7" --description "Maintenance task" --force
gh label create "type:docs" --color "0075CA" --description "Documentation" --force
gh label create "type:security" --color "B60205" --description "Security issue" --force

Keyword-to-label mapping:

Keywords in Title/Body Label
crash, broken, error, fail, bug, not working type:bug
feature, add, implement, support, request type:feature
refactor, cleanup, chore, update deps, migrate type:chore
docs, documentation, readme, typo type:docs
security, vulnerability, CVE, XSS, injection type:security
critical, production, outage, data loss priority:critical
urgent, ASAP, blocker priority:high
# Apply label to issue
gh issue edit {number} --add-label "type:bug,priority:high"

1.3 Detect stale issues

Find issues with no activity in the last 30 days:

gh issue list --state open --json number,title,updatedAt \
  --jq '[.[] | select(.updatedAt < (now - 2592000 | todate))] | .[] | "#\(.number) \(.title) (last updated: \(.updatedAt))"'

1.4 Prioritize into tiers

Tier Priority Examples
Tier 1 Critical — do first Production blockers, security vulnerabilities, data loss, launch blockers
Tier 2 High Important features, significant bugs, DX improvements
Tier 3 Medium Enhancements, documentation, minor bugs
Tier 4 Low Nice-to-haves, cosmetic fixes, minor refactors

1.5 Map dependencies

Build a dependency graph. Issues that must be done before others are blockers. Independent issues can run in parallel.

Example:
  #3 (Testing) ──> #7 (CI/CD) ──> #8 (Infrastructure)
  All others: independent

1.6 Group by area & file conflicts

Issues that modify the same files MUST go to the same developer to avoid merge conflicts. Signals:

  • Same directory or file paths listed in the issue
  • Same component, module, or page
  • Layout/config files shared across features (e.g., layout.tsx, package.json, config.yml)

Phase 2: Parallel Execution

2.1 Concurrency limits

  • Maximum parallel developers: 3–5 (to avoid resource exhaustion and merge conflict cascading)
  • Queue strategy: Start Tier 1 issues first, then backfill with Tier 2/3 as slots open
  • Shared file rule: Issues touching the same files go to the same developer — never parallelize overlapping file sets

2.2 Create isolated branches

Each issue (or issue group) gets its own branch:

fix/{issue-number}-short-description

Examples: fix/11-output-expiry-cleanup, fix/5-13-landing-page

2.3 Set up worktrees for isolation

# Create worktree for each developer
git worktree add ../worktree-issue-{number} -b fix/{number}-{slug} origin/main

# List active worktrees
git worktree list

# Clean up after done
git worktree remove ../worktree-issue-{number}
git worktree prune

2.4 Spawn parallel developers

Each developer works in an isolated environment (git worktree, separate clone, or sandboxed workspace) to avoid conflicts.

Developer prompt template:

You are a senior {specialty} developer. Implement GitHub Issue #{number}: {title}.

## Branch
Create and work on branch: `fix/{number}-{slug}`

## What to implement
{Full issue details and acceptance criteria}

## Files to read first
{List key files to understand before making changes}

## Verification
{Project-specific test/build/lint commands}

## Rules
- Read existing code FIRST before making changes
- Follow project conventions (read CLAUDE.md or CONTRIBUTING.md)
- Run {formatter} before committing
- Create a PR with `gh pr create` including "Closes #{number}" in the body
- Do NOT create a new PR if one already exists — push to the existing branch

2.5 Developer specialties

Match developers to issue domains:

Specialty Typical Issues
Backend API endpoints, database, auth, jobs, queues
Frontend UI components, pages, styling, client-side logic
DevOps CI/CD, infrastructure, deployment, monitoring
Core/Engine Libraries, algorithms, data processing
Testing Test suites, fixtures, coverage

2.6 Failure recovery

If a developer fails or produces incorrect output:

Decision Tree:
├── Build/test failure?
│   ├── Missing dependency → Install and retry
│   ├── Type error → Read error output, fix types, retry
│   └── Test failure → Read test output, fix implementation, retry
├── Merge conflict?
│   ├── Rebase onto latest main
│   └── If conflict is in shared file → pause, merge other PR first, then rebase
├── Developer produced wrong output?
│   ├── Misunderstood issue → Respawn with clearer instructions
│   └── Partial fix → Resume from where they stopped
└── Developer hung/timed out?
    └── Kill, review partial work, respawn or fix manually

2.7 Wait for all developers

Track each developer’s progress. As each completes:

  1. Collect the PR URL
  2. Verify the PR was created with Closes #N in the body
  3. Verify build/tests pass
  4. Shut down the developer

Phase 3: PR Review Comment Resolution

3.1 Fetch review comments for all PRs

# For each PR number
gh api repos/{owner}/{repo}/pulls/{pr_number}/comments \
  --jq '.[] | "ID:\(.id) [\(.path):\(.line // .original_line)] \(.body)"'

Skip PRs with no actionable comments (bot headers without suggestions are not actionable).

3.2 Review comment decision tree

For each comment:
├── Is it a valid suggestion/required change?
│   └── Yes → Fix it (step 3.3)
├── Is it a nitpick or style preference?
│   └── Fix if trivial, otherwise reply explaining project convention
├── Is it a question, not a change request?
│   └── Reply with explanation, no code change needed
├── Is the comment incorrect or outdated?
│   └── Reply explaining why, with evidence (code references, docs)
└── Is it out of scope?
    └── Reply acknowledging, create a follow-up issue if warranted

3.3 Fix each comment

For each PR with actionable comments, spawn a fix agent that:

  1. Checks out the existing PR branch (does NOT create a new branch)
  2. Reads the commented file to understand current code
  3. Applies the fix
  4. Runs verification (tests, build, lint)
  5. Commits and pushes to the same branch

3.4 Reply to each comment

After fixes are pushed, reply to every comment confirming the fix:

gh api repos/{owner}/{repo}/pulls/{pr_number}/comments/{comment_id}/replies \
  -f body="Fixed — {description of what was changed}. See commit {short_hash}."

3.5 Resolve review threads

# Step 1: Get unresolved thread IDs
gh api graphql -f query='
query {
  repository(owner: "{owner}", name: "{repo}") {
    pullRequest(number: {pr_number}) {
      reviewThreads(first: 50) {
        nodes {
          id
          isResolved
          comments(first: 1) {
            nodes { path body }
          }
        }
      }
    }
  }
}' --jq '.data.repository.pullRequest.reviewThreads.nodes[] | select(.isResolved == false) | .id'

# Step 2: Resolve each thread
gh api graphql -f query='
mutation {
  resolveReviewThread(input: { threadId: "{thread_id}" }) {
    thread { isResolved }
  }
}'

3.6 Iterate

If new comments appear after pushing fixes, repeat Phase 3.


Phase 4: Merge All PRs

4.1 Merge in dependency order

Merge independent PRs first. PRs that depend on others merge after their dependencies.

gh pr merge {number} --squash --delete-branch

4.2 Handle merge conflicts

After each merge, subsequent PRs may conflict with the updated main. Rebase them:

git fetch origin main
git fetch origin {branch}
git checkout {branch}
git rebase origin/main
git push origin {branch} --force-with-lease

Wait 3–5 seconds for GitHub to recalculate mergeability, then retry.

4.3 Handle stale worktrees

If rebase fails because a branch is locked by a worktree:

git worktree remove {worktree_path} --force
git worktree prune
# Then retry the rebase

4.4 Verify all issues closed

gh issue list --state open --json number,title

Phase 5: Cleanup

# 1. Prune stale remote tracking refs
git remote prune origin

# 2. Delete leftover local branches
git branch | grep -v '^\* main$' | grep -v '^  main$' | xargs -r git branch -D

# 3. Clean up worktrees
git worktree prune
git worktree list  # Should show only the main worktree

# 4. Final verification
git checkout main
git pull origin main
git status          # Should be clean
git branch          # Should only show main

Part 2: Agile Process Management

Sprint Planning & Backlog Management

Create a milestone (sprint)

# Create milestone with due date
gh api repos/{owner}/{repo}/milestones \
  -f title="Sprint 1" \
  -f description="Sprint goal: {goal}" \
  -f due_on="2025-02-14T23:59:59Z" \
  -f state="open"

# List milestones
gh api repos/{owner}/{repo}/milestones --jq '.[] | "#\(.number) \(.title) — due \(.due_on) (\(.open_issues) open, \(.closed_issues) closed)"'

Assign issues to a sprint

# Batch assign issues to milestone
for issue in 1 2 3 4 5; do
  gh issue edit "$issue" --milestone "Sprint 1"
done

Capacity planning

Factor Adjustment
Base velocity Average story points completed in last 3 sprints
PTO / holidays Reduce by percentage of team-days lost
New team member Reduce by 20–30% for onboarding
Tech debt sprint Reduce feature capacity by 30–50%
Bug-heavy backlog Reserve 20% buffer for unplanned bug fixes
Sprint length 2 weeks recommended; 1 week for high-urgency projects

Sprint goal template

## Sprint {N} Goal
**Duration:** {start_date} → {end_date}
**Theme:** {one-line theme}

### Committed Stories
| # | Title | Points | Assignee |
|---|-------|--------|----------|
| {number} | {title} | {points} | {assignee} |

### Sprint Goal
{2-3 sentences describing the primary objective and what "done" looks like}

### Stretch Goals
- {optional items if capacity allows}

### Risks / Dependencies
- {known blockers or external dependencies}

Issue creation templates

Bug report:

gh issue create --title "Bug: {short description}" \
  --body "## Description
{What happened}

## Expected Behavior
{What should happen}

## Steps to Reproduce
1. {step}

## Environment
- OS: {os}
- Version: {version}

## Screenshots / Logs
{attach if applicable}" \
  --label "type:bug"

Feature request:

gh issue create --title "Feature: {short description}" \
  --body "## Summary
{What and why}

## User Story
As a {role}, I want {capability} so that {benefit}.

## Acceptance Criteria
- [ ] {criterion 1}
- [ ] {criterion 2}

## Design Notes
{Optional technical approach or mockup}" \
  --label "type:feature"

Chore:

gh issue create --title "Chore: {short description}" \
  --body "## Description
{What needs to be done and why}

## Tasks
- [ ] {task 1}
- [ ] {task 2}

## Notes
{Any relevant context}" \
  --label "type:chore"

Spike (research/investigation):

gh issue create --title "Spike: {question to answer}" \
  --body "## Objective
{What we need to learn}

## Time Box
{max hours/days}

## Key Questions
1. {question}

## Expected Output
{Document, POC, recommendation, etc.}" \
  --label "type:spike"

Complete label taxonomy

# Priority labels
gh label create "priority:critical" --color "B60205" --description "Production blocker — drop everything" --force
gh label create "priority:high" --color "D93F0B" --description "Must fix this sprint" --force
gh label create "priority:medium" --color "FBCA04" --description "Should fix soon" --force
gh label create "priority:low" --color "0E8A16" --description "Nice to have" --force

# Type labels
gh label create "type:bug" --color "D73A4A" --description "Something isn't working" --force
gh label create "type:feature" --color "0075CA" --description "New functionality" --force
gh label create "type:chore" --color "CFD3D7" --description "Maintenance / housekeeping" --force
gh label create "type:docs" --color "0075CA" --description "Documentation only" --force
gh label create "type:security" --color "B60205" --description "Security issue" --force
gh label create "type:spike" --color "D4C5F9" --description "Research / investigation" --force
gh label create "type:test" --color "BFD4F2" --description "Test improvements" --force

# Size labels (T-shirt sizing)
gh label create "size:XS" --color "EDEDED" --description "< 1 hour" --force
gh label create "size:S" --color "D4C5F9" --description "1–4 hours" --force
gh label create "size:M" --color "BFD4F2" --description "Half day to 1 day" --force
gh label create "size:L" --color "FBCA04" --description "1–3 days" --force
gh label create "size:XL" --color "D93F0B" --description "3+ days — consider splitting" --force

# Area labels (customize per project)
gh label create "area:frontend" --color "61DAFB" --description "UI / client-side" --force
gh label create "area:backend" --color "3572A5" --description "API / server-side" --force
gh label create "area:infra" --color "E99695" --description "Infrastructure / DevOps" --force
gh label create "area:database" --color "F9D0C4" --description "Database / migrations" --force
gh label create "area:auth" --color "FBCA04" --description "Authentication / authorization" --force

# Status labels
gh label create "status:blocked" --color "B60205" --description "Blocked by external dependency" --force
gh label create "status:in-review" --color "FBCA04" --description "PR open, awaiting review" --force
gh label create "status:ready" --color "0E8A16" --description "Groomed and ready to pick up" --force
gh label create "status:needs-info" --color "D4C5F9" --description "Needs more information" --force
gh label create "status:wontfix" --color "FFFFFF" --description "Decided not to fix" --force
gh label create "status:duplicate" --color "CFD3D7" --description "Duplicate of another issue" --force

Backlog grooming process

# 1. Find ungroomed issues (no priority or size label)
gh issue list --state open --json number,title,labels \
  --jq '[.[] | select((.labels | map(.name) | any(startswith("priority:"))) | not)] | .[] | "#\(.number) \(.title)"'

# 2. For each ungroomed issue:
#    a. Read the issue body
#    b. Verify acceptance criteria exist
#    c. Apply type, priority, and size labels
#    d. Assign to milestone if sprint-ready

# 3. Find issues missing acceptance criteria
gh issue list --state open --json number,title,body \
  --jq '[.[] | select(.body | test("acceptance|criteria|\\[[ x]\\]") | not)] | .[] | "#\(.number) \(.title)"'

Issue linking and dependencies

# Reference dependencies in issue body using keywords:
# "Depends on #X" or "Blocked by #X" in the issue body
# "Part of #X" for epic relationships
# GitHub auto-links these in the timeline

# Query issues that reference a specific issue
gh api graphql -f query='
query {
  repository(owner: "{owner}", name: "{repo}") {
    issue(number: {number}) {
      timelineItems(first: 50, itemTypes: [CROSS_REFERENCED_EVENT]) {
        nodes {
          ... on CrossReferencedEvent {
            source {
              ... on Issue { number title state }
              ... on PullRequest { number title state }
            }
          }
        }
      }
    }
  }
}'

Story Point Estimation

Fibonacci scale

Points Complexity Duration (solo dev) Examples
1 Trivial < 1 hour Typo fix, copy change, config tweak
2 Simple 1–4 hours Add a field, simple UI change, add test
3 Small Half day New API endpoint, simple component, bug fix with known cause
5 Medium 1–2 days Feature with multiple files, integration work, moderate refactor
8 Large 2–4 days Cross-cutting feature, complex algorithm, significant refactor
13 Very large 1 week+ Major feature, architectural change — consider splitting
21 Epic-sized 2+ weeks Too large for a single story — MUST split

Programmatic estimation algorithm

INPUT: issue description, codebase context

1. Count files to change
   - 1 file = base 1
   - 2–3 files = base 2
   - 4–6 files = base 3
   - 7+ files = base 5

2. Estimate lines of code
   - < 20 lines = +0
   - 20–100 lines = +1
   - 100–300 lines = +2
   - 300+ lines = +3

3. Dependency factor
   - No new dependencies = +0
   - Uses existing internal APIs = +1
   - Requires new dependency or external API = +2
   - Requires database migration = +3

4. Test requirement
   - No tests needed = +0
   - Unit tests only = +1
   - Integration tests = +2
   - E2E tests = +3

5. Risk/uncertainty
   - Well-understood domain = +0
   - Some unknowns = +1
   - Significant unknowns (spike first) = +3

SUM all factors, then map to nearest Fibonacci:
  1–2 → 1 point
  3–4 → 2 points
  5–6 → 3 points
  7–9 → 5 points
  10–12 → 8 points
  13–16 → 13 points
  17+ → 21 points (split the story)

Apply estimates as labels

# Add story point label
gh issue edit {number} --add-label "points:5"

# Create point labels if needed
for pts in 1 2 3 5 8 13 21; do
  gh label create "points:$pts" --color "C5DEF5" --description "$pts story points" --force
done

Issue Triage & Auto-labeling

Triage decision tree

New issue arrives:
├── Is it a duplicate?
│   ├── Yes → Label "status:duplicate", comment referencing original, close
│   └── No → continue
├── Is it actionable?
│   ├── No (vague, no repro steps) → Label "status:needs-info", comment asking for details
│   └── Yes → continue
├── What type is it?
│   ├── Bug → "type:bug"
│   ├── Feature → "type:feature"
│   ├── Security → "type:security" + "priority:critical"
│   ├── Documentation → "type:docs"
│   └── Maintenance → "type:chore"
├── What priority?
│   ├── Production broken / security / data loss → "priority:critical"
│   ├── Significant user impact → "priority:high"
│   ├── Moderate impact → "priority:medium"
│   └── Minor / cosmetic → "priority:low"
└── Assign area label based on files/components mentioned

Priority SLAs

Priority Response Time Resolution Target
Critical < 1 hour < 4 hours
High < 4 hours < 2 days
Medium < 1 day < 1 sprint
Low < 1 week Next sprint or backlog

Auto-labeling script

# Fetch unlabeled issues and apply labels based on content
gh issue list --state open --json number,title,body,labels \
  --jq '[.[] | select(.labels | length == 0)]' | \
while read -r issue; do
  number=$(echo "$issue" | jq -r '.number')
  title=$(echo "$issue" | jq -r '.title' | tr '[:upper:]' '[:lower:]')
  body=$(echo "$issue" | jq -r '.body' | tr '[:upper:]' '[:lower:]')
  content="$title $body"

  labels=""
  # Type detection
  if echo "$content" | grep -qE "bug|broken|error|crash|fail|not working"; then
    labels="type:bug"
  elif echo "$content" | grep -qE "feature|add|implement|support|request"; then
    labels="type:feature"
  elif echo "$content" | grep -qE "security|vulnerability|cve|xss|injection"; then
    labels="type:security,priority:critical"
  elif echo "$content" | grep -qE "docs|documentation|readme|typo"; then
    labels="type:docs"
  elif echo "$content" | grep -qE "refactor|cleanup|chore|update dep|migrate"; then
    labels="type:chore"
  fi

  if [ -n "$labels" ]; then
    gh issue edit "$number" --add-label "$labels"
  fi
done

Sprint Retrospectives

Automated metrics collection

# Sprint velocity (closed issues with points in milestone)
gh issue list --state closed --milestone "Sprint 1" --json number,labels \
  --jq '[.[] | .labels[] | select(.name | startswith("points:")) | .name | ltrimstr("points:") | tonumber] | add'

# Average PR merge time (time from open to merge)
gh pr list --state merged --json number,createdAt,mergedAt \
  --jq '[.[] | ( (.mergedAt | fromdateiso8601) - (.createdAt | fromdateiso8601) ) / 3600] | (add / length) | round | "\(.) hours avg"'

# PR count
gh pr list --state merged --search "milestone:\"Sprint 1\"" --json number --jq 'length'

# Bug escape rate (bugs found after release vs total issues)
gh issue list --state closed --milestone "Sprint 1" --label "type:bug" --json number --jq 'length'

# Issues that missed the sprint (still open in milestone)
gh issue list --state open --milestone "Sprint 1" --json number,title \
  --jq '.[] | "#\(.number) \(.title)"'

Retro report template

## Sprint {N} Retrospective
**Date:** {date}
**Duration:** {start} → {end}

### Metrics
| Metric | Value | Trend |
|--------|-------|-------|
| Velocity (points) | {pts} | {↑↓→} |
| Issues completed | {count} | |
| PRs merged | {count} | |
| Avg PR merge time | {hours}h | |
| Bug escape rate | {percent}% | |
| Missed issues | {count} | |

### What Went Well
- {item}

### What Didn't Go Well
- {item}

### Action Items
- [ ] {action} — Owner: {name} — Due: {date}

### Shoutouts
- {recognition}

Action item tracking

# Create action items as issues
gh issue create --title "Retro Action: {action}" \
  --body "From Sprint {N} retrospective.

## Action
{detailed description}

## Owner
{name}

## Due
{date}" \
  --label "type:chore" --milestone "Sprint {N+1}"

Kanban Board Management

Create a GitHub Project board

# Create project
gh project create --title "{Project Name}" --owner "{owner}"

# List projects
gh project list --owner "{owner}"

Standard columns with WIP limits

Column Purpose WIP Limit Entry Criteria Exit Criteria
Backlog Ungroomed items None Issue exists Groomed + estimated
Ready Groomed, sprint-ready None Has acceptance criteria, estimated, labeled Picked up by developer
In Progress Actively being worked 3 per dev Assigned, branch created PR opened
In Review PR open, awaiting review 5 total PR passes CI Approved with no changes requested
Done Merged to main None PR merged, issue closed Sprint ends

Manage project items

# Add issue to project
gh project item-add {project_number} --owner "{owner}" --url "https://github.com/{owner}/{repo}/issues/{number}"

# Move item to column (update status field)
gh project item-edit --project-id {project_id} --id {item_id} --field-id {status_field_id} --single-select-option-id {option_id}

Kanban metrics

Metric Description Calculation
Lead time Backlog → Done Time from issue creation to merge
Cycle time In Progress → Done Time from first commit to merge
Throughput Issues completed per week Count of Done items / time period
WIP age How long items sit in progress Current time – move to In Progress time

Epic & Milestone Tracking

Create an epic (tracking issue)

gh issue create --title "Epic: {epic name}" \
  --body "## Overview
{Description of the epic}

## Stories
- [ ] #{story_1} — {title}
- [ ] #{story_2} — {title}
- [ ] #{story_3} — {title}

## Acceptance Criteria
- [ ] {criterion}

## Notes
{Technical approach, design links, etc.}" \
  --label "type:epic"

Milestone progress monitoring

# Check milestone progress
gh api repos/{owner}/{repo}/milestones --jq '.[] | "\(.title): \(.closed_issues)/\(.open_issues + .closed_issues) issues (\(.closed_issues * 100 / (.open_issues + .closed_issues) | round)% done)"'

# Issues remaining in milestone
gh issue list --state open --milestone "{milestone}" --json number,title,labels \
  --jq '.[] | "#\(.number) \(.title) [\(.labels | map(.name) | join(", "))]"'

Decomposition strategy

Epic → Stories → Tasks

Decision logic:
├── Can it be delivered in one sprint?
│   ├── Yes → It's a Story (assign directly)
│   └── No → It's an Epic (decompose further)
├── Can a story be completed by one developer in < 3 days?
│   ├── Yes → Keep as-is
│   └── No → Split into smaller stories
└── Does a story have clear acceptance criteria?
    ├── Yes → Ready for sprint
    └── No → Needs grooming (add "status:needs-info" label)

Status Reports & Standups

Daily standup report

echo "## Daily Standup — $(date +%Y-%m-%d)"
echo ""
echo "### Done (merged yesterday)"
gh pr list --state merged --search "merged:>=$(date -v-1d +%Y-%m-%d)" --json number,title \
  --jq '.[] | "- PR #\(.number): \(.title)"'
echo ""
echo "### In Progress"
gh pr list --state open --json number,title,author \
  --jq '.[] | "- PR #\(.number): \(.title) (@\(.author.login))"'
echo ""
echo "### Blocked"
gh issue list --state open --label "status:blocked" --json number,title \
  --jq '.[] | "- #\(.number): \(.title)"'

Sprint progress report

echo "## Sprint Progress — $(date +%Y-%m-%d)"
echo ""
# Total vs completed
total=$(gh issue list --milestone "{milestone}" --state all --json number --jq 'length')
closed=$(gh issue list --milestone "{milestone}" --state closed --json number --jq 'length')
open=$(gh issue list --milestone "{milestone}" --state open --json number --jq 'length')
echo "**Progress:** $closed / $total issues ($open remaining)"
echo ""
echo "### Remaining Issues"
gh issue list --state open --milestone "{milestone}" --json number,title,assignees,labels \
  --jq '.[] | "- #\(.number) \(.title) [\(.assignees | map(.login) | join(", "))]"'

Definition of Done

Universal DoD checklist

  • Code compiles/builds without errors
  • All existing tests pass
  • New tests written for new functionality
  • Code reviewed and approved (at least 1 reviewer)
  • No unresolved review comments
  • PR linked to issue with Closes #N
  • No linting errors or warnings
  • Documentation updated if user-facing behavior changed
  • No security vulnerabilities introduced

Per-type DoD

Bug fix:

  • Root cause identified and documented in PR
  • Regression test added that would catch recurrence
  • Fix verified in the environment where the bug was reported

Feature:

  • Acceptance criteria from the issue are met
  • Edge cases handled
  • Loading/error states handled (if UI)
  • Accessible (if UI — keyboard nav, screen reader, contrast)

Chore:

  • No functional regressions
  • Build/CI still passes
  • Relevant documentation updated

Automated DoD verification

# Run before marking any issue as done
echo "=== Definition of Done Check ==="
echo ""

# 1. Build
echo "1. Build..."
{build_command} && echo "   PASS" || echo "   FAIL"

# 2. Tests
echo "2. Tests..."
{test_command} && echo "   PASS" || echo "   FAIL"

# 3. Lint
echo "3. Lint..."
{lint_command} && echo "   PASS" || echo "   FAIL"

# 4. PR exists and references issue
echo "4. PR check..."
gh pr list --head "$(git branch --show-current)" --json number,body \
  --jq '.[0].body' | grep -q "Closes #" && echo "   PASS — PR references issue" || echo "   FAIL — PR missing Closes #N"

# 5. Review approval
echo "5. Review status..."
gh pr view --json reviewDecision --jq '.reviewDecision' | grep -q "APPROVED" && echo "   PASS" || echo "   NEEDS REVIEW"

Part 3: Repository Management

Branch Strategy

Decision tree

Choose your branch strategy:
├── Solo developer or very small team (1–3)?
│   └── GitHub Flow (simple)
├── Regular release schedule with staging?
│   └── GitFlow
├── Continuous deployment, trunk always deployable?
│   └── Trunk-Based Development
└── Unsure?
    └── Start with GitHub Flow, evolve to GitFlow if release complexity grows

GitHub Flow (recommended for most projects)

main ──●──●──●──●──●──●──●──●──●
        \         /
         feature/my-feature
  • main is always deployable
  • Create feature branches from main
  • Open PR, review, merge back to main
  • Deploy from main
git checkout -b feature/my-feature main
# ... work ...
git push -u origin feature/my-feature
gh pr create --base main --title "Add my feature"
# After review:
gh pr merge --squash --delete-branch

GitFlow

main ──●─────────────────●──────●
        \               / \    /
develop ──●──●──●──●──●    ●──●
            \     /   \     /
        feature/x  release/1.0
                          \
                       hotfix/urgent

Branch purposes:

  • main — production-ready, tagged releases only
  • develop — integration branch, next release
  • feature/* — new work, branch from develop
  • release/* — release prep, branch from develop, merge to both main and develop
  • hotfix/* — urgent production fix, branch from main, merge to both main and develop
# Start feature
git checkout -b feature/my-feature develop

# Finish feature
git checkout develop
git merge --no-ff feature/my-feature
git branch -d feature/my-feature

# Start release
git checkout -b release/1.0 develop

# Finish release
git checkout main
git merge --no-ff release/1.0
git tag -a v1.0.0 -m "Release 1.0.0"
git checkout develop
git merge --no-ff release/1.0
git branch -d release/1.0

# Hotfix
git checkout -b hotfix/urgent main
# ... fix ...
git checkout main
git merge --no-ff hotfix/urgent
git tag -a v1.0.1 -m "Hotfix 1.0.1"
git checkout develop
git merge --no-ff hotfix/urgent
git branch -d hotfix/urgent

Trunk-Based Development

main ──●──●──●──●──●──●──●──●──●
        \   / \   /
     short-lived branches (< 1 day)
  • Everyone commits to main (directly or via very short-lived branches)
  • Feature flags for incomplete work
  • CI/CD deploys every commit
  • Best for experienced teams with strong CI
# Short-lived branch
git checkout -b feat/quick-change main
# ... small, focused change ...
git push -u origin feat/quick-change
gh pr create --base main
# Merge same day
gh pr merge --squash --delete-branch

Conventional Commits

Format

<type>[optional scope][!]: <description>

[optional body]

[optional footer(s)]

Types

Type Purpose SemVer Bump Example
feat New feature Minor feat(auth): add OAuth2 login
fix Bug fix Patch fix(api): handle null response
docs Documentation only None docs: update API reference
style Formatting, semicolons, etc. None style: fix indentation in utils
refactor Code change that neither fixes nor adds None refactor(db): simplify query builder
perf Performance improvement Patch perf: cache user lookup results
test Adding or correcting tests None test: add login flow integration test
build Build system or dependencies None build: upgrade webpack to v5
ci CI configuration None ci: add Node 20 to test matrix
chore Other changes (no src/test) None chore: update .gitignore
revert Reverts a previous commit Varies revert: revert "feat(auth): add OAuth2"

Breaking changes

Two ways to signal a breaking change (SemVer Major bump):

# Method 1: ! after type/scope
feat(api)!: change authentication endpoint format

# Method 2: BREAKING CHANGE footer
feat(api): change authentication endpoint format

BREAKING CHANGE: The /auth endpoint now requires a JSON body instead of query params.
Migration: Update all API calls to send { "token": "..." } in the request body.

Scope conventions

Scopes should match your project’s module/area structure:

feat(auth):       # Authentication module
fix(ui/button):   # UI button component
docs(api):        # API documentation
ci(deploy):       # Deployment pipeline
build(deps):      # Dependency updates

Commitlint enforcement

# Install commitlint
npm install --save-dev @commitlint/cli @commitlint/config-conventional
# Or with bun:
bun add -d @commitlint/cli @commitlint/config-conventional

commitlint.config.js:

module.exports = {
  extends: ['@commitlint/config-conventional'],
  rules: {
    'type-enum': [2, 'always', [
      'feat', 'fix', 'docs', 'style', 'refactor',
      'perf', 'test', 'build', 'ci', 'chore', 'revert'
    ]],
    'subject-max-length': [2, 'always', 72],
    'body-max-line-length': [2, 'always', 100],
  },
};

Release Management

SemVer decision tree

What changed?
├── Breaking API/behavior change?
│   └── MAJOR bump (X.0.0)
├── New feature (backward compatible)?
│   └── MINOR bump (0.X.0)
├── Bug fix (backward compatible)?
│   └── PATCH bump (0.0.X)
└── Pre-release?
    └── Append suffix: 1.0.0-beta.1, 1.0.0-rc.1

Git tagging

# Annotated tag (recommended — stores author, date, message)
git tag -a v1.2.0 -m "Release 1.2.0: Add user profiles and fix login bug"
git push origin v1.2.0

# List tags
git tag -l "v*" --sort=-v:refname

# Delete tag (local + remote)
git tag -d v1.2.0
git push origin --delete v1.2.0

Changelog generation

# Using conventional-changelog
npx conventional-changelog -p angular -i CHANGELOG.md -s

# Using git log (manual)
git log v1.1.0..v1.2.0 --pretty=format:"- %s (%h)" --no-merges

# Group by type
echo "## [1.2.0] - $(date +%Y-%m-%d)"
echo ""
echo "### Features"
git log v1.1.0..v1.2.0 --pretty=format:"- %s (%h)" --no-merges --grep="^feat"
echo ""
echo "### Bug Fixes"
git log v1.1.0..v1.2.0 --pretty=format:"- %s (%h)" --no-merges --grep="^fix"

GitHub Releases

# Create release from tag
gh release create v1.2.0 --title "v1.2.0" --notes "$(cat <<'EOF'
## What's New

### Features
- Add user profiles (#42)
- Support dark mode (#55)

### Bug Fixes
- Fix login redirect loop (#38)
- Handle empty search results (#41)

### Breaking Changes
- None

**Full Changelog:** https://github.com/{owner}/{repo}/compare/v1.1.0...v1.2.0
EOF
)"

# Create pre-release
gh release create v2.0.0-beta.1 --prerelease --title "v2.0.0 Beta 1" --notes "Beta release for testing"

# Create draft release
gh release create v1.3.0 --draft --title "v1.3.0" --generate-notes

# Upload release assets
gh release upload v1.2.0 ./dist/app.zip ./dist/checksums.txt

Release checklist

## Release Checklist — v{X.Y.Z}

### Pre-release
- [ ] All issues in milestone are closed
- [ ] All PRs are merged
- [ ] CI/CD passes on main
- [ ] CHANGELOG.md updated
- [ ] Version bumped in package.json / pyproject.toml / Cargo.toml
- [ ] Documentation updated for new features
- [ ] No critical/high security alerts

### Release
- [ ] Create annotated tag: `git tag -a v{X.Y.Z} -m "Release {X.Y.Z}"`
- [ ] Push tag: `git push origin v{X.Y.Z}`
- [ ] Create GitHub Release with notes
- [ ] Upload any release assets
- [ ] Publish to package registry (npm, PyPI, crates.io) if applicable

### Post-release
- [ ] Verify deployment succeeded
- [ ] Smoke test critical paths
- [ ] Announce release (changelog link, migration guide if breaking)
- [ ] Close milestone
- [ ] Create next milestone

Rollback procedures

# Revert the release commit (safest)
git revert {release_commit_hash}
git push origin main

# Or point main back to previous release
git checkout main
git reset --hard v1.1.0
git push origin main --force-with-lease  # DANGEROUS — confirm with team first

# Delete the bad release
gh release delete v1.2.0 --yes
git tag -d v1.2.0
git push origin --delete v1.2.0

# Hotfix workflow (preferred over rollback)
git checkout -b hotfix/1.2.1 v1.2.0
# ... fix the issue ...
git push -u origin hotfix/1.2.1
gh pr create --base main --title "Hotfix: {description}"

Repository Setup & Configuration

.gitattributes template

# Auto-detect text files and normalize line endings
* text=auto

# Force LF for specific files
*.js text eol=lf
*.jsx text eol=lf
*.ts text eol=lf
*.tsx text eol=lf
*.json text eol=lf
*.md text eol=lf
*.yml text eol=lf
*.yaml text eol=lf
*.css text eol=lf
*.html text eol=lf
*.sh text eol=lf

# Binary files
*.png binary
*.jpg binary
*.jpeg binary
*.gif binary
*.ico binary
*.woff binary
*.woff2 binary
*.ttf binary
*.eot binary
*.pdf binary
*.zip binary

# Git LFS (uncomment and customize)
# *.psd filter=lfs diff=lfs merge=lfs -text
# *.sketch filter=lfs diff=lfs merge=lfs -text
# *.fig filter=lfs diff=lfs merge=lfs -text

# Linguist overrides (for accurate language stats)
# vendor/* linguist-vendored
# docs/* linguist-documentation

.gitignore best practices

# Dependencies
node_modules/
.pnp/
.pnp.js

# Build output
dist/
build/
.next/
out/

# Environment
.env
.env.local
.env.*.local

# IDE
.idea/
.vscode/
*.swp
*.swo
*~
.DS_Store

# Test / coverage
coverage/
.nyc_output/

# Logs
*.log
npm-debug.log*

# OS
Thumbs.db

CODEOWNERS

# Default owners for everything
* @team-lead

# Frontend
/src/components/ @frontend-team
/src/pages/ @frontend-team
/src/styles/ @frontend-team

# Backend
/src/api/ @backend-team
/src/server/ @backend-team
/src/db/ @backend-team

# Infrastructure
/.github/ @devops-team
/Dockerfile @devops-team
/docker-compose*.yml @devops-team
/terraform/ @devops-team

# Documentation
/docs/ @docs-team
*.md @docs-team

Branch protection rules

# Protect main branch
gh api repos/{owner}/{repo}/branches/main/protection \
  -X PUT \
  -H "Accept: application/vnd.github+json" \
  -f required_status_checks='{"strict":true,"contexts":["ci/test","ci/build"]}' \
  -f enforce_admins=true \
  -f required_pull_request_reviews='{"required_approving_review_count":1,"dismiss_stale_reviews":true}' \
  -f restrictions=null \
  -f allow_force_pushes=false \
  -f allow_deletions=false

# View current protection
gh api repos/{owner}/{repo}/branches/main/protection

Issue and PR templates

Create .github/ISSUE_TEMPLATE/bug_report.md:

---
name: Bug Report
about: Report a bug
labels: type:bug
---

## Description
<!-- What happened? -->

## Expected Behavior
<!-- What should have happened? -->

## Steps to Reproduce
1.

## Environment
- OS:
- Version:

## Screenshots / Logs
<!-- If applicable -->

Create .github/PULL_REQUEST_TEMPLATE.md:

## Summary
<!-- What does this PR do? -->

## Related Issue
Closes #

## Changes
-

## Testing
- [ ] Unit tests pass
- [ ] Manual testing done

## Screenshots
<!-- If UI changes -->

Repository Health

Stale branch detection and cleanup

# Find branches with no commits in 30+ days
git for-each-ref --sort=committerdate refs/remotes/origin/ \
  --format='%(committerdate:short) %(refname:short)' | \
  while read date branch; do
    if [ "$(date -d "$date" +%s 2>/dev/null || date -j -f "%Y-%m-%d" "$date" +%s)" -lt "$(date -v-30d +%s 2>/dev/null || date -d '30 days ago' +%s)" ]; then
      echo "STALE: $branch (last commit: $date)"
    fi
  done

# Delete stale remote branches (after confirmation)
git push origin --delete {branch_name}

# Prune local tracking refs
git remote prune origin

Orphaned PR detection

# Find PRs that reference deleted branches
gh pr list --state open --json number,title,headRefName,updatedAt \
  --jq '.[] | "#\(.number) \(.title) — branch: \(.headRefName) — updated: \(.updatedAt)"'

# Find PRs with no activity in 14+ days
gh pr list --state open --json number,title,updatedAt \
  --jq '[.[] | select(.updatedAt < (now - 1209600 | todate))] | .[] | "#\(.number) \(.title) (stale since \(.updatedAt))"'

Large file detection

# Find large files in current tree (> 1MB)
git ls-files -z | xargs -0 -I{} sh -c 'size=$(wc -c < "{}"); if [ "$size" -gt 1048576 ]; then echo "$size {}"; fi' | sort -rn | head -20

# Find large files in entire history
git rev-list --objects --all | \
  git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' | \
  awk '/^blob/ {print $3, $4}' | sort -rn | head -20

# Repo size
git count-objects -vH

Security alerts and dependency audit

# Check Dependabot alerts
gh api repos/{owner}/{repo}/dependabot/alerts --jq '.[] | "\(.security_advisory.severity): \(.security_advisory.summary) (\(.dependency.package.name))"'

# npm audit
npm audit --json | jq '.vulnerabilities | to_entries[] | "\(.value.severity): \(.key) — \(.value.title)"'

# Check for secrets in recent commits
git log --all --diff-filter=A --name-only --pretty=format: | sort -u | \
  grep -iE '\.(env|pem|key|secret|credentials|token)$'

Repository statistics

# Contributor stats
gh api repos/{owner}/{repo}/contributors --jq '.[] | "\(.login): \(.contributions) commits"'

# Code frequency (additions/deletions per week)
gh api repos/{owner}/{repo}/stats/code_frequency --jq '.[-4:][] | "Week \(.[0]): +\(.[1]) -\(.[2])"'

# File hotspots (most frequently changed files)
git log --name-only --pretty=format: --since="3 months ago" | sort | uniq -c | sort -rn | head -20

Monorepo Management

Workspace configurations

bun (bun workspaces):

{
  "workspaces": ["packages/*", "apps/*"]
}

pnpm (pnpm-workspace.yaml):

packages:
  - 'packages/*'
  - 'apps/*'

npm/yarn (package.json):

{
  "workspaces": ["packages/*", "apps/*"]
}

Changeset management

# Install changesets
bun add -d @changesets/cli

# Initialize
bun changeset init

# Create a changeset (after making changes)
bun changeset
# Prompts: which packages changed? major/minor/patch? description?

# Version packages (updates package.json + CHANGELOG.md)
bun changeset version

# Publish to registry
bun changeset publish

Selective CI (detect changed packages)

# Get changed files between current branch and main
changed_files=$(git diff --name-only origin/main...HEAD)

# Determine affected packages
affected_packages=""
for file in $changed_files; do
  pkg=$(echo "$file" | grep -oE '^(packages|apps)/[^/]+' || true)
  if [ -n "$pkg" ]; then
    affected_packages="$affected_packages $pkg"
  fi
done
affected_packages=$(echo "$affected_packages" | tr ' ' '\n' | sort -u)

echo "Affected packages:"
echo "$affected_packages"

Cross-package dependency management

# Install syncpack for version consistency
bun add -d syncpack

# Check for mismatched dependency versions
bun syncpack list-mismatches

# Fix mismatched versions
bun syncpack fix-mismatches

Git Hooks & Automation

Husky setup

# Install husky
bun add -d husky

# Initialize husky
bunx husky init

# This creates .husky/ directory with a pre-commit hook

Pre-commit hook (lint-staged)

# Install lint-staged
bun add -d lint-staged

.husky/pre-commit:

bunx lint-staged

package.json (lint-staged config):

{
  "lint-staged": {
    "*.{js,jsx,ts,tsx}": ["eslint --fix", "prettier --write"],
    "*.{json,md,yml,yaml}": ["prettier --write"],
    "*.css": ["stylelint --fix", "prettier --write"]
  }
}

Commit-msg hook (commitlint)

.husky/commit-msg:

bunx --no -- commitlint --edit "$1"

Pre-push hook

.husky/pre-push:

bun test --run

Post-merge hook (auto-install)

.husky/post-merge:

# Auto-install if lockfile changed
changed_files=$(git diff-tree -r --name-only --no-commit-id ORIG_HEAD HEAD)
if echo "$changed_files" | grep -qE "bun.lockb|package-lock.json|yarn.lock|pnpm-lock.yaml"; then
  echo "Lockfile changed — running install..."
  bun install
fi

Advanced Git Operations

Interactive rebase patterns

# Rebase last N commits for cleanup
git rebase -i HEAD~{N}

# Rebase onto main (update feature branch)
git rebase origin/main

# If rebase goes wrong — abort and start over
git rebase --abort

# If rebase has conflicts — resolve then continue
# (edit conflicted files, then:)
git add {resolved_files}
git rebase --continue

# Rebase recovery if you already completed a bad rebase
git reflog
git reset --hard {ref_before_rebase}

Cherry-pick workflows

# Pick a single commit
git cherry-pick {commit_hash}

# Pick multiple commits
git cherry-pick {hash1} {hash2} {hash3}

# Pick a range
git cherry-pick {start_hash}..{end_hash}

# Cherry-pick without committing (stage only)
git cherry-pick --no-commit {hash}

# If conflicts occur
git cherry-pick --abort     # Cancel
git cherry-pick --continue  # After resolving conflicts

Bisect for bug finding

# Manual bisect
git bisect start
git bisect bad                 # Current commit is broken
git bisect good v1.0.0         # This version was working
# Git checks out midpoint — test it, then:
git bisect good   # or   git bisect bad
# Repeat until Git identifies the first bad commit
git bisect reset  # Return to original state

# Automated bisect with test script
git bisect start HEAD v1.0.0
git bisect run {test_command}
# Example: git bisect run bun test -- --run tests/login.test.ts
git bisect reset

Worktree management

# Add a worktree for a branch
git worktree add ../worktree-feature feature/my-feature

# Add a worktree with a new branch
git worktree add -b hotfix/urgent ../worktree-hotfix main

# List worktrees
git worktree list

# Remove a worktree
git worktree remove ../worktree-feature

# Prune stale worktree references
git worktree prune

Stash management

# Stash changes with message
git stash push -m "WIP: feature description"

# Stash including untracked files
git stash push -u -m "WIP: includes new files"

# List stashes
git stash list

# Apply most recent stash (keep in stash list)
git stash apply

# Apply and remove most recent stash
git stash pop

# Apply specific stash
git stash apply stash@{2}

# Show stash diff
git stash show -p stash@{0}

# Drop specific stash
git stash drop stash@{1}

# Clear all stashes
git stash clear

Reflog recovery

# View reflog (all HEAD movements)
git reflog

# Recover deleted branch
git reflog | grep "checkout: moving from {branch_name}"
git checkout -b {branch_name} {hash}

# Recover after hard reset
git reflog
git reset --hard {hash_before_reset}

# Recover lost commit
git reflog
git cherry-pick {lost_commit_hash}

Submodules vs Subtrees

Decision:
├── Need independent versioning of sub-repo?
│   └── Submodule
├── Want simpler workflow (no .gitmodules)?
│   └── Subtree
├── Sub-repo contributors don't know about parent?
│   └── Subtree
└── Need to pin exact commit of dependency?
    └── Submodule

Submodule commands:

# Add submodule
git submodule add {url} {path}

# Clone repo with submodules
git clone --recurse-submodules {url}

# Update submodules
git submodule update --init --recursive

# Update to latest remote
git submodule update --remote

Subtree commands:

# Add subtree
git subtree add --prefix={path} {url} {branch} --squash

# Pull updates
git subtree pull --prefix={path} {url} {branch} --squash

# Push changes back to sub-repo
git subtree push --prefix={path} {url} {branch}

Part 4: CI/CD & Quality

GitHub Actions Workflow Templates

CI workflow (test on every push/PR)

# .github/workflows/ci.yml
name: CI

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main, develop]

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: [18, 20, 22]
    steps:
      - uses: actions/checkout@v4
      - uses: oven-sh/setup-bun@v2
      - run: bun install --frozen-lockfile
      - run: bun run lint
      - run: bun test --run
      - run: bun run build

PR checks workflow

# .github/workflows/pr-checks.yml
name: PR Checks

on:
  pull_request:
    types: [opened, synchronize, reopened]

jobs:
  checks:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: oven-sh/setup-bun@v2
      - run: bun install --frozen-lockfile
      - run: bun run lint
      - run: bun test --run
      - run: bun run build

      # Verify PR has issue reference
      - name: Check PR body
        run: |
          if ! echo "${{ github.event.pull_request.body }}" | grep -qE "Closes #|Fixes #|Resolves #"; then
            echo "::warning::PR body should reference an issue (Closes #N)"
          fi

Release workflow

# .github/workflows/release.yml
name: Release

on:
  push:
    tags:
      - 'v*'

jobs:
  release:
    runs-on: ubuntu-latest
    permissions:
      contents: write
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - uses: oven-sh/setup-bun@v2
      - run: bun install --frozen-lockfile
      - run: bun test --run
      - run: bun run build

      - name: Create GitHub Release
        run: |
          gh release create ${{ github.ref_name }} \
            --title "${{ github.ref_name }}" \
            --generate-notes
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Dependency update workflow

# .github/workflows/deps.yml
name: Dependency Updates

on:
  schedule:
    - cron: '0 9 * * 1'  # Every Monday at 9am
  workflow_dispatch:

jobs:
  update:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: oven-sh/setup-bun@v2
      - run: bun install
      - run: bun update
      - name: Create PR if changes
        run: |
          if [ -n "$(git status --porcelain)" ]; then
            git checkout -b chore/update-deps-$(date +%Y%m%d)
            git add -A
            git commit -m "chore(deps): update dependencies"
            git push -u origin HEAD
            gh pr create --title "chore(deps): weekly dependency update" \
              --body "Automated weekly dependency update."
          fi
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Test Gates & Coverage

# Add to CI workflow
- name: Run tests with coverage
  run: bun test --run --coverage

- name: Check coverage threshold
  run: |
    # Fail if coverage drops below threshold
    # Adjust the tool and threshold for your project
    coverage=$(bun test --run --coverage 2>&1 | grep -oP 'Statements\s*:\s*\K[\d.]+')
    threshold=80
    if (( $(echo "$coverage < $threshold" | bc -l) )); then
      echo "Coverage $coverage% is below threshold $threshold%"
      exit 1
    fi

Security Scanning

Dependabot configuration

# .github/dependabot.yml
version: 2
updates:
  - package-ecosystem: "npm"
    directory: "/"
    schedule:
      interval: "weekly"
    labels:
      - "type:chore"
      - "area:deps"
    commit-message:
      prefix: "chore(deps):"
    open-pull-requests-limit: 10
    groups:
      dev-dependencies:
        dependency-type: "development"
      production-dependencies:
        dependency-type: "production"

  - package-ecosystem: "github-actions"
    directory: "/"
    schedule:
      interval: "weekly"
    labels:
      - "type:ci"

Secret scanning

# Install gitleaks
brew install gitleaks  # macOS
# Or: go install github.com/gitleaks/gitleaks/v8@latest

# Scan current state
gitleaks detect --source . --verbose

# Scan git history
gitleaks detect --source . --verbose --log-opts="--all"

# Use in pre-commit hook
gitleaks protect --staged --verbose

Deployment Strategy Decision Tree

What are you deploying?
├── Static site / frontend?
│   ├── Vercel, Netlify, Cloudflare Pages
│   └── GitHub Pages (simple static)
├── Full-stack web app?
│   ├── Vercel (Next.js, Nuxt)
│   ├── Railway, Render, Fly.io
│   └── AWS/GCP/Azure (complex infra)
├── API / backend service?
│   ├── Serverless: Vercel Functions, AWS Lambda, Cloudflare Workers
│   └── Container: Docker → Railway, Fly.io, ECS, Cloud Run
├── Package / library?
│   ├── npm: `npm publish` or `bun publish`
│   ├── PyPI: `twine upload`
│   └── Crates.io: `cargo publish`
├── Mobile app?
│   ├── Expo EAS (React Native)
│   ├── Fastlane (iOS/Android)
│   └── App Store / Play Store manual
└── Desktop app?
    └── Electron Builder / Tauri

Part 5: Code Review Standards

Review Checklist

When reviewing a PR, check each category:

Correctness:

  • Does the code do what the PR/issue describes?
  • Are edge cases handled?
  • Are error conditions handled appropriately?

Tests:

  • Are there tests for new functionality?
  • Do tests cover edge cases?
  • Are tests deterministic (no flaky tests)?

Security:

  • No hardcoded secrets or credentials
  • User input is validated/sanitized
  • No SQL injection, XSS, or other OWASP top 10 vulnerabilities
  • Authentication/authorization checked where needed

Performance:

  • No N+1 queries
  • No unnecessary re-renders (React)
  • No memory leaks (event listeners, subscriptions)
  • Appropriate use of caching

Style & Maintainability:

  • Code follows project conventions
  • No dead code or commented-out code
  • Variable/function names are clear
  • Complex logic has comments explaining “why”

Dependencies:

  • No unnecessary new dependencies
  • Dependencies are well-maintained and secure
  • License compatibility checked

Comment Templates

Suggestion (optional improvement):

**Suggestion:** Consider using `Array.from()` here instead of spread for better readability with map.

{code suggestion}

Not blocking — just a thought.

Required change (must fix before merge):

**Required:** This will throw if `user` is null. We need a null check here since the API can return null for deleted users.

{code suggestion}

Nitpick (trivial, non-blocking):

**Nit:** Trailing whitespace on line 42.

Question (seeking clarification):

**Question:** Is there a reason we're using `setTimeout` instead of `requestAnimationFrame` here? Curious about the tradeoff.

Automated First-Pass Review

Use the agent to perform an initial review pass:

# 1. Get the PR diff
gh pr diff {number} > /tmp/pr-diff.txt

# 2. Get PR details
gh pr view {number} --json title,body,labels,files

# 3. Review each changed file
gh pr diff {number} --name-only | while read file; do
  echo "=== Reviewing: $file ==="
  gh pr diff {number} -- "$file"
done

# 4. Submit review
gh pr review {number} --approve --body "LGTM — {summary of what was checked}"
# Or request changes:
gh pr review {number} --request-changes --body "{detailed feedback}"
# Or comment only:
gh pr review {number} --comment --body "{observations}"

SVN-to-Git Migration Reference

Author mapping

# Extract SVN authors
svn log --quiet {svn_url} | grep "^r" | awk '{print $3}' | sort -u > svn-authors.txt

# Create author mapping file (authors.txt)
# Format: svn_username = Full Name <email@example.com>
# Example:
# jdoe = John Doe <john@example.com>
# asmith = Alice Smith <alice@example.com>

Clone with history preservation

# Standard clone (full history)
git svn clone {svn_url} --authors-file=authors.txt --stdlayout {repo_name}

# For large repos — batch fetching
git svn clone {svn_url} --authors-file=authors.txt --stdlayout --no-metadata \
  -r1:1000 {repo_name}
cd {repo_name}
git svn fetch -r1001:2000
git svn fetch -r2001:HEAD

# If trunk/branches/tags aren't standard layout:
git svn clone {svn_url} \
  --trunk=trunk \
  --branches=branches \
  --tags=tags \
  --authors-file=authors.txt \
  {repo_name}

Post-migration cleanup

cd {repo_name}

# Convert SVN tags to Git tags
git for-each-ref refs/remotes/origin/tags/ --format='%(refname:short)' | while read tag; do
  git_tag=$(echo "$tag" | sed 's|origin/tags/||')
  git tag "$git_tag" "$tag"
  git branch -rd "$tag"
done

# Convert SVN branches to Git branches
git for-each-ref refs/remotes/origin/ --format='%(refname:short)' | while read branch; do
  git_branch=$(echo "$branch" | sed 's|origin/||')
  if [ "$git_branch" != "trunk" ]; then
    git branch "$git_branch" "$branch"
    git branch -rd "$branch"
  fi
done

# Remove SVN metadata
git branch -rd origin/trunk 2>/dev/null
rm -rf .git/svn

# Clean up
git gc --aggressive --prune=now

Verification

# Verify commit count matches
svn_count=$(svn log --quiet {svn_url} | grep "^r" | wc -l)
git_count=$(git rev-list --count HEAD)
echo "SVN commits: $svn_count, Git commits: $git_count"

# Verify tags
git tag -l | wc -l

# Verify branches
git branch -a | wc -l

# Check repo size
git count-objects -vH

# Add remote and push
git remote add origin {git_url}
git push -u origin --all
git push origin --tags

Git Error Recovery Cheat Sheet

Situation Command
Undo last commit (keep changes staged) git reset --soft HEAD~1
Undo last commit (keep changes unstaged) git reset HEAD~1
Undo last commit (discard changes) git reset --hard HEAD~1
Unstage a file git restore --staged {file}
Discard changes to a file git restore {file}
Recover deleted branch git reflog → git checkout -b {name} {hash}
Abort a merge in progress git merge --abort
Abort a rebase in progress git rebase --abort
Abort a cherry-pick git cherry-pick --abort
Fix the last commit message git commit --amend -m "new message"
Add forgotten file to last commit git add {file} → git commit --amend --no-edit
Undo a pushed commit (safe) git revert {hash} → git push
Find which commit introduced a bug git bisect start → git bisect bad → git bisect good {hash}
See what happened to HEAD git reflog
Recover file from specific commit git checkout {hash} -- {file}
Remove file from Git but keep locally git rm --cached {file}
Clean untracked files git clean -fd (directories too)
Clean untracked + ignored files git clean -fdx
Fix detached HEAD git checkout main or git checkout -b {new_branch}
Undo git stash pop with conflicts git checkout -- . → stash is still in git stash list
Remove sensitive data from history git filter-repo --path {file} --invert-paths

Rules & Best Practices

Branching

  • Convention: fix/{issue-number}-short-description, feat/{issue-number}-short-description
  • One branch per issue (or per issue group if they share files)
  • Always rebase onto main before merging — never merge main into feature branches
  • Delete branches after merge

Pull Requests

  • Body MUST include Closes #{number} to auto-close issues on merge
  • Title: concise, under 70 characters, conventional commit style
  • Use squash merge to keep git history clean
  • Delete remote branch after merge
  • Request at least 1 review before merge

Commit Conventions

  • Use conventional commits format: type(scope): description
  • Subject line ≤ 72 characters
  • Body wrapped at 100 characters
  • Reference issues in the body: Refs #123
  • One logical change per commit

Parallel Safety

  • Issues touching the same files go to the same developer
  • Each developer works in an isolated worktree or clone
  • Never have two developers editing the same file concurrently
  • Maximum 3–5 parallel developers to manage resource usage

Review Etiquette

  • Always reply to comments explaining what was fixed and referencing the commit
  • Always resolve the review thread after replying
  • If a comment is not applicable, reply explaining why (don’t ignore it)
  • Distinguish between required changes, suggestions, and nitpicks

Release Safety

  • Always run full test suite before tagging
  • Use annotated tags with descriptive messages
  • Create GitHub Releases with changelogs
  • Have a rollback plan before deploying
  • Never force-push to main/release branches

Error Recovery

  • If a developer fails, read their output to diagnose the issue
  • Fix manually or respawn with better instructions
  • If merge conflicts arise, always rebase (never merge main into branches)
  • If worktrees are stuck, force-remove and prune
  • Use git reflog as your safety net — it records all HEAD movements for 90 days

Project Convention Discovery

  • Read CLAUDE.md, CONTRIBUTING.md, or equivalent for project rules
  • Run the project’s formatter/linter before committing
  • Run the project’s test suite before creating PRs
  • Use the project’s package manager (don’t mix npm/yarn/pnpm/bun)
  • Check for .editorconfig, prettier.config, eslint.config for style rules

Platform-Specific Notes

Claude Code

  • Use Task tool with isolation: "worktree" for parallel developers
  • Use TeamCreate / TeamDelete for team orchestration
  • Use TaskCreate / TaskUpdate for task tracking
  • Use SendMessage with type: "shutdown_request" to dismiss developers
  • Use Bash tool for all gh and git CLI commands
  • Use Read / Glob / Grep tools for code exploration before making changes
  • Use EnterPlanMode before major implementation work

Cursor / Windsurf / Copilot

  • Open multiple terminal tabs for parallel work
  • Use git worktree add manually to create isolated workspaces
  • Track progress in a checklist or project board
  • Run fix agents sequentially if parallel execution isn’t supported
  • Use inline code actions for quick fixes during review
  • Leverage built-in Git integration for staging, committing, and pushing

Codex / OpenClaw

  • Use sandbox environments for isolated execution
  • Batch operations where possible to reduce API calls
  • Use structured output for parsing gh command results
  • Chain commands with && for atomic operations
  • Log all operations for audit trail

Aider / CLI-based Assistants

  • Use git worktree add ../worktree-{issue} -b fix/{issue}-{slug} for isolation
  • Run one instance per worktree for parallelism
  • Coordinate via shared task file or git notes
  • Use --yes flag for non-interactive operation where supported
  • Pipe gh output through jq for structured processing

Universal (All Platforms)

  • The core workflows (issue resolution, sprint planning, releases) are platform-agnostic
  • All gh CLI commands work everywhere GitHub CLI is installed
  • All git commands are standard and platform-independent
  • Adapt tool calls to your platform’s specific API
  • When in doubt, fall back to raw git and gh commands in the terminal
  • Test all commands in a safe environment before running on production repos