Files
holocron/plugins/gitea/.apm/skills/gitea-prs/references/pull-requests.md
Defame1297 be9b8d277f fix(gitea): restore the withLines exception and route rename_branch through the orchestrator
gitea-files' always-loaded Gotchas said "content is base64 both ways" without
qualification. The `main` text carried an exception for `withLines: true` and both
halves were dropped. Verified live: `get_file_contents` with `withLines: true`
returns plain JSON text while the same response still reports `"encoding":"base64"`.
An agent that follows the recommendation two sentences later and applies the
unconditional decode gets garbage, with the response's own field confirming the
wrong answer. Exception restored, and the lying field named.

gitea-orchestrate was never updated for `rename_branch`: absent from the operation
enum, so an agent caller got "unknown operation", and absent from the
destructive-confirm list, though branches.md requires a rename with open PRs or a
protection rule to be confirmed exactly as `delete_branch` is. Added to both — the
confirm gate rather than the enum alone, because accepting the operation without it
routes around a rule the skill states while appearing to support it. The
compatibility frontmatter, which the agent reads, still omitted the tool too.

Two more always-loaded Gotchas contradicted their own reference files, and the
Gotcha was wrong both times: issues and PRs are distinguishable on a list item by
the `html_url` path segment (confirmed live — #129 at /pulls/, #128 at /issues/),
and `get_repository_tree` takes `tree_sha`, not `ref`.

`review_comments` was asserted as unconditionally present on the PR get response.
It is absent on a PR with no review comments, so the claim is downgraded to
present-when-non-zero rather than stated as response shape.

The label-exclusivity relocation moved the rule out of label-inference.md and into
labels.md without updating sources.md, leaving the one rule in this branch that
writes differently to live repos citing a file that no longer carries it. The rule
itself is correct as it stands and `main` was wrong — every Kind/* label on this
instance is exclusive:false, every Priority/* and Status/* is true — so only the
provenance record is corrected.

Routing: gitea-workflow lost the human-caller discriminator and widened from status
checks to any request, which sent "close #42" to a branch that resolves the number
and presents detail without ever closing it. gitea-branches and gitea-issues regain
trigger phrasings the retrofit dropped.

Refs: #92
2026-09-01 12:38:53 +00:00

8.4 KiB

topic, source_keys
topic source_keys
pull-requests
gitea-mcp-repo
gitea-mcp-slim-go

Pull request read/write execution detail

Parameter signatures below are cross-checked live against the deployed gitea-mcp server tool schemas at authoring time — not copied verbatim from the plugin's research doc for this domain, which has a known history of drifting from the deployed server. These files were last verified against gitea-mcp v1.7.0, as reported by get_gitea_mcp_server_version. Re-verify via ToolSearch before trusting this file if the deployed version differs — drift has bitten this skill in both directions, adding methods it does not list and fixing quirks it still warns about.

list_pull_requests

Parameters:

  • owner (string, required)
  • repo (string, required)
  • state (string, optional, default "all") — "open" | "closed" | "all"
  • sort (string, optional, default "recentupdate") — "oldest" | "recentupdate" | "leastupdate" | "mostcomment" | "leastcomment" | "priority"
  • milestone (number, optional) — milestone ID filter, not a title
  • page (number, optional, default 1)
  • per_page (number, optional, default 30)

List responses trim PRs down to summary fields — head/base are bare ref strings and milestone does not appear as an object. Don't rely on this call to resolve a milestone's ID; see the Gotcha below.

pull_request_read

Parameters:

  • method (string, required) — "get" | "get_diff" | "get_files" | "get_status" | "get_reviews" | "get_review" | "get_review_comments"
  • owner (string, required)
  • repo (string, required)
  • pull_number (number, required)
  • review_id (number, optional) — required for "get_review", which errors with review_id is required without it. Optional for "get_review_comments": omit it to list every inline comment on the PR in one call. See references/reviews.md
  • binary (boolean, optional) — include binary diff content for "get_diff"
  • page (number, optional, default 1)
  • per_page (number, optional, default 30)

"get", "get_diff", "get_files", and "get_status" are covered here. "get_reviews", "get_review", and "get_review_comments" are covered in references/reviews.md.

  • "get" returns the full PR object: state, draft, merged, mergeable flags; head/base as full objects ({ref, sha, repo?}); milestone as a bare title string (not {id, title}); and review_comments, when present, as an integer count rather than comment objects — it was absent from a live "get" on a PR with no inline comments, so verify the key before reading it (see references/reviews.md).
  • "get_diff" returns raw diff text.
  • "get_files" returns the list of changed file objects.
  • "get_status" returns the combined commit status for the PR's head commit — CI result only, not review/approval state (see references/merging.md).

Milestone gotcha: because pull_request_read only ever returns a milestone title, never an ID, resolving "which milestone ID does this PR belong to" requires calling into gitea-labels-milestones' milestone_read method: "list" and matching by title. Do not attempt to infer or guess the ID. This is the read-side milestone problem; for the separate write-side one, see the "create" drop Gotcha under pull_request_write.

pull_request_write

Parameters:

  • method (string, required) — "create" | "update" | "close" | "reopen" | "merge" | "update_branch" | "add_reviewers" | "remove_reviewers"
  • owner (string, required)
  • repo (string, required)
  • pull_number (number, required for every method except "create" — this is enforced by convention, not by the tool's schema, so passing it incorrectly produces a runtime error rather than a client-side validation error)
  • title (string, required for "create"; optional for "update")
  • body (string, required for "create"; optional for "update")
  • head (string, required for "create") — source branch; same-repo PRs use a bare branch name, cross-repo fork PRs use "fork-owner:branch-name" (see Gotcha)
  • base (string, required for "create"; optional for "update") — target branch; passing it on "update" retargets an open PR onto a different base
  • assignee (string, optional) — single login; "update" only — silently dropped on "create" (see Gotcha)
  • assignees (array of strings, optional) — login names; "update" only — silently dropped on "create" (see Gotcha)
  • milestone (number, optional) — milestone ID, never a title; "update" only — silently dropped on "create" (see Gotcha)
  • state (string, optional, for "update") — "open" | "closed" (no "all" — unlike issue state filters)
  • allow_maintainer_edit (boolean, optional, for "update")
  • labels (array of numbers, optional) — label IDs, never names — resolve via gitea-labels-milestones first
  • deadline (string, optional) — ISO 8601
  • remove_deadline (boolean, optional) — "update" only — silently dropped on "create" (harmless there, but it does not do anything)
  • reviewers (array of strings, optional) — login names; "add_reviewers"/"remove_reviewers" only — silently dropped on both "create" and "update" (see Gotcha)
  • team_reviewers (array of strings, optional) — same as reviewers: "add_reviewers"/"remove_reviewers" only
  • draft (boolean, optional) — prepends "WIP:" to the title; honoured on both "create" and "update" (see Gotcha)

Merge-specific parameters (merge_style, delete_branch, force_merge, merge_when_checks_succeed, head_commit_id, message as merge commit message) are covered in references/merging.md.

"create" silently drops most optional parameters. "create" reads only owner, repo, title, body, head, base, draft, labels, and deadline. Every other optional parameter — including assignee, assignees, milestone, reviewers, team_reviewers and remove_deadline — is accepted without error and discarded. Nothing marks the drop: no error, no warning, and nothing in the response distinguishing a dropped parameter from one that was never passed — the response simply omits the key. Setting any of them requires a second call after the PR exists — "update" for assignee/assignees/milestone, "add_reviewers" for reviewers/team_reviewers.

Two things make this easy to miss:

  • labels does apply on "create". It sits next to milestone in the parameter list and reads identically, so a caller who confirms the labels landed will reasonably assume the milestone did too.
  • issue_write method: "create" does honour assignees and milestone. The asymmetry is specific to pull requests; experience with the issue write does not transfer.

To verify a milestone actually applied, re-read the PR and check for the milestone key, or check that the milestone's open_issues count moved — the create response alone cannot tell you.

Cross-repo head format: head must be "fork-owner:branch-name" for a PR originating from a fork of the base repo. Passing a bare branch name causes Gitea to search for that branch in the base repo instead, and returns 422 when it isn't found there.

Draft/WIP behavior: draft: true on "create" is implemented by prepending "WIP:" to the title — there is no first-class draft boolean stored separately from the title. The title returned by subsequent reads will include the prefix. To un-draft, call "update" with draft: false and no title — the server reads the PR's current title and strips the prefix itself, so you do not need to reconstruct the un-prefixed text. Two prefixes are recognised for stripping — WIP: and [WIP] — matched case-insensitively, even though only "WIP: " is ever added. Passing title alongside draft applies the prefix rule to the title you passed rather than the stored one.

update_branch: takes only owner, repo, pull_number — no other parameters. It merges the current base branch into the PR's head branch server-side, resolving a PR that Gitea reports as behind its base (analogous to GitHub's "Update branch" button). Use it when a PR shows mergeable: false or an out-of-date status due to base-branch drift rather than an actual conflict; if the head and base have truly diverged with conflicting changes, this call fails and the conflict must be resolved by pushing a merge/rebase to the head branch directly, outside this skill's scope.