Son of Anton Docs
Code review

Triggers and Commands

What starts a review automatically, the @anton comment commands, and who is allowed to use them.

This page describes son-of-anton-review (feat/cloudflare-native). Pull request webhooks, manual review comments and operator requeues can request reviews. Configured competitor-review events can also request audits. These paths share review processing, but do not all use the same queue-job or dedupe key.

Automatic triggers

A pull_request webhook can request a review for opened, reopened, ready_for_review or synchronize. The native ingress filters events before enqueueing; configuration and authorization are checked downstream, not all before a Cloudflare Queue slot is used.

edited updates stored PR metadata when delivered directly to ReviewService. The native ingress instead records it as an ignored unsupported_action and does not dispatch it to that service.

The standalone service webhook handler applies src/config.js / shouldAutoReview:

Config keyDefaultEffect
enabledtrueRepo is reviewed at all
review.autotrueWebhooks may queue reviews
branches.include["main", "dev"]Base branch must be in this list
review.onDraftfalseDraft PRs are skipped

The native container instead seeds a run directly and applies evaluateRuntimeAdmission. It does not call shouldAutoReview, so the main/dev, review.auto and review.onDraft defaults above are not native admission gates. A configured repository uses its enabled value; without config, admission depends on prior review history or autoEnableNewRepos (policy default false).

The pinned review policy (src/operator-review-policy.js, DEFAULT_REVIEW_POLICY) applies:

Policy keyDefaultEffect
autoReviewNewCommitstruefalse skips synchronize; open, reopen and ready-for-review remain eligible
reviewDraftsfalseDraft PRs return draft_review_disabled
fileChangeLimit500PRs changing more files return file_change_limit
pausedAuthors[]Logins whose PRs are never reviewed, manual commands included
filters[]Rule list, see below

Standalone event filtering

src/pr-update-engine.js rejects unsupported actions, merge-commit events and no-op updates. Merge detection uses supplied metadata: an explicit merge flag, multiple head-commit parents, or a message beginning Merge branch, Merge pull request or Merge remote-tracking branch. It does not fetch the head commit to prove that it is a merge.

For synchronize, equal previous/current SHAs or a head already stored for the PR count as no_op. An explicit noChanges also skips the event. The service passes skipBots: false and skipDraft: false to this helper; draft admission is handled by repo config and review policy instead.

The transition helper defines a latest-waiting key, {owner}/{repo}#{pr}:latest-waiting, and can return replace_waiting when given an earlier waiting job. Do not equate that helper with removal of a message already in Cloudflare Queues.

Dedupe keys

Two layers:

  • Native ingress writes delivery:{X-GitHub-Delivery} into DEDUPE KV with DEDUPE_TTL_SECONDS (default 604800 seconds, seven days). A repeat answers duplicate_delivery. Recording/enqueue failures attempt to delete the key and return HTTP 500 so a redelivery can be accepted. KV is eventually consistent; downstream leases also matter. This setting is read in the Worker, not the container.
  • Review key {owner}/{repo}#{pr}@{headSha} identifies the run. Manual commands append a variant, manual-{commentId}, so a fresh @anton review on an unchanged head is a new run rather than a skipped_locked hit.

Comment commands

Post a top-level PR comment. The parser (src/commands.js) accepts:

@anton review
@anton rerun
@anton status
@anton help

@gilf is an alias for every verb. Matching is case-insensitive, whitespace is collapsed, and the comment must start with the command:

^(?:@anton|@gilf)\s+(review|rerun|status|help)(?:\s+(.*))?$
VerbWhat happens
reviewQueues a run for the stored PR head
rerunSame review-request behavior as review
statusReplies with the latest stored PR run status and stored head abbreviation, no new run; the latest run is not filtered to that head
helpReplies with the command list, no run

The standalone service only executes commands on created comments. Native ingress accepts created and edited issue comments and its consumer keeps only parsed review/rerun commands; native seeding does not repeat the standalone created-only check. The native review identity remains scoped to the comment ID, so editing one comment is not the same as posting a new rerun command.

Trailing text is parsed as args, but does not select another PR or head. The standalone service dedupes commands by {owner}/{repo}#{pr}@{commentId} and returns duplicate_command for an existing record. Native dispatch uses the review key and lease instead.

