feat: initial agent-reviewer meta-agent

A2A agent that audits another deployed agent's source pre-deploy.
Reads the target Gitea repo via a short-lived read-only token minted
through ctx.mint_gitea_token(), runs an inner DeepAgents graph backed
by GiteaBackend, and emits a typed ReviewReport.

Skill bundles:
- security-anti-patterns (credentials, eval, sandbox bypass, egress)
- a2apack-best-practices (class shape, decorators, types, timeouts)
- grant-scope-evaluation (declared vs actual workspace scope)

Tools:
- sandbox_a2a_card  : round-trips the project through microsandbox
- sandbox_ruff_check: objective static checks
- submit_review_report: typed final report

7 smoke tests pass; agent card loads cleanly via `a2a card`.
This commit is contained in:
robert
2026-05-28 09:59:40 -03:00
commit 64a601a85a
17 changed files with 1065 additions and 0 deletions

View File

@@ -0,0 +1,75 @@
---
name: a2apack-best-practices
description: Shape of a well-formed A2A Pack agent. Use when reviewing agent.py for class structure, @skill decorators, type hints, error handling, idempotency, and timeouts.
---
# A2A Pack Best Practices
Use this skill when reviewing the *shape* of an agent — not its security
posture (that's `security-anti-patterns`) and not its grants (that's
`grant-scope-evaluation`).
## Class contract
* The class must inherit from `A2AAgent[ConfigT, AuthT]` with concrete
generic parameters. Missing parameters → `warning`.
* Class variables `name`, `description`, `version` must be set. Missing →
`warning`. `description` shorter than ~30 chars → `info`.
* `config_model` and `auth_model` must reference declared Pydantic
models (or `NoAuth`). A mismatched generic and class var → `warning`.
## @skill decorators
* Every public skill should declare `description`. Missing → `warning`.
* `timeout_seconds` should be set explicitly. Default is short; long-running
skills that omit it will time out in production. Missing on a skill that
does file work, LLM calls, or sandbox exec → `warning`.
* `stream=True` is required if the skill calls `ctx.emit_progress`,
`ctx.ask`, `ctx.collect`, or `ctx.request_scope`. Missing while the body
does emit → `critical`.
* `idempotent=True` matters for skills that can be safely retried. Skills
that write files, mutate state, or charge money → `info` if not set
explicitly (either direction is fine, just be intentional).
## Type hints
* Every skill parameter must have a concrete type hint (no `Any`, no missing
annotation). The Card's `input_schema` is built from these. Missing → `warning`.
* Return type should be `dict[str, Any]`, a concrete Pydantic model, or `str`.
Returning untyped values surprises callers → `info`.
## Error handling
* Skills should return structured error dicts (e.g. `{"error": "..."}`), not
raise unhandled exceptions for *expected* failure modes (bad input, missing
workspace, timeouts). Bare `raise` for invalid input → `info`.
* `try/except Exception` that swallows the error without logging or returning
`warning`.
## ctx.workspace / ctx.sandbox usage
* If the skill calls `ctx.workspace_backend()`, the class must declare
`workspace_access = WorkspaceAccess.dynamic(...)`. Mismatch → `critical`.
* Subprocesses that produce user-visible files must run through
`ctx.workspace_shell` or `ctx.workspace_python`, not raw
`asyncio.create_subprocess_exec`. Already covered in
`security-anti-patterns` but worth a second look here.
## Recursion limits
* If the skill invokes a DeepAgents graph via `ainvoke` or `astream_events`,
it must pass `config={"recursion_limit": 500}` to match agent-builder.
Missing → `warning`.
## Manifest (a2a.yaml)
* `name` must match the agent's `name` class var. Mismatch → `critical`.
* `entrypoint` must point at a real `module:Class`. Stub or broken → `critical`.
* `version` should be semantic (major.minor.patch). Bad shape → `info`.
## Severity rubric (specific to this skill)
* `critical` — breaks the runtime contract (stream/emit mismatch, manifest
doesn't import, name disagreement).
* `warning` — works today but degrades the developer or caller experience
(no timeout, no type hint, bare raise).
* `info` — style nudges.