Skip to content
Merged
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
89 changes: 47 additions & 42 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -1,58 +1,63 @@
# Default owner for files without a more specific area rule.
* @BobbyZhouZijian
# Each area lists a primary owner followed by a backup owner. GitHub requests
# review from every listed owner, and one approval from any of them is enough.
# The last matching rule wins, so the more specific area rules below override
# the default.

# Default owners for files without a more specific area rule.
* @BobbyZhouZijian @quao627

# Community process, repository automation, packaging, and deployment.
/.github/ @BobbyZhouZijian
/docker/ @BobbyZhouZijian
/pyproject.toml @BobbyZhouZijian
/README.md @BobbyZhouZijian
/README.zh.md @BobbyZhouZijian
/README.i18n.yaml @BobbyZhouZijian
/.github/ @BobbyZhouZijian @Benjamin-eecs
/docker/ @BobbyZhouZijian @MikeZheng777
/pyproject.toml @BobbyZhouZijian @Benjamin-eecs
/README.md @BobbyZhouZijian @Benjamin-eecs
/README.zh.md @BobbyZhouZijian @Benjamin-eecs
/README.i18n.yaml @BobbyZhouZijian @Benjamin-eecs

# Core product areas. Keep these entries separate so ownership can be
# delegated one subsystem at a time as the maintainer group grows.
/reef/service/ @BobbyZhouZijian
/reef/scenario/ @BobbyZhouZijian
/reef/core/ @BobbyZhouZijian
/recipes/basic/ @BobbyZhouZijian
/third_party/ @BobbyZhouZijian
/reef/service/ @BobbyZhouZijian @quao627
/reef/scenario/ @BobbyZhouZijian @quao627
/reef/core/ @BobbyZhouZijian @quao627
/recipes/basic/ @BobbyZhouZijian @quao627
/third_party/ @BobbyZhouZijian @Benjamin-eecs

# Harness-facing product layer.
/reef/harness/ @Benjamin-eecs
/recipes/sao/ @Benjamin-eecs
/recipes/tttd/ @Benjamin-eecs
/recipes/openclawrl/ @Benjamin-eecs
/reef/train/cordis_backend/ @Benjamin-eecs
/reef/surface/ @Benjamin-eecs
/third_party/cordis/ @Benjamin-eecs
/tutorials/evolve-your-harness/ @Benjamin-eecs
/recipes/skillclaw/ @Benjamin-eecs
/recipes/gepa/ @simonucl
/reef/harness/ @Benjamin-eecs @quao627
/recipes/sao/ @Benjamin-eecs @MikeZheng777
/recipes/tttd/ @Benjamin-eecs @MikeZheng777
/recipes/openclawrl/ @Benjamin-eecs @MikeZheng777
/reef/train/cordis_backend/ @Benjamin-eecs @hanfeiyu
/reef/surface/ @Benjamin-eecs @quao627
/third_party/cordis/ @Benjamin-eecs @quao627
/tutorials/evolve-your-harness/ @Benjamin-eecs @quao627
/recipes/skillclaw/ @Benjamin-eecs @quao627
/recipes/gepa/ @simonucl @Benjamin-eecs

# Runnable examples of the weight methods (the method packages above stay
# with the product layer).
/recipes/sao/examples/ @BobbyZhouZijian
/recipes/tttd/examples/ @BobbyZhouZijian
/recipes/openclawrl/examples/ @BobbyZhouZijian
/recipes/sao/examples/ @BobbyZhouZijian @MikeZheng777
/recipes/tttd/examples/ @BobbyZhouZijian @MikeZheng777
/recipes/openclawrl/examples/ @BobbyZhouZijian @MikeZheng777

# Training execution, artifact handling, and pipeline reliability.
/reef/train/ @hanfeiyu
/reef/runtime/ @hanfeiyu
/reef/artifact/ @hanfeiyu
/reef/dispatcher.py @hanfeiyu
/recipes/openclawrl/examples/openclawrl/serve.yaml @hanfeiyu
/reef/train/ @hanfeiyu @MikeZheng777
/reef/runtime/ @hanfeiyu @MikeZheng777
/reef/artifact/ @hanfeiyu @MikeZheng777
/reef/dispatcher.py @hanfeiyu @MikeZheng777
/recipes/openclawrl/examples/openclawrl/serve.yaml @hanfeiyu @MikeZheng777

