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
79 changes: 79 additions & 0 deletions .agents/skills/aic-codeowners/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
---
name: aic-codeowners
description: Use when working with aiconfigurator's generated CODEOWNERS - finding out who reviews a change, fixing a failing codeowners CI check, changing review routing, or granting an external contributor area-scoped ownership. Trigger when the codeowners check fails on a PR, a new directory is unclaimed, someone asks who reviews a path or PR, or review routing needs to change.
---

# AIC CODEOWNERS Operations

The root `CODEOWNERS` is a build artifact generated from
`.github/codeowners/areas.yaml` (one entry per area mapping path globs to a
GitHub team). Never hand-edit `CODEOWNERS` - CI regenerates it and fails on
any drift. Every change goes through `areas.yaml` (or
`external_contributors.yaml`) followed by regeneration.

## Flow 1: Who Reviews This Change?

```bash
# owners of your working tree's changed files (union, as GitHub will request)
python .github/codeowners/who_owns.py --codeowners CODEOWNERS --changed

# owners of specific paths
python .github/codeowners/who_owns.py --codeowners CODEOWNERS <path> [<path> ...]
```

Add `--people` to expand each team to its member logins (org members with an
authenticated `gh` only; GitHub hides team membership from non-members).

## Flow 2: The `codeowners` CI Check Failed

Read the failing step before changing ownership:

1. **Unit tests (matcher + minimal_cover):** fix the matcher, generator, or test
failure and rerun the exact test command from the workflow. Do not change
`areas.yaml` to bypass a unit-test failure.
2. **Validate 100% coverage (strict):** the report prints the total uncovered
count and at most 15 paths under `catch-all-only sample`. Add the narrowest
claim or claims under the owning areas' `path_globs` (directory claims end
with `/`). If the paths form a new subsystem, add an area or an appropriate
`classify` rule instead. Rerun the strict gate and repeat until
`catch-all only` is zero.
3. **Regenerate and check for drift:** regenerate from the source files. Commit
every changed generated artifact with its source: `CODEOWNERS`,
and `CONTRIBUTORS.md`.

For coverage, routing, removal, or source-file changes, regenerate and verify:

```bash
python .github/codeowners/build_codeowners.py \
--areas .github/codeowners/areas.yaml --repo . --strict
python .github/codeowners/emit_codeowners.py \
--areas .github/codeowners/areas.yaml --repo . --out CODEOWNERS
```

Rerun the failing workflow step until it passes. Commit the changed source and
all changed generated artifacts together, signed (`git commit -s`).

Removals fail the DRIFT step instead (deleting a directory never fails
coverage): prune the now-dead glob, run the regeneration commands above, and
commit the deletion, `areas.yaml`, and every generated artifact that changed.
The coverage report lists globs that no longer match any file.

## Flow 3: Change Review Routing

Edit `.github/codeowners/areas.yaml` - move a glob between areas, add a
`shared:` entry (multi-team; any one team's approval satisfies the gate), or
adjust `classify` rules - then regenerate as in Flow 2. Changes to the
policy itself route to aiconfigurator-infra + maintainers (the `CODEOWNERS`
and `.github/` shared lines).

## Flow 4: Grant an External Contributor Area-Scoped Ownership

Add an entry to `.github/codeowners/external_contributors.yaml` (name,
github, level, affiliation, `areas: [<label>]`); regeneration appends the
handle as a co-owner on every line the area's team owns and rebuilds
`CONTRIBUTORS.md`. Commit all three files together.

## Reference

Schema and the last-match-wins model: `.github/codeowners/README.md`. The
gate and drift check run in `.github/workflows/codeowners.yml` on every PR.
10 changes: 10 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,13 @@ Dependencies are managed via `uv` with a `uv.lock` lockfile. The virtual environ
1. **LFS data:** `github-cloud.githubusercontent.com` may be blocked by network egress restrictions. If `git lfs pull` fails, unit tests and CLI `generate`/`support` modes still work. The `default` mode and `build`-marked tests will fail.
2. **TTY tests:** 4 tests in `tests/unit/cli/test_plain_output.py` may fail because the agent runs in a non-TTY environment.
3. **Rust tests:** `tests/unit/sdk/test_rust_engine_step.py` requires `cargo` with network access to `crates.io`. It will fail if that domain is blocked.

## CODEOWNERS

The root `CODEOWNERS` is generated from `.github/codeowners/areas.yaml` - never
hand-edit it; CI fails on drift. Repository rules must require the `codeowners`
check to make failures merge-blocking. If the check fails on a new directory,
claim it in `areas.yaml`, regenerate with
`emit_codeowners.py`, and commit every changed source and generated artifact
together. The `aic-codeowners` skill covers all flows (who reviews a change,
gate failures, routing changes, external contributor grants).
9 changes: 9 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,15 @@ Join the community on [Discord](https://discord.gg/mRJ2KNzwYE) to get help, shar

- Make sure all tests pass.

- Reviewers are auto-requested from the team that owns the areas your
PR touches (see the generated `CODEOWNERS`). To preview them:
`python .github/codeowners/who_owns.py --codeowners CODEOWNERS --changed`.
If the `codeowners` check fails because your PR adds a directory no
area claims, add a one-line claim in `.github/codeowners/areas.yaml`,
regenerate, and commit both files (see `.github/codeowners/README.md`
or the `aic-codeowners` skill). Never edit `CODEOWNERS` directly - it
is generated.


- Make sure that you can contribute your work to open source (no
license and/or patent conflict is introduced by your code).
Expand Down
Loading