nisse-review marks a reply that settles its thread; the PR's author resolves it
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 1m58s
CI / e2e (pull_request) Successful in 7m41s

The reviewer is read-only (R3), so Gitea refuses it resolving a thread.
Now each reply says whether it settles its thread, and a settled reply
carries <!-- nisse-review: settled -->. nisse-dev, as the author, resolves
every comment on that thread's line when it watches the PR, and doesn't
take the settled reply as a point to answer. scripts/resolve_settled.py
does the same for PRs made by hand.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J5Utyfzw7gF7UhjRDEtjTk
This commit is contained in:
dongarandClaude Opus 5.5 committed 2026-10-19 22:06:56 +00:00
1 parent 6b85e5a039
commit 33d030590d
11 files changed
+384 -12

No files matched your search

+26
View File
@@ -86,6 +86,26 @@ class ReviewNote:
author: str
body: str
where: str # "path:line" for a line comment, "" for a review body
resolved: bool = False # a line comment's thread, marked resolved
# A reviewer's reply that settles its thread: nothing more is needed from
# it there. It can't resolve the thread itself (read-only, R3), so the PR's
# author does.
SETTLED_MARKER = "<!-- nisse-review: settled -->"
def to_resolve(notes: list[ReviewNote]) -> list[int]:
"""The ids of the unresolved line comments in threads a settled reply
closed: every comment on that path:line, as Gitea groups a thread."""
settled = {
n.where for n in notes if n.key.startswith("line-") and SETTLED_MARKER in n.body
}
return [
int(n.key.removeprefix("line-"))
for n in notes
if n.key.startswith("line-") and n.where in settled and not n.resolved
]
@dataclass(frozen=True)
@@ -198,10 +218,16 @@ class GiteaClient:
author=(comment.get("user") or {}).get("login", author),
body=str(comment.get("body") or ""),
where=f"{comment.get('path', '')}:{line}",
resolved=bool(comment.get("resolver")),
)
)
return notes
def resolve_comment(self, repo: str, comment_id: int) -> None:
"""Mark a line comment's thread resolved: the PR's author or someone
with write access may."""
self._request("POST", f"/repos/{repo}/pulls/comments/{comment_id}/resolve")
def find_pull_request(self, repo: str, head: str) -> PullRequest | None:
"""External truth for L8: did the PR for this branch already get
opened? Includes closed PRs — a crash after opening must not be