Metadata-Version: 2.5
Name: bylaw
Version: 0.1.1
Summary: Reviews pull requests against your repository's own rules and requirements.
Project-URL: Homepage, https://github.com/tunahanaliozturk/bylaw
Project-URL: Documentation, https://github.com/tunahanaliozturk/bylaw#readme
Project-URL: Issues, https://github.com/tunahanaliozturk/bylaw/issues
Project-URL: Changelog, https://github.com/tunahanaliozturk/bylaw/blob/main/CHANGELOG.md
Author: Tunahan Ali Ozturk
License-Expression: MIT
License-File: LICENSE
Keywords: code-review,editorconfig,github-actions,llm,pull-requests,requirements
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Quality Assurance
Requires-Python: >=3.13
Requires-Dist: anthropic>=1.14.0
Requires-Dist: httpx2>=2.13.1
Requires-Dist: httpx>=0.28.1
Requires-Dist: openai>=3.31.0
Requires-Dist: pydantic>=2.14.1
Description-Content-Type: text/markdown

<p align="center">
  <picture>
    <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/tunahanaliozturk/bylaw/main/docs/images/wordmark-dark.svg">
    <img src="https://raw.githubusercontent.com/tunahanaliozturk/bylaw/main/docs/images/wordmark-light.svg" alt="bylaw" width="236">
  </picture>
</p>

<p align="center">
  Pull request review against your repository's own rules and the requirements the change claims to implement.
</p>

<p align="center">
  <a href="https://github.com/tunahanaliozturk/bylaw/actions/workflows/ci.yml"><img src="https://github.com/tunahanaliozturk/bylaw/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
  <a href="LICENSE"><img src="https://img.shields.io/badge/licence-MIT-blue" alt="MIT licence"></a>
  <img src="https://img.shields.io/badge/python-3.13%2B-blue" alt="Python 3.13+">
</p>

Most AI reviewers give general advice. bylaw reviews a pull request against what your repository already wrote down:

- **Your rules.** `.editorconfig`, linter configs, `CONTRIBUTING.md`, `AGENTS.md`. Every rule finding cites the line it comes from.
- **Your requirements.** The acceptance criteria in the issues the pull request closes and the specs it links, including what maintainers added in the issue's comments. An issue written as prose gets criteria inferred from its text, marked as such. The summary says which are met, partly met or missing, and flags changes nobody asked for.
- **Security and bugs.** Injection, secrets, unsafe deserialisation, missing authorisation, and plain bugs.

Findings go on the changed lines as review comments. A re-run never repeats a comment and resolves the threads of findings that were fixed.

## What a review looks like

