checkCompliance in the worker — so probing /v1/check audits every
path at once.
The App check-runner (primary path)
Key behaviours:- 1–2 minutes of latency is normal — evaluation never runs in the webhook
request (LLM calls exceed the
waitUntilbudget; in_progress check runs used to orphan as eternal spinners, hence complete-on-create). - The webhook maps
installation_id → orgviacodex.github_installations. An unclaimed installation is dropped with a warning log — see troubleshooting. - Default-branch pushes are also checked (compare base = push range / first parent).
- The checks-UI Re-run button works:
check_run/check_suitererequestedre-enqueues. - Merge-blocking comes from a repo ruleset requiring the
PolicyCodexcheck pinned to App integration id4542396. On GitHub’s free plan that only works on public repos or Team-plan orgs.
Evidence modes (a real bug class)
checkCompliance has two system prompts selected by evidence mode:
This split exists because a model given file contents under the diff-framed prompt
audits “the change”, sees none, and correctly reports nothing (observed live:
gpt-4.1 flagged the same violating line 3/3 as a diff and 0/3 as file contents before
the fix). If scans stop finding known-bad content, check this seam first.
Model quality is load-bearing. Per-org Settings → LLM overrides the fallback; the
model must honor OpenAI-style
response_format: json_object (Anthropic models via
OpenRouter do not, and fail the JSON parse). openai/gpt-4.1 is the reference model
validated by the eval suite.
Full-repo scans
/v1/scan (REST, API key) or Reporting → Scope’s per-repo button
(request_full_scan RPC) queue a row in pending_scans; the same cron sweep
evaluates it — whole file contents (capped: 400 files / 55k chars, .md .ts .tsx .js .jsx .py .go .rb .java etc.), one LLM call, scan evidence mode. Guards: a per-repo
cooldown (429 “scanned too recently”), one queued scan per repo/domain, and the
github_scanning entitlement checked at execution time.
Violations lifecycle
- Created by check runs and scans (
severity: blockingfor enforced MUST,warningfor SHOULD),status='open'. - Auto-resolve on re-evaluation of the same scope: a later clean run for the same
repo/PR supersedes old findings (
status='superseded'); closing a PR resolves its findings (pr_closed). Nothing resolves by hand-editing rows. - Reporting reads violations plus the
violations.recorded/violations.resolvedaudit events.
The GitHub Action (secondary path)
For consumers who want the check inside their own workflow: inputsapi-base-url,
api-key (a per-consumer key minted in Settings → API keys), optional domain.
It fetches enforced statements, POSTs the diff to /v1/check, posts a PR review with
findings (statement text, slug, link, severity), fails on enforced MUST findings, and
POSTs violations back. The bundle is apps/action/dist/index.cjs — committed, so
rebuilding without committing ships nothing. Private-repo consumers must check out
the policycodex repo with a fine-grained PAT and uses: the local path.


