Investigate: a permanent grant refusal is retried like a transient failure, because IsGrantDenial has no caller #825

Closed
opened 2026-08-15 17:07:48 +00:00 by coilyco-ops · 0 comments
Member

Filed by Delphi (design seat) at Kai's instruction, 2026-08-15. Split from #621.

The artifact

IsGrantDenial   grants.go   classifies a refusal as record-do-not-retry

This is the one of #621's four with a live consequence. GrantTable.Permits returns a GrantDenial, and jobrunner.go:169 passes that error straight up without classifying it. So a permanent refusal - a grant the deployment does not hold and will not hold - is handled identically to a transient failure and retried.

IsGrantDenial exists precisely to tell those apart, and nothing calls it.

What to establish

  1. What the retry actually costs today. How many times a denied grant is retried, and whether it burns a model call, a tool round, or only a job step. Angie assessed the cost as retry behaviour rather than a wrong answer, which is right and is not the same as free.
  2. Whether the member sees anything different. A permanent refusal retried three times and a transient failure retried three times may produce the same notice, which would make this the same family as #449 - a true sentence that misdirects.
  3. Whether wiring it is the whole fix. Classifying the error is one line. Acting on the classification - stopping, recording, and reporting it as a refusal rather than a failure - is the behaviour change, and it is the part worth designing.

Outcome

Wiring it is probably right, and it is a behaviour change rather than a deletion, so it needs the reasoning recorded either way. This is the one of the four where doing nothing has an ongoing cost.

Parent - #621.

Filed by Delphi (design seat) at Kai's instruction, 2026-08-15. Split from #621. ## The artifact ``` IsGrantDenial grants.go classifies a refusal as record-do-not-retry ``` **This is the one of #621's four with a live consequence.** `GrantTable.Permits` returns a `GrantDenial`, and `jobrunner.go:169` passes that error straight up without classifying it. So a permanent refusal - a grant the deployment does not hold and will not hold - is handled identically to a transient failure and retried. `IsGrantDenial` exists precisely to tell those apart, and nothing calls it. ## What to establish 1. **What the retry actually costs today.** How many times a denied grant is retried, and whether it burns a model call, a tool round, or only a job step. Angie assessed the cost as retry behaviour rather than a wrong answer, which is right and is not the same as free. 2. **Whether the member sees anything different.** A permanent refusal retried three times and a transient failure retried three times may produce the same notice, which would make this the same family as #449 - a true sentence that misdirects. 3. **Whether wiring it is the whole fix.** Classifying the error is one line. Acting on the classification - stopping, recording, and reporting it as a refusal rather than a failure - is the behaviour change, and it is the part worth designing. ## Outcome **Wiring it is probably right**, and it is a behaviour change rather than a deletion, so it needs the reasoning recorded either way. This is the one of the four where doing nothing has an ongoing cost. **Parent** - #621.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
coilyco-gaming/sirens-echo#825
No description provided.