Files
holocron/plugins/gitea/skills/gitea-prs/references/reviews.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

6.4 KiB

topic, source_keys
topic source_keys
reviews
gitea-mcp-repo
gitea-mcp-slim-go

PR review execution detail

Parameter signatures below are cross-checked live against the deployed gitea-mcp server tool schema, not copied from the plugin's research doc verbatim — same sourcing discipline as references/pull-requests.md. Last verified against v1.7.0, as reported by get_gitea_mcp_server_version.

Review state machine

A review is not a single write. It moves through states:

  1. create — opens a review in "PENDING" state, optionally attaching inline comments. Nothing is visible to other users yet.
  2. submit — finalizes the pending review with a terminal state: "APPROVED", "REQUEST_CHANGES", or "COMMENT". This is the point at which the review becomes visible and counts toward merge-gate requirements (see references/merging.md).
  3. dismiss — invalidates an already-submitted review (e.g. an approval that's no longer valid after force-push), with an optional message giving the reason. Dismissal does not delete the review record — it stays visible but marked dismissed.
  4. delete — removes a review outright. Use only for a review that was never submitted (e.g. abandoning a PENDING draft); do not use delete to retract a submitted review — use dismiss instead.

pull_request_review_write

Parameters:

  • method (string, required) — "create" | "submit" | "delete" | "dismiss" | "reply_comment" | "resolve_thread" | "unresolve_thread"
  • owner (string, required)
  • repo (string, required)
  • pull_number (number, required for every method except "resolve_thread" and "unresolve_thread", which locate the thread from comment_id alone) — the schema's own required list is only method/owner/repo, so a missing pull_number surfaces as a runtime error, not client-side validation
  • review_id (number) — required for "submit", "delete" and "dismiss"; "create" returns the ID to use for that follow-up call. Not used by "reply_comment", "resolve_thread" or "unresolve_thread", which key off comment_id instead
  • comment_id (number, required for "reply_comment", "resolve_thread" and "unresolve_thread") — an individual review comment's ID, obtained from pull_request_read method: "get_review_comments". For the two thread methods this must be the thread's first comment, not an arbitrary one in it
  • state (string, optional) — "APPROVED" | "REQUEST_CHANGES" | "COMMENT" | "PENDING" — set on "create" (typically "PENDING", or a terminal state to create-and-submit in one call if the server supports it) or "submit" (terminal state)
  • body (string, optional) — the overall review comment text on "create"/"submit"; on "reply_comment" it is the reply text and is the payload of the call
  • commit_id (string, optional, for "create") — anchors inline comments to a specific commit SHA (typically the PR's current head SHA from pull_request_read method: "get")
  • message (string, optional, for "dismiss") — dismissal reason
  • comments (array of objects, optional, for "create") — inline comments, each: {path, body, old_line_num, new_line_num} — path is the file path, body is the comment text, new_line_num anchors to a line in the new (added) side of the diff, old_line_num anchors to a line in the old (removed) side; use whichever side the comment applies to, not both

Comment threads

Three further methods act on an individual review comment rather than on a review as a whole. They sit outside the state machine above — a thread can be replied to or resolved whatever state its parent review is in — and none of them takes a review_id.

  • reply_comment — posts body as a reply to the comment named by comment_id, threading under it rather than starting a new top-level comment. Takes pull_number.
  • resolve_thread — marks the thread containing comment_id resolved. Pass the thread's first comment ID; another ID in the same thread is not equivalent. Does not take pull_number.
  • unresolve_thread — reopens a resolved thread, under the same first-comment rule.

Get the comment_id from pull_request_read method: "get_review_comments". Call it with no review_id to list every inline comment on the PR, then pick the thread to act on; scoping it to one review_id only finds threads opened by that review.

Reading reviews (pull_request_read)

  • method: "get_reviews" — array of review summaries: id, state, body, user (login), comments_count, submitted_at, html_url, stale (bool — the PR was pushed to after this review was submitted, meaning it may be outdated), official (bool), dismissed (bool).
  • method: "get_review" (requires review_id — omitting it fails with review_id is required) — single review detail.
  • method: "get_review_comments" (review_id optional — omit it to list every inline comment on the PR in one call, rather than one review's) — array of inline comments: id, body, path, position, old_position, diff_hunk, user, html_url, created_at, updated_at.

review_comments on the "get" response is a count, not the comments — and it may be absent. Where the full PR object returned by pull_request_read method: "get" carries review_comments, it is an integer: the number of inline review comments. Presence is not guaranteed. A live "get" against a PR with zero inline comments carried no such key at all — only comments, which counts issue-style comments, not review ones. Treat it as present only when non-zero, and check for the key before reading it rather than assuming the response shape. Either way it is distinct from the get_review_comments method above, which returns the actual comment objects; reading the count is no substitute for that call. Older gitea-mcp releases misspelled this key as review_scomments; the misspelling was corrected upstream and the deployed v1.7.0 response carries no such key, so treat any instruction that reaches for review_scomments as stale.

Inline-comment field names differ between write and read. The comments array on pull_request_review_write method: "create" uses old_line_num/new_line_num. The get_review_comments read response uses different field names for the same concept — position (new-side line) and old_position (old-side line). Do not assume the same key names apply on both sides of the round trip.