Skip to content

rateShellCommand

rateShellCommand(command, config, options?): Promise<{ outcome: "safe" | "destructive" | "catastrophic" | "attack"; reason: string; suggestedTool?: string; }>

Defined in: _worktrees/docs-release/gaunt-sloth/packages/core/src/core/shell/rater.ts:1458

Rate a single shell command with the rater model and return a structured ShellSafetyVerdict.

  • Builds an injection-hardened, normalized prompt (buildRaterPrompt).
  • Calls the rater model (defaults to config.llm) via withStructuredOutput(schema).
  • Races the call against RATER_DEFAULT_TIMEOUT_MS.
  • Fail-closed: any throw / timeout / parse failure returns FAIL_CLOSED_VERDICT (destructive + “could not assess”), never an approval.

Note: this only produces a verdict; the approve / escalate / halt decision (including fail-closed-on-ambiguity) is made by mapVerdictToAction in the runner.

string

GthConfig

boolean

[[EXT-106]] (§4.6) — whether the user-provenance carve-out lifted the open-world floor on this command. Passed straight to buildRaterPrompt; see the option there for what it changes and why it changes both halves of the prompt.

readonly GrantedToolSummary[]

EXT-58 (§4.4) — the already-granted built-ins of the current rung. Supplied, the rater is asked to name one whenever it does not return safe and one would do the job; omitted, the prompt is exactly as before and no suggestion is ever produced.

string

BaseChatModel<BaseChatModelCallOptions, AIMessageChunk<MessageStructure<MessageToolSet>>>

boolean

[[EXT-29]] (§5.2) — whether a rejection is addressed to the agent (the rung negotiates). Passed straight to buildRaterPrompt; it changes the system prompt’s wording rules and nothing the rating is allowed to SEE.

(capture) => void

[[TUI-C27]] — the sink for the diagnostic record of THIS call, handed over at the send site, carrying the prompt strings that are about to be sent.

It is called once, BEFORE the model is invoked, with a record this function then fills in as the answer arrives. Two properties follow, and both are the point:

  • The prompt is captured, never re-rendered. The caller receives the very strings passed to invoke, so nothing downstream can rebuild a prompt that disagrees with the one that was actually sent — the one thing a diagnostic archive must never do.
  • A rater that never answers still leaves a record of what it was asked. The record is in the caller’s hands before the call is made, so a hang, a timeout or a throw cannot take the question with it.

Omitted (the eval target, and every caller that wants no diagnostics) costs nothing: no record is built.

string

[[TUI-C27]] — approvals.rater, recorded on the capture so a dump names WHO rated.

number

Promise<{ outcome: "safe" | "destructive" | "catastrophic" | "attack"; reason: string; suggestedTool?: string; }>