Skip to main content

AI-Assisted GitHub Issue Resolution

How Cursor resolves a GitHub Issue in this repository: a strict, auditable workflow with mandatory human validation before merge. The binding rule is .cursor/rules/github-issue-resolution.mdc; this page explains the same process for humans.

Why this exists​

We want Cursor to be able to take a GitHub Issue end-to-end — read it, investigate, propose a fix, implement it, open a PR — without ever merging code on its own or working directly on a protected branch. Every implementation is gated behind two public comments (analysis + proposal) and an explicit uncertainty check. If Cursor is not confident, it stops and asks instead of guessing.

How to invoke it​

From Cursor​

Resuelve https://github.com/GekkotechSL/UPPV4_APPLICATION/issues/123

or in English:

Resolve https://github.com/GekkotechSL/UPPV4_APPLICATION/issues/123

Any phrasing that clearly asks Cursor to resolve/fix/implement a GitHub Issue, or references an issues/<n> URL, activates the rule.

From GitHub​

@cursor resuelve esta incidencia siguiendo el workflow del repositorio
note

@cursor mentions on GitHub only work if the Cursor GitHub App / background-agent integration is installed and connected for this repository (Cursor dashboard → Integrations → GitHub). That connection is an external, one-time setup step and is not part of this repo's files — see GitHub configuration still required. Until it is connected, use the "From Cursor" form above, or run the same prompt inside a Cursor session with gh access to this repo.

What Cursor uses to talk to GitHub​

Preference order (see the rule for exact scope):

  1. Cursor's GitHub/MCP integration, if configured in the session.
  2. GitHub CLI (gh), authenticated — this is the mechanism verified and available today for this repo (repo, workflow, read:org scopes). Used to read issues/comments/labels, post comments, add labels, and create PRs.
  3. If neither is available, Cursor stops and states exactly what's missing instead of guessing or asking for a pasted token.

Cursor never prints, logs, or commits GitHub tokens, and never stores credentials inside the repository.

The phases​

PhaseWhat happensCan Cursor write code/commits?
0 — Read & investigateReads the issue (title, description, labels, all comments), Project field Rama, related issues/PRs, and the relevant code/tests/rules. Resolves <rama-app> (UPPV4_APPLICATION base).No
0b — IncompleteIf Rama is missing/unusable (e.g. only e2e/base with no app branch): post ## ⛔ Incomplete report, add incomplete, set Project Status to Ready, STOP.No
1 — Analysis commentPublishes a ## 🔎 Analysis comment: problem summary, expected vs. actual behaviour, likely root cause + confidence level, affected files, assumptions, risks, existing/needed tests.No
1b — Invalid dispositionIf analysis concludes (high confidence) there is no defect because behaviour is already the designed/delivered contract (misunderstanding / false positive): add invalid without removing existing labels, Status → Ready, STOP. No proposal, no code, no PR.No
1c — Pending enhancementIf the symptom is real but the effect was never fully delivered (explicit TODO / RF says implementation pending): remove bug, add enhancement, Status → Backlog, STOP. Do not use invalid. No bugfix PR. If a PR was opened by mistake, close it without merge.No
2 — Implementation proposalPublishes a ## 🛠 Implementation proposal comment: proposed solution, steps, files to touch, tests, backwards compatibility, migrations, security implications, risks, edge cases, definition of done. Skipped when disposition is invalid or pending enhancement (1c).No
3 — Uncertainty gateExplicitly checks for material doubts (see below).No
4 — Worktree + branchCreates/reuses a git worktree at .worktrees/issue-<n> with a dedicated branch from origin/<rama-app>. Must not checkout/switch/stash the developer's primary workspace checkout.No (worktree setup only)
5 — ImplementationImplements the smallest solution consistent with the published proposal; adds/updates tests — only inside the issue worktree.Worktree only
6 — ValidationRuns the project's tests/lint/type-check/build (and PHPUnit/php -l when touching server/**) inside nx-dev / docker/pw with cwd /app/.worktrees/issue-<n> (so Docker's /app mount sees the fix). FAIL blocks progress.Worktree only
6b — Quality gateBlocking pre-commit. Opens and applies stack rules: Angular devil-advocate (APTO) + done-is-done + preconditions; PHP backend/devil-advocate (FIT) + backend/done-is-done + PHPUnit/coverage/_CHANGESLOG. FAIL → Phase 5.Worktree only
7 — Self-reviewReviews the full diff before committing (no accidental files, no secrets, matches the published proposal, Phases 6+6b PASS).Worktree only
7b — Pre-commit commentPosts ## ✅ Pre-commit quality gate and the full Devil's Advocate, Documentation Review, and Done Is Done write-ups (the formats those rules require, not a one-line verdict). Required before any commit/PR. Repeat them if the diff changes.No code
— Commit & pushCommits and pushes only the dedicated branch from the worktree — only if Phase 7b is PASS.Yes (scoped exception, see below)
8 — Pull RequestOpens a PR against <rama-app> only if the pre-commit quality gate comment is PASS; cites that evidence in Validation; sets QA Project Status to In progress.Yes (PR creation only)
— Human gateSTOP. No merge, no auto-merge, no self-approval. Issue stays open until QA closes it.Never