# Documentation defaults to the Merge Oncall. Domain references override it.
/docs/ @BobbyZhouZijian
/docs/user-guide/evolve-your-harness.rst @Benjamin-eecs
/docs/developer-guide/harness-adapters.rst @Benjamin-eecs
/docs/developer-guide/write-a-harness-method.rst @Benjamin-eecs
/docs/developer-guide/write-a-recipe.rst @Benjamin-eecs
/docs/user-guide/recipes.rst @Benjamin-eecs
/docs/user-guide/recipes/ @Benjamin-eecs
/docs/user-guide/evolve-your-model.rst @hanfeiyu
/docs/developer-guide/loss-families.rst @hanfeiyu
/docs/reference/cli.rst @BobbyZhouZijian
# Documentation defaults to these owners. Domain references override it.
/docs/ @BobbyZhouZijian @Benjamin-eecs
/docs/user-guide/evolve-your-harness.rst @Benjamin-eecs @quao627
/docs/developer-guide/harness-adapters.rst @Benjamin-eecs @quao627
/docs/developer-guide/write-a-harness-method.rst @Benjamin-eecs @quao627
/docs/developer-guide/write-a-recipe.rst @Benjamin-eecs @quao627
/docs/user-guide/recipes.rst @Benjamin-eecs @quao627
/docs/user-guide/recipes/ @Benjamin-eecs @quao627
/docs/user-guide/evolve-your-model.rst @hanfeiyu @MikeZheng777
/docs/developer-guide/loss-families.rst @hanfeiyu @MikeZheng777
/docs/reference/cli.rst @BobbyZhouZijian @quao627
# python-api.rst merges the former recipe/surface and batch/processor/preparer
# pages, so it keeps both prior owners.
/docs/reference/python-api.rst @Benjamin-eecs @hanfeiyu
105 changes: 56 additions & 49 deletions .github/MAINTAINER.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,27 @@ of the project as it grows.
Roles describe work, not status. One person may hold more than one role for a
pull request.

## Current Merge Oncall
## Review routing

The current Merge Oncall is configured in
[`merge-oncall.json`](merge-oncall.json): **@BobbyZhouZijian**.
Reef has no single on-call maintainer. [`CODEOWNERS`](CODEOWNERS) routes each
pull request: GitHub requests review from the code owners of every changed
path when the pull request is ready for review. Each area lists a primary owner
and a backup owner, and an approval from either one satisfies that area.
Changes outside a specific area fall back to the default owners listed at the
top of that file.

When a pull request is opened, reopened, or marked ready for review, the
`assign merge oncall` workflow assigns the configured account and posts or
updates a single on-call comment. The workflow uses `pull_request_target`
without checking out or executing pull-request code, so assignment also works
for contributions from forks without exposing a write token to their code.
Who merges depends on the author:

- An author with repository write access merges their own pull request after
receiving at least one approval and meeting the acceptance conditions below.
- A pull request from an external contributor is merged by one of the code
owners who approved it.

The `remind reviewers of idle pull requests` workflow runs every three days. It
posts one comment on a fixed tracking issue listing ready pull requests without
activity for three days and mentions whoever the next step waits on: the
requested reviewers, the author when changes are requested or no reviewer is
requested, or the merging person after approval.

## Roles

Expand All @@ -29,29 +40,27 @@ whole. They can merge and close pull requests and are responsible for:
- deciding whether a contribution fits Reef's direction and maintenance
budget;
- identifying when an RFC is required;
- selecting reviewers for affected areas;
- requesting additional reviewers when path rules do not cover an affected
area;
- resolving cross-area or project-level disagreements;
- merging changes when the acceptance conditions are met; and
- reverting or coordinating a fix when a merged change causes a regression.

An approval from a maintainer accepts responsibility for the change, not only
its local implementation.

### Merge Oncall
### Code owner

The Merge Oncall is the maintainer actively responsible for moving one pull
request toward a clear outcome. The on-call:
Code owners are the maintainers listed for an area in
[`CODEOWNERS`](CODEOWNERS). For pull requests in their area, a code owner:

