# pragent pilot The pilot is a central, stdlib-only Gitea webhook service. It reviews opted-in pull requests with an on-network model, posts inline findings, and emits review telemetry to Langfuse. The service is fail-open: a review failure is reported as a PR comment and does not block CI. ## Runtime flow 1. Gitea sends a signed `pull_request` webhook. 2. `webhook_server.py` validates the request, checks the base branch's `.pr-review.json` for `"enabled": true`, and claims `(repo, PR, SHA)`. 3. `ai_review.review_pr()` fetches the diff, trusted config, and prior reviews. 4. `opencode_review.py` checks out the PR head in a sanitized temporary directory and runs the review agent. The legacy Ollama-compatible path is still available through `PRAGENT_ENGINE`. 5. The review output is parsed and normalized, valid post-change line anchors are separated from summary-only findings, and Gitea receives the result. 6. `langfuse_trace.py` records usage, cost basis, findings, and evaluation scores when Langfuse credentials are configured. ## Module map | Module | Responsibility | |---|---| | `webhook_server.py` | HTTP ingress, signature verification, opt-in gate, concurrency | | `review_config.py` | Trusted base-branch opt-in policy; transport injected for tests | | `gitea_client.py` | HTTP transport adapter and repository-scoped client | | `ai_review.py` | Compatibility facade and review orchestration | | `model_client.py` | Anthropic-compatible model adapter and response text extraction | | `opencode_review.py` | Hostile-checkout containment and agent execution | | `diff_compress.py` | Diff compression and prior-review extraction | | `feedback*.py` | Feedback persistence, harvesting, analysis, and Langfuse scores | | `langfuse_trace.py` | Fail-open Langfuse ingestion and cost metadata | | `cost_model.py` | Provider price catalog and equivalent-cost calculations | | `eval_*.py` | Dataset bootstrap, evaluators, and behavioral scoring | `ai_review.py` remains the stable import surface for existing workflow and webhook deployments. New code should put policy, adapters, and pure transforms in the focused modules above rather than adding unrelated functions there. ## Onboard a repository 1. Add `pragent-bot` as a Write collaborator. 2. Commit this file to the default branch: ```json {"enabled": true} ``` 3. Open or update a pull request. No per-repository workflow, secret, or label is required for the central webhook path. See [`README-webhook.md`](README-webhook.md) for deployment, security, and webhook registration details. ## Configuration | Variable | Default | Purpose | |---|---:|---| | `GITEA_API` | in-cluster URL | Gitea API base URL | | `PRAGENT_BOT_TOKEN` | — | Bot credential | | `OLLAMA_URL` / `OLLAMA_MODEL` | headroom / `glm-5.2:cloud` | Legacy model path | | `PRAGENT_ENGINE` | `opencode` | `opencode` or legacy model path | | `DIFF_MAX_CHARS` | `150000` | Diff input cap | | `PRAGENT_MAX_CONCURRENT_REVIEWS` | `2` | Process concurrency bound | | `LANGFUSE_HOST` + keys | unset | Enables telemetry; unset is a no-op | ## Tests ```bash python3 -m pytest tests -q ``` Tests use mocked transports and local fixtures. They do not require Gitea, Langfuse, a model endpoint, or network access.