Files
pragent/README.md
T
Marcos 789fb38bae pilot: central webhook service (user-level Gitea webhook + AI-REVIEW gate)
- pilot/webhook_server.py: stdlib HTTP receiver. HMAC-verifies X-Gitea-Signature,
  gates on pull_request action + AI-REVIEW label, runs review_pr in a background
  thread (responds 202 immediately so Gitea's delivery timeout never fires).
  Accepts both GitHub-style (labeled/synchronize) and Gitea event-type-style
  (label_updated/synchronized) action names.
- pilot/ai_review.py: extract review_pr() core so both the CI run() and the
  webhook server share one review path. run() is now an env-driven wrapper.
- pilot/README-webhook.md: architecture, onboarding, one-time per-owner
  user-webhook setup, the Gitea 1.26.1 system-webhook bug, the SSRF
  ALLOWED_HOST_LIST change, K8s deploy + script-update recipe.
- README.md + design doc: note the webhook service as the preferred delivery
  path (partially reverses 'central webhook = non-goal', pilot only).

Gitea 1.26.1 system webhooks broken (POST /admin/hooks -> 201 but never
persists); user-level webhooks (one per repo-owner) are the working fallback.
Gitea SSRF allow-list blocks in-cluster webhook targets by default; required a
scoped [webhook] ALLOWED_HOST_LIST addition + gitea restart.

E2E verified 2026-08-17: pragent-bot reviewed gitea_admin/pragent PR #2 and
masi/portfolio PR #3 via the webhook service (glm-5.2:cloud).

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-17 19:38:07 +00:00

99 lines
4.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# pragent
An extensible, forge-agnostic PR review framework. Not a product — a toolkit that teams
extend with their own review dimensions.
**Status:** design approved; framework build deferred. A **pilot** is live on
`glm-5.2:cloud` with two delivery paths:
- **Central webhook service** (preferred, least per-repo setup): a Gitea
user-level webhook posts PR events to an always-on in-cluster service that
gates on the `AI-REVIEW` label. Onboarding a repo = add `pragent-bot`
collaborator + create the label + label a PR. See
[`pilot/README-webhook.md`](pilot/README-webhook.md).
- **CI-step** (legacy): a per-repo Gitea Action fetches the reviewer script at
runtime. See [`pilot/README.md`](pilot/README.md).
The framework design remains at
[`docs/plans/2026-08-04-pragent-design.md`](docs/plans/2026-08-04-pragent-design.md);
the pilot is its bootstrap and will be superseded by `pragent review` when the
framework build resumes.
## What it is
`pragent` runs as a CI step. It reads a pull request, decides how much attention the
change deserves, runs the analyzers that apply, and posts ranked findings back to the
forge.
```
pragent init # one-time repo scan → .pragent/profile.yml (committed, reviewable)
pragent review # the CI step: tier → analyze → aggregate → publish
pragent explain # why did this PR get this tier / these findings?
pragent replay # re-run a past PR against a new prompt or model (the eval loop)
pragent doctor # config, credentials, and adapter health
```
## Why not CodeRabbit / Greptile / Qodo
Those are good products with fixed review dimensions and per-seat pricing. `pragent`
targets the case where a platform team needs to **add its own dimensions** — an internal
compliance rule, a service-catalog ownership check, a house performance idiom — without
forking a vendor's reviewer. Cost lands in the same range (~$25/dev/month at 350 PRs/mo
for 20 devs), but the analyzers, the data, and the analytics are yours.
## Attention tiers
Every PR is classified before any expensive work happens. Deterministic rules decide
first; an ambiguous case gets one cheap model call as tie-breaker.
| Tier | What it means | Cost/PR |
|---|---|---|
| `trivial` | lockfile bumps, generated code, docs typos | ~$0.005 |
| `lite` | small change, no risk paths | ~$0.08 |
| `full` | the default for real changes | ~$0.802.00 |
| `oversized` | too big to review whole; structural summary + deep pass on the hot subset | ~$5 ceiling |
Every tier decision records *why*, so a surprising outcome is explainable rather than
mysterious.
## Extension points
Five, all documented in the design doc. Teams override or add; nobody forks.
1. **Analyzers** — drop a YAML + prompt in `.pragent/analyzers/`, or install from npm
2. **Forge adapters** — Gitea, GitLab, GitHub, local diff
3. **Tier policy** — thresholds and the path risk map, per repo or per org
4. **Profile enrichers** — extend what `pragent init` learns about a repo
5. **Emitter sinks** — JSONL by default, OpenTelemetry, or your own
Org config can lock keys, so a repo cannot quietly disable the security analyzer.
## Design principles
- **Polyglot by construction.** Language knowledge lives in the repo profile, not in the
reviewer. A new language is a profile change, not a core change.
- **One shared prompt prefix.** All analyzers for a PR share a byte-identical cached
prefix. This is what makes fan-out affordable; it is enforced, not hoped for.
- **Everything is traceable.** Tier reasons, token counts, cost, latency, and finding
outcomes are recorded per run. False-positive rate is measurable per analyzer.
- **Fail open.** A budget ceiling or an analyzer crash yields a partial review with a
clear note, never a blocked pipeline with no explanation.
## Stack
TypeScript + Node, built on the [`pi`](https://github.com/badlogic/pi-mono) agent SDK.
Shipped as an npm package and an OCI image, so CI runners need no local Node install.
## Roadmap
1. Walking skeleton — local diff, one analyzer, rules-only tiering
2. Gitea end to end — adapter, Woodpecker step, PR comments, status checks
3. Profile + full tier — `pragent init`, shared-prefix caching, analyzer fan-out
4. Extensibility hardening — plugin loading, config layering, `explain` / `replay`
5. Second forge — GitLab adapter, Jenkins recipe
6. Analytics maturity — OTel export, feedback loop, eval harness
## License
TBD.