- performs the initial scope and RFC check;
- identifies affected areas and requests the right reviews;
- reviews the change or hands the review to the backup owner;
- distinguishes blocking feedback from optional follow-up work;
- keeps the pull request state clear when review stalls or changes direction;
- confirms that acceptance conditions are met; and
- merges, closes, or hands the pull request to another maintainer.
- requests review from other areas the change materially affects; and
- merges or closes external contributions they approved.

The Merge Oncall is an active coordination role. An area reviewer may protect
a specific subsystem without being responsible for driving the entire pull
request.
Code owners must have repository write permission.

### Area reviewer

Expand All @@ -60,10 +69,9 @@ operational concern. They are responsible for reviewing changes in that area
for correctness, compatibility, tests, documentation, and maintainability.

Area reviewers do not need merge permission. Their approval is a technical
signal to the Merge Oncall; the final repository decision remains with a
maintainer. An area reviewer must have repository write permission before they
can be listed in [`CODEOWNERS`](CODEOWNERS), but qualified reviewers may still
be requested manually without being code owners.
signal to the code owners; the final repository decision remains with a
maintainer. Qualified reviewers may be requested manually without being code
owners.

Current primary area ownership is:

Expand All @@ -72,7 +80,9 @@ Current primary area ownership is:
- **@hanfeiyu** — training execution, runtime integration, artifact handling,
pipeline reliability, and their focused documentation; and
- **@BobbyZhouZijian** — service and core boundaries, scenario lifecycle,
repository automation, packaging, and cross-cutting changes.
repository automation, and packaging.

[`CODEOWNERS`](CODEOWNERS) lists the backup owner for each area.

## Issue process

Expand Down Expand Up @@ -166,19 +176,15 @@ The maintainer may ask the author to narrow the change, move design discussion
to the appropriate issue form, or close work that does not fit project
direction. The reason should be stated clearly.

### 3. On-call assignment and review routing
### 3. Review routing

