fix(ci): surface collection errors behind invalid_payload truth-gate verdicts - #1285
fix(ci): surface collection errors behind invalid_payload truth-gate verdicts#1285groupthinking wants to merge 2 commits into
Conversation
…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 latest updates on your projects. Learn more about Vercel for GitHub.
|
|
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 |
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 evidence collection errors alongside invalid_payload verdicts while preserving fail-closed behavior.
Changes:
- Adds reusable collection-error normalization.
- Includes diagnostics in malformed-payload details.
- Adds regression coverage for filtering and malformed values.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
scripts/ci/agent_completion_gate.py |
Surfaces collection diagnostics during validation failures. |
tests/unit/test_agent_completion_gate.py |
Tests diagnostic propagation and filtering. |
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
|
Publish gate — HALTED(awaiting_merge_approval). This PR is green and merge-ready: all required checks pass, CodeRabbit approved, Vercel deployed, The automated remediation run does not auto-merge to No further automated action is needed here — only your sign-off. Generated by Claude Code |
|
Closing as superseded by #1331. #1331 cherry-picks both commits from this PR cleanly onto the current No work is lost — #1331 is the live continuation. Reopen this if #1331 is abandoned. Generated by Claude Code |
Canonical issue
Closes #1286
Outcome
Every PR blocked by the agent-completion truth gate now learns why. The gate previously answered
invalid_payloadand nothing else for 47 of the 69 open PRs; it now returns the collector's own diagnostics alongside that verdict, so an author can act instead of guessing.Before (real PR #1270 payload):
{"verdict":"blocked","reasons":["invalid_payload"], "details":{"invalid_fields":["policy.agent_login","policy.run_id"]}}After, same payload:
{"verdict":"blocked","reasons":["invalid_payload"], "details":{"invalid_fields":["issue.number","policy.agent_login","policy.run_id"], "collection_errors":["missing_linked_issue","missing_closing_issue_reference", "missing_agent_run_id","missing_agent_login"]}}Scope
scripts/ci/agent_completion_gate.py(extract_collection_errors(); attach it to theinvalid_payloadearly return),tests/unit/test_agent_completion_gate.py(4 regression tests).agentTaskApplicable()branch-name heuristic inpr-checks.yml. It over-triggers onclaude/*,codex/*,copilot/*worktree branches from human authors, but changing it changes which PRs are policed. This PR only changes what the gate says. Tracked as follow-up in Truth gate reports bare invalid_payload and discards the collector's diagnostics, stranding ~47 open PRs #1286.Risk
verdictandreasonsare byte-identical for every input; the change is purely additive todetails. Noblockedverdict can becomeready, and no field is dropped from validation, so the gate remains fail-closed. A malformedcollection_errors(non-list, blank strings,None) is filtered rather than raised — covered by tests.Verification
Against head
4001c8db5952ec2ee068bcc2d38e2eda2a7d9204:New tests: real-world
invalid_payloadcascade (reproduces PR #1270), empty-list omission, non-list tolerance (None/str/dict/int), blank-entry filtering, plus both early short-circuit paths.Review follow-up (
4001c8d): the diagnostic was initially attached only to the late field-validation return, so the three early short-circuits (payload not a dict,policynot a dict, invalidpolicy.applicable) stayed opaque. All fourinvalid_payloadreturns now route through a shared_invalid_payload()builder.Backward compatibility asserted explicitly — a non-dict payload still returns
details: {}, andpolicy/policy.applicablereturns keep their exact priorinvalid_fields:Manual: replayed the exact PR #1270 collector payload through
evaluate()and confirmed the after-output above.Production evidence
Not applicable — this changes a CI verdict-reporting path only. No runtime, application, or deployed surface is touched.
The gate itself is the evidence: this PR is on a
fix/branch rather thanclaude/*, andagent-completion/truth-gate/pr-1285returnsnot_applicable: all rules passed, which is precisely the branch-heuristic asymmetry described in #1286.Agent handoff