Skip to content

source-control:babysit-prs: an unproven readiness verdict is enforced only by prose, not by the gate predicate #1387

Description

@kyle-sexton

Problem

When the host permission classifier denies the readiness gate, nothing mechanical stops an orchestrator from reporting a PR as merge-ready anyway. The guard is prose in skills/babysit-prs/reference/loop.md:484-488 (a NEVER-do bullet) and :536-541 (§5.5 "Gate verdict, quoted verbatim") — instructions to an agent, not a predicate that refuses.

The plugin's own philosophy, stated in scripts/babysit-readiness-gate.sh, is the standard this fails:

Prose "MANDATORY" is a word; this gate counts rows, not intentions.

Why the existing READINESS_UNPROVEN verdict does not close it

PR #1264 added an unproven() helper (scripts/babysit-readiness-gate.sh:109-112) that prints READINESS_UNPROVEN reason=<...> pr=<n>. That is a real improvement to the gate's own output hygiene and should land on its merits. It is not enforcement:

  • Exit codes are unchanged (3 and 4), which that PR's CHANGELOG states outright: "Exit codes are unchanged, so existing callers keyed on them are unaffected." No caller's behavior changes.
  • No executable consumer parses the token. git grep -n "READINESS_" across plugins/source-control, excluding the gate and its own tests, returns only CHANGELOG, reference/review-discipline.md, reference/loop.md, reference/safety.md, skills/babysit-prs/evals/evals.json, two Python source comments (babysit_classify.py, babysit_findings.py), and test files. The only consumer is an LLM told to quote it.
  • The branch concedes the gap in writing (reference/safety.md:383-385): "a gate the harness never let run cannot report its own non-invocation, which is why the quoted-verdict requirement lives on the report rather than inside the script."

Scope note — #787's gate is a different script

#787's denied invocation was the merge-readiness gate:

python .../babysit_merge.py <pr> --allowed-owners ... --self-logins @me

babysit_merge.py still emits a JSON object with exit codes 0/10/2/3 and has no state distinguishing "readiness could not be proven" from "the command never ran". Any mechanical fix has to reach it, not only scripts/babysit-readiness-gate.sh.

The setup canary does not detect the condition either

skills/setup/SKILL.md probes reachability with --help invocations only. A classifier decision is per-call, so a host that permits --help and denies the production argument shapes (owner/repo#N --allowed-owners ...) yields a PASS from a lane that cannot prove readiness. Raised independently by the Codex reviewer on #1264 (skills/setup/SKILL.md:146, :147).

What would actually close it

Not prescribing a design, but the shape has to satisfy: an orchestrator that never obtained a passing gate verdict cannot emit a merge-ready verdict, and the refusal is made by code rather than by an instruction. Candidates worth weighing:

  • A readiness assertion the orchestrator must present, produced only by a real gate run and checked mechanically before a merge-ready line is accepted — moving the trust anchor from the report to an artifact.
  • Extending the readiness-gate predicate so that consuming machinery (rather than an LLM) reads the verdict and refuses on READINESS_UNPROVEN or on absence.
  • Giving babysit_merge.py the same unproven state and a non-zero exit distinct from "not ready", so a caller keyed on exit codes can tell the two apart.

Whichever shape wins, a canary that exercises the production argument shapes rather than --help is part of it, or the lane still cannot tell a permitted probe from a permitted job.

Related

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    needs-humanHuman-in-the-loop required; autonomous sessions must not resolve items carrying this.priority: mediumReal value, no hard deadline; normal backlog flow.wayfind: designWayfind decision item: design-space or domain-model decision; human in the loop.work-class: structuralRefactors, migrations, contract changes; cross-cutting and hard to reverse.

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions