← ShipFrameCONTENT HISTORY

Update to ShipFrame

Snapshot Sep 30, 2026 · 23:14 UTC · version 0.4.2

Collection source: not recorded for this historical snapshot.

WHAT CHANGED · RULE-BASED ANALYSIS

First saved snapshot

No earlier snapshot is available to establish a change.

Compare saved observations

Download comparison JSON
Full technical diff · 0 changed fields
Full snapshot data
{
  "description": "Create a Draft GitHub PR or GitLab MR from git diff, commits, CODEOWNERS, and the ShipFrame PR template.",
  "included_files": [],
  "name": "create-pr",
  "skill_md_contents": "---\nname: create-pr\ndescription: Create a Draft GitHub PR or GitLab MR from git diff, commits, CODEOWNERS, and the ShipFrame PR template.\nargument-hint: '[--base <branch>] [--ticket-id <id>] [--provider <auto|github|gitlab>] [--auto]'\nallowed-tools: Bash AskUserQuestion mcp__github__create_pull_request mcp__github__list_branches\neffort: low\n---\n\n# create-pr\n\n**Role:** Senior engineer opening a pull request or merge request.\n**Goal:** Auto-generate a complete, reviewer-ready PR/MR from git context alone. Every section is derived from the diff, commits, branch name, and project files — no manual writing required. When `--auto` is passed (or when called by another skill/agent), skip all confirmation steps and create the PR/MR immediately.\n\n---\n\n## Step 1 — Parse arguments\n\nParse `$ARGUMENTS` for:\n- `--base <branch>` — target branch for the PR/MR (skip inference if provided)\n- `--ticket-id <id>` — ClickUp or issue ID to reference (optional)\n- `--provider <auto|github|gitlab>` — host provider to use; default is `auto`\n- `--auto` — skip all confirmation steps and create the PR/MR without asking\n\nCapture any provided values. Set `AUTO_MODE = true` if `--auto` is present. Set `PROVIDER_INPUT = auto` when `--provider` is omitted. Reject any provider value outside `auto`, `github`, or `gitlab` with a clear error before doing network operations.\n\n---\n\n## Step 2 — Gather git context\n\nRun all commands via Bash. Capture every output — it feeds every section of the template.\n\n```bash\n# Current branch\ngit branch --show-current\n\n# Remote URL (to detect provider and extract host/owner/repo)\ngit remote get-url origin\n\n# Current git user email (to exclude from FYI tagging)\ngit config user.email\n\n# All remote branches (for base branch inference)\ngit branch -r --format='%(refname:short)' | sed 's/origin\\///'\n\n# Last 20 commits on this branch (used for description and module inference)\ngit log HEAD --oneline -20\n\n# All changed files vs each candidate base branch (resolved once base is confirmed)\n# Run after base is resolved:\ngit diff <BASE_BRANCH>...HEAD --name-only\ngit diff <BASE_BRANCH>...HEAD --stat\ngit diff <BASE_BRANCH>...HEAD\n```\n\nExtract `HOST`, `OWNER`, and `REPO` from the remote URL:\n- GitHub SSH: `git@github.com:owner/repo.git`\n- GitHub HTTPS: `https://github.com/owner/repo.git`\n- GitLab SSH: `git@gitlab.com:owner/repo.git` or `git@gitlab.example.com:group/subgroup/repo.git`\n- GitLab HTTPS: `https://gitlab.com/owner/repo.git` or `https://gitlab.example.com/group/subgroup/repo.git`\n\nDetermine `PROVIDER`:\n- If `--provider github` was passed, use `github`.\n- If `--provider gitlab` was passed, use `gitlab`.\n- If `--provider auto` is active and `origin` contains `github.com`, use `github`.\n- If `--provider auto` is active and `origin` contains `gitlab.com`, use `gitlab`.\n- If `--provider auto` is active and the host is not GitHub, treat remotes whose host or path contains `gitlab` as self-hosted GitLab and use `gitlab`.\n- If auto-detection cannot identify the provider, stop and ask the caller to rerun with `--provider github` or `--provider gitlab`.\n\nFor GitLab repositories with nested groups, keep the full namespace as `OWNER` (for example, `group/subgroup`) and the final path segment as `REPO`.\n\nIf the working tree has uncommitted changes, warn:\n> \"Uncommitted changes detected. These will not be included in the PR/MR. Commit them first or proceed anyway.\"\nIn `AUTO_MODE`, proceed without asking.\n\n---\n\n## Step 3 — Infer the base branch\n\nIf `--base` was provided, use it as `BASE_BRANCH` without any confirmation or inference and skip to Step 4. This is always correct when called by `implement-task` — do not second-guess it.\n\nOtherwise, infer from the remote branches list using this priority order:\n\n1. `main`\n2. `master`\n3. `develop`\n4. `staging`\n5. First `release/*` branch found\n6. If none of the above exist, use the most recently committed remote branch\n\nIf `AUTO_MODE` is false and the inferred branch is not `main` or `master`, confirm with the user:\n> \"Inferred base branch: `<branch>`. Is this correct?\"\nIn `AUTO_MODE`, proceed with the inferred branch silently.\n\nIf the current branch equals `BASE_BRANCH`, stop:\n> \"The current branch is the same as the base branch. Switch to a feature branch first.\"\n\n---\n\n## Step 4 — Infer PR/MR title\n\nDerive the PR/MR title from the branch name:\n1. Strip the type prefix: `feat/`, `fix/`, `chore/`, `refactor/`, `docs/`, `hotfix/`\n2. Strip any ticket/sprint/module prefix (e.g. `CU-abc123-`, `M3-S12-`)\n3. Replace hyphens and underscores with spaces\n4. Title-case the result\n5. Prepend the type label in brackets: `[Feature]`, `[Fix]`, `[Refactor]`, `[Docs]`, `[Chore]`, `[Hotfix]`\n6. If a ticket ID is available (from `--ticket-id` or extracted from the branch name), append it: `(CU-abc123)`\n\nExample: `feat/CU-abc123-user-auth-flow` → `[Feature] User auth flow (CU-abc123)`\n\n---\n\n## Step 5 — Populate the PR/MR template\n\nThe canonical PR/MR body structure is defined in `templates/pull_request_template.md` at the project root of the **ShipFrame** repo (the repo where this skill lives). Read that file and use it as the exact skeleton — do not invent or remove sections. Populate every placeholder by analyzing the git context from Step 2. Instructions inside each section below describe how to derive the content — follow them precisely. The rendered output must not contain the instruction text or placeholder markers.\n\n---\n\n### Section: Description\n\nUsing the commit messages and `git diff` output:\n\n- Write 2–4 bullet points summarising the \"Why\" (motivation / problem solved) and \"What\" (what was changed at a high level)\n- Every bullet must start with exactly one of these semantic keywords: `add`, `update`, `fix`, `refactor`, `delete`\n- Do not paste raw commit messages — rewrite them as coherent intent statements\n- Be specific: reference function names, component names, or API routes where relevant\n\n---\n\n### Section: Type of Change\n\nFrom the PR/MR title type label (inferred in Step 4) or the branch prefix, tick exactly one checkbox:\n\n| Branch prefix / label | Checkbox to tick |\n|---|---|\n| `feat/` / `[Feature]` | `- [x] Feature` |\n| `fix/` / `[Fix]` | `- [x] Bug Fix` |\n| `refactor/` / `[Refactor]` | `- [x] Refactor` |\n| `docs/` / `[Docs]` | `- [x] Docs` |\n| `chore/` / `[Chore]` | `- [x] Chore` |\n| `hotfix/` / `[Hotfix]` | `- [x] Hotfix` |\n\nLeave all others unchecked.\n\n---\n\n### Section: Related Ticket\n\n- If `--ticket-id` was provided, format it as a ClickUp URL: `https://app.clickup.com/t/<id>`\n- If a ticket ID was extracted from the branch name (e.g. `CU-abc123`), use the same format\n- If no ticket is available, write: `N/A`\n\n---\n\n### Section: Module\n\nParse the branch name and the last 20 commit messages for:\n\n- **Migration Number / Section Name** — look for patterns like `M1`, `M2`, `M3`, `migration-1`, `section-2` in the branch name or commits. Extract as `M{N}`. If not found, write `<!-- TBD -->`.\n- **Sprint** — look for patterns like `S12`, `sprint-12`, `sprint/12` in the branch name or commits. Extract as `S{N}`. If not found, write `<!-- TBD -->`.\n\nNever invent values. Placeholders are correct when data is absent.\n\n---\n\n### Section: Shared Code Impact\n\nInspect the list of changed files (`git diff --name-only`) for any files inside directories that suggest shared or cross-cutting code:\n\n- Common directory names: `shared/`, `core/`, `common/`, `lib/`, `utils/`, `helpers/`, `hooks/`, `composables/`, `services/`, `types/`, `constants/`\n\nIf any matches are found:\n- Answer: **Yes**\n- List each affected file path\n- Add: `Team notified: No` (the author must verify before merge)\n\nIf no matches: Do not include the `### Shared Code Impact` section in the rendered PR body.\n\n---\n\n### Section: Breaking Changes\n\nAnalyze the git diff and commit messages for indications of breaking changes, such as:\n- Modified or removed API route parameters/responses\n- Changes to shared library function signatures/interfaces\n- Database schema changes that remove or alter columns\n- Commit messages containing `BREAKING CHANGE:` or `!` in the type prefix (e.g. `feat!:`)\n\nIf breaking changes are detected:\n- Answer: **Yes**\n- Describe what breaks and the required migration path for other developers\n\nIf no breaking changes: Do not include the `### Breaking Changes` section in the rendered PR body.\n\n---\n\n### Section: FYI\n\n1. Check if a `CODEOWNERS` file exists at the project root or `.github/CODEOWNERS`.  \n   If it exists, read it and extract GitHub handles (`@username`) mapped to the changed files.\n\n2. Also run:\n   ```bash\n   git log <BASE_BRANCH>...HEAD --invert-grep -E --format=\"%ae\" -- <changed files> | sort | uniq\n   ```\n   Map contributor emails to GitHub handles where possible (use the handle from CODEOWNERS if the same person appears there).\n\n3. Combine both sources into a de-duplicated list of `@handles`.\n\n4. **Mandatory:** remove the current PR author's handle from the list (identified by `git config user.email` from Step 2).\n\n5. If the list is empty after deduplication, write: `No additional stakeholders identified.`\n\n---\n\n### Section: Screenshots\n\nInspect the changed file paths for UI indicators:\n- Directories: `pages/`, `views/`, `routes/`, `screens/`, `app/`, `src/app/`\n- File extensions or names containing: `.vue`, `.svelte`, `Page.`, `View.`, `Screen.`, `Layout.`\n- Any component file touched inside a route-level directory\n\n**If UI changes are detected:**\n- List each modified route or page\n- For each, provide a provider-specific raw/blob URL format for evidence screenshots:\n  ```\n  # GitHub\n  https://github.com/<OWNER>/<REPO>/blob/<CURRENT_BRANCH>/.github/evidence/<filename>.png?raw=true\n\n  # GitLab\n  https://<HOST>/<OWNER>/<REPO>/-/blob/<CURRENT_BRANCH>/.github/evidence/<filename>.png\n  ```\n- Note: \"Add screenshots at the paths above before requesting review.\"\n\n**If no UI changes:** write: `No UI changes in this PR.`\n\n---\n\n### Section: Test Plan\n\nDerive a concrete, ordered checkbox list a reviewer can follow to verify the changes end-to-end.\n\nRules:\n- Every step must come from the actual diff — no generic steps like \"verify the app works\"\n- Start from the entry point a real user or caller would use (navigate to a route, call an endpoint, trigger an action)\n- Cover the happy path first, then at least one edge or error case if changes touch validation, error handling, or conditional logic\n- Include any required setup (env vars, feature flags, seed data, running migrations)\n- One action per checkbox — short and imperative\n- If the change is backend-only: describe the API call (method, endpoint, payload, expected response)\n- If the change is UI-only: describe the user interaction and the expected visual or functional outcome\n- If new tests were added: include a step to run them with the specific command (e.g. `npm test -- --testPathPattern=<file>`)\n\nFormat:\n```\n- [ ] <imperative step>\n- [ ] <imperative step>\n```\n\n---\n\n### Section: Release Readiness\n\n- `Ready for release:` Yes — if all test plan steps are expected to pass based on the implementation\n- `Needs additional work:` No — unless there are known gaps, open questions, or incomplete items identified during implementation\n\n---\n\n## Step 6 — Render and confirm\n\nAssemble the full PR body using this exact structure:\n\n```markdown\n## Description 📝\n<populated description bullets>\n\n### Type of Change\n<checkbox list with exactly one item checked based on branch type>\n\n### Related Ticket\n<ticket URL or \"N/A\">\n\n### Module\n- Migration: <M{N} or TBD>\n- Sprint: <S{N} or TBD>\n\n### Shared Code Impact\n<Include only if Yes: file list and Team notified>\n\n### Breaking Changes\n<Include only if Yes: describe what breaks and the migration path>\n\n### FYI 🙋\n<@handles or \"No additional stakeholders identified.\">\n\n### Screenshots 📸\n<screenshot entries or \"No UI changes in this PR.\">\n\n### Test Plan 🧪\n<checkbox list>\n\n### Release Readiness\n- Ready for release: <Yes/No>\n- Needs additional work: <Yes/No>\n```\n\nIf `AUTO_MODE` is **false**, present the rendered body and the inferred title to the user and ask:\n> \"Does this PR/MR look correct? Reply Yes to create it, or paste corrections.\"\nApply any corrections before proceeding.\n\nIf `AUTO_MODE` is **true**, skip confirmation and proceed immediately.\n\n---\n\n## Step 7 — Create the PR/MR\n\n**All PRs and MRs must be created as Draft. This is non-negotiable — never omit `--draft`.**\n\nBefore invoking provider CLIs, write the rendered body to a temporary file and keep its path in `BODY_FILE` so the user can reuse it if creation fails:\n\n```bash\nBODY_FILE=\"$(mktemp -t shipframe-pr-mr-body.XXXXXX.md)\"\nprintf '%s\\n' \"<rendered PR/MR body>\" > \"$BODY_FILE\"\n```\n\n### GitHub provider: gh CLI\n\nUse this path when `PROVIDER=github`.\n\nFirst verify the local CLI and authentication:\n\n```bash\ncommand -v gh\ngh auth status\n```\n\nIf `gh` is missing or unauthenticated, stop and report:\n\n```text\nGitHub PR not created. ShipFrame generated the body at <BODY_FILE>.\nInstall/authenticate GitHub CLI, then rerun:\n  brew install gh\n  gh auth login\n  gh auth status\n```\n\nCreate the Draft PR:\n\n```bash\ngh pr create \\\n  --title \"<PR/MR title>\" \\\n  --body-file \"$BODY_FILE\" \\\n  --base \"<BASE_BRANCH>\" \\\n  --head \"<current branch>\" \\\n  --draft\n```\n\nIf the command exits with a non-zero status, capture the error and proceed to the GitHub MCP fallback below.\n\n### GitHub fallback: GitHub MCP (only if gh CLI fails)\n\nIf `gh pr create` failed, create the PR using the MCP tool:\n\n```\nmcp__github__create_pull_request {\n  owner: \"<OWNER>\",\n  repo: \"<REPO>\",\n  title: \"<PR/MR title>\",\n  body: \"<rendered PR/MR body>\",\n  head: \"<current branch>\",\n  base: \"<BASE_BRANCH>\",\n  draft: true\n}\n```\n\nIf both GitHub methods fail, report the errors from both attempts, include `BODY_FILE`, and stop.\n\n### GitLab provider: glab CLI\n\nUse this path when `PROVIDER=gitlab`. There is no GitLab MCP fallback in ShipFrame v1.\n\nFirst verify the local CLI and authentication:\n\n```bash\ncommand -v glab\nglab auth status\n```\n\nIf `glab` is missing or unauthenticated, stop and report:\n\n```text\nGitLab MR not created. ShipFrame generated the body at <BODY_FILE>.\nInstall/authenticate GitLab CLI, then rerun:\n  brew install glab\n  glab auth login\n  glab auth status\n```\n\nCreate the Draft MR:\n\n```bash\nglab mr create \\\n  --title \"<PR/MR title>\" \\\n  --description \"$(cat \"$BODY_FILE\")\" \\\n  --target-branch \"<BASE_BRANCH>\" \\\n  --source-branch \"<current branch>\" \\\n  --draft \\\n  --yes\n```\n\nIf `glab mr create` fails, report the captured error, include `BODY_FILE`, and stop. Do not fall back to GitHub MCP for GitLab remotes.\n\n---\n\n## Step 8 — Report\n\n```\n## Pull Request / Merge Request Created (Draft)\n\nTitle:    <title>\nURL:      <pr_or_mr_url>\nProvider: <github|gitlab>\nBase:     <BASE_BRANCH> <- <current branch>\nFiles:    <count> changed\nMethod:   <gh CLI | GitHub MCP (fallback) | glab CLI>\nBody:     <BODY_FILE>\n```\n\nStore `PR_URL` or `MR_URL` and the request number/IID in context — downstream skills or agents may need them.\n"
}

SHA-256 of public snapshot: 50e07cd44d706e6bd0ff97dff2f348ceaaeb8dff612f2a87f4c497e07bdca207