The assignment workflow makes the configured Merge Oncall the pull request
assignee. The Merge Oncall requests reviews for every materially affected area.
GitHub also requests reviewers using [`CODEOWNERS`](CODEOWNERS). Its current
area-specific entries route harness-facing work to @Benjamin-eecs and training
and reliability work to @hanfeiyu, while cross-cutting work stays with the
Merge Oncall. The pull-request labeler applies the corresponding `area:*`,
`dependencies`, and `type: tests` labels from
GitHub requests reviewers using [`CODEOWNERS`](CODEOWNERS), as described in
[Review routing](#review-routing). The pull-request labeler applies the
corresponding `area:*`, `dependencies`, and `type: tests` labels from
[`labeler.yml`](labeler.yml), including when the changed-file set is updated.
Labels are routing hints rather than approvals. The on-call remains responsible
for checking that every affected area has a qualified reviewer and requesting
additional reviews when path rules are insufficient.
Labels are routing hints rather than approvals. The author and the requested
code owners request additional reviews when path rules do not cover an
affected area.

### 4. Technical review

Expand Down Expand Up @@ -231,8 +237,8 @@ run the full matrix. Manual dispatches are diagnostic runs; use the original
PR workflow's full rerun to satisfy merge checks for that PR.

Required checks must pass on the reviewed revision. CI is a gate, not a
substitute for review. The Merge Oncall may request focused or environment-
specific validation when the standard checks do not cover the affected path.
substitute for review. Reviewers may request focused or environment-specific
validation when the standard checks do not cover the affected path.
Dependabot groups weekly GitHub Actions, Python, documentation-site, and Docker
updates into bounded pull-request queues. Dependency pull requests follow the
same ownership, review, and required-check rules as author-submitted changes;
Expand All @@ -243,9 +249,8 @@ they are not merged automatically.
A pull request is ready to merge when:

- an RFC is accepted if the change requires one;
- at least one maintainer approves the pull request;
- every materially affected area has an approval from a maintainer or an area
reviewer selected by the Merge Oncall;
- at least one code owner of an affected area or another maintainer approves
the pull request;
- all required checks pass;
- no blocking review or design discussion remains;
- tests cover the behavior change; and
Expand All @@ -258,8 +263,9 @@ and rationale should be recorded on the pull request.

### 7. Merge and follow-up

A maintainer merges the accepted revision and ensures linked issues are closed
or updated. Deferred work should be captured in explicit follow-up issues
An author with repository write access merges their own accepted pull
request; for an external contribution, an approving code owner merges it. The
person who merges ensures linked issues are closed or updated. Deferred work should be captured in explicit follow-up issues
rather than left only in review comments.

If a merge causes a serious regression, restoring a known-good state takes
Expand All @@ -270,16 +276,17 @@ design or debugging in a follow-up pull request.

Small documentation fixes, clear test-only changes, reversions, release
blockers, and fixes for active regressions may receive an expedited review. The
Merge Oncall must state why the change is being fast-tracked and which review
or validation remains required. Any exception is still subject to repository
approving reviewer must state why the change is being fast-tracked and which
review or validation remains required. Any exception is still subject to repository
permissions and branch protections.

## Stalled pull requests

When a pull request is waiting on the author, the Merge Oncall should identify
the remaining work and leave a clear prompt before closing it. When it is
waiting on review, the on-call should request another qualified reviewer or
hand the role to another maintainer.
When a pull request is waiting on the author, the reviewer should identify the
remaining work and leave a clear prompt before closing it. When it is waiting on
review, the requested code owner should review it or ask the area's backup owner
to take over. The reminder described in [Review routing](#review-routing)
lists pull requests in either state.

The stale workflow marks a non-draft pull request after 60 days without
activity and closes it after another 21 days. Drafts and work labeled `KIV`,
Expand All @@ -304,7 +311,7 @@ does not delete labels that are absent from the catalog.
## Disagreements and escalation

Reviewers should first seek a decision through concrete technical discussion
on the issue, RFC, or pull request. The Merge Oncall may request additional
on the issue, RFC, or pull request. Any maintainer may request additional
area review when expertise or ownership is disputed. Maintainers make the final
repository-level decision and record the rationale when consensus is not
possible.
Expand Down
2 changes: 1 addition & 1 deletion .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,6 @@ remains responsible for every submitted line, claim, and test result.

## Review and merge

The Merge Oncall is assigned automatically. See the
Reviewers are requested automatically from `CODEOWNERS`. See the
[maintenance model](https://github.com/Human-Agent-Society/reef/blob/main/.github/MAINTAINER.md)
for review and merge requirements.
3 changes: 0 additions & 3 deletions .github/merge-oncall.json

This file was deleted.

20 changes: 2 additions & 18 deletions .github/scripts/check_community_files.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,8 @@ def pattern_matches(pattern: str, paths: list[str]) -> bool:
return any(fnmatch.fnmatchcase(path, normalized) for path in paths)


def validate_codeowners(paths: list[str]) -> set[str]:
def validate_codeowners(paths: list[str]) -> None:
codeowners = ROOT / ".github" / "CODEOWNERS"
owners: set[str] = set()
errors = 0
for number, raw_line in enumerate(codeowners.read_text().splitlines(), 1):
line = raw_line.strip()
Expand All @@ -82,22 +81,8 @@ def validate_codeowners(paths: list[str]) -> set[str]:
if not owner.startswith("@") or not all(GITHUB_LOGIN.fullmatch(part) for part in owner[1:].split("/", 1)):
fail(f"CODEOWNERS:{number}: invalid owner: {owner}")
errors += 1
owners.add(owner.removeprefix("@").split("/", 1)[-1])
if errors:
raise ValueError("invalid CODEOWNERS")
return owners


def validate_oncall(owners: set[str]) -> None:
path = ROOT / ".github" / "merge-oncall.json"
config = json.loads(path.read_text())
if set(config) != {"login"}:
raise ValueError("merge-oncall.json must contain exactly the 'login' key")
login = config["login"]
if not isinstance(login, str) or not GITHUB_LOGIN.fullmatch(login):
raise ValueError("merge-oncall.json contains an invalid GitHub login")
if login not in owners:
raise ValueError("the merge oncall must also appear in CODEOWNERS")


def validate_labels() -> set[str]:
Expand Down Expand Up @@ -205,8 +190,7 @@ def validate_workflows() -> None:
def main() -> int:
try:
paths = tracked_files()
owners = validate_codeowners(paths)
validate_oncall(owners)
validate_codeowners(paths)
labels = validate_labels()
validate_issue_templates(labels)
validate_workflows()
Expand Down
Loading
Loading