One dedicated branch per issue (lifecycle)​

Team policy for Quality Assurance issues:

  1. One dedicated branch per issue (fix/issue-<n>-…). That branch is created once and reused for every follow-up (QA rejection, residual bug, base-branch change) until a human deletes it after Done. Do not invent a second fix/issue-<n>-other-slug. Prefer one open PR; if GitHub closed the PR on merge, continue on the same branch (reopen or open a new PR from that same head name).
  2. Merge does not end the issue. Humans may merge the PR into <rama-app> when ready; the issue stays open and the Project stays In progress until QA validates.
  3. Do not use Fixes # / Closes # in the PR body — use Related to #<n> (or Addresses #<n>) so merge does not auto-close the issue. QA closes the issue after validation → Status Done.
  4. Branch/PR cleanup happens from Done only (human). Deleting the dedicated branch / housekeeping the (possibly already merged) PR is done when the item is in Done, not right after merge and not by Cursor in Phase 8.

Cursor searches for an existing *issue-<n>* branch before creating one, reuses it for all commits, and only opens a new PR number when the previous one is merged/closed — still with the same head branch.

Required QA field: Rama​

Every issue resolved by this workflow must include a usable test/application branch. Cursor reads it from:

  1. Project Quality Assurance → field Rama (preferred),
  2. otherwise the issue body/comments (Rama:, Branch:, or última rama UPPV4_APPLICATION integrada: …).

Typical QA value:

e2e/base commit <sha> (última rama UPPV4_APPLICATION integrada: feature/<name>)

  • e2e/base / testing-repo SHAs are reproduction context.
  • The fix/PR base is the UPPV4_APPLICATION branch named after integrada: (or a plain app-branch name if that is all that was provided).
  • If the field is missing, empty, only names e2e/base without an app branch, or names a branch that does not exist on origin → disposition incomplete (below). Cursor must not fall back to master.

When incomplete is used​

If Phase 0 cannot resolve a usable <rama-app>:

  1. Posts a ## ⛔ Incomplete report comment explaining what is missing and the expected format.
  2. Adds the incomplete label (without removing existing labels).
  3. Returns the item to QA when it is on Project Quality Assurance: Status → Ready.
  4. Does not post Analysis/Proposal, does not change product code, does not open a PR.
  5. Stops.

After QA fills Rama and the workflow is re-invoked, Cursor removes incomplete (only once the data is usable) and continues from Phase 0.

Quality Assurance project board (Status)​

When the issue is on Project Quality Assurance, Cursor updates Status as part of the workflow:

SituationStatus
incomplete (rejected / returned for missing Rama)Ready
invalid — false bug / misunderstanding of delivered behaviourReady
Pending planned implementation — remove bug, add enhancement (symptom is real; effect never fully shipped)Backlog
PR opened/updated and waiting for human review + QAIn progress
Issue closed by QA after validationDone (human / board automation — never Cursor)

