feat: harden PR queue reconciliation against stale/conflicting state (#166)
- Add updated_at (list_prs), + merged_at/merge_commit_sha/closed_at/updated_at (view_pr) for staleness detection in tool output and inventory. - Surface updated_at in gitea_review_pr inventory report. - Strengthen gitea-pr-review skill steps, _COMMON_WORKFLOWS, _GUIDE_RULES with explicit live reconciliation checklist, 'do not trust prior handoffs', stop on conflict. - Add dedicated live queue reconciliation runbook section in docs/llm-workflow-runbooks.md. - Add passthrough tests and assertions for new fields. - All gates, redaction, author/reviewer separation untouched. - Tests pass, py_compile clean, diff clean, secret sweep clean. Closes #166
This commit is contained in:
@@ -303,7 +303,8 @@ class TestListPRs(unittest.TestCase):
|
||||
{
|
||||
"number": 1, "title": "PR 1", "state": "open",
|
||||
"head": {"ref": "branch1"}, "base": {"ref": "main"},
|
||||
"html_url": "http://url1", "mergeable": True
|
||||
"html_url": "http://url1", "mergeable": True,
|
||||
"updated_at": "2026-07-05T12:00:00Z"
|
||||
}
|
||||
]
|
||||
with patch.dict(os.environ, {}, clear=True):
|
||||
@@ -312,6 +313,8 @@ class TestListPRs(unittest.TestCase):
|
||||
self.assertEqual(result[0]["number"], 1)
|
||||
self.assertEqual(result[0]["head"], "branch1")
|
||||
self.assertNotIn("url", result[0])
|
||||
# Staleness fields for queue reconciliation (#166)
|
||||
self.assertEqual(result[0]["updated_at"], "2026-07-05T12:00:00Z")
|
||||
|
||||
@patch("mcp_server.api_get_all")
|
||||
@patch("mcp_server.get_auth_header", return_value=FAKE_AUTH)
|
||||
@@ -320,7 +323,8 @@ class TestListPRs(unittest.TestCase):
|
||||
{
|
||||
"number": 1, "title": "PR 1", "state": "open",
|
||||
"head": {"ref": "branch1"}, "base": {"ref": "main"},
|
||||
"html_url": "http://url1", "mergeable": True
|
||||
"html_url": "http://url1", "mergeable": True,
|
||||
"updated_at": "2026-07-05T12:00:00Z"
|
||||
}
|
||||
]
|
||||
with patch.dict(os.environ, {"GITEA_MCP_REVEAL_ENDPOINTS": "1"}, clear=True):
|
||||
@@ -340,7 +344,11 @@ class TestViewPR(unittest.TestCase):
|
||||
"number": 1, "title": "PR 1", "state": "open",
|
||||
"head": {"ref": "branch1"}, "base": {"ref": "main"},
|
||||
"html_url": "http://url1", "mergeable": True, "body": "description",
|
||||
"user": {"login": "user1"}
|
||||
"user": {"login": "user1"},
|
||||
"updated_at": "2026-07-05T12:00:00Z",
|
||||
"merged_at": None,
|
||||
"merge_commit_sha": None,
|
||||
"closed_at": None
|
||||
}
|
||||
with patch.dict(os.environ, {}, clear=True):
|
||||
result = gitea_view_pr(pr_number=1)
|
||||
@@ -348,6 +356,10 @@ class TestViewPR(unittest.TestCase):
|
||||
self.assertEqual(result["body"], "description")
|
||||
self.assertEqual(result["user"], "user1")
|
||||
self.assertNotIn("url", result)
|
||||
# Staleness / merge fields for live reconciliation (#166) - passthrough
|
||||
self.assertEqual(result["updated_at"], "2026-07-05T12:00:00Z")
|
||||
self.assertIsNone(result["merged_at"])
|
||||
self.assertIsNone(result["merge_commit_sha"])
|
||||
|
||||
@patch("mcp_server.api_request")
|
||||
@patch("mcp_server.get_auth_header", return_value=FAKE_AUTH)
|
||||
@@ -356,7 +368,8 @@ class TestViewPR(unittest.TestCase):
|
||||
"number": 1, "title": "PR 1", "state": "open",
|
||||
"head": {"ref": "branch1"}, "base": {"ref": "main"},
|
||||
"html_url": "http://url1", "mergeable": True, "body": "description",
|
||||
"user": {"login": "user1"}
|
||||
"user": {"login": "user1"},
|
||||
"updated_at": "2026-07-05T12:00:00Z", "merged_at": None, "merge_commit_sha": None, "closed_at": None
|
||||
}
|
||||
with patch.dict(os.environ, {"GITEA_MCP_REVEAL_ENDPOINTS": "1"}, clear=True):
|
||||
result = gitea_view_pr(pr_number=1)
|
||||
|
||||
Reference in New Issue
Block a user