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
2 changes: 1 addition & 1 deletion .github/workflows/format.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
- name: Run Ultralytics Actions
uses: ultralytics/actions@main
with:
token: ${{ secrets._GITHUB_TOKEN || github.token }} # Auto-generated fallback
token: ${{ secrets._GITHUB_TOKEN || secrets.GITHUB_TOKEN }} # Auto-generated token
labels: true # Auto-label issues/PRs using AI
python: true # Format Python with Ruff
prettier: true # Format YAML, JSON, Markdown, CSS
Expand Down
28 changes: 12 additions & 16 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,27 @@ This file provides guidance to AI coding agents (Claude Code, etc.) when working

## 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**.

**Less is more. The simplest solution is the best solution.**
1. **Solve at the owner**: Put behavior in the code path that owns or observes it. For fixes, never guard a symptom with a staleness check, initialization flag, skip-first-call branch, or `try/except` around broken logic; relocate the trigger and delete the wrong path. For features, extend the existing owner rather than creating a parallel abstraction.
2. **Search and reuse first**: Search the whole repository before creating a feature, component, helper, workflow, or utility. Reuse or adapt what exists, consolidate in-scope duplication in the shared owner, and delete duplicate paths. Three similar lines beat a helper nobody else calls.
3. **Delete and modify existing code before creating new code**: Bugfixes are net-negative by default unless deletion and relocation are demonstrably impossible. A new file must first prove it cannot fit cleanly in an existing owner.
4. **Keep scope minimal**: Implement only the simplest complete solution. Avoid impossible-state handling, speculative flags, compatibility shims, policy scaffolding, and unrelated cleanup. Tests are out of scope by default — rely on existing coverage and focused validation; only an uncovered, high-risk regression path justifies minimal new test code.
5. **Ship zero-regression, production-ready changes**: Understand what you remove instead of retaining broken code as insurance. Remove unused imports, functions, types, files, and comments; run relevant cleanup checks; and thoroughly debug and validate the changed owner. Do not break existing features or workflows unless the PR intentionally removes them with evidence.

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.
**Review gate:** for every addition, the reviewer decides whether deleting or changing existing code would have fixed the problem instead — if it would, that is a blocking finding. A missing or thin PR description is never itself a finding.

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?"**
NEVER push to `main`. NEVER force push. Always start work in a new git worktree (`git worktree add`) on a feature branch and open a PR — never edit the primary checkout directly, it may hold in-flight work.

## 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`.
2. Review the full diff in-session against the Core Principles, performance, and the review gate above, then batch the fixes into one commit and push. After each round of bot or human commits, pull and resume the same reviewer on `<last-reviewed-sha>..HEAD` plus anything that delta could have invalidated. Repeat until the local head matches the live head.
3. Hand off or merge only on a clean final pass: one cold full-diff review returning LGTM with no findings, on a head that is still live at merge time.
4. 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 reset or revert commits you did not author.
5. After the PR merges, clean up: remove local worktrees and branches for it, then `git checkout main && git pull`.

## Commands

Expand Down
6 changes: 2 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
# - [tool.*]: Configures settings for various tools (pytest, yapf, etc.) used in the project.

# Installation:
# The Template library can be installed using the command: 'pip install git+https://TOKEN:x-oauth-basic@github.com/ultralytics/template.git@main'
# The Template library can be installed using the command: 'pip install git+https://github.com/ultralytics/template.git'
# For development purposes, you can install the package in editable mode with: 'pip install -e .'
# This approach allows for real-time code modifications without the need for re-installation.

Expand Down Expand Up @@ -85,7 +85,6 @@ example-cli-command = "template.module1:main" # executes `template.module1.main
# Tools settings -------------------------------------------------------------------------------------------------------
[tool.setuptools] # configuration specific to the `setuptools` build backend.
packages = { find = { where = ["."], include = ["template", "template.*"] } }
package-data = { "sample" = ["*.yaml"] }

[tool.setuptools.dynamic]
version = { attr = "template.__version__" }
Expand All @@ -95,8 +94,7 @@ addopts = "--doctest-modules --durations=30 --color=yes"
norecursedirs = [".git", "dist", "build"]

[tool.ruff]
line-length = 120
target-version = "py310"
line-length = 120 # target-version is inferred from project.requires-python

[tool.ruff.lint]
select = ["UP"] # enables Python-upgrade rules
Expand Down
18 changes: 8 additions & 10 deletions template/module1.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,18 @@


def add_numbers(a: int | float, b: int | float) -> int | float:
"""Adds two numbers together using element-wise addition.
"""Add two numbers together.

Args:
a (int | float | torch.Tensor): First number or tensor to add.
b (int | float | torch.Tensor): Second number or tensor to add.
a (int | float): First number to add.
b (int | float): Second number to add.

Returns:
(int | float | torch.Tensor): Sum of the input numbers or tensors. If inputs are tensors, returns a tensor of
the same shape.
(int | float): Sum of the input numbers.

Examples:
>>> result = add_numbers(1, 2) # returns 3
>>> x = torch.tensor([1, 2])
>>> y = torch.tensor([3, 4])
>>> result = add_numbers(x, y) # returns tensor([4, 6])
>>> add_numbers(1, 2)
3
"""
return a + b

Expand All @@ -30,7 +27,8 @@ def main() -> None:
serves as a basic demonstration of program flow and function calling within the Ultralytics framework.

Examples:
>>> main() # Runs the main function which adds 1 + 2
>>> main()
Added 1 + 2 = 3
"""
a = 1
b = 2
Expand Down
Loading