Real output on [bylaw-demo pull request 7](https://github.com/tunahanaliozturk/bylaw-demo/pull/7). An inline finding with its rule citation and a one-click fix:

<picture>
  <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/tunahanaliozturk/bylaw/main/docs/images/screenshot-inline-dark.png">
  <img src="https://raw.githubusercontent.com/tunahanaliozturk/bylaw/main/docs/images/screenshot-inline-light.png" alt="A critical SQL injection finding citing CONTRIBUTING.md line 3, with a suggested change" width="600">
</picture>

The summary checks the change against the acceptance criteria of the issue it closes:

<picture>
  <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/tunahanaliozturk/bylaw/main/docs/images/screenshot-summary-dark.png">
  <img src="https://raw.githubusercontent.com/tunahanaliozturk/bylaw/main/docs/images/screenshot-summary-light.png" alt="The bylaw summary with a requirements table: one criterion partly met, two missing" width="600">
</picture>

## Quick start

**GitHub Action.** Add `.github/workflows/bylaw.yml`:

```yaml
name: bylaw
on:
  pull_request:
    types: [opened, synchronize, reopened, ready_for_review]
permissions:
  contents: read
  pull-requests: write
  issues: read
jobs:
  review:
    runs-on: ubuntu-latest
    steps:
      - uses: tunahanaliozturk/bylaw@v0
        with:
          api-key: ${{ secrets.ANTHROPIC_API_KEY }}
```

Without a key it still runs the deterministic checks. OpenAI works too (`provider: openai`, `model: ...`). Fork pull requests need [the `pull_request_target` recipe](https://github.com/tunahanaliozturk/bylaw/blob/main/docs/recipes/pull-request-target.yml); read the warning at its top first.

**Claude Code or Codex.** The host's own model reviews, so no API key is needed:

```
/plugin marketplace add tunahanaliozturk/bylaw        # Claude Code
/plugin install bylaw@bylaw
codex plugin marketplace add tunahanaliozturk/bylaw   # Codex, then /plugins
```

Then ask "review pull request 12 with bylaw", or run `/bylaw-review 12` in Claude Code. Details: [docs/hosts.md](https://github.com/tunahanaliozturk/bylaw/blob/main/docs/hosts.md).

**On your branch, before the pull request.** Ask Claude Code or Codex to "review this branch with bylaw", or use the CLI with [uv](https://docs.astral.sh/uv/):

```
alias bylaw='uvx bylaw'
bylaw context --base main --output context.json
bylaw review --context context.json   # prints the findings as JSON; set ANTHROPIC_API_KEY for the model review
```

## How it works

<picture>
  <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/tunahanaliozturk/bylaw/main/docs/images/flow-dark.png">
  <img src="https://raw.githubusercontent.com/tunahanaliozturk/bylaw/main/docs/images/flow-light.png" alt="Pull request, then context, then deterministic checks and the reviewer, then validation, then comments on the pull request" width="100%">
</picture>

1. **Context.** bylaw reads the diff, the rule files and `.bylaw.toml` from the **base** branch (so a change cannot loosen its own review), and the issues and specs the change links.
2. **Review.** A model reviews with a fixed brief and a strict output schema. Text from the pull request, its issues and specs is treated as data, never as instructions.
3. **Validate.** Every finding must sit on a line the change adds, and every rule citation must point at a real line. Anything else is dropped before it can be posted.
4. **Post.** Inline comments for findings at or above the threshold, one summary comment with the requirement checklist. State lives in that summary, so there is no server and no database.

The design and its trade-offs: [docs/design.md](https://github.com/tunahanaliozturk/bylaw/blob/main/docs/design.md) and the [ADRs](https://github.com/tunahanaliozturk/bylaw/tree/main/docs/adr/).

## Configuration

Optional `.bylaw.toml` at the repository root, always read from the base branch:

```toml
severity_threshold = "medium"   # inline comments at or above this; the rest go in the summary
max_comments = 15               # inline comments per run, 0 to 50
spec_globs = ["docs/specs/**", "docs/adr/**", "**/REQUIREMENTS.md"]
issue_repos = []                # other repositories whose issues may be quoted, e.g. ["acme/roadmap"]
input_token_budget = 300000     # model input in tokens; the largest files are left out first
```

## Evaluation

bylaw is measured on 50 labelled pull requests in Python, TypeScript, Go and C#: planted security problems, bugs, rule breaks, missed acceptance criteria, scope creep, and clean changes. Results are per model and date: [docs/eval/README.md](https://github.com/tunahanaliozturk/bylaw/blob/main/docs/eval/README.md).

Runs from 16 October 2026: the GitHub Action calling the API, and Claude Code and Codex reviewing as hosts with no API key ([API](https://github.com/tunahanaliozturk/bylaw/blob/main/eval/results/2026-10-16-opus-5-5/report.md), [Claude Code](https://github.com/tunahanaliozturk/bylaw/blob/main/eval/results/2026-10-16-claude-code-host/report.md), [Codex](https://github.com/tunahanaliozturk/bylaw/blob/main/eval/results/2026-10-16-codex-host/report.md)):

| | Action, `claude-opus-5-5` | Claude Code host | Codex host, `gpt-6-sol` |
| --- | --- | --- | --- |
| Planted security problems found | 10 of 10 | 10 of 10 | 10 of 10 |
| Planted bugs found | 10 of 10 | 10 of 10 | 10 of 10 |
| Rule breaks found | 10 of 10 | 10 of 10 | 10 of 10 |
| Rule citations on the right line | 8 of 8 | 8 of 8 | 8 of 8 |
| Acceptance criteria judged correctly | 21 of 21 | 21 of 21 | 21 of 21 |
| Scope creep found | 4 of 4 | 4 of 4 | 4 of 4 |
| Clean pull requests with an inline comment | 1 of 9 | 0 of 9 | 1 of 9 |
| Model findings dropped by validation | 1 of 74 | 0 of 53 | 0 of 56 |
| Median review time, cost per review | 6.5 s, about $0.03 | no API cost | no API cost |

Both inline comments on clean changes are the same remark on the same case (`py-clean-contained-path`): the upload path is compared after resolving one side only. Host runs saw the briefs under neutral names, so case names could not hint at the answers.

These are small, planted changes; real pull requests are larger and messier ([ADR 0010](https://github.com/tunahanaliozturk/bylaw/blob/main/docs/adr/0010-evaluation-on-planted-cases.md)), so treat the numbers as an upper bound on what the model catches.

## Costs

A review is one model call. On the evaluation above it used about 3,900 input and 520 output tokens per pull request, about $0.03 at Claude Opus 5.5 prices; a large pull request costs more, up to the input budget (`input_token_budget`, 300,000 tokens by default). To cap spending, set a monthly limit for the key or workspace in the provider's console; bylaw cannot see your balance.

## Contributing and security

Contributions are welcome: [CONTRIBUTING.md](https://github.com/tunahanaliozturk/bylaw/blob/main/CONTRIBUTING.md). Please report vulnerabilities privately as described in [SECURITY.md](https://github.com/tunahanaliozturk/bylaw/blob/main/SECURITY.md), not in a public issue.
bylaw has no server and collects no data; what it sends where is in [docs/privacy.md](https://github.com/tunahanaliozturk/bylaw/blob/main/docs/privacy.md).

## Licence

[MIT](https://github.com/tunahanaliozturk/bylaw/blob/main/LICENSE)
