ToolRejectScope
ToolRejectScope =
"once"|"session"|"always"
Defined in: _worktrees/docs-release/gaunt-sloth/packages/core/src/core/types.ts:399
§6 — persistence scope for a reject decision, the always reject half of the escalation menu:
once— refuse this single invocation; remember nothing (the default).session— additionally record a deny entry for this call, in the one entry grammar, for the life of this runner instance. The matcher consults it before anything else, so the next identical call is refused without reaching a person at all.always— additionally persist that entry to the project store (ToolApprovalScope’s mirror:.gsloth/.gsloth-settings/shell-denylist.json) so the refusal survives a restart. This is what every escalation menu’s always reject control sends.
The two scopes stay different types even now that they list the same three values. They are
different questions with different bounds — a reject has no catastrophic clamp and no
unresolvable-command exclusion, since refusing more is safe in every direction — and collapsing
them would let a future value added for one side become answerable on the other by accident.
A caller may still ask for session, and the runner honours it rather than upgrading it: the
lifetime that lands is reported back through the /approvals display, so a refusal held only for
this session is never shown as a saved one. It is also where an always refusal lands when the
project file cannot be opened. That is NOT merely “a re-prompt next session”: the refusal is
held for this run only, the unreadable file is left as it is, and next session nothing in it
applies — so the same call is left to the rest of the gate, which may refuse it under another
rule, prompt for it, or run it without asking (bypass, or a matching saved allow). The user is
told at load time; see PersistedApprovalGrants.