From 84dccc74f4891da901f48eb83c00c0c6c5e5c042 Mon Sep 17 00:00:00 2001 From: Glenn Jocher Date: Sat, 4 Jul 2026 16:51:40 +0200 Subject: [PATCH] Add AGENTS.md agent guidance with CLAUDE.md symlink (#787) Co-authored-by: UltralyticsAssistant --- AGENTS.md | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ CLAUDE.md | 1 + 2 files changed, 80 insertions(+) create mode 100644 AGENTS.md create mode 120000 CLAUDE.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..5903944 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,79 @@ +# AGENTS.md + +This file provides guidance to AI coding agents (Claude Code, etc.) when working with code in this repository. CLAUDE.md is a symlink to this file. + +## Core Principles (CRITICAL) + +Respecting these principles is critical for every PR. + +**Less is more. The simplest solution is the best solution.** + +The action hierarchy for every change: **Delete > Replace > Add**. The best code change is a deletion. The second best is modifying what exists. Adding new code is the last resort. + +1. **Minimal**: The simplest solution that works. Do not over-engineer, over-abstract, or add code just in case. Three similar lines beat a premature abstraction. Avoid error handling for impossible states, feature flags, compatibility shims, or policy scaffolding unless they are truly required. +2. **Solve at the source**: Do not hack fixes. Solve problems at their root. If something is broken, fix or remove the broken thing. Never patch over a broken abstraction, add workarounds, or add synchronization code for state that should not be duplicated. +3. **Delete ruthlessly**: When replacing code, delete what it replaced. Remove unused imports, functions, types, files, and commented-out code. Git preserves history. Run the repo's relevant dead-code or cleanup check when available. +4. **Replace > Add**: Modify existing code over adding new code. Edit existing files, extend existing components or functions with minimal parameters, and reuse existing utilities. If creating a new file, first prove it cannot fit cleanly in an existing file. +5. **Check existing**: Search the entire repo before creating anything new. If a feature, component, helper, responder, workflow, or utility already solves a similar problem, reuse or adapt it and delete the duplicate path. +6. **Deduplicate**: Do not duplicate existing code when updating the repo. Consolidate or refactor duplicates you find when it is in scope and low risk. +7. **Zero Regression**: Do not break existing features or workflows unless the PR intentionally removes them with evidence. +8. **Production ready**: All changes must be thoroughly debugged, validated, and production ready. + +**When fixing bugs, ask: "What can I delete?" before "What can I replace?" before "What should I add?"** + +## PR Workflow + +After opening a PR: + +1. Wait for the automated PR review and auto-format commit from Ultralytics Actions (`format.yml`), then pull and address every finding. +2. Launch an independent adversarial review agent with cold context (just the PR diff and this file) to hunt for bugs, regressions, and Core Principles violations. Fix, push, and repeat with a fresh agent until one reports LGTM. +3. Never fight other commits: Ultralytics Actions pushes auto-format and header commits, and multiple users may work on the same PR. `git pull --rebase` before pushing; never force-push, reset, or revert commits you did not author. +4. After the PR merges, clean up: remove local worktrees and branches for it, then `git checkout main && git pull`. + +## Commands + +```bash +pip install -e ".[dev]" # install for development (or: uv pip install --system -e ".[dev]") + +pytest tests -v # run all tests +pytest tests/test_common_utils.py -v # run one test file +pytest tests/test_github_utils.py::test_name -v # run one test +pytest tests -v --cov=actions --cov-report=xml:coverage.xml # tests with coverage (CI command) + +# Lint/format — mirrors the "Run Python" step in action.yml (source of truth if these drift) +ruff check --fix --unsafe-fixes --extend-select F,I,D,UP,RUF,FA --target-version py39 \ + --ignore D100,D104,D203,D205,D212,D213,D401,D406,D407,D413,RUF001,RUF002,RUF012 . +ruff format --line-length 120 . +``` + +Notes: + +- CI tests Python 3.8 and 3.14 on ubuntu and macos — code must stay 3.8-compatible. Use `from __future__ import annotations` for modern type hints. + +## Architecture + +This repo is two things at once: + +1. **A Python package (`actions/`)** published as `ultralytics-actions` on PyPI. Top-level modules (`first_interaction.py`, `review_pr.py`, `summarize_pr.py`, `summarize_release.py`, `dependabot.py`, `github_report.py`, etc.) are standalone scripts, most exposed as `ultralytics-actions-*` CLI entry points in `pyproject.toml` `[project.scripts]`. +2. **GitHub composite actions.** The root `action.yml` is the main "Ultralytics Actions" marketplace action: it installs the Python package, then runs formatters (Ruff, Prettier, Biome, swift-format, dart format, codespell) and the CLI entry points conditioned on event type and inputs, then commits results back to the PR. Subdirectories `retry/`, `cleanup-disk/`, `dependabot/`, `github-report/` are standalone composite actions with their own `action.yml` + README. + +Key flow: GitHub workflow event → `action.yml` step (gated by `github.event_name` / `github.event.action` / inputs) → env vars (`GITHUB_TOKEN`, `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, `MODEL`, ...) → CLI entry point → module `main()`/`run()`. + +`actions/utils/` is the shared core: + +- **`github_utils.py`** — the `Action` class, the central abstraction. Initializes from GitHub Actions env vars (`GITHUB_TOKEN`, `GITHUB_EVENT_NAME`, `GITHUB_EVENT_PATH`), wraps REST (`get`/`post`/`patch`/...) and GraphQL requests with unified status checking, and provides high-level operations (PR diffs, labels, comments, discussions, alerts). +- **`openai_utils.py`** — AI provider abstraction supporting OpenAI and Anthropic. The provider/model is auto-detected from which API key env var is set; defaults live here as single source of truth (`OPENAI_MODEL_DEFAULT`, `ANTHROPIC_MODEL_DEFAULT`, `PR_REVIEW_MODEL_DEFAULT`, `MODEL_COSTS`). Also holds shared prompt-building and response sanitization. +- **`common_utils.py`** — URL/redirect checking, diff filtering, file-skip patterns, HTML comment removal. +- **`version_utils.py`** — PyPI/pub.dev version checks used for publish gating. + +Most shared utilities are re-exported through `actions/utils/__init__.py` — keep `__all__` updated when adding exports. + +Self-hosting detail: workflows in this repo pin `ultralytics/actions@main`, but `action.yml` installs the Python package from the current git branch — so PRs here dogfood Python package changes via `.github/workflows/format.yml`, while changes to `action.yml` itself only take effect after merging to main. + +## Conventions + +- License headers (`# Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license`) are added automatically by Ultralytics Actions (`ultralytics-actions-headers`, extensions in `COMMENT_MAP`) — don't add or revert them manually. +- Bump `__version__` in `actions/__init__.py` when a PR changes package behavior — publishing to PyPI is gated on the version change (`publish.yml`). +- Google-style docstrings, single-line summaries where possible; formatting is enforced by the repo's own action (`format.yml`), which auto-commits fixes to PRs. +- Tests use `unittest.mock` to patch env vars and network calls, except `tests/test_urls.py` which makes live HTTP requests. Modules listed in `[tool.coverage.run] omit` are excluded from coverage requirements. +- Commits and PRs use plain git identity — no AI attribution, co-author lines, or generated-with footers. diff --git a/CLAUDE.md b/CLAUDE.md new file mode 120000 index 0000000..47dc3e3 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1 @@ +AGENTS.md \ No newline at end of file