Skip to content

T-VBFY-pr-check-no-checks-verdict

Status: closed/done · Impact: low · Complexity: small

Auto-generated from a /sdlc:task-work post-mortem. Review and promote to open/ready before picking up.

When a PR has no configured CI checks, gh pr view --json statusCheckRollup returns an empty array. The current /sdlc:pr-check (from T-8896-add-pr-check-skill) silently treats this the same as “checks all green” and falls through to CLEAN. The orchestrator can’t tell “checks passed” from “checks never ran” — both look identical in the verdict line. Make the “no checks” fact visible so the orchestrator’s digest can flag it without re-querying GitHub.

From the originating post-mortem:

gh pr view --json statusCheckRollup returns an empty array on PRs without checks; the SKILL.md handles this by simply not matching rule 4. But “no checks” is also a fact worth reporting in the digest. Could be a future verdict refinement (NO-CHECKS) or just a richer reason string in CLEAN.

In plugin/skills/pr-check/SKILL.md, rule 4 of the priority ladder only fires when at least one check in statusCheckRollup is failing. An empty rollup falls through to rule 6 and is reported as CLEAN reason="awaiting review" — indistinguishable from a PR whose checks all passed.

Adopt option (A) — richer reason string. Keep the five-verdict enum and encode the rollup state in the CLEAN reason — e.g. CLEAN reason="no checks configured; awaiting review" vs. CLEAN reason="checks passing; awaiting review". Cheapest and preserves the existing enum contract; additive reason strings are reversible, enum expansion is harder to walk back.

Rejected alternative: option (B) — extending the enum with a new NO-CHECKS verdict. Highest visibility but every consumer (orchestrator, lint invariants, any harness fixtures) has to learn the new token. Revisit only if reason-string parsing becomes a real burden downstream.

  1. Edit plugin/skills/pr-check/SKILL.md rule 6 (the catch-all) to inspect len(statusCheckRollup) == 0 and emit CLEAN reason="no checks configured; awaiting review" when the rollup is empty, vs the existing CLEAN reason="awaiting review" (or "checks passing; awaiting review") when checks exist.
  2. Re-run plugin/scripts/lint_skill_prose.py plugin/skills/pr-check/SKILL.md to confirm invariants pass.
  • plugin/skills/pr-check/SKILL.md — rule 6 inspects rollup length and emits a richer reason string.
  • AC-1: A PR with zero entries in statusCheckRollup produces a verdict line whose CLEAN reason string is distinguishable from a PR with checks passing — e.g. CLEAN reason="no checks configured; awaiting review". (auto, via a --mock-state fixture once T-BM56-pr-check-mock-state-flag lands)
  • AC-2: plugin/scripts/lint_skill_prose.py plugin/skills/pr-check/SKILL.md exits 0. (auto)
  • Distinguishing “no checks configured” from “checks not yet run” — GraphQL doesn’t cleanly expose this; treat both as no-checks.

Spawned by /sdlc:task-work post-mortem of T-8896-add-pr-check-skill on 2026-05-20.

Captured by /sdlc:task-work on 2026-05-21. PR: pending.

  • AC-1: agent-manual — edited plugin/skills/pr-check/SKILL.md rule 6 to distinguish empty statusCheckRollup from passing checks; the four CLEAN reason strings are now distinguishable (no checks configured; awaiting review, checks passing; awaiting review, no checks configured; approved, awaiting merge, checks passing; approved, awaiting merge). Added a fixtures/clean-no-checks.json fixture so the next harness run that exercises the mock-state path covers the empty-rollup case. The spec is the executable contract for this skill (no compiled code path); deterministic execution against the fixture happens once the eval harness asserts the new fixture.
  • AC-2: auto — plugin/scripts/lint_skill_prose.py plugin/skills/pr-check/SKILL.md exits 0 (verified locally; no invariant phrases drift).
  • The change scope was small enough (rule 6 + one fixture + the bundled-fixtures bullet) to implement without delegating to a sub-agent — the colocation of fixture, invariants, and SKILL.md made the blast radius obvious.
  • lint_skill_prose.py immediately confirmed AC-2 with no invariant-phrase regressions, even though the new prose introduced several new reason-string examples — the existing invariants list is well-scoped (verdict tokens, contract phrases) rather than pinning the full reason text.
  • sdlc.yaml validation fails with Additional properties are not allowed ('pr_check' was unexpected) because the pr_check.author_comments block landed in sdlc.yaml (commit e463491, May 21) without a corresponding update to plugin/schemas/sdlc-yaml.schema.json. This blocks run_quality_checks.py --key worktree_init in Step 4 and run_quality_checks.py (default key) in Step 7 from succeeding. Multiple in-flight /sdlc:task-work runs likely hit the same block — a follow-up task should add the pr_check: block to plugin/schemas/sdlc-yaml.schema.json so the validator stops rejecting documented configuration. → T-DN76-pr-check-schema-promote
  • T-DN76-pr-check-schema-promote — linked existing task that already covers adding pr_check: to the bundled sdlc-yaml.schema.json so run_quality_checks.py stops rejecting the documented author-comment block.

← Back to Tasks