create-pr

SkillDev tools

Create a pull request from dev to main with proper formatting and draft release

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the create-pr skill

What this skill tells your AI

The instructions your AI receives, as published by glowingkitty/openmates in .agents/skills/create-pr/SKILL.md and read by ahel’s review.

Instructions

IMPORTANT: Only create a PR when the user explicitly asks.

OpenCode users invoke this workflow through /pullrequest. That command creates a visible user turn and loads this skill through the skill tool. Keep this file static: execute commands explicitly during the workflow rather than using Claude command-template shell expansion in SKILL.md.

Step 0 — Summarize Changelog Markdown Before Asking Questions (CRITICAL)

Identify the most recent merged devmain PR using --state merged and its mergedAt value. Read every compact docs/releases/daily/YYYY-MM-DD.md on or after that merge date and every docs/releases/weekly/YYYY-Www.md whose covered date range overlaps the post-merge period. Do not refresh or write release-intelligence artifacts yet.

Start with explicit read-only discovery:

git fetch origin main dev
latest_pr=$(gh pr list --base main --head dev --state merged --limit 1 \
  --json number,title,mergedAt,mergeCommit,headRefOid,url)
latest_head=$(printf '%s' "$latest_pr" | jq -r '.[0].headRefOid // empty')
if [ -n "$latest_head" ] && ! git merge-base --is-ancestor "$latest_head" origin/main; then
  printf 'Blocked: previous dev PR head %s is not an ancestor of origin/main. Repair merge history before preparing another PR.\n' "$latest_head"
  exit 1
fi

repo=$(gh repo view --json nameWithOwner --jq '.nameWithOwner')
merge_policy=$(gh api "repos/$repo" \
  --jq '[.allow_merge_commit, .allow_squash_merge, .allow_rebase_merge] | @tsv')
expected_merge_policy=$(printf 'true\tfalse\tfalse')
if [ "$merge_policy" != "$expected_merge_policy" ]; then
  printf 'Blocked: repository must allow merge commits only; squash and rebase rewrite dev commit ancestry.\n'
  exit 1
fi

printf '%s\n' "$latest_pr"
git rev-list --left-right --count origin/main...origin/dev
git diff --stat origin/main...origin/dev

This merge-history gate is mandatory. It prevents a squash or rebase promotion from making previously released dev commits appear unreleased and preserves their exact hashes on main. Do not continue by substituting a tree-diff check: identical trees do not prove that commit ancestry was retained.

Use the merged PR's mergedAt date to select the daily Markdown files, then inspect weekly Markdown files whose stated date range overlaps that boundary. Read the selected files in full before producing the summary. For the merge-day file, include only entries supported by commits in origin/main..origin/dev; exclude entries already reachable from the prior PR's merge commit. This keeps changes made later on the merge day without repeating the prior release.

Before asking any clarifying question, give the user one concise, source-grounded summary with these headings:

  • Released/User-Facing Changes
  • Bug Fixes
  • Internal/Platform Work
  • Disabled Or Unreleased Preparation
  • Risks And Unclear Decisions

Use Markdown companions as the primary source. Use origin/main..origin/dev, changed files, companion YAML, and full commit messages only as supporting evidence or to resolve ambiguity. Do not claim a feature is released merely because its code is in dev.

Step 1 — Ask Exactly Five Clarifying Questions (CRITICAL)

After presenting the changelog summary, ask exactly five clarifying questions before changing feature availability, reconciling branches, drafting the PR body, or creating the PR.

  • Ask one question per assistant message and wait for the user's response before asking the next.
  • Label them Question 1 of 5 through Question 5 of 5.
  • Include a concrete recommendation in each question using Recommendation: with the evidence-based preferred answer and rationale, plus Examples: with task-specific options or outcomes. If uncertain, recommend the safest reversible default and state the uncertainty.
  • Incorporate answers already provided by the user, but still ask for confirmation when the answer controls release scope or branch history.
  • Cover these five decision areas, adapting the wording to the discovered changes: code inclusion versus public release-note treatment; enabled versus disabled feature readiness; main-only commit reconciliation; required validation/risk exceptions; and PR narrative/release emphasis.
  • For branch reconciliation, inspect the main-only commits before making a recommendation. Recommend preserving legitimate fixes and merge history. Ask the user about ambiguous commits or behavioral conflicts rather than guessing.

After the fifth answer, summarize the confirmed decisions and execution plan, then continue autonomously through the readiness gates and PR creation. Do not ask for a separate plan approval; the user's explicit /pullrequest invocation and five answers authorize the workflow. Stop only for a failed required gate, an unclassified feature introduced after the questions, or another concrete safety/reconciliation decision that the five answers could not cover.

Step 2 — Resolve Worktree Readiness (CRITICAL)

Before release intelligence or PR drafting, fetch dev and run reconciliation readiness against its exact remote commit:

git fetch origin dev
python3 scripts/sessions.py worktree release-readiness --target origin/dev

The gate blocks stale, blocked, orphaned, malformed, unique unresolved, and unclassified worktrees. Do not merge or delete worktree content manually to bypass it. Run the reported sessions.py worktree reconcile action and stop when meaningful unique work still needs an operator decision.

Recent active work may remain outside this release only after the user explicitly confirms the exclusion. Rerun with one flag per confirmed session, for example:

python3 scripts/sessions.py worktree release-readiness \
  --target origin/dev \
  --exclude-active 253b

Record the excluded session IDs in the PR preparation summary, rerun the gate after any cleanup or deploy, and continue only when it reports Ready: yes for the final exact origin/dev commit.

