Skip to content

APPROVAL_RUNG_DESCRIPTIONS

const APPROVAL_RUNG_DESCRIPTIONS: Record<ApprovalRung, string>

Defined in: _worktrees/docs-release/gaunt-sloth/packages/core/dist/config/shell-policy.d.ts:457

§10 — what each mode is for, in at most two sentences, shown wherever a mode is chosen or displayed.

The first sentence is load-bearing and must stand alone. The /approvals picker, the text fallback and the usage hint all render one line per mode through firstSentence, so sentence one has to answer “what is this mode for” on its own and sentence two carries the qualification. Keep it short enough to read as a menu row.

Say what the mode is for, not only what it permits. A description that lists permissions invites the category error these modes actually suffer: Manual reads as “the safe one”, so it gets picked for a long unattended run — where the deciding is done by a human, and a human is the fastest-degrading decider in the system. Manual and Write are bounded-volume tools and their copy says so.

The wording is constrained by four normative rules (state what the mode PERMITS, state the allow-list carve-out, never claim safety this system cannot deliver, use the display spelling) plus §8.1 — the hardline floor is real but is NEVER advertised, so descriptions cite only protections the user can inspect and extend, i.e. the deny list. Six further constraints bind every edit here:

  1. No description may imply containment. The gate protects against accidents, not intent, and a working-folder claim collapses the moment the agent has a shell — write_file refuses a path that touch then writes. The narrow true form (the built-in file tools are confined) is stated once, on write, alongside the fact that the shell is not confined that way.

  2. Claims are scoped to the session the user is in — ratified by Andrew on 2026-08-13 as the standing rule for every in-product approval promise ([[CFG-40]]), so it is a decision and not a habit inherited from whichever string happened to be written last. What makes it true rather than merely convenient: these strings render on terminal surfaces only, and every surface that renders them is a session a person is sitting in, so a claim scoped to this session describes the only place the sentence appears rather than hedging around a falsehood. Unscoped it would not: a sentence whose subject is “Gaunt Sloth” and whose claim is that it always asks is false over the AG-UI server, which drives the agent itself and drains no approval interrupt ([[EXT-54]] — worth fixing on its own merits, never as a gate on this copy).

    The ACP server does ask, and that does not re-open this rule. It drives GthAgentRunner, registers a per-turn tool-approval callback and raises session/request_permission, so a human there really is asked. What it puts in front of them is assembled from the rater’s verdict, the matched approvals.escalate entry and the grant preview — never from APPROVAL_RUNG_DESCRIPTIONS or any other posture copy — so no string governed here renders on a server surface, and the ruling’s conclusion is untouched.

    That is also the boundary: the moment an approvals string is rendered by a server surface this ruling stops covering it, and the scoped sentence has to be re-earned there rather than inherited from here.

  3. assisted MUST keep the sentence saying files are still rewritten and deleted without asking — it sounds safer than it is, and that clause is the correction.

  4. A qualification may not live in the second sentence alone. The picker, the text fallback and the usage hint all render firstSentence and nothing else, so the opener is the whole message on the three surfaces a user reads while choosing a mode. An opener that sells a behavioural difference the product does not have is not rescued by a sentence two those surfaces never print — check a wording by rendering it, not by reading the constant.

  5. auto is the mode a reader most wants to hear is quiet, and it is not. It settles some risky commands with the rater instead of interrupting — that difference is real and may be stated — but the copy MUST also say that a bounded exchange ends at the user, and MUST NOT promise the user watches it happen. The rounds reach a person at the escalation, all of them at once, and nothing renders them before that ([[TUI-C26]]), so a sentence implying a live commentary would be describing a screen that does not exist.

  6. Every rated rung states a LIMIT ON USE in its opener, and recoverable is the word that carries it ([[CFG-48]]). A rated rung settles some risky commands without asking anyone, so the sentence offering it has to say what kind of work that is acceptable for — and a terminus is not a limit on use. “then asks you” and “anything riskier comes to you” say where the exchange ends; they do not say when the mode is a bad idea, which is what the three UNRATED rungs each say (“not a mode to leave running”, “a bounded stretch”, “a throwaway environment you would not mind losing”). Constraint 4 is why it must be the opener: the three surfaces a user chooses from print firstSentence and nothing else.

    “Unrated”, not “deterministic”, and the distinction is this file’s own. The complement of isRatedRung is {manual, write, bypass} — the rungs that consult no rater. That is NOT the set isDeterministicRung names, which is {manual, write}: bypass gates nothing at all, so it is not a rung that decides deterministically, it is the absence of a decision. Prose elsewhere in the repo calls the three “deterministic”; against the predicate exported a hundred lines below, that reading is wrong, so this constraint says “unrated” and means the complement.

    A lexical test watches the word, and its failure is not a false positive. “Carries a limit-on-use clause” has no mechanical predicate, so the rule names its own carrier token instead: packages/app/spec/tui/slashCommands.spec.ts“every rated rung’s opener says what kind of work it is for, and only the rated ones do” — takes the rated set from isRatedRung rather than a literal pair, so a sixth rated rung is required to carry a clause on the day it is added, and asserts the three unrated rungs do NOT carry the token, so that spreading recoverable across all five cannot satisfy it. Rewriting this copy is fine; dropping the word is the thing that must not happen quietly, because that is exactly how Auto’s cautionary clause was lost once already — in an ordinary rewrite that broke no test.

Everything these two sentences cannot hold lives at APPROVAL_PROTECTION_DOCS_URL, which the surfaces print beside the copy rather than each description repeating it.