Ownerloom
Keep CODEOWNERS readable as your repository grows. Ownerloom groups literal paths by directory, removes redundant rules, and preserves the order that decides who owns each path. One Python package replaces copied formatting scripts across projects.
Table of contents
- Quick start
- Why Ownerloom
- Examples
- Architecture
- Inputs and results
- Integrations and development
- License and provenance
Quick start
With Python 3.12+ and Git available, run inside your existing repository:
python -m pip install ownerloom
ownerloom --check
ownerloom --write
git diff -- .github/CODEOWNERS
Review and stage the result yourself. Ownerloom never commits, pushes or changes repository permissions. Python 3.14.1 is excluded by the NetworkX dependency.
Why Ownerloom
- Readable policy: keep related directories together without moving an override ahead of the rule it overrides.
- Conservative changes: preserve comments, GitLab sections, wildcard rules and unfamiliar syntax as boundaries. Retained syntax still needs provider validation.
- Reviewable automation: check the exact committed file and tree before push, rather than allowing an unstaged fix to mask stale committed policy.
- Reusable integration: the same typed library powers the CLI, pre-commit and CI. Normal compilation is offline and does not execute repository hooks or source.
Examples
These examples use tracked paths and placeholder team handles. Expand each case to see the policy before and after compilation.
1. Keep shared ownership clear while retaining a team's override
The platform team owns pkg/, the API team owns pkg/api/, and the docs team owns
docs/. Repeated file rules scatter those responsibilities across the file.
The tracked paths are pkg/core.py, pkg/api/routes.py, pkg/api/models.py and
docs/usage.md.
Before: seven rules
/pkg/api/routes.py @acme/api
/docs/usage.md @acme/docs
/pkg/ @acme/platform
/pkg/core.py @acme/platform
/pkg/api/ @acme/api
/docs/ @acme/docs
/pkg/api/models.py @acme/api
Run ownerloom --write.
After: three rules
/docs/ @acme/docs
/pkg/ @acme/platform
/pkg/api/ @acme/api
Reviewers can see each team's scope together. The API override stays after the broader package rule, so it still wins. Existing directory rules already cover new files; removing the repeated file rules does not change that policy.
2. Give a complete component one maintainable ownership rule
The payments team owns every tracked file in pkg/billing/: invoice.py,
refunds.py and tax.py. The catalog team separately owns
pkg/catalog/search.py. The teams agree that future billing files should also
belong to payments.
Before: four rules
/pkg/billing/tax.py @acme/payments
/pkg/catalog/search.py @acme/catalog
/pkg/billing/invoice.py @acme/payments
/pkg/billing/refunds.py @acme/payments
Run ownerloom --write --consolidate.
After: two rules
/pkg/billing/ @acme/payments
/pkg/catalog/search.py @acme/catalog
A new billing module now inherits the team's ownership without another file rule.
This is an explicit policy choice: --consolidate checks complete, uniform tracked
coverage and introduces ownership for future files in the new directory scope.
Normal --write does not introduce that scope. Review it with the affected teams.
Architecture
flowchart LR
A[CODEOWNERS text] --> C[Literal runs and opaque boundaries]
B[Tracked Git inventory] --> C
C --> D[Remove shadowed and inherited rules]
D --> E[Precedence DAG]
E --> F[Deterministic tree order]
F --> G[Compilation result]
G --> H[Check or atomic write]
classDef input fill:#829B85,stroke:#647D8B,color:#243746
classDef pass fill:#C4AC70,stroke:#647D8B,color:#243746
class A,B input
class C,D,E,F,G,H pass
The pure compiler accepts explicit text and paths. The CLI owns Git reads and atomic writes. NetworkX orders the precedence graph; it does not interpret provider policy. See the compiler contract for supported syntax, consolidation and failure behavior.
Inputs and results
| Input | Default | Purpose |
|---|---|---|
--repo PATH |
Current directory | Existing repository root |
--file PATH |
.github/CODEOWNERS |
Relative ownership file; select GitLab's path explicitly |
--check |
Required choice | Report whether selected text is normalized |
--write |
Required choice | Atomically replace working text; never stage it |
--revision REV |
Index inventory and working text | Check committed text and its tree together; check mode only |
--consolidate |
Off | Explicitly combine complete uniform subtrees, including future files |
Exit status is 0 for normalized or written content, 1 for formatting drift,
and 2 for invalid inputs or operational errors. Runtime use requires no credentials.
Release jobs use the repository secrets PYPI_API_TOKEN, COSIGN_PRIVATE_KEY and
COSIGN_PASSWORD, plus the trusted COSIGN_PUBLIC_KEY_SHA256 variable. GitHub
supplies the repository, source SHA, tag and job token. See release setup
for these administrator-managed inputs.
from ownerloom import compile_owners
result = compile_owners("/z @team\n/a @team\n", frozenset({"a", "z"}))
assert result.text == "/a @team\n/z @team\n"
Integrations and development
Use the pre-commit and migration guide to replace local copies. Keep a provider-aware syntax/path linter alongside Ownerloom; formatting does not establish account eligibility or enforce required reviews.
See contributing, security reporting, development, release verification, CI permissions, and the portable SKILL.md (browse online). The implementation follows RFC #94.
License and provenance
The runtime compiler is Apache-2.0, copyright Astrivant LLC. The extraction manifest binds its source to Polyad's merged compiler and records the owner's licensing choice. Development helpers retain their separate notices; they are excluded from the wheel.
Metadata
Release files for ownerloom 0.0.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| ownerloom-0.0.2.tar.gz | 13.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| ownerloom-0.0.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 29.5 kB
Release files / ownerloom-0.0.2.tar.gz
| Download URL | ownerloom-0.0.2.tar.gz |
|---|---|
| Size | 13.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
474dd8a094d294a1db8ab8da666e6a7e00f86df1d1629d8e18f7d84763aa28f1
|
|
BLAKE2b-256 checksum How to use checksums |
22f1bcaf3b2515a22b33ea028638c1949e2042ded5e91d1b0dc36eef9a7ded48
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Release files / ownerloom-0.0.2-py3-none-any.whl
| Download URL | ownerloom-0.0.2-py3-none-any.whl |
|---|---|
| Size | 15.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
cfe2fac7967f4b1cd70bc2ee81f8c721a0b43e8e8c236a50fc13e4607b3dda3f
|
|
BLAKE2b-256 checksum How to use checksums |
8c34d894a4e448c2759bb8e03e9795f8ccdc7dd6ad9bfe53c09cfd59ddd67853
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|