Step 3 — Verify Remote Refs And Main-Only Commits (CRITICAL)

ALWAYS use remote refs (origin/main, origin/dev) — never local refs. Local refs can be stale and produce wildly incorrect commit counts.

git fetch origin main dev
git rev-list --left-right --count origin/main...origin/dev
git log --format="%h %s%n%b" origin/dev..origin/main
git log --oneline origin/main..origin/dev

Confirm the commit count makes sense and classify every main-only commit before reconciling branches. If the commits are legitimate fixes or merge history and reconciliation is conflict-free, follow the user's approved strategy. Stop and ask about unexpected commits or behavioral conflicts.

Step 4 — Refresh Release Intelligence

Before writing the PR body, always refresh the current daily changelog so the last 24 hours are represented:

today=$(date -u +%F)
python3 scripts/release_intelligence.py daily \
  --since "24 hours ago" \
  --date "$today" \
  --write \
  --output "docs/releases/daily/${today}.yml"

Use the most recent merged devmain PR boundary established in Step 0. Re-read the refreshed daily Markdown companion and update the changelog summary if it materially changed.

latest_pr_date=$(gh pr list --base main --head dev --state merged --limit 1 --json mergedAt --jq '.[0].mergedAt // empty' | cut -dT -f1)
ls docs/releases/daily/*.md | while read -r file; do
  day=$(basename "$file" .md)
  if [ -z "$latest_pr_date" ] || [ "$day" = "$latest_pr_date" ] || [ "$day" ">" "$latest_pr_date" ]; then
    echo "$file"
  fi
done

Use the Markdown overview, grouped changes, and newsletter guidance to build the PR body. Keep unreleased/disabled-feature work out of public release/newsletter language, but include it in the PR when it is part of the code diff. Use companion YAML fields such as sections, marketing_candidates, and unreleased_progress only when deeper structured evidence is required. Apply the same merge-day commit-evidence filter used in Step 0 before adding items from the refreshed Markdown companion.

Step 5 — Feature Readiness Gate (CRITICAL)

Before drafting or creating the PR, run and read the deterministic feature readiness report:

latest_pr_date=$(gh pr list --base main --head dev --state merged --limit 1 --json mergedAt --jq '.[0].mergedAt // empty' | cut -dT -f1)
if [ -n "$latest_pr_date" ]; then
  next_daily_date=$(date -u -d "${latest_pr_date} +1 day" +%F)
  python3 scripts/release_intelligence.py pr-readiness \
    --from-ref origin/main \
    --to-ref origin/dev \
    --daily-start-date "$next_daily_date" \
    --format markdown \
    --stdout
else
  python3 scripts/release_intelligence.py pr-readiness \
    --from-ref origin/main \
    --to-ref origin/dev \
    --format markdown \
    --stdout
fi

Use this report to list every changed user-facing or potentially user-facing feature area, especially default-disabled platform features and app/skill/provider work such as projects, tasks, plans, workflows, teams, Revolut Business finance, and code image-to-HTML/image-to-code.

Reconcile this deterministic report with the five confirmed answers. If the report introduces a feature area that the questions did not cover, stop for a focused follow-up decision. Do not silently infer release readiness, draft the final PR body, or run gh pr create while any listed feature remains unclassified.

If the user says a feature is not ready, keep the code but deactivate access through the existing feature availability model:

  • For platform features, remove any matching feature_overrides.enabled entry and/or add a feature_overrides.disabled entry in backend/config/backend_config.yml.
  • For apps, skills, embeds, focus modes, or memory types, set default_enabled: false on the relevant backend/apps/*/app.yml entry.
  • Re-run python3 scripts/release_intelligence.py pr-readiness --from-ref origin/main --to-ref origin/dev --format markdown --stdout and show the updated status before continuing.

Continue automatically when the five answers classify every reported feature and confirm that the remaining accessible features are ready for the PR. Do not request the same confirmation again at this gate.

Step 6 — Analyze Remaining Commit Details

Use raw commit history only as supporting evidence or to fill gaps not covered by daily changelogs. Read the full commit messages (not just one-liners):

git log origin/main..origin/dev --format="%h %s%n%b"

Group commits into:

  • Features (feat:) — new user-facing functionality
  • Bug Fixes (fix:) — resolved issues
  • Improvements (refactor:, perf:, improve:) — internal improvements
  • Other (docs:, chore:, build:, ci:, test:) — maintenance

Step 7 — Write PR Description

Write a human-readable PR description — not a commit dump. Structure:

## Summary
<2-4 sentence overview of what this PR does and why>

## Features
- <grouped by feature area>

## Bug Fixes
- <grouped by fix area>

## Improvements
- <grouped by improvement area>

## Future Release Preparation
- <briefly summarize included code for explicitly unreleased features without claiming availability>

## Other Changes
- <docs, chore, config items>

Only include sections that have content. Write for a developer audience — specific and clear.

Step 8 — Create the PR

gh pr create --base main --head dev --title "<short descriptive title>" --body "$(cat <<'EOF'
<PR description>
EOF
)"

Present the PR URL to the user.

Step 9 — Offer Draft Release

After PR creation, ask the user if they want a draft release prepared. If yes, use the /create-release skill. Tell the user:

  • The PR URL
  • That the draft release should be published after the PR is merged into main

Signals

GitHub stars
46
Forks
3
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
create-pr-glowingkitty
Source
github.com/glowingkitty/openmates