Skip to content

GitHub PR notifications

The built-in GitHub webhook plugin resolves pull-request updates through their attached managed Linear issue. Most events are concise human-visible notifications. A top-level comment, review, inline review comment, or single-PR check failure on a PR attached to one managed Linear issue wakes that issue's existing conversation and worktree for follow-up. The GitHub webhook never creates a conversation or Discord thread. When no existing issue control exists, Pynchy ignores the event. Closed pull requests produce no Discord update; the linked Linear issue's terminal webhook owns work-item completion and thread archival. A route authenticates one GitHub repository and selects its Linear account. Linear project ownership determines the target workspace.

Configure repository routes

Add one route for each repository:

[[plugins.github.options.webhook_routes]]
name = "project"
repository = "owner/project"
tool = "linear"
secret_env = "GITHUB_PROJECT_WEBHOOK_SECRET" # pragma: allowlist secret

Store the corresponding webhook secret in the host environment, not in data/personalization/pynchy.toml:

GITHUB_PROJECT_WEBHOOK_SECRET="replace-with-a-random-webhook-secret" # pragma: allowlist secret

The route becomes POST /webhooks/github/project. It accepts a delivery only when its repository.full_name exactly matches owner/project; a valid signature for a different repository still receives 400 and cannot be routed anywhere. Configure a separate route and secret for every project that should notify a different workspace.

Trust selected GitHub senders

Routes treat GitHub content as public input by default and cannot target an admin workspace. To accept PR feedback only from trusted GitHub accounts, add an explicit sender allowlist:

allowed_senders = ["repo-owner"]

Pynchy verifies the webhook signature, then compares sender.login case-insensitively. It returns 204 for missing or unlisted senders without storing a receipt, resolving a workspace, or waking an agent. An allowlisted route treats accepted content as trusted and may target an admin workspace. Include every account whose comments belong inside that workspace's trust boundary; omit this option for public review.

Create the GitHub webhook

Pynchy must have a public HTTPS URL before GitHub can reach this endpoint. Configure the control-plane listener with its public-bind safeguards, then place a TLS reverse proxy or tunnel in front of it. Do not expose the unauthenticated loopback listener directly; see Control plane.

In the repository's Settings → Webhooks → Add webhook form, configure:

Field Value
Payload URL https://pynchy.example.com/webhooks/github/project
Content type application/json
Secret The value of GITHUB_PROJECT_WEBHOOK_SECRET
Active Enabled
Events Pull requests, Issue comments, Pull request reviews, Pull request review comments, and Check runs

GitHub delivers a GUID in X-GitHub-Delivery and a SHA-256 HMAC in X-Hub-Signature-256; Pynchy authenticates the raw bytes, deduplicates that GUID, and records only receipt metadata plus a body digest. The route accepts up to 25 MiB because that is GitHub's documented maximum webhook payload. It remains a hard limit—GitHub will not deliver payloads larger than that maximum.

What the Linear issue channel receives

The plugin emits concise direct host notifications for:

  • New commits, nonterminal PR lifecycle updates, title changes, and description changes.
  • Approved or dismissed reviews.
  • Failed check runs associated with several pull requests.
  • An explicit non-mergeable state included in a pull-request delivery.

Development agents include every pull request URL in the evidence_refs for their Awaiting Review outcome. The transition creates the native Linear attachment before changing state. For new or edited top-level PR comments, actionable submitted or edited reviews, inline review comments, and a failed check associated with one PR, the webhook resolves that exact attachment. One matching managed issue receives the event in its existing canonical Linear conversation. The agent fetches current review details, triages them, applies warranted changes in the existing worktree, and runs local CI. It doesn't rerun GitHub CI, merge, or deploy solely because of the event. Missing, ambiguous, off-board, or not-yet-created Linear controls are ignored instead of creating a conversation or choosing a repository-level fallback workspace.

Closed pull requests remain silent. Linear's GitHub integration moves the linked issue, and Pynchy's Linear webhook lifecycle completes managed work and archives the existing Discord thread when that issue becomes terminal.

Recover missed PR updates

The built-in integration scans each configured repository every two hours. It checks open PRs attached to a managed Linear issue with an existing open conversation control, regardless of the PR author. It reads comments, reviews, inline feedback, checks, commit statuses, and mergeability directly from GitHub. This recovers missed webhooks and merge conflicts that GitHub does not announce through a dedicated event.

The host needs a repository credential with read access to PRs, issues, checks, and commit statuses. It uses the existing repository-token resolution. Provider errors or an unstable head/base leave the scan incomplete; they never acknowledge unseen feedback. Scan failures appear in Temporal under pynchy-github-pr-reconciliation.

Follow-up uses the issue's existing conversation and worktree. Pending updates survive restarts and failed dispatches, and an active delivery is not duplicated. A completed turn acknowledges its observed revision; checks or conflicts that remain failing are eligible for follow-up on subsequent scans. Unchanged comments do not repeatedly wake completed turns. Feedback from the PR author is included because humans and agents may share an account. The agent rechecks current state and ignores already-handled feedback.

Polling respects sender allowlists for comments and reviews, and never clears /pause. Paused conversations retain pending follow-up for a later scan after resume. Polling does not create issue controls or directly mutate GitHub. Webhooks remain the immediate notification path.

The plugin deliberately ignores non-PR issue comments, successful checks, checks that GitHub cannot associate with a PR, and event types outside the configured read-only scout surface. This avoids turning a project channel into a repository firehose.

For the exact event headers, payload limits, and event availability, see GitHub's webhook event documentation.