refactor(forge): address PR #318 review — PR/Issue split, sqlite state, drop footer
Addresses the five review comments on PR #318: - Split PullRequest from Issue and add a dedicated read_pr method on Forge/ScopedForge/GiteaForge (a PR carries merge state an issue does not); is_pr_open now derives from read_pr. - Replace the JSON-file forge state with a thin swappable CRUD interface (ForgeStateStore) backed by SQLite (SqliteForgeStateStore) at ~/.bot-bottle/bot-bottle.db. - Remove the provenance footer (provenance.py + its test): a mutable, unsigned PR comment is not an audit record. - Reword the PRD: provenance is exposed via an API, not surfaced in the PR; document the Issue/PullRequest split and the SQLite store. pyright clean (whole repo), pylint 10/10, 38 forge/resume unit tests pass; no remaining refs to the removed provenance module or old JSON state API. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WL77TgFxKbs3cidGMG9dz7
This commit is contained in:
@@ -20,7 +20,7 @@ import urllib.error
|
||||
import urllib.request
|
||||
from typing import Any
|
||||
|
||||
from ..forge.base import Comment, Forge, Issue
|
||||
from ..forge.base import Comment, Forge, Issue, PullRequest
|
||||
|
||||
# Bound every Gitea call: a hung instance must not stall the sidecar.
|
||||
_API_TIMEOUT_SECS = 30
|
||||
@@ -124,6 +124,16 @@ class GiteaForge(Forge):
|
||||
state=str(raw.get("state", "")),
|
||||
)
|
||||
|
||||
def read_pr(self, number: int) -> PullRequest:
|
||||
raw = self._client.get_pull(number)
|
||||
return PullRequest(
|
||||
number=int(raw.get("number", number)),
|
||||
title=str(raw.get("title", "")),
|
||||
body=str(raw.get("body", "") or ""),
|
||||
state=str(raw.get("state", "")),
|
||||
merged=bool(raw.get("merged", False)),
|
||||
)
|
||||
|
||||
def read_comments(self, number: int) -> list[Comment]:
|
||||
return [
|
||||
Comment(
|
||||
@@ -154,7 +164,7 @@ class GiteaForge(Forge):
|
||||
return None
|
||||
|
||||
def is_pr_open(self, number: int) -> bool:
|
||||
return self._client.get_pull(number).get("state") == "open"
|
||||
return self.read_pr(number).state == "open"
|
||||
|
||||
|
||||
def _read_error_body(exc: urllib.error.HTTPError) -> str:
|
||||
|
||||
Reference in New Issue
Block a user