Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
131 changes: 131 additions & 0 deletions .github/reviewers.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
# Expertise map consumed by assign-reviewers.yml at PR time (see
# .github/workflows/ci-assign-reviewers.yml, this repo's caller).
#
# Despite the workflow's name it writes the ASSIGNEE field, not reviewer
# requests — "this org routes/alerts people via the ASSIGNEE field"
# (assign-reviewers.yml's header). So a `reviewers:` entry below means "gets
# assigned", which is what actually gets a PR looked at here.
#
# HOW THIS MAP WAS SEEDED, and why it is not derived from git history: nearly
# every commit on main in this repo has one author, so authorship carries no
# routing signal at all. The people below are instead the ones who have actually
# APPROVED merged PRs in the matching area. Approval counts at seed time:
# wei-hai 9, huntcsg 3, deepme987 3, sundar-svg 2, synap5e 1,
# luke-mino-altherr 1, bigcat88 1.
#
# ORDER OF OPERATIONS with refresh-reviewers (#63, BE-4116): that generator
# treats the committed `rules:` globs as its BUCKET DEFINITIONS and only
# re-scores who belongs in each — it cannot invent buckets, so this file has to
# exist first. Two things to know when its first drift PR arrives:
# 1. It scores recency-decayed COMMIT authorship, so on this repo it will want
# to collapse most buckets to the single dominant committer. That is a
# history artifact, not a routing improvement — read that PR, don't
# rubber-stamp it.
# 2. The bucket globs below are therefore the durable part of this file. Edit
# them deliberately; they outlive the names.
#
# Selection at PR time: changed paths -> union of matching rules -> drop the PR
# author -> rank ascending by open assignee load -> assign `num_reviewers`.
# NOTE the author drop: a bucket whose only member is the author empties, so
# `default_pool` is the real safety net and must never be just one person (and
# must not be the person who opens most PRs here).

default_pool:
- wei-hai
- deepme987
- huntcsg

