fix(ci): surface collection errors behind invalid_payload truth-gate verdicts - #1331
Conversation
|
Important Review skippedAuto reviews are limited based on label configuration. 🏷️ Required labels (at least one) (1)
Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository YAML (base), Repository UI (inherited), Organization UI (inherited) Review profile: ASSERTIVE Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Dependency Review✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.Snapshot WarningsEnsure that dependencies are being submitted on PR branches and consider enabling retry-on-snapshot-warnings. See the documentation for more information and troubleshooting advice. Scanned FilesNone |
Agent Completion Truth Gate: NOT_APPLICABLEEvidence agrees. Machine-readable verdict{
"details": {},
"reasons": [],
"verdict": "not_applicable"
} |
There was a problem hiding this comment.
Pull request overview
Surfaces collector diagnostics when the agent-completion gate rejects malformed payloads.
Changes:
- Centralizes
invalid_payloadverdict construction. - Sanitizes and exposes
collection_errors. - Adds regression and malformed-input tests.
Current blocker: PR Governance does not recognize Closes groupthinking/EventRelay#1286; use Closes #1286.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
scripts/ci/agent_completion_gate.py |
Adds shared diagnostic helpers. |
tests/unit/test_agent_completion_gate.py |
Covers invalid-payload diagnostic behavior. |
…verdicts The agent-completion truth gate blocks ~47 of the 69 open PRs with a bare `invalid_payload` and no remediation path. Root cause: `agentTaskApplicable()` in pr-checks.yml classifies any branch matching /^(?:agent|claude|codex|copilot|jules)[\/-]/ as agent work, so human-authored Claude Code worktree branches are held to the full AgentTask provenance contract. With no linked AgentTask issue, the collector emits `policy.agent_login` and `policy.run_id` as null and records the real reasons in `collection_errors` (missing_linked_issue, missing_agent_login, missing_agent_run_id). `evaluate()` then returned at the schema check and discarded `collection_errors` entirely -- they are only read further down, after the early return. Authors saw `invalid_payload` and nothing else. This keeps the gate fail-closed and byte-identical in `verdict` and `reasons`, and only adds `details.collection_errors` so the gate says what to fix. Verified: 112 passed against the reproduced PR #1270 payload. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
The collection_errors diagnostic was only attached to the late
field-validation return. The three early invalid_payload short-circuits
(payload not a dict, policy not a dict, missing/invalid policy.applicable)
returned bare verdicts, so a malformed payload that never reaches field
validation stayed just as opaque despite the collector having already
recorded why — exactly the case the review thread raised
(evaluate({"policy": {}, "collection_errors": [...]})).
Extract _invalid_payload(payload, invalid_fields) and route all four
invalid_payload returns through it so the diagnostic is applied
consistently. verdict and reasons stay byte-identical for every input;
only details is enriched, and only when the collector recorded errors —
the gate remains fail-closed.
Add regression coverage for both early paths and confirm a non-dict
payload still returns an empty details.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011L6jqdhrKTYLinTnJYKEg9
df6a5db to
510726c
Compare
groupthinking
left a comment
There was a problem hiding this comment.
Review at head 510726c (formal Approve is blocked by GitHub since the review identity matches the PR author, so recording it as a comment). Verdict: LGTM — correct, fail-closed, and satisfies issue #1286's acceptance criteria. No changes requested.
What I verified
- Fail-closed preserved. All four
invalid_payloadreturns route through_invalid_payload(), which keepsverdict: "blocked"andreasons: ["invalid_payload"]byte-identical and only enrichesdetails.invalid_fieldsis stillsorted(set(...)), so existing field output is unchanged. - No fail-open from the new
isinstance(list)guard. I specifically checked whether routing the happy-pathcollection_errorsthrough_collection_errors()(which returns[]for a non-list) could let a malformed payload slip toready. It cannot: a non-listcollection_errorsis already rejected upstream at field validation (agent_completion_gate.py:88-94→invalid_fields.append("collection_errors")), so it returnsinvalid_payloadbefore the success path. Confirmed by probe —collection_errors="boom"on an otherwise-valid payload →blocked,invalid_fields: ["collection_errors"]. The guard is defense-in-depth, and its blank-string filtering matches the upstream element rule at:146-150. - Backward compatibility. Non-dict payload still returns
details: {}; thepolicy/policy.applicableearly returns keep their exact priorinvalid_fields. Covered bytest_non_dict_payload_reports_no_collection_errorsand the early-path test. - Tests pass on this head.
pytest tests/unit/test_agent_completion_gate.py tests/unit/test_agent_completion_enforcement.py→ 114 passed, 89 subtests passed. Coverage includes the real ~47-PR cascade, empty-list omission, non-list tolerance, blank-entry filtering, and both early short-circuit paths.
Notes for the merger (not blocking)
- The
agent-completion/truth-gatered across the repo is the known #1286 false-positive on agent-heuristic branches; this PR is on aland-pr-*branch and is not tripped by it. The over-triggering heuristic is explicitly out of scope here (tracked in #1286). - Merge into protected
mainremains a human decision — nothing here auto-merges.
Generated by Claude Code
Canonical issue
Closes #1286
Lands #1285 (both commits cherry-picked cleanly onto current
main; that PR's base had fallen behind, and it is now closed as superseded by this one).Outcome
PRs blocked by the agent-completion truth gate with
invalid_payloadnow also receive the collector's own diagnostics (details.collection_errors), so authors can see why the payload was invalid instead of guessing. This unblocks PR #1270, which currently gets an opaqueinvalid_payloadverdict.Scope
scripts/ci/agent_completion_gate.py(all fourinvalid_payloadreturns route through a shared_invalid_payload()builder that attaches sanitizedcollection_errors), plus regression tests intests/unit/test_agent_completion_gate.py.agentTaskApplicable()branch-name heuristic inpr-checks.yml(tracked in the canonical issue).Risk
verdictandreasonsare unchanged for every input; the change is purely additive todetails. Malformedcollection_errors(non-list, blank entries,None) are filtered, not raised.Verification
Against head
510726c58bb991de7b4ca1d7009c2bb988b5ad1d(rebased onto currentmainto pick up the removal of the orphaned ci-investigator governance test that was failingtest/coverage repo-wide):4001c8d)Production evidence
Not applicable — this changes a CI verdict-reporting path only; no runtime or deployed surface is touched.
Agent handoff