# 0x-rekt/perchly architecture

> Architecture diagram of the GitHub repository 0x-rekt/perchly, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-09-27). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/0x-rekt/perchly
- Repository: https://github.com/0x-rekt/perchly

## Overview

Perchly is a GitHub App–based AI pull-request review system. GitHub PR events enter the webhook API, which filters and deduplicates events before starting a durable Temporal review. The review retrieves repository context, runs four specialist checks, aggregates findings, and applies posting policy; uncertain results wait for human approval before publication. The React console supports queue decisions and fix-PR previews, and exposes review-run and observability views. PostgreSQL-backed queue, tenant, and telemetry state supports these flows. The README documents the major capabilities; sampled source confirms key entry points, while unsampled wiring is represented only where documented.

Main entry points: [`server/app/temporal/activities.py`](https://github.com/0x-rekt/perchly/blob/main/server/app/temporal/activities.py) (Review activities), [`server/app/routers/reviews.py`](https://github.com/0x-rekt/perchly/blob/main/server/app/routers/reviews.py) (Review routes), [`server/app/main.py`](https://github.com/0x-rekt/perchly/blob/main/server/app/main.py) (FastAPI application), [`server/app/services/review_queue.py`](https://github.com/0x-rekt/perchly/blob/main/server/app/services/review_queue.py) (Review queue)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_ingestion["Event intake"]
  node_webhook["Webhook API<br/>[github_webhooks.py]"]
  node_idempotency["Delivery deduplication<br/>[idempotency.py]"]
  node_temporal_client["Temporal client<br/>[client.py]"]
end

subgraph group_review["Review execution"]
  node_workflow["Review workflow<br/>[workflows.py]"]
  node_activities["Review activities<br/>[activities.py]"]
  node_retrieval["Context retrieval<br/>[retrieval.py]"]
  node_github_api["GitHub API client<br/>[github_api.py]"]
  node_specialists["Specialist agents"]
  node_aggregation["Finding aggregation<br/>[aggregation.py]"]
  node_routing["Posting policy<br/>[routing.py]"]
end

subgraph group_decisions["Decisions and fixes"]
  node_queue_service["Review queue<br/>[review_queue.py]"]
  node_fix_service["Fix PR service<br/>[fix_pr.py]"]
end

subgraph group_platform["API and state"]
  node_api["FastAPI application<br/>[main.py]"]
  node_review_routes["Review routes<br/>[reviews.py]"]
  node_postgres[("PostgreSQL")]
  node_telemetry["Telemetry service<br/>[telemetry.py]"]
end

subgraph group_console["Web console"]
  node_web_app["React console<br/>[App.tsx]"]
  node_queue_ui["Approval queue UI<br/>[QueuePage.tsx]"]
  node_review_detail["Review detail<br/>[ReviewDetail.tsx]"]
  node_observability_ui["Observability views<br/>[Overview.tsx]"]
  node_runs_ui["Review runs<br/>[ReviewRuns.tsx]"]
end

node_github(("GitHub"))
node_temporal["Temporal service"]
node_gemini{{"Gemini"}}

node_github -->|"sends PR events"| node_webhook
node_webhook -->|"claims delivery"| node_idempotency
node_webhook -->|"starts review"| node_temporal_client
node_temporal_client -->|"starts workflow"| node_temporal
node_temporal -->|"runs durably"| node_workflow
node_workflow -->|"dispatches steps"| node_activities
node_activities -->|"fetches PR data"| node_github_api
node_activities -->|"builds context"| node_retrieval
node_retrieval -.->|"retrieves context"| node_postgres
node_activities -->|"runs checks"| node_specialists
node_specialists -->|"requests analysis"| node_gemini
node_activities -->|"aggregates results"| node_aggregation
node_activities -->|"applies policy"| node_routing
node_activities -->|"posts review"| node_github_api
node_routing -->|"queues uncertain reviews"| node_queue_service
node_queue_service -->|"stores decisions"| node_postgres
node_workflow -->|"records outcomes"| node_queue_service
node_api -->|"mounts routes"| node_review_routes
node_review_routes -->|"reads queue"| node_queue_service
node_review_routes -->|"signals decisions"| node_temporal_client
node_review_routes -->|"creates fix PR"| node_fix_service
node_review_routes -->|"opens GitHub PR"| node_github_api
node_fix_service -->|"creates branch and PR"| node_github_api
node_api -->|"initializes and refreshes"| node_telemetry
node_telemetry -->|"persists spans"| node_postgres
node_web_app -->|"routes queue"| node_queue_ui
node_web_app -->|"routes overview"| node_observability_ui
node_web_app -->|"routes runs"| node_runs_ui
node_queue_ui -->|"opens review"| node_review_detail
node_review_detail -->|"submits decisions"| node_review_routes
node_review_detail -->|"requests fix PR"| node_review_routes
node_observability_ui -->|"loads metrics"| node_api
node_runs_ui -->|"loads traces"| node_api

click node_webhook "https://github.com/0x-rekt/perchly/blob/main/server/app/routers/github_webhooks.py"
click node_idempotency "https://github.com/0x-rekt/perchly/blob/main/server/app/services/idempotency.py"
click node_temporal_client "https://github.com/0x-rekt/perchly/blob/main/server/app/temporal/client.py"
click node_workflow "https://github.com/0x-rekt/perchly/blob/main/server/app/temporal/workflows.py"
click node_activities "https://github.com/0x-rekt/perchly/blob/main/server/app/temporal/activities.py"
click node_retrieval "https://github.com/0x-rekt/perchly/blob/main/server/app/services/retrieval.py"
click node_github_api "https://github.com/0x-rekt/perchly/blob/main/server/app/services/github_api.py"
click node_specialists "https://github.com/0x-rekt/perchly/tree/main/server/app/agents"
click node_aggregation "https://github.com/0x-rekt/perchly/blob/main/server/app/services/aggregation.py"
click node_routing "https://github.com/0x-rekt/perchly/blob/main/server/app/services/routing.py"
click node_api "https://github.com/0x-rekt/perchly/blob/main/server/app/main.py"
click node_review_routes "https://github.com/0x-rekt/perchly/blob/main/server/app/routers/reviews.py"
click node_queue_service "https://github.com/0x-rekt/perchly/blob/main/server/app/services/review_queue.py"
click node_fix_service "https://github.com/0x-rekt/perchly/blob/main/server/app/services/fix_pr.py"
click node_telemetry "https://github.com/0x-rekt/perchly/blob/main/server/app/services/telemetry.py"
click node_web_app "https://github.com/0x-rekt/perchly/blob/main/web/src/App.tsx"
click node_queue_ui "https://github.com/0x-rekt/perchly/blob/main/web/src/components/queue/QueuePage.tsx"
click node_review_detail "https://github.com/0x-rekt/perchly/blob/main/web/src/components/queue/ReviewDetail.tsx"
click node_observability_ui "https://github.com/0x-rekt/perchly/blob/main/web/src/components/observability/Overview.tsx"
click node_runs_ui "https://github.com/0x-rekt/perchly/blob/main/web/src/components/observability/ReviewRuns.tsx"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_webhook,node_idempotency,node_temporal_client toneBlue
class node_workflow,node_activities,node_retrieval,node_github_api,node_specialists,node_aggregation,node_routing toneAmber
class node_queue_service,node_fix_service toneMint
class node_api,node_review_routes,node_postgres,node_telemetry toneRose
class node_web_app,node_queue_ui,node_review_detail,node_observability_ui,node_runs_ui,node_github,node_temporal,node_gemini toneIndigo
```

## Components

### Event intake

- [Webhook API](https://github.com/0x-rekt/perchly/blob/main/server/app/routers/github_webhooks.py): `server/app/routers/github_webhooks.py`
- [Delivery deduplication](https://github.com/0x-rekt/perchly/blob/main/server/app/services/idempotency.py): `server/app/services/idempotency.py`
- [Temporal client](https://github.com/0x-rekt/perchly/blob/main/server/app/temporal/client.py): `server/app/temporal/client.py`

### Review execution

- [Review workflow](https://github.com/0x-rekt/perchly/blob/main/server/app/temporal/workflows.py): `server/app/temporal/workflows.py`
- [Review activities](https://github.com/0x-rekt/perchly/blob/main/server/app/temporal/activities.py): `server/app/temporal/activities.py`
- [Context retrieval](https://github.com/0x-rekt/perchly/blob/main/server/app/services/retrieval.py): `server/app/services/retrieval.py`
- [GitHub API client](https://github.com/0x-rekt/perchly/blob/main/server/app/services/github_api.py): `server/app/services/github_api.py`
- [Specialist agents](https://github.com/0x-rekt/perchly/tree/main/server/app/agents): `server/app/agents`
- [Finding aggregation](https://github.com/0x-rekt/perchly/blob/main/server/app/services/aggregation.py): `server/app/services/aggregation.py`
- [Posting policy](https://github.com/0x-rekt/perchly/blob/main/server/app/services/routing.py): `server/app/services/routing.py`

### Decisions and fixes

- [Review queue](https://github.com/0x-rekt/perchly/blob/main/server/app/services/review_queue.py): `server/app/services/review_queue.py`
- [Fix PR service](https://github.com/0x-rekt/perchly/blob/main/server/app/services/fix_pr.py): `server/app/services/fix_pr.py`

### API and state

- [FastAPI application](https://github.com/0x-rekt/perchly/blob/main/server/app/main.py): `server/app/main.py`
- [Review routes](https://github.com/0x-rekt/perchly/blob/main/server/app/routers/reviews.py): `server/app/routers/reviews.py`
- **PostgreSQL**
- [Telemetry service](https://github.com/0x-rekt/perchly/blob/main/server/app/services/telemetry.py): `server/app/services/telemetry.py`

### Web console

- [React console](https://github.com/0x-rekt/perchly/blob/main/web/src/App.tsx): `web/src/App.tsx`
- [Approval queue UI](https://github.com/0x-rekt/perchly/blob/main/web/src/components/queue/QueuePage.tsx): `web/src/components/queue/QueuePage.tsx`
- [Review detail](https://github.com/0x-rekt/perchly/blob/main/web/src/components/queue/ReviewDetail.tsx): `web/src/components/queue/ReviewDetail.tsx`
- [Observability views](https://github.com/0x-rekt/perchly/blob/main/web/src/components/observability/Overview.tsx): `web/src/components/observability/Overview.tsx`
- [Review runs](https://github.com/0x-rekt/perchly/blob/main/web/src/components/observability/ReviewRuns.tsx): `web/src/components/observability/ReviewRuns.tsx`

### Other components

- **GitHub**
- **Temporal service**
- **Gemini**

## Connections

- GitHub → Webhook API: sends PR events
- Webhook API → Delivery deduplication: claims delivery
- Webhook API → Temporal client: starts review
- Temporal client → Temporal service: starts workflow
- Temporal service → Review workflow: runs durably
- Review workflow → Review activities: dispatches steps
- Review activities → GitHub API client: fetches PR data
- Review activities → Context retrieval: builds context
- Context retrieval → PostgreSQL: retrieves context
- Review activities → Specialist agents: runs checks
- Specialist agents → Gemini: requests analysis
- Review activities → Finding aggregation: aggregates results
- Review activities → Posting policy: applies policy
- Review activities → GitHub API client: posts review
- Posting policy → Review queue: queues uncertain reviews
- Review queue → PostgreSQL: stores decisions
- Review workflow → Review queue: records outcomes
- FastAPI application → Review routes: mounts routes
- Review routes → Review queue: reads queue
- Review routes → Temporal client: signals decisions
- Review routes → Fix PR service: creates fix PR
- Review routes → GitHub API client: opens GitHub PR
- Fix PR service → GitHub API client: creates branch and PR
- FastAPI application → Telemetry service: initializes and refreshes
- Telemetry service → PostgreSQL: persists spans
- React console → Approval queue UI: routes queue
- React console → Observability views: routes overview
- React console → Review runs: routes runs
- Approval queue UI → Review detail: opens review
- Review detail → Review routes: submits decisions
- Review detail → Review routes: requests fix PR
- Observability views → FastAPI application: loads metrics
- Review runs → FastAPI application: loads traces
