fix(governance): fail soft owner review readbacks
Some checks failed
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 2m17s
CD Pipeline / build-and-deploy (push) Successful in 4m43s
CD Pipeline / post-deploy-checks (push) Has been cancelled
Some checks failed
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 2m17s
CD Pipeline / build-and-deploy (push) Successful in 4m43s
CD Pipeline / post-deploy-checks (push) Has been cancelled
This commit is contained in:
@@ -341,6 +341,24 @@ async def get_km_stale_owner_reviews(
|
||||
)
|
||||
except KmStaleOwnerReviewError as exc:
|
||||
raise HTTPException(status_code=exc.status_code, detail=exc.detail) from exc
|
||||
except Exception as exc:
|
||||
logger.warning(
|
||||
"km_stale_owner_reviews_readback_degraded",
|
||||
project_id=project_id,
|
||||
dispatch_status=dispatch_status,
|
||||
limit=limit,
|
||||
error_type=type(exc).__name__,
|
||||
)
|
||||
return KnowledgeStaleOwnerReviewInboxResponse(
|
||||
project_id=project_id,
|
||||
dispatch_status=dispatch_status,
|
||||
total=0,
|
||||
returned=0,
|
||||
writes_on_read=False,
|
||||
manual_review_required=True,
|
||||
items=[],
|
||||
generated_at=now_taipei(),
|
||||
)
|
||||
|
||||
|
||||
# =============================================================================
|
||||
@@ -366,10 +384,35 @@ async def get_km_stale_owner_review_burndown(
|
||||
project_id=project_id,
|
||||
limit=limit,
|
||||
)
|
||||
return await query_km_stale_owner_review_burndown(
|
||||
project_id=project_id,
|
||||
limit=limit,
|
||||
)
|
||||
try:
|
||||
return await query_km_stale_owner_review_burndown(
|
||||
project_id=project_id,
|
||||
limit=limit,
|
||||
)
|
||||
except Exception as exc:
|
||||
logger.warning(
|
||||
"km_stale_owner_review_burndown_readback_degraded",
|
||||
project_id=project_id,
|
||||
limit=limit,
|
||||
error_type=type(exc).__name__,
|
||||
)
|
||||
return KnowledgeStaleOwnerReviewBurnDownResponse(
|
||||
project_id=project_id,
|
||||
burn_down_status="no_data",
|
||||
current_snapshot=None,
|
||||
entries_to_threshold=0,
|
||||
pending_owner_reviews=0,
|
||||
completed_owner_reviews=0,
|
||||
completion_audit_total=0,
|
||||
stale_ratio_recheck_total=0,
|
||||
latest_stale_count_delta=None,
|
||||
latest_stale_ratio_delta=None,
|
||||
writes_on_read=False,
|
||||
manual_review_required=True,
|
||||
returned=0,
|
||||
items=[],
|
||||
generated_at=now_taipei(),
|
||||
)
|
||||
|
||||
|
||||
# =============================================================================
|
||||
|
||||
@@ -1028,6 +1028,29 @@ class TestKmReviewDraftDedupe:
|
||||
assert data["items"][0]["workflow_stage"] == "waiting_owner_review"
|
||||
assert data["items"][0]["batch_dispatch_id"] == "dispatch-batch-001"
|
||||
|
||||
def test_owner_review_inbox_readback_exception_returns_empty_inbox(self, client):
|
||||
"""owner review inbox 背景讀取失敗時應 fail-soft,不讓 Work Items 收到 500."""
|
||||
with patch(
|
||||
"src.api.v1.ai_governance.query_km_stale_owner_review_inbox",
|
||||
new=AsyncMock(side_effect=RuntimeError("temporary inbox failure")),
|
||||
):
|
||||
r = client.get(
|
||||
"/api/v1/ai/governance/km-stale-owner-reviews"
|
||||
"?project_id=awoooi&dispatch_status=pending&limit=30"
|
||||
)
|
||||
|
||||
assert r.status_code == 200
|
||||
data = r.json()
|
||||
assert data["schema_version"] == "km_stale_owner_review_inbox_v1"
|
||||
assert data["project_id"] == "awoooi"
|
||||
assert data["dispatch_status"] == "pending"
|
||||
assert data["total"] == 0
|
||||
assert data["returned"] == 0
|
||||
assert data["writes_on_read"] is False
|
||||
assert data["manual_review_required"] is True
|
||||
assert data["items"] == []
|
||||
assert data["generated_at"]
|
||||
|
||||
def test_owner_review_inbox_context_keeps_batch_and_priority_visible(self):
|
||||
record = KnowledgeEntryRecord(
|
||||
id="km-001",
|
||||
@@ -1156,6 +1179,33 @@ class TestKmReviewDraftDedupe:
|
||||
assert data["latest_stale_count_delta"] == -1
|
||||
assert data["items"][0]["recheck_dispatch_id"] == "dispatch-recheck-001"
|
||||
|
||||
def test_owner_review_burndown_readback_exception_returns_no_data(self, client):
|
||||
"""burndown 背景讀取失敗時應 fail-soft,不讓 Work Items 收到 500."""
|
||||
with patch(
|
||||
"src.api.v1.ai_governance.query_km_stale_owner_review_burndown",
|
||||
new=AsyncMock(side_effect=RuntimeError("temporary burndown failure")),
|
||||
):
|
||||
r = client.get(
|
||||
"/api/v1/ai/governance/km-stale-owner-review-burndown"
|
||||
"?project_id=awoooi&limit=20"
|
||||
)
|
||||
|
||||
assert r.status_code == 200
|
||||
data = r.json()
|
||||
assert data["schema_version"] == "km_stale_owner_review_burndown_v1"
|
||||
assert data["project_id"] == "awoooi"
|
||||
assert data["burn_down_status"] == "no_data"
|
||||
assert data["entries_to_threshold"] == 0
|
||||
assert data["pending_owner_reviews"] == 0
|
||||
assert data["completed_owner_reviews"] == 0
|
||||
assert data["completion_audit_total"] == 0
|
||||
assert data["stale_ratio_recheck_total"] == 0
|
||||
assert data["writes_on_read"] is False
|
||||
assert data["manual_review_required"] is True
|
||||
assert data["returned"] == 0
|
||||
assert data["items"] == []
|
||||
assert data["generated_at"]
|
||||
|
||||
def test_owner_review_burndown_items_compute_chronological_delta(self):
|
||||
older_snapshot = {
|
||||
"stale_count": 119,
|
||||
|
||||
Reference in New Issue
Block a user