Not available: @anton ignore, @anton resolve, @anton learn. Those parse to no_command and are ignored.

Comment handling can be switched off per repo with manual.enabled: false.

Who can run commands

isAuthorizedCommenter checks the GitHub author_association on the comment against the repo config:

{
  "manual": {
    "enabled": true,
    "allowAssociations": ["OWNER", "MEMBER", "COLLABORATOR"],
    "allowUsers": []
  }
}

A login in allowUsers passes regardless of association. Anyone else is recorded as unauthorized_commenter and gets no reply. pausedAuthors still applies to manual runs.

The service requires a stored PR head even for help and status, otherwise it returns unknown_pr_head. Its reply strings still use the legacy Gilf name and help lists the @gilf aliases. The parser accepts both names.

Manual review requests bypass the policy's automatic draft, file-count and filter checks, but not pausedAuthors or separate repository admission/execution checks. Native seeding also checks manual.enabled and isAuthorizedCommenter against the authenticated webhook comment. Native status/help comments are acknowledged as no_review_command without dispatching a reply container.

Policy filters

filters is a list of rules. Any matching rule satisfies this filter gate; within a rule every condition must match. An empty list imposes no filter restriction, but other admission gates still apply. Maximum 50 rules, 20 conditions each.

FieldOperatorsValues
labelis, is_notLabel names
authoris, is_notLogins, lowercased
repositoryis, is_notowner/repo
targetBranchis, is_notGlobs
sourceBranchis, is_notGlobs
pathis, is_notGlobs against changed paths
titlecontains, not_containsSubstrings
keywordcontains, not_containsSubstrings in title or body
draftis, is_notNone
filesChangedat_most, more_thanOne nonnegative integer string, for example "500"
{
  "filters": [
    { "conditions": [
      { "field": "targetBranch", "operator": "is", "values": ["main", "release/*"] },
      { "field": "path", "operator": "is_not", "values": ["docs/**"] }
    ] }
  ]
}

Globs are validated: no .., no partial ** segments. A rule that needs metadata not yet available (for example changed paths) defers the decision until preflight fills it.

Execution mode gate

Sandbox validation is gated separately from review admission:

{ "execution": { "mode": "always", "filters": [] } }
ModeEffect
alwaysAllows validation; docs/generated skips and executor availability still apply
neverAnalysis only, summary shows execution_disabled
filtersSame rule engine as above, unmatched PRs show execution_filters_not_matched

Operator rerun and requeue

From the host:

node bin/gilf-review.mjs requeue owner/repo#123
node bin/gilf-review.mjs requeue "owner/repo#123@<sha>" --variant manual-retry

Without --variant, the CLI appends operator-{timestamp} to the base review key. --json prints the result object, including reviewKey.

The separate son-of-anton-operator-parity tree (feat/greptile-operator-parity) implements the following durable command endpoint. It is not an endpoint on the native ingress Worker:

POST /operator/api/commands/requeue
{ "repo": "owner/name", "number": 123, "variant": "manual-20260824", "reason": "operator_force_review" }

POST requires OPERATOR_COMMAND_TOKEN; GET /operator/api/commands and /operator/api/commands/:commandId accept OPERATOR_READ_TOKEN or OPERATOR_BRIDGE_TOKEN. Sibling commands: retry-publish and replay-webhook.

The CLI needs a stored PR head or exact stored review key and an installation ID. Run it from the engine checkout against the intended store/queue; it is not a stateless remote API client.

Source evidence

  • son-of-anton-review/src/commands.js:9-39; src/config.js:1-45,86-97.
  • son-of-anton-review/src/pr-update-engine.js:81-122,195-231; src/review-service.js:661-838.
  • son-of-anton-review/src/operator-review-policy.js:26-78,138-180.
  • son-of-anton-review/cloudflare-native/src/consumer.js:344-355; cloudflare-native/src/d1-store-adapter.js:146-170; src/review-policy-runtime.js:39-42.
  • son-of-anton-review/cloudflare-native/src/ingress.js:59-132,295-345.
  • son-of-anton-review/src/operator-cli.js:187-261,629-644.
  • son-of-anton-operator-parity/cloudflare/src/worker.js:69-80; cloudflare/src/review-state-api.js:934-942.

See Context graph for preflight behavior and Publish modes for publication boundaries.

On this page