Metadata-Version: 2.4
Name: ownerloom
Version: 0.0.3
Summary: Compile readable CODEOWNERS policies without changing ownership precedence
License-Expression: Apache-2.0
License-File: LICENSE
License-File: NOTICE
Keywords: codeowners,git,pre-commit,compiler,ownership
Author: Astrivant LLC
Requires-Python: >=3.12,!=3.14.1,<4
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Operating System :: MacOS
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Software Development :: Quality Assurance
Classifier: Topic :: Software Development :: Version Control :: Git
Classifier: Typing :: Typed
Requires-Dist: networkx (>=3.7,<4)
Project-URL: Documentation, https://github.com/astrivant/ownerloom/tree/main/docs
Project-URL: Homepage, https://pypi.org/project/ownerloom/
Project-URL: Issues, https://github.com/astrivant/ownerloom/issues
Project-URL: Repository, https://github.com/astrivant/ownerloom
Description-Content-Type: text/markdown

# Ownerloom

[![Coverage](https://raw.githubusercontent.com/astrivant/ownerloom/gh-pages/badges/coverage.svg)](https://github.com/astrivant/ownerloom/blob/gh-pages/badges/coverage.json)

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.

<!-- toc:start -->
**Table of contents**

- [Quick start](#quick-start)
- [Why Ownerloom](#why-ownerloom)
- [Examples](#examples)
- [Architecture](#architecture)
- [Inputs and results](#inputs-and-results)
- [Integrations and development](#integrations-and-development)
- [License and provenance](#license-and-provenance)
<!-- toc:end -->

## Quick start

With Python 3.12+ and Git available, run inside your existing repository:

```bash
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.

<details>
<summary>1. Keep shared ownership clear while retaining a team's override</summary>

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

```text
/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**

```text
/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.

</details>

<details>
<summary>2. Give a complete component one maintainable ownership rule</summary>

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

```text
/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**

```text
/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.

</details>

## Architecture

```mermaid
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](docs/compiler.md) 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](docs/releases.md#configure-signing-and-publication)
for these administrator-managed inputs.

```python
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](docs/integrations.md) 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](CONTRIBUTING.md), [security reporting](SECURITY.md),
[development](docs/development.md), [release verification](docs/releases.md),
[CI permissions](docs/permissions.md), and the portable [SKILL.md](SKILL.md)
([browse online](https://github.com/astrivant/ownerloom/blob/main/SKILL.md)).
The implementation follows [RFC #94](https://github.com/astrivant/product-research/pull/94).

## License and provenance

The runtime compiler is [Apache-2.0](LICENSE), copyright Astrivant LLC.
The [extraction manifest](docs/provenance.json) binds its source to Polyad's merged
compiler and records the owner's licensing choice. Development helpers retain
their [separate notices](scripts/NOTICE.md); they are excluded from the wheel.

