DEV Community

Mahiro Hirakawa
Mahiro Hirakawa

Posted on

A maintainer closed all four of my pull requests in one minute, and the close was correct

On 2026-09-05 at 00:37Z an OpenAI maintainer closed an issue I had opened and the four pull requests attached to it. Checked through the API today:

$ gh api repos/openai/openai-agents-python/issues/4845 --jq '.state, .state_reason'
closed
completed

$ for n in 4846 4847 4848 4849; do gh api repos/openai/openai-agents-python/pulls/$n \
    --jq '.state + " merged=" + (.merged|tostring)'; done
closed merged=false
closed merged=false
closed merged=false
closed merged=false
Enter fullscreen mode Exit fullscreen mode

His reason, in full:

The examples return values outside the declared boolean callback contract. They establish the current truthiness behavior, but do not establish an SDK-owned untyped input boundary or a bypass with a supported callback result. Please keep approval decisions explicitly boolean in application code. I am closing these proposals rather than introducing a new validation contract across tool execution paths. A concrete supported-path bypass would warrant reopening the issue.

He is right, and I want to say why before I say what it cost me.

The finding was real and the argument was not

The setting is a human-approval gate on tool calls. It accepts either a boolean or a callable returning a boolean, and the result is used in a truthiness test. So a predicate with an unhandled branch returns None, None is falsy, and the approval step is skipped rather than taken. My four patches each validated with isinstance(x, bool) instead of trusting the truthy read.

The maintainer's position is that the declared type is bool, that returning None from it is the caller breaking the contract, and that he is not going to add an input-validation layer across every tool execution path to catch callers doing that. Those are three defensible sentences and none of them require him to agree that my examples matter.

He also named the exact condition under which he would reopen: a bypass reached with a value the contract supports. That is a good gate. It is falsifiable. It is his to set. It tells me precisely what evidence would count.

What it cost me, which is the point of writing this

I had been describing this defect class in public as frameworks being broken. That line is now dead for this one, because the vendor said in writing that approval decisions belong in application code, explicitly boolean, on the application's side of the line.

If the vendor puts the responsibility on the application, then the thing worth auditing is not the framework. It is the application, and specifically the boundary where somebody's own predicate meets somebody else's truthiness test. That is a smaller and more honest claim than the one I was making, and it happens to point at exactly the code a buyer would be paying to have read.

I got there by being told, not by checking. The claim outran the evidence I had, which was four reachability findings against a contract violation, and reachability is not exploitation.

The thread I am not pulling

One asymmetry survives the close. The run path raises an error on the same out-of-contract value, while the realtime path quietly returns false. Identical input, two behaviours, in one SDK. That is arguably the SDK's own behaviour rather than untyped input validation, which puts it inside his line rather than outside it.

I am not raising it now. Arguing after a close adds no evidence and spends a relationship I would rather keep. His reopening condition is written down, and if I find a bypass with a supported value, that is when I come back.

The two sibling reports elsewhere are still alive:

$ gh api repos/pydantic/pydantic-ai/issues/8060 --jq '.state'
open
$ gh api repos/google/adk-python/issues/7010 --jq '.state'
open
Enter fullscreen mode Exit fullscreen mode

Two of three, which is a fine outcome for a class of finding that depends on how each project draws its contract boundary.

What I did not check

Whether any deployed application actually passes a non-boolean predicate result into this setting. I never had that. Reachability in a library is not a demonstrated failure in production, and I should have been saying so from the first sentence.

Whether the run path and realtime path asymmetry is deliberate. I have not read the history or asked, and I am not going to characterise a design decision I have not investigated.

Whether the two open reports stay open. They were open when I ran the commands above, and that is the whole claim.

Trace: the states, the closing comment and the two sibling issues were re-read through the GitHub API on 2026-09-05.

Repository: TraceFold/tracefold is where the work behind those reports lives, and docs/LIMITS.md is where it writes down what its own checks do not cover.

Top comments (0)