Done is not “PR merged”. Merge may happen earlier; Done means QA closed the issue. Clean up the PR from the Done column (delete head branch, etc.) — not while the item is still In progress.

When invalid is used​

If Phase 1 concludes with high confidence that the report is not a defect because the observed behaviour is already the designed/delivered product (misunderstanding, false positive, intentional contract already shipped) — Cursor:

  1. States that disposition clearly in the ## 🔎 Analysis comment (expected behaviour, code/test references, why no fix).
  2. Adds the invalid label (already in this repo's label set: "This doesn't seem right") without removing or replacing any labels the issue already has (bug, documentation, etc.). Typical command: gh issue edit <n> --add-label "invalid".
  3. Sets Project Status to Ready when the issue is on Quality Assurance.
  4. Does not post an implementation proposal, does not change product code, does not open a PR, and does not close or reopen the issue (closing remains human).
  5. Stops.

Do not use invalid when the failure is real but the feature was never finished (TODO / RF pending): that is the next section (enhancement + Backlog).

If confidence that it is "not a bug" is only medium/low, Cursor must not use invalid: continue to proposal / uncertainty gate, or use help wanted when a product decision is required.

When pending implementation becomes enhancement (Backlog)​

If Phase 1 concludes with high confidence that the symptom is real (the flow does not complete the expected effect) but it is a planned incomplete implementation — not a regression of previously delivered behaviour — Cursor:

Examples of signals:

  • the reported handler still has an explicit TODO / console.info('TODO: …') placeholder for the effect QA expected;
  • the feature .mdc / RF states that the UI action exists but full implementation is pending;
  • there is no evidence of a regression from a previously delivered complete behaviour.

Then Cursor:

  1. States clearly in ## 🔎 Analysis that this is pending product work (not a bugfix): symptom is real, implementation is deferred, references to TODO/RF, item goes to Backlog as enhancement.
  2. Removes the bug label: gh issue edit <n> --remove-label "bug".
  3. Adds enhancement: gh issue edit <n> --add-label "enhancement". If a previous wrong pass left invalid, remove it too.
  4. Sets Project Status to Backlog.
  5. Does not open a bugfix PR to “complete the TODO” under this workflow. If such a PR was already opened by mistake: gh pr close without merge.
  6. Stops.

If confidence that it is "only a planned TODO" is only medium/low, Cursor must not use this path: continue to proposal / uncertainty gate, or use help wanted.

When help wanted is used​

If, at the uncertainty gate (or later, mid-implementation), Cursor finds a material doubt — something that could change user-visible behaviour, business/product logic, API contracts, data format, storage/schema, permissions, security, backwards compatibility, migration strategy, architecture, or acceptance criteria — it:

  1. Adds the help wanted label (already present in this repo's label set).
  2. Posts a ## ❓ Blocking questions comment with specific, answerable questions (e.g. "When X happens, should the endpoint return 404 or 200 with an empty collection?" — never a generic "what do you want me to do?").
  3. Stops and waits. It never invents an answer to keep going.

The same happens if new information invalidates the published proposal during implementation: Cursor stops, keeps any local changes safely on the dedicated branch, and asks before continuing.

Pre-commit quality gate before a PR can open (Phases 6 + 6b + 7b)​

Passing tests alone is not enough. Before any commit or PR, Cursor must complete all three layers and get an explicit global PASS:

  1. Phase 6 — run the applicable executable checks in nx-dev / docker/pw (unit/integration/E2E, lint, type-check, build, php -l / PHPUnit / coverage). Record real PASS/FAIL. Any FAIL blocks progress.
  2. Phase 6b — open and apply the stack Definition of Done pipeline:
    • Angular/TypeScript (apps/**, libs/**): unpispas-preconditions.mdc; .cursor/rules/angular/devil-advocate.mdc → explicit APTO; then .cursor/rules/angular/done-is-done.mdc (compile, RF-*/RV-*/CA-* tests, coverage thresholds, functional-coverage audit cumple, entregable .mdc / Gobierno de cambios, no production-only-for-tests code, unused i18n keys, desktop/mobile when applicable).
    • PHP (server/**): .cursor/rules/backend/devil-advocate.mdc → explicit FIT; then .cursor/rules/backend/done-is-done.mdc (dedicated tests, PHPUnit PASS, coverage, _CHANGESLOG when applicable, server/tests/README.md, context docs sync) plus phptests-bestpractices.mdc / slimphp-bestpractices.mdc / backend context rules.
    • Mixed diffs must PASS both stacks.
  3. Phase 7b — publish a ## ✅ Pre-commit quality gate comment on the issue, and with it the full certification write-ups (not a one-line verdict): Devil's Advocate in the format of devil-advocate.mdc (FIT / APTO), Documentation Review in the format of Documentation-review.mdc (VALIDO), and the Done Is Done checklist from done-is-done.mdc item by item. The gate comment ends with Gate global: PASS — se procede a commit/PR only when those three are published and passing. If the diff changes afterwards, publish them again on the final diff. Without this PASS comment and those full reports, commit/push/gh pr create are forbidden in this workflow.

A FAIL on any layer sends the work back to Phase 5. Cursor must not open a PR with a missing or failing gate, and must not patch around a gate finding just to make it pass (product/architecture decisions become help wanted). The PR Validation section must cite the Phase 7b comment.

How the flow continues after a human answers​

Once a human answers the blocking questions in the issue (as a comment, or by removing help wanted and/or replying), re-invoke the same prompt (Resuelve https://github.com/.../issues/<n>). Cursor re-reads the issue — including the new answers — re-runs the uncertainty gate, and either proceeds (Phase 4 onward) or asks again if the answer still leaves a material gap.

How the Pull Request is created​

Before opening a PR, Cursor checks whether the issue already has a dedicated branch and/or an open PR. Commits always go to that branch; an open PR is reused, otherwise a PR is opened from that same head.

Otherwise the PR is opened against <rama-app> from the QA Rama field (not blindly against the default branch). After a successful gh pr create (or when resuming the existing PR), Cursor sets Quality Assurance Status to In progress. The PR body uses .github/pull_request_template.md: Issue (Related to #<n> — not Fixes/Closes, so merge does not auto-close the issue), Summary, Root cause, Base branch, Implementation, Validation (with real PASS/FAIL results, including the Phase 6b quality gate — never claimed without having run it), Manual validation, Risks, and Notes for reviewer.

Why merge is always manual​

Cursor is deliberately never granted merge authority: no merge, no squash-merge, no rebase-merge, no auto-merge, no self-approval, no skipping required reviews/checks, no editing branch protections. After Phase 8 the correct state is "dedicated branch for the issue + review PR ready for humans; issue remains open until QA closes it; branch stays until Done." Approval and merge are exclusively a human responsibility; closing the issue is exclusively QA; branch/PR cleanup happens from the Done column (human only).

This mirrors the repository-wide .cursor/rules/developer-only-git-operations.mdc policy (staging/history/remote are human-only). github-issue-resolution.mdc defines the only scoped exceptions to that policy: (1) for disposition incomplete, comment + incomplete label + Project Status Ready; (2) for disposition invalid, comment + labels + Project Status Ready; (3) for pending planned implementation, remove bug, add enhancement, Project Status Backlog, and gh pr close without merge only when correcting a wrongly opened PR; (4) for a valid fix after Phases 6+6b+7b PASS, commit/push/gh writes limited to the dedicated issue branch in .worktrees/issue-<n> (from origin/<rama-app>, without touching the developer's primary checkout), opening or updating the single PR with --base <rama-app>, and Project Status In progress — never merging, never closing the issue, never cleaning the PR before Done.

Parallel work: issues vs. in-progress development​

QA may report a bug on branch feature/foo while you are actively developing on feature/bar with local uncommitted changes. Cursor must keep those worlds separate:

DoDo not
git worktree add .worktrees/issue-<n> -b fix/issue-<n>-… origin/<rama-app>git checkout / switch away from your current branch in the main workspace
Edit/test/commit only under .worktrees/issue-<n>git stash your WIP so the agent can change branches
In nx-dev: cd /app/.worktrees/issue-<n> && npx nx …Run validations against /app (primary checkout) when the fix lives in the worktree

Worktree directories stay gitignored (dot-path under .*). Remove them when the issue reaches Done (or when you ask), not as part of opening the PR.

GitHub configuration still required​

This repository is on a GitHub Free organization plan (private repo). Branch protection and Rulesets APIs currently return 403 Upgrade to GitHub Pro, so they cannot be configured from this repo/CLI today. When the plan allows it, an administrator should configure, on the default branch (master):

  • Require a pull request before merging.
  • Require at least one human approval.
  • Require status checks to pass before merging (once CI workflows exist under .github/workflows/; none exist yet in this repo).
  • Disallow force-pushes on the default branch.
  • Disallow direct pushes to the default branch (require the PR flow even for admins, if acceptable for the team).

Until that is enabled, the enforcement is: (a) this rule + Cursor's behaviour, and (b) humans never merging a Cursor PR without review. allow_auto_merge is already false at the repository level; nothing was changed there.

If you want @cursor mentions to work directly on GitHub issues/PRs, install and connect the Cursor GitHub App for this repository from the Cursor dashboard (Integrations → GitHub) — that step happens outside this repo and could not be completed from here.

Troubleshooting​

SymptomLikely causeFix
Cursor says it can't read/comment on the issuegh not authenticated in the session, or no GitHub/MCP integration configuredRun gh auth status; re-authenticate with gh auth login if needed (never paste a token into a repo file)
gh label create "help wanted" ... / "invalid" ... / "incomplete" ... failsMissing permissions on the repoAsk an admin to create the label once; report this explicitly in the issue instead of skipping the label
Cursor marks the issue incomplete and stopsMissing/unusable Project field Rama (or only e2e/base without an UPPV4_APPLICATION branch)QA fills Rama with the app branch under test (see format above), then re-invoke the workflow
PR creation failsNo push access to a personal fork / branch, or repo requires a different base branch nameConfirm the real default branch (gh repo view --json defaultBranchRef) and that gh has repo scope
@cursor on GitHub does nothingGitHub App integration not installed/connected for this org/repoConnect it from the Cursor dashboard, or use the "From Cursor" invocation instead
Cursor implemented code without posting Analysis/Proposal firstThe rule wasn't triggered (phrasing didn't mention an issue/URL) or was skippedRe-run with an explicit issue URL; if it happens again, treat it as a bug in the rule and fix .cursor/rules/github-issue-resolution.mdc
Cursor opened a PR without ## ✅ Pre-commit quality gatePhase 7b skippedClose or hold the PR for human review; treat as workflow bug — no merge until gate evidence exists on the issue
Agent stashed WIP or switched the main checkoutPhase 4 isolation violatedRestore stash / return to your branch; re-run the fix from .worktrees/issue-<n> only — treat as workflow bug
Tests in nx-dev do not see the fixValidations ran in /app instead of /app/.worktrees/issue-<n>Re-run with cwd set to the issue worktree inside the container

See also​

  • .cursor/rules/github-issue-resolution.mdc — the binding rule (single source of truth for the exact phase-by-phase behaviour).
  • .cursor/rules/developer-only-git-operations.mdc — general git/GitHub policy and the scoped exception.
  • .cursor/rules/docker-dev-environment.mdc — where validations must run.
  • .cursor/rules/agent-verify-changes.mdc — verification obligations.
  • .cursor/rules/angular/done-is-done.mdc, .cursor/rules/angular/devil-advocate.mdc, .cursor/rules/angular/unpispas-preconditions.mdc — pre-commit quality gate for Angular/TypeScript fixes.
  • .cursor/rules/backend/done-is-done.mdc, .cursor/rules/backend/devil-advocate.mdc, .cursor/rules/phptests-bestpractices.mdc — pre-commit quality gate for PHP fixes.
  • .cursor/rules/agent-verify-changes.mdc — agent must run the validations itself.
  • .github/pull_request_template.md — PR body structure.