Originally created by: sosidudku1
The five-step approval ladder (#97, [#100]) is a standing global posture: an operator picks one level for the whole session. There is no way to make a targeted, temporary exception ("I trust git this session") without permanently raising the level for a whole category. [#79] asks for exactly this at the prompt itself, and notes a session-scoped grant is a safer default than a durable global toggle.
The approval prompt now offers, on top of y/n: s (allow this category for the session) and a (allow this shell command shape, i.e. the binary). Grants live in-memory on the ApprovalGate, are checked after the standing level and before a prompt is emitted, and are dropped on every session change. Pressing s/a drops a confirmation line into the transcript ("granted: shell command for this session") so the operator sees the grant land. Offered on the TUI modal and the CLI run stdin prompt; Telegram keeps per-request approval only.
Grants never bypass the two hard limits. Hardline shell-guard rules return block in shell.ts before the gate is reached, so no grant can unblock a catastrophic command (rm -rf / stays blocked even with shell/rm granted). trust_config (config.json / .env) is never grantable on either the record or the auto-approve path, so the agent cannot silence a write that raises its own trust for the next boot.
Honest boundary: the trust_config guard covers the fs tools (categorizeFsMutation), not the shell. A write to config via a shell redirect (echo >> config.json) stays under the shell category and is silenced by a shell grant, the same as at standing level 4. Grants do not widen this pre-existing class; closing it means intercepting shell redirects, a separate piece of work.
Grants are in-memory only, never persisted, and TUI/CLI-local (never granted from a remote Telegram channel).
Unit tests for the gate (grant category / shape / trust_config-refused / clear / no-shape), the grant-eligibility helper, the modal option rendering, key routing, and the grant-confirmation message; two end-to-end bootstrap.test.ts cases through the real runtime and real shell guard (category grant silences later shell while rm -rf / stays hardline-blocked; shape grant silences one binary while another still prompts). Full suite delta versus origin/main is zero new failures.
Closes [#79] - both halves are now done: the standing ladder (#97/#100) and the prompt-side session grants (this PR).
Surface active session grants on the Privacy panel with a one-key clear, for at-a-glance visibility of raised point exceptions. The gate already exposes sessionGrants() for this.
Ticket changed by: sosidudku1