Found by the systematic sweep for "the CLI disclaiming knowledge it is already holding" (the class behind #343, #346 and #367).
The claim
ExclusionReason (internal/genapi/status.go) checks !Available first:
switch {
case !o.Available:
return "not available (the job finished without producing a usable file)"
case hasBlockedReason(o):
return "blocked by moderation: " + strings.TrimSpace(*o.BlockedReason)
case o.Hidden:
return "hidden (you deleted this result on the website)"
}
So for a blob carrying both available:false and blockedReason:"…", the CLI prints a specific causal claim — "the job finished without producing a usable file" — and discards the server's own moderation string, which is in the struct it already parsed (Blob.BlockedReason *string).
That sentence is not a hedge. It asserts a cause (the job ran and produced nothing) that a present blockedReason contradicts (moderation withheld it).
Why the combination is plausible — and what is NOT claimed
The platform's own predicate, vendored verbatim in Deliverable, ANDs the two independently:
output.filter((x) => x.available && !x.blockedReason && !x.hidden)
An independent AND only earns its keep if the operands vary independently. BlockedReason is modelled as a pointer specifically to keep "moderation said something" distinct from "it didn't".
🔴 No payload in this repo carries both, and I am not claiming the combination is common or even that it occurs — that would be exactly the per-key rule manufactured from one observation that item 13 and the #343 retraction forbid. The point is narrower and does not depend on frequency: the CLI should not assert a cause while holding a different one.
Note the interaction with #372 (open)
#372 rewrites this same function for #367, making the !Available branch prefer the step-level output.errors:
case !o.Available:
if r := joinReasons(o.StepErrors); r != "" {
return "not available (the server reported: " + r + ")"
}
return "not available (the job finished without producing a usable file)"
Its comment addresses the other two branches deliberately — "a moderation block and a user deletion already carry their own specific cause, and a step-level failure reason does not explain either of them" — but that reasoning is about step errors vs. the other branches. It does not cover the case here: available:false plus a per-blob blockedReason and no step errors still falls through to the fabricated generic sentence.
So this is a distinct question from #367, on the same function. It should be resolved on top of #372, not in a competing PR — which is why it is filed rather than fixed.
What would settle it
- Capture one real
orchestrator.getWorkflow payload for a moderation-blocked output and record whether available is false or true alongside blockedReason. That is the missing evidence, and it costs no Buzz (getWorkflow is a read).
- Whatever it shows, the safe change is to stop discarding: when both are present, report both rather than picking one. That is correct whether or not the combination is common, and it requires no decision about which cause is "closest".
Secondary, same function, same shape
Blob.Available is a plain bool, not a pointer. An absent available key therefore decodes to false and produces the same confident sentence about a field the server never sent. Worth deciding deliberately (pointer + fail-closed, as BlockedReason already does) rather than by zero-value accident.
Found by the systematic sweep for "the CLI disclaiming knowledge it is already holding" (the class behind #343, #346 and #367).
The claim
ExclusionReason(internal/genapi/status.go) checks!Availablefirst:So for a blob carrying both
available:falseandblockedReason:"…", the CLI prints a specific causal claim — "the job finished without producing a usable file" — and discards the server's own moderation string, which is in the struct it already parsed (Blob.BlockedReason *string).That sentence is not a hedge. It asserts a cause (the job ran and produced nothing) that a present
blockedReasoncontradicts (moderation withheld it).Why the combination is plausible — and what is NOT claimed
The platform's own predicate, vendored verbatim in
Deliverable, ANDs the two independently:An independent AND only earns its keep if the operands vary independently.
BlockedReasonis modelled as a pointer specifically to keep "moderation said something" distinct from "it didn't".🔴 No payload in this repo carries both, and I am not claiming the combination is common or even that it occurs — that would be exactly the per-key rule manufactured from one observation that item 13 and the #343 retraction forbid. The point is narrower and does not depend on frequency: the CLI should not assert a cause while holding a different one.
Note the interaction with #372 (open)
#372 rewrites this same function for #367, making the
!Availablebranch prefer the step-leveloutput.errors:Its comment addresses the other two branches deliberately — "a moderation block and a user deletion already carry their own specific cause, and a step-level failure reason does not explain either of them" — but that reasoning is about step errors vs. the other branches. It does not cover the case here:
available:falseplus a per-blobblockedReasonand no step errors still falls through to the fabricated generic sentence.So this is a distinct question from #367, on the same function. It should be resolved on top of #372, not in a competing PR — which is why it is filed rather than fixed.
What would settle it
orchestrator.getWorkflowpayload for a moderation-blocked output and record whetheravailableisfalseortruealongsideblockedReason. That is the missing evidence, and it costs no Buzz (getWorkflowis a read).Secondary, same function, same shape
Blob.Availableis a plainbool, not a pointer. An absentavailablekey therefore decodes tofalseand produces the same confident sentence about a field the server never sent. Worth deciding deliberately (pointer + fail-closed, asBlockedReasonalready does) rather than by zero-value accident.