The quarantine digest
What happens to a call that scores between 3.0 and 8.0, who answers it, and what happens if nobody does.
A call that scores above 3.0 but not above 8.0 is neither clearly safe nor clearly hostile, so grith does not guess. It holds the calling thread at its kernel stop, writes the call to the digest queue, and asks you.
Resolution is real-time and blocking. There is no batching, no schedule, no delivery interval: the syscall is paused until somebody answers or the review times out.
What is held, and what is not
Only the thread that made the syscall. Its siblings keep running - a Node-based agent carries on rendering its UI while the prompt is on screen. grith does not stop the process tree.
That matters both ways. It keeps a supervised tool responsive, and it means a multi-threaded tool can do other work on other threads while a decision is pending.
Who does the asking
In an interactive grith exec session, the prompt is an overlay in the terminal:
| Key | Action |
|---|---|
a | Allow this request; the exact target stays allowed for this session. |
d | Block it; identical retries are blocked without asking again for 60 seconds. |
l | Allow and save a permanent rule for this exact target. Sensitive targets are never saved. |
s | Allow a directory, for the operations you pick, this session only. |
b | Block a directory for the rest of the session - no more prompts for it. |
t | Deny and stop the supervised tool. |
i | Show the raw arguments and the request id. |
esc | Deny this request. |
s and b are offered only when a scope makes sense for the call. A call that was
denied outright - scored above 8.0 - is shown as a read-only record of what was blocked,
with no actions on it.
Nothing here outlives the session unless you saved it with l.
The dashboard at http://127.0.0.1:3141 shows the same queue live, and
grith digest review walks it from the terminal.
If a prompt is still waiting after about 15 seconds, grith raises a desktop notification and the dashboard updates live.
When the answer never comes
The review timeout is 300 seconds (supervisor.freeze_timeout_seconds). On expiry
the queue does one final re-read - so an answer given elsewhere in the last moment is not
stomped - and then records the item as denied with the action auto_deny_timeout.
A timeout is treated exactly like a deny: the held syscall returns EPERM and the thread
resumes. The process is not killed unless you explicitly chose deny-and-terminate.
Headless sessions fail closed
With no terminal and no dashboard overlay there is nobody to answer, so grith does not
wait 300 seconds to find out. A queued call in a non-interactive session is denied
immediately and recorded as informational, with a log line telling you the three ways
out: allowlist it in the profile, run with a terminal, or pass --allow-queued.
--allow-queued flips that to allow-and-log - except for calls that were queued
because of containment or taint. Those still fail closed.
⚠️This is the usual CI surprise
A pipeline step that legitimately runs docker build under grith exec will be denied,
because the delegating spawn escalates into the queue band and there is no reviewer. See
running in CI.
Short-circuits that resolve a call without asking
Four things can settle a queued call before a prompt is ever raised:
- Deny replay. An identical call denied within the last 60 seconds is denied again.
- Approve replay. An identical call approved within the last 60 seconds is allowed again - disabled while containment is active, and it earns no reputation credit, so a loop cannot launder trust.
- Control-socket replay. An answer about a session D-Bus, X11 or tmux connection is remembered for the session. This one is not disabled under containment.
- Scope drain. If a grant you made on another prompt now covers this target, the call resolves against it with none of the side effects of a manual approval.
What is stored
The queue is its own SQLite database next to the audit log. Each item holds the call type, an argument summary, the decision reason, the composite score, the full filter breakdown, and - once resolved - the action taken and who took it. Where a DLP filter matched, the argument summary is redacted before it is written.
Items are Pending, Approved, Denied, Expired or Escalated. Only pending and
escalated items are actionable, and informational items never are.
ℹ️The `[digest]` config block does nothing
interval_active, interval_idle, delivery and max_queue_size parse and are never
read. There is no scheduled or batched delivery to configure.