From 84f053d6716fba306cc2271c92cadeb8248e5b32 Mon Sep 17 00:00:00 2001 From: VinPropane Date: Sat, 25 Apr 2026 19:46:31 -0400 Subject: [PATCH] chore: document opening PRs via GitHub MCP instead of gh CLI commit-and-review: primary path is user-github create_pull_request; owner/repo from origin; fallback URL + optional gh for humans. Cross-link AGENTS, kickoff, story-end, linear-git-naming, git-workflow. --- .cursor/rules/commit-and-review.md | 16 +++++++++------- .cursor/rules/git-workflow.md | 2 +- .cursor/rules/linear-git-naming.md | 2 +- .cursor/rules/story-end.md | 4 ++-- .cursor/rules/story-kickoff.md | 2 +- AGENTS.md | 2 +- 6 files changed, 15 insertions(+), 13 deletions(-) diff --git a/.cursor/rules/commit-and-review.md b/.cursor/rules/commit-and-review.md index c9e4a2b..ba0e248 100644 --- a/.cursor/rules/commit-and-review.md +++ b/.cursor/rules/commit-and-review.md @@ -1,5 +1,5 @@ --- -description: Commits at agent discretion; push only when user asks; gh pr create with NEO-* title when opening PRs; PR text without tool boilerplate +description: Commits at agent discretion; push only when user asks; GitHub MCP create_pull_request with NEO-* title when opening PRs; PR text without tool boilerplate alwaysApply: true --- @@ -25,12 +25,14 @@ alwaysApply: true When the user asks to **open**, **create**, or **file** a pull request (or clearly wants one opened for the current branch): -1. **Use the GitHub CLI** — Run **`gh pr create`** (not only a browser **`/pull/new/...`** link). That way you control the **title** and avoid GitHub’s default, which title-cases the branch name and turns **`NEO-25`** into **`Neo 25`**. -2. **Title** — **`--title`** must **begin** with the **Linear issue key** in canonical form: **`NEO-123:`** (see [linear-git-naming](linear-git-naming.md): uppercase team prefix, hyphen, issue number), then a short human summary. Example: **`NEO-25: InteractableDescriptor list / fetch-driven client`**. -3. **Infer the key** — In order: the **current branch**’s leading segment (e.g. `NEO-25-my-slug` → `NEO-25`); the matching **`docs/plans/{KEY}-implementation-plan.md`** on the branch; Linear MCP / issue in chat; or **ask** the user if ambiguous. -4. **Body** — Pass **`--body`** or **`--body-file`** with scope, how to verify (`dotnet test`, manual QA path, etc.), and pointers to `docs/plans/` when useful. -5. **Upstream** — If **`gh pr create`** fails because the branch is not on `origin`, push first (**only** as allowed under **Never push** above—i.e. the same user message asked to open the PR or explicitly to push). -6. **Fallback** — If **`gh`** is missing or not authenticated (`gh auth status`), tell the user and optionally still give the **`pull/new/...`** URL, with an explicit reminder to **edit the title** so it starts with **`NEO-123:`** (not `Neo 123`). +1. **Use the GitHub MCP** — Call **`create_pull_request`** on the **`user-github`** MCP server (read the tool descriptor under the workspace MCP folder first, same as other MCP tools). Pass **`owner`**, **`repo`**, **`head`**, **`base`**, **`title`**, and **`body`**. You set the **title** explicitly—do not rely only on GitHub’s **Compare & pull request** default, which title-cases the branch and can turn **`NEO-25`** into **`Neo 25`**. +2. **Repository** — Set **`owner`** and **`repo`** from **`git remote get-url origin`** (e.g. `git@github.com:ViPro-Technologies/neon-sprawl.git` → `ViPro-Technologies`, `neon-sprawl`). For this repo they are almost always **`ViPro-Technologies`** / **`neon-sprawl`**. +3. **Branches** — **`head`** is the branch that contains the work (e.g. `NEO-26-selectionevent-surface-debug-consumer`); **`base`** is usually **`main`** unless the user names another target. +4. **Title** — Must **begin** with the **Linear issue key** in canonical form: **`NEO-123:`** (see [linear-git-naming](linear-git-naming.md): uppercase team prefix, hyphen, issue number), then a short human summary. Example: **`NEO-25: InteractableDescriptor list / fetch-driven client`**. +5. **Infer the key** — In order: the **current branch**’s leading segment (e.g. `NEO-25-my-slug` → `NEO-25`); the matching **`docs/plans/{KEY}-implementation-plan.md`** on the branch; Linear MCP / issue in chat; or **ask** the user if ambiguous. +6. **Body** — Pass **`body`** with scope, how to verify (`dotnet test`, manual QA path, etc.), and pointers to `docs/plans/` when useful. When building JSON for the MCP tool, use **real newlines** in markdown strings (not literal `\n` escape sequences), per MCP guidance for this server. +7. **Upstream** — If **`create_pull_request`** fails because **`head`** is not on **`origin`**, push first (**only** as allowed under **Never push** above—i.e. the same user message asked to open the PR or explicitly to push). +8. **Fallback** — If the GitHub MCP is unavailable or the call fails after push, give **`https://github.com/{owner}/{repo}/pull/new/{head}`** and tell the user to set the PR title to **`NEO-123:`** … . They may use **`gh pr create`** locally if they prefer the CLI. ## Commit message format when a Linear issue applies diff --git a/.cursor/rules/git-workflow.md b/.cursor/rules/git-workflow.md index d687da0..9fe4f2e 100644 --- a/.cursor/rules/git-workflow.md +++ b/.cursor/rules/git-workflow.md @@ -17,4 +17,4 @@ When a change mixes documentation and code, treat it as a **code change** (use a After the PR for a story branch is **merged**, clean up locally per [story-end](story-end.md) (`checkout main`, `pull`, `branch -d`). -When the user asks the agent to **open a PR**, use **`gh pr create`** with a **`NEO-*:`** title prefix per [commit-and-review](commit-and-review.md) **Opening a PR when the user asks**—not only a GitHub **Compare & pull request** link (the web UI mangles issue-key casing in the default title). +When the user asks the agent to **open a PR**, use the **GitHub MCP** **`create_pull_request`** tool with a **`NEO-*:`** title prefix per [commit-and-review](commit-and-review.md) **Opening a PR when the user asks**—not only a GitHub **Compare & pull request** link (the web UI mangles issue-key casing in the default title). diff --git a/.cursor/rules/linear-git-naming.md b/.cursor/rules/linear-git-naming.md index 8dca119..cab194e 100644 --- a/.cursor/rules/linear-git-naming.md +++ b/.cursor/rules/linear-git-naming.md @@ -32,4 +32,4 @@ When suggesting or creating a branch for **NEO-5**, use something like **`NEO-5- ## Agent behavior - When creating a **branch** or **commit** for tracked work, **infer the id** from the current story (e.g. user says NEO-5), the branch already in use, or the Linear issue fetched via MCP (`plugin-linear-linear`, e.g. `get_issue` / `list_issues`). -- When the user asks the agent to **open a PR**, the PR **title** must start with that same **`NEO-*:`** form (use **`gh pr create --title`** per [commit-and-review](commit-and-review.md)); do not ship a default web-only title that lowercases the key to **`Neo`**. +- When the user asks the agent to **open a PR**, the PR **title** must start with that same **`NEO-*:`** form (set **`title`** on the GitHub MCP **`create_pull_request`** call per [commit-and-review](commit-and-review.md)); do not ship a default web-only title that lowercases the key to **`Neo`**. diff --git a/.cursor/rules/story-end.md b/.cursor/rules/story-end.md index 4106e73..b992b50 100644 --- a/.cursor/rules/story-end.md +++ b/.cursor/rules/story-end.md @@ -20,7 +20,7 @@ When the user **ends story work** on a ticketed branch—phrases like “end sto ## 2a. When `main` is push-protected -If the user asks to **push** changes that sit on **`main`** and **`git push origin main` fails** (required PR / status checks), create a branch from current `main` (e.g. `chore/…`), **`git push -u origin`** that branch, then open the PR with **`gh pr create`** and a title keyed per [commit-and-review](commit-and-review.md) **Opening a PR when the user asks** (or give the **`pull/new/...`** URL **and** remind them to fix the title to **`NEO-123:`**). **`git reset --hard origin/main`** if you had temporarily advanced local `main` so local `main` matches remote until the PR merges. +If the user asks to **push** changes that sit on **`main`** and **`git push origin main` fails** (required PR / status checks), create a branch from current `main` (e.g. `chore/…`), **`git push -u origin`** that branch, then open the PR with the **GitHub MCP** **`create_pull_request`** tool and a title keyed per [commit-and-review](commit-and-review.md) **Opening a PR when the user asks** (or give the **`pull/new/...`** URL **and** remind them to fix the title to **`NEO-123:`**). **`git reset --hard origin/main`** if you had temporarily advanced local `main` so local `main` matches remote until the PR merges. ## 3. What not to do @@ -58,4 +58,4 @@ Then give any **git** details (branch deleted, `main` ahead, etc.) **after** the - [story-kickoff](story-kickoff.md) — start of story workflow - [git-workflow](git-workflow.md) — branch vs `main` - [linear-git-naming](linear-git-naming.md) — branch names -- [commit-and-review](commit-and-review.md) — push and **`gh pr create`** only when the user requests it; PR title **`NEO-*:`** prefix +- [commit-and-review](commit-and-review.md) — push and **GitHub MCP `create_pull_request`** only when the user requests it; PR title **`NEO-*:`** prefix diff --git a/.cursor/rules/story-kickoff.md b/.cursor/rules/story-kickoff.md index bcb1ab8..2e287c7 100644 --- a/.cursor/rules/story-kickoff.md +++ b/.cursor/rules/story-kickoff.md @@ -67,4 +67,4 @@ These three lists (**files to add**, **files to modify**, **tests**) must **alwa When the story is **done** and merged to `main`, follow [story-end](story-end.md) to return to `main`, pull, and remove the local story branch. -When the user asks to **open or create a PR** for this story, follow [commit-and-review](commit-and-review.md) **Opening a PR when the user asks**: use **`gh pr create`** with a title that **starts with the Linear key** (e.g. **`NEO-25:`**), not GitHub’s default title from the web UI alone. +When the user asks to **open or create a PR** for this story, follow [commit-and-review](commit-and-review.md) **Opening a PR when the user asks**: use the **GitHub MCP** **`create_pull_request`** tool with a title that **starts with the Linear key** (e.g. **`NEO-25:`**), not GitHub’s default title from the web UI alone. diff --git a/AGENTS.md b/AGENTS.md index a9714cc..265308f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -7,6 +7,6 @@ Optional **personas** for Cursor. Enable by **@ mentioning** the rule in chat or | **Code review** | [`.cursor/rules/code-review-agent.md`](.cursor/rules/code-review-agent.md) | PR / diff / pre-merge review; **always writes** `docs/reviews/YYYY-MM-DD-{slug}.md` with **Documentation checked** vs `docs/plans/` and `docs/decomposition/modules/`; **when suggestions are fixed, strike through those bullets + `Done.` in that file** ([planning-implementation-docs](.cursor/rules/planning-implementation-docs.md)); short chat pointer | | **Docs review** | [`.cursor/rules/docs-review-agent.md`](.cursor/rules/docs-review-agent.md) | Coherence / links / dev-guide fitness for `docs/` (especially `docs/game-design/` + decomposition); **writes** `docs/reviews/YYYY-MM-DD-{slug}.md`; **when suggestions are fixed, strike through + `Done.` in that file** ([planning-implementation-docs](.cursor/rules/planning-implementation-docs.md)); use when working in **documents** or @ mention | -Project-wide conventions live under [`.cursor/rules/`](.cursor/rules/) (many are `alwaysApply`). **Planning / implementation decisions** must be written into `docs/plans/` (and related docs)—[`.cursor/rules/planning-implementation-docs.md`](.cursor/rules/planning-implementation-docs.md). **Manual QA checklists** for user-visible ticketed work are generated during implementation at `docs/manual-qa/{KEY}.md` (same rule). **Godot client layout** (thin `main.gd`, split by concern): [`.cursor/rules/godot-client-script-organization.md`](.cursor/rules/godot-client-script-organization.md). **Git:** agents may **commit** at discretion on story/ticket work; **never** `git push` unless the user asks — [`.cursor/rules/commit-and-review.md`](.cursor/rules/commit-and-review.md). **Open PR:** when the user asks, use **`gh pr create`** with a title starting **`NEO-123:`** (same rule file). **Story lifecycle:** kickoff [`.cursor/rules/story-kickoff.md`](.cursor/rules/story-kickoff.md); after merge / end of story — `checkout main`, `pull`, delete local story branch — [`.cursor/rules/story-end.md`](.cursor/rules/story-end.md). **Linear:** on **end story**, use **`AskQuestion`** multiple choice for **In Test** / **Done** / **Skip** when Agent mode supports it ([story-end](.cursor/rules/story-end.md) §4a); otherwise ask in prose. Wait for the choice (or the same message naming the state) **before** `save_issue`; do not guess. **PR / push text:** no “Made-with: Cursor” boilerplate (same file). +Project-wide conventions live under [`.cursor/rules/`](.cursor/rules/) (many are `alwaysApply`). **Planning / implementation decisions** must be written into `docs/plans/` (and related docs)—[`.cursor/rules/planning-implementation-docs.md`](.cursor/rules/planning-implementation-docs.md). **Manual QA checklists** for user-visible ticketed work are generated during implementation at `docs/manual-qa/{KEY}.md` (same rule). **Godot client layout** (thin `main.gd`, split by concern): [`.cursor/rules/godot-client-script-organization.md`](.cursor/rules/godot-client-script-organization.md). **Git:** agents may **commit** at discretion on story/ticket work; **never** `git push` unless the user asks — [`.cursor/rules/commit-and-review.md`](.cursor/rules/commit-and-review.md). **Open PR:** when the user asks, use the **GitHub MCP** **`create_pull_request`** tool (`user-github`) with a title starting **`NEO-123:`** ([commit-and-review](.cursor/rules/commit-and-review.md)). **Story lifecycle:** kickoff [`.cursor/rules/story-kickoff.md`](.cursor/rules/story-kickoff.md); after merge / end of story — `checkout main`, `pull`, delete local story branch — [`.cursor/rules/story-end.md`](.cursor/rules/story-end.md). **Linear:** on **end story**, use **`AskQuestion`** multiple choice for **In Test** / **Done** / **Skip** when Agent mode supports it ([story-end](.cursor/rules/story-end.md) §4a); otherwise ask in prose. Wait for the choice (or the same message naming the state) **before** `save_issue`; do not guess. **PR / push text:** no “Made-with: Cursor” boilerplate (same file). **Commits tied to a Linear issue** must start the subject with the **issue id** and a colon (e.g. `NEO-8: …`). Branch naming and exceptions (`chore:` when there is no ticket) — [`.cursor/rules/linear-git-naming.md`](.cursor/rules/linear-git-naming.md).