# carreromarcos/pr-reviewer architecture

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

- Interactive diagram: https://gitdiagram.com/carreromarcos/pr-reviewer
- Repository: https://github.com/carreromarcos/pr-reviewer
- Video tour (about a minute): https://gitdiagram.com/carreromarcos/pr-reviewer/video

## Overview

PR Reviewer is an AWS serverless GitHub bot: webhook intake queues review jobs; a worker fetches and reviews the diff, then safely creates or updates one canonical PR comment. It also runs an experimental multi-agent review in shadow mode, archives reviews for replay, and provides a token-gated browser viewer. Edges follow the README and SOURCE INDEX references; unsampled implementation details are not inferred beyond those references.

Main entry points: [`lambda/worker_handler.py`](https://github.com/carreromarcos/pr-reviewer/blob/main/lambda/worker_handler.py) (Review worker), [`lambda/common/fanout.py`](https://github.com/carreromarcos/pr-reviewer/blob/main/lambda/common/fanout.py) (Shadow multi-agent panel), [`lambda/common/assemble.py`](https://github.com/carreromarcos/pr-reviewer/blob/main/lambda/common/assemble.py) (Payload and comment assembly), [`lambda/common/archive.py`](https://github.com/carreromarcos/pr-reviewer/blob/main/lambda/common/archive.py) (Review archive)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_intake["Webhook intake"]
  node_ingress["Webhook ingress<br/>[ingress_handler.py]"]
  node_queue["Work queue"]
end

subgraph group_review["Review pipeline"]
  node_worker["Review worker<br/>[worker_handler.py]"]
  node_config["Runtime configuration<br/>[config.py]"]
  node_diff["Diff retrieval<br/>[diff.py]"]
  node_assembly["Payload and comment assembly<br/>[assemble.py]"]
  node_validation["Publication validation<br/>[validate.py]"]
  node_llm["Single-pass model client<br/>[llm.py]"]
  node_prompts["Review prompts<br/>[system_prompt.md]"]
  node_panel["Shadow multi-agent panel<br/>[fanout.py]"]
  node_findings["Finding schema<br/>[findings.py]"]
  node_events["Review stage events<br/>[events.py]"]
end

subgraph group_state["Fencing and storage"]
  node_state_store[("Review state")]
  node_state_codec["State codec<br/>[state.py]"]
  node_protocol["Fenced executor<br/>[protocol.py]"]
  node_reconcile["Comment reconciliation<br/>[reconcile.py]"]
  node_marker["Canonical marker<br/>[marker.py]"]
end

subgraph group_replay["Archive and replay"]
  node_archive["Review archive<br/>[archive.py]"]
  node_s3[("S3 storage")]
  node_viewer["Archive viewer handler<br/>[viewer_handler.py]"]
  node_browser["Review browser<br/>[review.js]"]
end

node_github(("GitHub"))
node_ssm[("AWS Parameter Store")]

node_github -->|"sends webhook"| node_ingress
node_ingress -->|"enqueues job"| node_queue
node_queue -->|"dispatches job"| node_worker
node_worker -->|"loads configuration"| node_config
node_worker -->|"fetches diff"| node_diff
node_worker -->|"requests review"| node_llm
node_worker -->|"assembles comment"| node_assembly
node_assembly -->|"validates output"| node_validation
node_assembly -->|"renders diff"| node_diff
node_worker -->|"runs shadow review"| node_panel
node_panel -->|"dispatches model calls"| node_llm
node_panel -->|"handles findings"| node_findings
node_panel -->|"emits stage events"| node_events
node_worker -->|"records review stages"| node_events
node_worker -->|"executes fenced publish"| node_protocol
node_protocol -->|"uses expressions"| node_state_codec
node_worker -->|"reads and updates state"| node_state_store
node_worker -->|"converges comments"| node_reconcile
node_reconcile -->|"uses update expressions"| node_state_codec
node_worker -->|"builds comment marker"| node_marker
node_worker -->|"fetches and publishes"| node_github
node_worker -->|"archives review"| node_archive
node_archive -->|"stores reviews"| node_s3
node_archive -->|"uses event schema"| node_events
node_viewer -->|"serves archived review"| node_s3
node_browser -->|"requests replay"| node_viewer
node_worker -->|"hydrates credentials"| node_ssm
node_llm -.->|"uses review instructions"| node_prompts

click node_ingress "https://github.com/carreromarcos/pr-reviewer/blob/main/lambda/ingress_handler.py"
click node_worker "https://github.com/carreromarcos/pr-reviewer/blob/main/lambda/worker_handler.py"
click node_config "https://github.com/carreromarcos/pr-reviewer/blob/main/lambda/common/config.py"
click node_diff "https://github.com/carreromarcos/pr-reviewer/blob/main/lambda/common/diff.py"
click node_assembly "https://github.com/carreromarcos/pr-reviewer/blob/main/lambda/common/assemble.py"
click node_validation "https://github.com/carreromarcos/pr-reviewer/blob/main/lambda/common/validate.py"
click node_llm "https://github.com/carreromarcos/pr-reviewer/blob/main/lambda/common/llm.py"
click node_prompts "https://github.com/carreromarcos/pr-reviewer/blob/main/prompts/system_prompt.md"
click node_panel "https://github.com/carreromarcos/pr-reviewer/blob/main/lambda/common/fanout.py"
click node_findings "https://github.com/carreromarcos/pr-reviewer/blob/main/lambda/common/findings.py"
click node_events "https://github.com/carreromarcos/pr-reviewer/blob/main/lambda/common/events.py"
click node_state_codec "https://github.com/carreromarcos/pr-reviewer/blob/main/lambda/common/state.py"
click node_protocol "https://github.com/carreromarcos/pr-reviewer/blob/main/lambda/common/protocol.py"
click node_reconcile "https://github.com/carreromarcos/pr-reviewer/blob/main/lambda/common/reconcile.py"
click node_marker "https://github.com/carreromarcos/pr-reviewer/blob/main/lambda/common/marker.py"
click node_archive "https://github.com/carreromarcos/pr-reviewer/blob/main/lambda/common/archive.py"
click node_viewer "https://github.com/carreromarcos/pr-reviewer/blob/main/lambda/viewer_handler.py"
click node_browser "https://github.com/carreromarcos/pr-reviewer/blob/main/static/review.js"

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_ingress,node_queue toneBlue
class node_worker,node_config,node_diff,node_assembly,node_validation,node_llm,node_prompts,node_panel,node_findings,node_events,node_ssm toneAmber
class node_state_store,node_state_codec,node_protocol,node_reconcile,node_marker toneMint
class node_archive,node_s3,node_viewer,node_browser toneRose
class node_github toneIndigo
```

## Components

### Webhook intake

- [Webhook ingress](https://github.com/carreromarcos/pr-reviewer/blob/main/lambda/ingress_handler.py): `lambda/ingress_handler.py`
- **Work queue**

### Review pipeline

- [Review worker](https://github.com/carreromarcos/pr-reviewer/blob/main/lambda/worker_handler.py): `lambda/worker_handler.py`
- [Runtime configuration](https://github.com/carreromarcos/pr-reviewer/blob/main/lambda/common/config.py): `lambda/common/config.py`
- [Diff retrieval](https://github.com/carreromarcos/pr-reviewer/blob/main/lambda/common/diff.py): `lambda/common/diff.py`
- [Payload and comment assembly](https://github.com/carreromarcos/pr-reviewer/blob/main/lambda/common/assemble.py): `lambda/common/assemble.py`
- [Publication validation](https://github.com/carreromarcos/pr-reviewer/blob/main/lambda/common/validate.py): `lambda/common/validate.py`
- [Single-pass model client](https://github.com/carreromarcos/pr-reviewer/blob/main/lambda/common/llm.py): `lambda/common/llm.py`
- [Review prompts](https://github.com/carreromarcos/pr-reviewer/blob/main/prompts/system_prompt.md): `prompts/system_prompt.md`
- [Shadow multi-agent panel](https://github.com/carreromarcos/pr-reviewer/blob/main/lambda/common/fanout.py): `lambda/common/fanout.py`
- [Finding schema](https://github.com/carreromarcos/pr-reviewer/blob/main/lambda/common/findings.py): `lambda/common/findings.py`
- [Review stage events](https://github.com/carreromarcos/pr-reviewer/blob/main/lambda/common/events.py): `lambda/common/events.py`

### Fencing and storage

- **Review state**
- [State codec](https://github.com/carreromarcos/pr-reviewer/blob/main/lambda/common/state.py): `lambda/common/state.py`
- [Fenced executor](https://github.com/carreromarcos/pr-reviewer/blob/main/lambda/common/protocol.py): `lambda/common/protocol.py`
- [Comment reconciliation](https://github.com/carreromarcos/pr-reviewer/blob/main/lambda/common/reconcile.py): `lambda/common/reconcile.py`
- [Canonical marker](https://github.com/carreromarcos/pr-reviewer/blob/main/lambda/common/marker.py): `lambda/common/marker.py`

### Archive and replay

- [Review archive](https://github.com/carreromarcos/pr-reviewer/blob/main/lambda/common/archive.py): `lambda/common/archive.py`
- **S3 storage**
- [Archive viewer handler](https://github.com/carreromarcos/pr-reviewer/blob/main/lambda/viewer_handler.py): `lambda/viewer_handler.py`
- [Review browser](https://github.com/carreromarcos/pr-reviewer/blob/main/static/review.js): `static/review.js`

### Other components

- **GitHub**
- **AWS Parameter Store**

## Connections

- GitHub → Webhook ingress: sends webhook (evidence: `README.md`)
- Webhook ingress → Work queue: enqueues job (evidence: `README.md`)
- Work queue → Review worker: dispatches job (evidence: `README.md`)
- Review worker → Runtime configuration: loads configuration (evidence: `lambda/worker_handler.py`)
- Review worker → Diff retrieval: fetches diff (evidence: `lambda/worker_handler.py`)
- Review worker → Single-pass model client: requests review (evidence: `lambda/worker_handler.py`)
- Review worker → Payload and comment assembly: assembles comment (evidence: `lambda/worker_handler.py`)
- Payload and comment assembly → Publication validation: validates output (evidence: `lambda/common/assemble.py`)
- Payload and comment assembly → Diff retrieval: renders diff (evidence: `lambda/common/assemble.py`)
- Review worker → Shadow multi-agent panel: runs shadow review (evidence: `lambda/worker_handler.py`)
- Shadow multi-agent panel → Single-pass model client: dispatches model calls (evidence: `lambda/common/fanout.py`)
- Shadow multi-agent panel → Finding schema: handles findings (evidence: `lambda/common/fanout.py`)
- Shadow multi-agent panel → Review stage events: emits stage events (evidence: `lambda/common/fanout.py`)
- Review worker → Review stage events: records review stages (evidence: `lambda/worker_handler.py`)
- Review worker → Fenced executor: executes fenced publish (evidence: `lambda/worker_handler.py`)
- Fenced executor → State codec: uses expressions (evidence: `lambda/common/protocol.py`)
- Review worker → Review state: reads and updates state (evidence: `README.md`)
- Review worker → Comment reconciliation: converges comments (evidence: `lambda/worker_handler.py`)
- Comment reconciliation → State codec: uses update expressions (evidence: `lambda/common/reconcile.py`)
- Review worker → Canonical marker: builds comment marker (evidence: `lambda/worker_handler.py`)
- Review worker → GitHub: fetches and publishes (evidence: `README.md`)
- Review worker → Review archive: archives review (evidence: `README.md`)
- Review archive → S3 storage: stores reviews (evidence: `README.md`)
- Review archive → Review stage events: uses event schema (evidence: `lambda/common/archive.py`)
- Archive viewer handler → S3 storage: serves archived review (evidence: `README.md`)
- Review browser → Archive viewer handler: requests replay (evidence: `README.md`)
- Review worker → AWS Parameter Store: hydrates credentials (evidence: `README.md`)
- Single-pass model client → Review prompts: uses review instructions
