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:
2026-07-05 12:45:05 -04:00
parent a02d990bc5
commit 194301359e
4 changed files with 77 additions and 12 deletions
+17 -4
View File
@@ -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)