一键导入
pending-approvals
Use when the user invokes approvals directly -- "ver pendientes", "aprobar P-XXXX", "rechazar P-XXXX", "approve P-", "reject P-"
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Use when the user invokes approvals directly -- "ver pendientes", "aprobar P-XXXX", "rechazar P-XXXX", "approve P-", "reject P-"
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
| name | pending-approvals |
| description | Use when the user invokes approvals directly -- "ver pendientes", "aprobar P-XXXX", "rechazar P-XXXX", "approve P-", "reject P-" |
| metadata | {"user-invocable":true,"type":"technique"} |
pending-approvals is the workflow the orchestrator follows when the user
drives an approval -- "ver pendientes", "aprobar P-XXXX", "rechazar P-XXXX".
Approvals are in-loop and single-session: a pending is raised and resolved
within the same session, and there is no proactive surfacing of it outside
that flow -- no [ACTIONABLE] block at SessionStart, no per-turn resurfacing.
The orchestrator's role here is to translate an explicit user ask into the
right gaia approvals subcommand against the right store. See "Approvals do
not resurface across sessions" below for what does and does not survive
cross-session.
For the universal envelope of an approval payload see agent-approval-protocol;
for how the orchestrator relays a subagent-initiated APPROVAL_REQUEST into
AskUserQuestion see orchestrator-present-approval -- that skill owns the
verbatim-COMANDO, [P-{nonce8}] label, and single-use grant discipline; this
skill does not restate them.
There are two stores for pending approvals, and the CLI subcommands do not cover them symmetrically. Misreading this surface is what makes the orchestrator report "rejected" when nothing actually changed.
| Subcommand | Store | Backed by |
|---|---|---|
gaia approvals pending | DB only | store.list_pending |
gaia approvals history | DB only | store.list_all |
gaia approvals approve P-xxx | DB only | store.approve |
gaia approvals revoke P-xxx | DB only | store.revoke (falls back to legacy) |
gaia approvals show P-xxx | DB first, then filesystem | cmd_show_v2 in bin/cli/approvals.py |
gaia approvals list | DB grants + filesystem pendings | cmd_list (mixed) |
gaia approvals reject NONCE | filesystem only | reject_pending in hooks/modules/security/approval_grants.py |
gaia approvals reject-all | filesystem only | loops reject_pending |
gaia approvals clean | DB (cross-session stale pendings) + filesystem | cmd_clean in bin/cli/approvals.py: calls store.list_pending(all_sessions=True), transitions every pending older than DEFAULT_PENDING_TTL_MINUTES (24 h) to revoked via store.revoke(), then calls cleanup_expired_grants for filesystem files |
The practical consequence: revoke is the DB-aware single-id verb; reject and
reject-all only touch the legacy filesystem queue. If you need to mark a DB
row as terminated, use revoke. Bulk DB cleanup currently has no first-class
CLI -- it requires a Python loop over store.revoke().
Pendings are in-loop: they are raised by a blocked T3 command in the current
session and expected to be resolved in that same session, by the user acting
on the block message or asking directly ("ver pendientes", "aprobar P-XXXX").
There is no automatic resumption surface -- no [ACTIONABLE] block injected
at SessionStart, no per-turn feed of verified pendings. If the user does not
act on a pending in the session where it was raised, it is not re-presented
later; it simply ages toward expiry.
Two things survive cross-session, and neither is surfacing:
gaia approvals clean (and the periodic grant-expiry sweep)
still drains orphaned pendings and expired grants regardless of which
session created them. This is housekeeping, not a resumption prompt to the
user -- it never asks "do you want to resume P-XXXX?".check_db_semantic_grant) is not
scoped to a single session_id, because the block -> approve -> re-dispatch
cycle can legitimately span the subagent's session and the orchestrator's
session inside the SAME user-facing turn. This is an implementation detail
of one in-loop approval, not a mechanism for reaching back into a prior
session's unresolved pendings.When the user explicitly asks to see pendings from another session (e.g.
gaia approvals pending --all-sessions), that is a deliberate, user-invoked
query -- distinct from proactive resurfacing, and still supported.
gaia approvals show P-XXXX -- cmd_show_v2 checks the DB row first,
then falls back to the filesystem pending. Either path returns the verbatim
command and the context fields.gaia approvals show P-XXXX to load the
verbatim command and context fields (cmd_show_v2 checks the DB then the
filesystem).AskUserQuestion following
orchestrator-present-approval -- 5 labeled fields and the [P-{nonce8}]
option label. The same presentation works for both stores; the nonce-prefix
matcher (activate_db_pending_by_prefix in
hooks/modules/security/approval_grants.py) covers DB rows and the legacy
path covers filesystem pendings."Approve", the ElicitationResult hook writes SHOWN + APPROVED
events and activates a single-use grant (5-minute TTL) in the current
session.reference.md
(preflight + recovery, mode per target).The grant is consumed at match -- the moment the retried command authorizes against the grant, before it executes -- not after the command finishes. This has two consequences:
The CLI gaia approvals approve P-XXXX is the explicit, user-invoked admin
path: it inserts APPROVED directly in the DB and does not create a
hook-side grant, so it does not trigger the approve-executes-automatically
flow above. Use it only when the user explicitly wants the CLI-only path
(audit, marking a row from a different session as decided). For any approval
that needs to execute the blocked command in this session, AskUserQuestion is
the only path that activates the grant and the automatic re-dispatch.
Single rejection has two routes; pick by which store owns the row.
gaia approvals revoke P-XXXX --yes -- store.revoke inserts a
REVOKED event and updates approvals.status to revoked.gaia approvals reject P-XXXX -- reject_pending
rewrites the JSON file with status: "rejected" (no rm, which would itself
be T3).Confirm to the user: "P-XXXX rechazado." If revoke returns not_found, fall
back to reject before declaring failure -- the row may have been a legacy
filesystem pending.
Offer bulk cleanup when the user says "limpia todos los pendings", "borra los
pendientes", or when the user explicitly checks gaia approvals pending --all-sessions and finds a backlog of orphaned rows. This is never something
the orchestrator surfaces proactively -- there is no SessionStart scan that
counts stale pendings and offers to clean them; the user has to ask, or to
have already looked.
gaia approvals reject-all -- bulk soft-reject across the filesystem queue.
Returns "0 rejected" when the queue is empty. Does not touch DB rows.gaia approvals clean -- the first-class cross-session bulk drain for stale
DB pendings: cmd_clean calls store.list_pending(all_sessions=True) and
transitions every pending older than 24 h (DEFAULT_PENDING_TTL_MINUTES) to
revoked via store.revoke(), then runs cleanup_expired_grants to clean
expired filesystem grant files. Runs without a T3 prompt (consent-reducing,
listed in CONSENT_REDUCING_SUBCOMMAND_EXCEPTIONS). This is hygiene, not
surfacing: it drains orphans without presenting them for resumption. Use it
when gaia approvals pending --all-sessions shows a backlog of stale rows.Do not report "bulk cleanup done" after reject-all alone -- it only clears
the filesystem queue. Run gaia approvals clean to drain the DB backlog, then
confirm with gaia approvals pending --all-sessions.
Do not offer reject-all when there are active same-session pendings the user
may still want to approve.
orchestrator-present-approval; this skill does not restate it.gaia approvals reject-all as a full cleanup -- it operates on the
filesystem queue only; DB rows survive the call. Use gaia approvals clean
to drain the DB backlog.revoke returns
not_found for filesystem-only pendings; the inverse happens for reject on
DB rows. Pick the verb by store, or be ready to fall back.[ACTIONABLE]
block or a per-turn feed -- that surfacing no longer exists. A pending not
resolved in the session where it was raised is not re-presented; only an
explicit user query (gaia approvals pending --all-sessions) or the
hygiene sweep (gaia approvals clean) touches it afterward.rm on a pending-*.json file -- deletion itself is T3 and blocks.
The legacy soft-reject path rewrites the file in place; use it.For the dispatch template (preflight, recovery, mode selection) and the
filesystem pending JSON schema, read reference.md.
Use when constructing or interpreting the approval handoff envelope between subagent and orchestrator -- sealed_payload schema, approval_id format, APPROVAL_REQUEST contract shape, and reading a granted approval from the DB
Use when producing any agent response
Use when classifying any operation before executing it, or deciding whether user approval is required
Use when a mutative command was blocked by the hook and you need to request user approval, or when presenting a plan for a T3 operation before executing it
Use when the user wants to build, design, or extend a diagram — an architecture overview, a timeline, a planner board, a flow diagram, a presentation, a comparison, or a mind-map — as a portable, data-driven deck rendered from plain YAML. Triggers — "build a diagram", "architecture diagram", "diagram deck", "timeline", "flow diagram", "planner board", "add a page/section/component to the diagram".
Use when the user wants something to run routinely / on a schedule rather than once now -- "tarea programada", "rutinariamente", "cada mañana", "cada N horas", "todas las noches", "schedule", "cron". Covers mounting, structuring, and running an unattended headless task that reports back, plus consuming its reports. NOT for a live in-session agentic loop (that is agentic-loop).