Problem
The toolkit safely projects non-zero OCR results through the bounded ocr.llm-retry-report/v1 contract. However, HTTP 402 and HTTP 429 currently collapse into the same public rate-or-spending-limit reason in both the merge-request summary and the useful part of the CI log.
Keeping one public reason is appropriate: a merge-request note should not expose provider details or claim provider-specific billing semantics. The CI log, however, currently lacks enough safe information to distinguish:
- HTTP 402 payment or account-policy rejection;
- HTTP 429 rate limiting;
- a request that failed immediately;
- a request that exhausted retries;
- a run containing recovered requests before its terminal failure.
This makes operator diagnosis unnecessarily difficult. Raw response bodies, messages, headers, URLs, model/provider identities, request IDs, and credentials must remain private and must not be parsed to infer a cause.
The existing remediation text is also too prescriptive. It recommends a fixed OCR_LLM_MAX_COMPLETION_TOKENS=4096, although reducing the output cap helps only when a provider actually reserves admission capacity from the requested cap. It also does not explain when lowering OCR_REVIEW_CONCURRENCY may help.
This is a narrow follow-up to #129, not a replacement for its closed provider-neutral projection.
Proposed behavior
Keep the existing merge-request summary structure and its public closed classification unchanged:
- HTTP 402 and HTTP 429 continue to publish
rate-or-spending-limit;
- no retry-report details are added to the merge-request note structure;
- no provider-controlled response text enters publication.
Add one bounded, deterministic toolkit-authored diagnostic line to the CI log, derived only from the already validated structured retry report.
At minimum, distinguish:
- HTTP 402 as
http-payment-required;
- HTTP 429 as
http-rate-limited.
The log line may include a small closed set of useful aggregate fields already validated by the toolkit, for example:
OCR provider diagnostics: summary=rate-or-spending-limit detail=http-rate-limited status=429 failed_requests=1 retried_requests=1 total_retries=2 recovered_requests=0
For mixed terminal failures, aggregate bounded category counts into one line instead of logging individual requests or attempts. Omit zero-value or unavailable fields where that improves readability. Keep this as an operator diagnostic, not toolkit telemetry, a receipt field, or an approval input.
Apply the same small projection consistently to other validated terminal provider failures when the failure phase or HTTP status adds useful information beyond the public summary. Do not introduce a general-purpose provider-diagnostics framework.
Replace the current remediation with a short actionable message:
Try lowering OCR_REVIEW_CONCURRENCY and/or OCR_LLM_MAX_COMPLETION_TOKENS, then start a new merge request pipeline. If it still fails, check the provider's request and account limits.
Safety and compatibility considerations
- Preserve the current merge-request summary structure and public
rate-or-spending-limit classification.
- Treat CI logs as potentially exposed output even when the current runner is private.
- Read diagnostic values only from a fully validated
ocr.llm-retry-report/v1.
- Do not parse, match, summarize, or publish provider response bodies.
- Do not log credentials, headers, URLs, model/provider identities, request IDs, provider-specific error codes, messages, paths, warnings, or stderr.
- An HTTP status is bounded protocol metadata, not proof of the provider's business reason. In particular,
http-payment-required must not be rendered as a confirmed spending-limit diagnosis.
- Legacy warnings without a valid structured status must retain the existing aggregate classification and report detailed status as unavailable.
- Malformed, oversized, contradictory, or unsupported reports must keep the current fail-closed behavior.
- Emit at most one bounded diagnostic line per failed review; do not print one line per request, retry, or attempt.
- Add focused tests for 402, 429, retries, recovered requests, mixed failures, malformed reports, deterministic aggregation, bounds, and absence of forbidden provider data.
- Update operations documentation and the threat-model description of the CI diagnostic surface.
- Add no new environment variable, public result schema, telemetry field, receipt field, or approval input.
Problem
The toolkit safely projects non-zero OCR results through the bounded
ocr.llm-retry-report/v1contract. However, HTTP 402 and HTTP 429 currently collapse into the same publicrate-or-spending-limitreason in both the merge-request summary and the useful part of the CI log.Keeping one public reason is appropriate: a merge-request note should not expose provider details or claim provider-specific billing semantics. The CI log, however, currently lacks enough safe information to distinguish:
This makes operator diagnosis unnecessarily difficult. Raw response bodies, messages, headers, URLs, model/provider identities, request IDs, and credentials must remain private and must not be parsed to infer a cause.
The existing remediation text is also too prescriptive. It recommends a fixed
OCR_LLM_MAX_COMPLETION_TOKENS=4096, although reducing the output cap helps only when a provider actually reserves admission capacity from the requested cap. It also does not explain when loweringOCR_REVIEW_CONCURRENCYmay help.This is a narrow follow-up to #129, not a replacement for its closed provider-neutral projection.
Proposed behavior
Keep the existing merge-request summary structure and its public closed classification unchanged:
rate-or-spending-limit;Add one bounded, deterministic toolkit-authored diagnostic line to the CI log, derived only from the already validated structured retry report.
At minimum, distinguish:
http-payment-required;http-rate-limited.The log line may include a small closed set of useful aggregate fields already validated by the toolkit, for example:
For mixed terminal failures, aggregate bounded category counts into one line instead of logging individual requests or attempts. Omit zero-value or unavailable fields where that improves readability. Keep this as an operator diagnostic, not toolkit telemetry, a receipt field, or an approval input.
Apply the same small projection consistently to other validated terminal provider failures when the failure phase or HTTP status adds useful information beyond the public summary. Do not introduce a general-purpose provider-diagnostics framework.
Replace the current remediation with a short actionable message:
Safety and compatibility considerations
rate-or-spending-limitclassification.ocr.llm-retry-report/v1.http-payment-requiredmust not be rendered as a confirmed spending-limit diagnosis.