[verified] Support explicit review-only provider counters

This commit is contained in:
2026-10-13 07:48:51 +00:00
parent dbd381a41b
commit e1be0dd526
3 changed files with 88 additions and 3 deletions
@@ -58,6 +58,17 @@ Shape example only, **not a claim about this deployment**:
}
```
For `inline.components`, the explicit projection modes are `["inline"]`,
`["reviews"]`, and `["reviews", "inline"]`. The review-only mode projects
only the number of reviews into `review_comments`; it does not add per-review
inline comments. The inline-only mode projects collected per-review inline
comments; the combined mode projects both. These are caller-supplied policies:
select one only from independently verified deployed-provider semantics, never
automatically detect a mode or choose one to fit observed counters. Both
`per_review` and `per_review_or_pr_count` retain the same explicit fallback
policy; per-review counters, complete collection pagination, duplicate IDs and
record cardinality remain checked.
`per_review` requires every exact-review comment endpoint. Only the explicit
`per_review_or_pr_count` capability permits endpoint-unavailable 404/405 fallback.
Permission errors, redirects, malformed JSON and conflicting metadata never
@@ -72,7 +83,11 @@ and `html_url` as HTML URLs, and PR-Issue `pull_request.html_url` without a nati
`pull_request.url`. Require the actual native relation URL; do not invent a
missing field. This source pin is fixture/protocol evidence, not a claim about
the deployment version. The caller's independent provider contract still binds
that version. In `per_review` mode only, an omitted `review_comments` is accepted
that version. In Gitea `v1.27.3`, `services/convert/pull.go` delegates the PR
review-comment count to `models/issues/pull.go`'s `GetReviewCommentsCount`,
which filters `CommentTypeReview`; this is source evidence for that version's
review-only projection, not a blanket claim for all versions or a live-gate
success. In `per_review` mode only, an omitted `review_comments` is accepted
as zero only when complete per-review records and their counters prove a zero
projection. Explicit null, nonzero projection or counts-only fallback with a
missing scalar is rejected. Raw pagination Link evidence is preserved and
@@ -147,7 +147,7 @@ class ReworkReadbackAdapter:
if (set(inline) != {'mode','field','components'}
or inline.get('mode') not in ('per_review','per_review_or_pr_count')
or inline.get('field') != 'review_comments'
or inline.get('components') not in (['inline'], ['reviews','inline'])):
or inline.get('components') not in (['inline'], ['reviews'], ['reviews','inline'])):
raise ReadbackError('invalid inline count declaration')
return copy.deepcopy(contract)
@@ -347,7 +347,9 @@ class ReworkReadbackAdapter:
for row in collected['rows']:
if row['id'] in inline_ids: raise ReadbackError('duplicate cross-review inline ID')
inline_ids.add(row['id'])
computed = inline + (len(raw['reviews']['rows']) if 'reviews' in self.provider['inline']['components'] else 0)
parts = self.provider['inline']['components']
computed = ((inline if 'inline' in parts else 0)
+ (len(raw['reviews']['rows']) if 'reviews' in parts else 0))
field = self.provider['inline']['field']
if field not in raw['pr']:
if (self.provider['inline']['mode'] != 'per_review' or fallback or computed != 0