rules:
# The shared caller-bump machinery + every per-fleet entrypoint. wei-hai owns
# this area by approval history (the CURSOR_REVIEW_CALLERS variable migration,
# the trailing-newline fix, the caller-list additions); deepme987 approved the
# wire-bot identity injection.
- paths:
- .github/bump-callers/**
- .github/workflows/bump-*.yml
Comment thread
mattmillerai marked this conversation as resolved.
# `test-bump-callers.yml` does not match `bump-*.yml` — name it, the same
# way every other bucket names its own `test-*.yml`.
- .github/workflows/test-bump-callers.yml
reviewers:
- wei-hai
- deepme987

# groom: briefs, ledger, sandbox/broker, and the reusable + its own caller.
# synap5e approved the builder PR-body convention and holds the open sandbox
# PRs; luke-mino-altherr approved the direct-CLI agent phases; bigcat88
# approved the caller-permissions correction.
- paths:
- .github/groom/**
- .github/workflows/groom.yml
- .github/workflows/ci-groom.yml
- .github/workflows/test-groom-scripts.yml
reviewers:
- synap5e
- luke-mino-altherr
- bigcat88

# cursor-review: the review panel, judge, prompts and auto-label. huntcsg
# approved the blocking gate and the judge-parsing recovery; sundar-svg
# approved the runs_on/self-hosted parameterization.
- paths:
- .github/cursor-review/**
- .github/workflows/cursor-review.yml
- .github/workflows/cursor-review-auto-label.yml
- .github/workflows/ci-cursor-review.yml
- .github/workflows/test-cursor-review-scripts.yml
reviewers:
- huntcsg
- sundar-svg
- deepme987

# PR-size gate + its Go classifier. guill carries the open pr-size token work;
# wei-hai approved it.
- paths:
- scripts/check-pr-size/**
- .github/workflows/pr-size.yml
- .github/workflows/test-pr-size.yml
reviewers:
- guill
- wei-hai

# The assignee-routing machinery itself, including the generator that will
# later rewrite this very file. wei-hai approved both the expertise-aware
# assign-reviewers workflow and assign-prs-to-author; deepme987 approved the
# non-author-assignee skip.
- paths:
- .github/refresh-reviewers/**
- .github/workflows/assign-*.yml
# The `ci-` prefixed self-enrollment caller does NOT match `assign-*.yml`,
# so it needs naming outright — otherwise a change to this repo's own
# routing caller falls through to default_pool.
- .github/workflows/ci-assign-reviewers.yml
- .github/workflows/refresh-reviewers.yml
- .github/reviewers.yml
reviewers:
- wei-hai
- deepme987

# AGENTS.md standard checker + housekeeping workflows.
- paths:
- .github/agents-md-integrity/**
- .github/workflows/agents-md-integrity.yml
- .github/workflows/test-agents-md-integrity.yml
- .github/workflows/stale.yml
- .github/workflows/detect-unreviewed-merge.yml
Comment thread
mattmillerai marked this conversation as resolved.
# Its `ci-` prefixed self-enrollment caller, named outright for the same
# reason ci-assign-reviewers.yml is below: no glob here reaches it.
- .github/workflows/ci-detect-unreviewed-merge.yml
reviewers:
- wei-hai
- deepme987

# Repo-level docs and standards. Deliberately the broad pool, since an
# AGENTS.md or README change can come from any of the areas above.
- paths:
- AGENTS.md
- CLAUDE.md
- README.md
reviewers:
- wei-hai
- huntcsg
- deepme987
76 changes: 76 additions & 0 deletions .github/workflows/ci-assign-reviewers.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
name: CI - Assign Reviewers

# Thin caller enrolling THIS repo in its own expertise-aware assignee routing.
# The logic lives in assign-reviewers.yml in this same repo; the caller pins it
# by full commit SHA like every external consumer — a local `uses: ./...` path
# would run the PR's OWN copy of the router, letting a PR rewrite who gets
# assigned to review it. Named ci-assign-reviewers.yml because the canonical
# caller path (assign-reviewers.yml) is occupied here by the reusable itself,
# same as ci-cursor-review.yml / ci-detect-unreviewed-merge.yml / ci-groom.yml.
#
# WHAT IT WRITES: the ASSIGNEE field, not reviewer requests — despite the
# workflow's name. "This org routes/alerts people via the ASSIGNEE field"
# (assign-reviewers.yml's header). That is the point of enrolling: PRs here were
# sitting with no assignee, so nothing routed them to anyone who could approve.
#
# The expertise map is .github/reviewers.yml in this repo (seeded from who has
# actually APPROVED merged PRs per area — see that file's header for why git
# history was NOT the source). It is read from the PR HEAD sha, so a PR's own
# edit to the map takes effect on that same PR.
#
# PREREQUISITES, both already provisioned here for cursor-review / the bumpers:
# vars.APP_ID + secrets.CLOUD_CODE_BOT_PRIVATE_KEY. The App token (not
# GITHUB_TOKEN) does the assigning — the reusable needs `Pull requests: write`
# to set assignees and this job therefore needs only `contents: read` itself.
#
# FORK PRs ARE NOT ROUTED, and that is deliberate. `pull_request` withholds
# repository secrets from fork-originated runs, so CLOUD_CODE_BOT_PRIVATE_KEY
# arrives empty and the App-token mint hard-fails — a red X and no routing
# either way. The job is guarded to skip cleanly on forks instead (see `if:`
# below). Routing them would mean `pull_request_target`, which runs privileged
# against untrusted HEAD and would turn the head-sha map read described above
# into a real escalation; not a trade worth making for assignee routing.
#
# PIN FRESHNESS (operator): the pin below only tracks assign-reviewers.yml once
# this repo is listed in vars.ASSIGN_REVIEWERS_CALLERS, which
# bump-assign-reviewers-callers.yml fans bumps out to. Until then the pin is
# updated by hand, same as any other consumer that isn't enrolled.

on:
pull_request:
# `opened` covers ready PRs; `ready_for_review` catches a draft being
# promoted (the reusable skips drafts, so a PR opened as a draft would
# otherwise never get routed); `reopened` gives a second chance to a PR that
# was closed still unrouted (e.g. its `opened` run failed). Deliberately NOT
# `synchronize` — re-running on every push would fight a human who
# reassigned the PR on purpose. Re-firing is safe regardless: the reusable
# skips any PR that already has a non-author assignee.
types: [opened, ready_for_review, reopened]

# Never let routing fight itself: two events for the same PR (opened, then
# ready_for_review moments later) would both read open-assignee load and could
# both assign, overshooting num_reviewers.
concurrency:
group: assign-reviewers-${{ github.event.pull_request.number }}
cancel-in-progress: false

jobs:
assign:
# Same-repo branches only. On a fork PR the secret below is empty (see
# "FORK PRs" in the header), so without this the App-token step fails and
# every external contribution carries a red check for a routing decision
# that could never have been made anyway. A skipped job reports as neutral.
if: github.event.pull_request.head.repo.full_name == github.repository
permissions:
# Only `contents: read` — the reusable reads .github/reviewers.yml from the
# head sha and does every write with the CLOUD_CODE_BOT App token, so no
# pull-requests/issues GITHUB_TOKEN scope is needed here.
contents: read
uses: Comfy-Org/github-workflows/.github/workflows/assign-reviewers.yml@29a81cab43766adc52a6f2adadcab63f0db7f6c5 # main @ 29a81ca — assign-reviewers.yml not on the v1 tag
Comment thread
mattmillerai marked this conversation as resolved.
with:
# ONE assignee per PR, matching how this repo's PRs are actually tracked
# (a single named owner, not a pair). Raise to 2 if single-owner PRs start
# stalling — the reusable's own default is 2.
num_reviewers: 1
secrets:
CLOUD_CODE_BOT_PRIVATE_KEY: ${{ secrets.CLOUD_CODE_BOT_PRIVATE_KEY }}
Comment thread
mattmillerai marked this conversation as resolved.
6 changes: 3 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,9 @@ tests — run the matching command above for whatever you touched.
- **Scripts are the single source of truth**, loaded at run time from a pinned
ref of THIS repo — never from the caller's checkout. That's what makes the
reviewer/checker tamper-proof: a PR can't rewrite the logic judging it. The
self-enrollment callers (`ci-cursor-review.yml`, `ci-detect-unreviewed-merge.yml`)
deliberately pin a merged-main SHA instead of a local `./` path for the same
reason — do not "simplify" them to a local path.
self-enrollment callers (`ci-cursor-review.yml`, `ci-assign-reviewers.yml`,
`ci-detect-unreviewed-merge.yml`) deliberately pin a merged-main SHA instead
of a local `./` path for the same reason — do not "simplify" them to a path.
- **One bumper, not several.** `bump-callers.sh` backs every fleet; the
`bump-*-callers.yml` files are thin per-fleet wrappers (they stay separate so a
`cursor-review.yml` change doesn't spuriously bump agents-md or pr-size
Expand Down