diffly-cli 0.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- diffly_cli-0.4.0/.github/workflows/ci.yml +21 -0
- diffly_cli-0.4.0/.github/workflows/example-diffly.yml +10 -0
- diffly_cli-0.4.0/.github/workflows/publish.yml +48 -0
- diffly_cli-0.4.0/.gitignore +27 -0
- diffly_cli-0.4.0/CHANGELOG.md +53 -0
- diffly_cli-0.4.0/CONTRIBUTING.md +39 -0
- diffly_cli-0.4.0/LICENSE +107 -0
- diffly_cli-0.4.0/PKG-INFO +341 -0
- diffly_cli-0.4.0/README.md +212 -0
- diffly_cli-0.4.0/SECURITY.md +20 -0
- diffly_cli-0.4.0/action/format_comment.py +66 -0
- diffly_cli-0.4.0/action/post_comment.py +86 -0
- diffly_cli-0.4.0/action.yml +41 -0
- diffly_cli-0.4.0/assets/diffly-cli-demo.gif +0 -0
- diffly_cli-0.4.0/assets/logo.png +0 -0
- diffly_cli-0.4.0/assets/real-captures/kubernetes-141413.ansi +41 -0
- diffly_cli-0.4.0/assets/real-captures/ruff-27808.ansi +41 -0
- diffly_cli-0.4.0/assets/real-captures/vscode-330848.ansi +41 -0
- diffly_cli-0.4.0/assets/screenshots/kubernetes-141413.png +0 -0
- diffly_cli-0.4.0/assets/screenshots/ruff-27808.png +0 -0
- diffly_cli-0.4.0/assets/screenshots/vscode-330848.png +0 -0
- diffly_cli-0.4.0/demo/kubernetes-141413-phase2.md +389 -0
- diffly_cli-0.4.0/demo/kubernetes-141413.md +293 -0
- diffly_cli-0.4.0/demo/ruff-27808-phase2.md +469 -0
- diffly_cli-0.4.0/demo/ruff-27808.md +383 -0
- diffly_cli-0.4.0/demo/vscode-330848.md +201 -0
- diffly_cli-0.4.0/docs/audit-report.md +63 -0
- diffly_cli-0.4.0/docs/benchmarks.md +50 -0
- diffly_cli-0.4.0/docs/launch/reddit-opensource.md +32 -0
- diffly_cli-0.4.0/docs/launch/reddit-programming.md +32 -0
- diffly_cli-0.4.0/docs/launch/show-hn.md +30 -0
- diffly_cli-0.4.0/docs/launch/x-thread.md +44 -0
- diffly_cli-0.4.0/docs/live-model-catalog.json +1 -0
- diffly_cli-0.4.0/docs/phase-0-research.md +27 -0
- diffly_cli-0.4.0/docs/phase-2-contract.md +31 -0
- diffly_cli-0.4.0/docs/visual-verification.md +11 -0
- diffly_cli-0.4.0/homebrew/diffly-cli.rb +24 -0
- diffly_cli-0.4.0/install.sh +27 -0
- diffly_cli-0.4.0/pyproject.toml +40 -0
- diffly_cli-0.4.0/scripts/capture_real_sessions.sh +21 -0
- diffly_cli-0.4.0/scripts/discover_benchmarks.py +84 -0
- diffly_cli-0.4.0/scripts/render_real_captures.py +85 -0
- diffly_cli-0.4.0/scripts/run_benchmarks.py +101 -0
- diffly_cli-0.4.0/scripts/validate_action.py +11 -0
- diffly_cli-0.4.0/scripts/write_benchmarks_doc.py +83 -0
- diffly_cli-0.4.0/src/diffly_cli/__init__.py +3 -0
- diffly_cli-0.4.0/src/diffly_cli/__main__.py +6 -0
- diffly_cli-0.4.0/src/diffly_cli/astmap.py +121 -0
- diffly_cli-0.4.0/src/diffly_cli/cli.py +770 -0
- diffly_cli-0.4.0/src/diffly_cli/diffparse.py +117 -0
- diffly_cli-0.4.0/src/diffly_cli/explainer.py +227 -0
- diffly_cli-0.4.0/src/diffly_cli/github.py +181 -0
- diffly_cli-0.4.0/src/diffly_cli/local.py +151 -0
- diffly_cli-0.4.0/src/diffly_cli/models.py +68 -0
- diffly_cli-0.4.0/src/diffly_cli/redact.py +59 -0
- diffly_cli-0.4.0/src/diffly_cli/triage.py +142 -0
- diffly_cli-0.4.0/src/diffly_cli/update.py +161 -0
- diffly_cli-0.4.0/tests/test_action.py +113 -0
- diffly_cli-0.4.0/tests/test_explainer.py +125 -0
- diffly_cli-0.4.0/tests/test_local.py +141 -0
- diffly_cli-0.4.0/tests/test_regressions.py +212 -0
- diffly_cli-0.4.0/tests/test_triage.py +74 -0
- diffly_cli-0.4.0/upgrade.sh +70 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
pull_request:
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
test:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
strategy:
|
|
11
|
+
matrix:
|
|
12
|
+
python-version: ["3.10", "3.11", "3.12", "3.13"]
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v4
|
|
15
|
+
- uses: actions/setup-python@v5
|
|
16
|
+
with:
|
|
17
|
+
python-version: ${{ matrix.python-version }}
|
|
18
|
+
- name: Install
|
|
19
|
+
run: python -m pip install .[dev]
|
|
20
|
+
- name: Test
|
|
21
|
+
run: pytest -q
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
id-token: write # required for trusted publishing (OIDC)
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
build:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
environment: pypi
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
|
|
18
|
+
- uses: actions/setup-python@v5
|
|
19
|
+
with:
|
|
20
|
+
python-version: "3.13"
|
|
21
|
+
|
|
22
|
+
- name: Install build tools
|
|
23
|
+
run: pip install build
|
|
24
|
+
|
|
25
|
+
- name: Build package
|
|
26
|
+
run: python -m build
|
|
27
|
+
|
|
28
|
+
- name: Upload artifacts
|
|
29
|
+
uses: actions/upload-artifact@v4
|
|
30
|
+
with:
|
|
31
|
+
name: dist
|
|
32
|
+
path: dist/
|
|
33
|
+
|
|
34
|
+
publish:
|
|
35
|
+
needs: build
|
|
36
|
+
runs-on: ubuntu-latest
|
|
37
|
+
environment: pypi
|
|
38
|
+
permissions:
|
|
39
|
+
id-token: write
|
|
40
|
+
steps:
|
|
41
|
+
- name: Download artifacts
|
|
42
|
+
uses: actions/download-artifact@v4
|
|
43
|
+
with:
|
|
44
|
+
name: dist
|
|
45
|
+
path: dist/
|
|
46
|
+
|
|
47
|
+
- name: Publish to PyPI
|
|
48
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
__pycache__/
|
|
2
|
+
*.py[cod]
|
|
3
|
+
*$py.class
|
|
4
|
+
|
|
5
|
+
.venv/
|
|
6
|
+
venv/
|
|
7
|
+
env/
|
|
8
|
+
.env
|
|
9
|
+
.env.*
|
|
10
|
+
!.env.example
|
|
11
|
+
|
|
12
|
+
.pytest_cache/
|
|
13
|
+
.coverage
|
|
14
|
+
htmlcov/
|
|
15
|
+
.mypy_cache/
|
|
16
|
+
.ruff_cache/
|
|
17
|
+
|
|
18
|
+
build/
|
|
19
|
+
dist/
|
|
20
|
+
*.egg-info/
|
|
21
|
+
|
|
22
|
+
.DS_Store
|
|
23
|
+
.idea/
|
|
24
|
+
.vscode/
|
|
25
|
+
|
|
26
|
+
# Local demo and scratch files
|
|
27
|
+
*.local.md
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to diffly are documented here. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
4
|
+
|
|
5
|
+
## [Unreleased]
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- Interactive mode no longer breaks imports on platforms without POSIX terminal support; it now falls back to the standard report.
|
|
10
|
+
- Running bare `diffly` in non-interactive environments (CI, pipes) prints help instead of hanging on prompts.
|
|
11
|
+
- Pressing Escape alone in the interactive selector no longer blocks waiting for arrow-key bytes.
|
|
12
|
+
- `CHECKS_PENDING` risk-flag evidence now lists the actual pending check names instead of the literal state string.
|
|
13
|
+
- Diff parsing ignores `` markers when computing changed line numbers, fixing off-by-one symbol attribution.
|
|
14
|
+
- GitHub Action comment publishing distinguishes listing 404s (no comments yet) from publish failures via a typed error instead of string matching.
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
|
|
18
|
+
- **Local mode (`diffly local`):** triage git changes in any folder on disk — uncommitted working-tree edits by default, or a branch comparison with `--base main`. Works fully offline for private, archived, or removed repositories; untracked files are included and CI-check rules are skipped as not applicable.
|
|
19
|
+
- Generated explanations now render in the interactive review screen as a toggleable section, including clear setup guidance when no LLM key is configured.
|
|
20
|
+
- Loading spinners with progress messaging while pull-request data is fetched.
|
|
21
|
+
- Centered terminal composition across the wizard, setup walkthrough, interactive review, doctor, and version screens.
|
|
22
|
+
- The guided wizard prompts for a **Repository URL** with explicit format hints, confirms when deterministic-only mode was chosen, and accepts pasted pull-request URLs without asking for the number again.
|
|
23
|
+
- `-V` / `--version` flag on the root command and a `python -m diffly_cli` entry point.
|
|
24
|
+
- Guided wizard arguments are built from the real parser defaults so new options cannot drift between the wizard and the CLI.
|
|
25
|
+
- The repository argument now accepts full pull-request URLs (`diffly pr https://github.com/owner/repo/pull/12`), inferring the number; the guided wizard skips the number prompt when a URL is pasted.
|
|
26
|
+
- `CONTRIBUTING.md`, `SECURITY.md`, and this changelog.
|
|
27
|
+
|
|
28
|
+
### Changed
|
|
29
|
+
|
|
30
|
+
- Expanded LICENSE from the bare MIT template to a documented four-part license that keeps the standard MIT grant and adds definitions, contribution terms, verdict disclaimers, an extended warranty/liability statement, and general terms.
|
|
31
|
+
- Usage examples in the README and `--help` epilog point at live public pull requests.
|
|
32
|
+
|
|
33
|
+
## [0.2.1] - 2026-08-21
|
|
34
|
+
|
|
35
|
+
### Changed
|
|
36
|
+
|
|
37
|
+
- Renamed the all-clear verdict from `SHIP` to `PASS`; `SHIP` remains accepted as a legacy alias and `legacy_verdict` preserves it in JSON output.
|
|
38
|
+
- `diffly` is now the primary executable name with `diffly-cli` kept as a compatibility alias.
|
|
39
|
+
- Consolidated the interactive UX: bare `diffly` opens the guided PR wizard, plus new `setup`, `doctor`, `help`, and `version` subcommands.
|
|
40
|
+
- Pending checks are quarantined explicitly (`CHECKS_PENDING`) rather than folded into unknown-check handling.
|
|
41
|
+
|
|
42
|
+
## [0.2.0] - 2026-08-20
|
|
43
|
+
|
|
44
|
+
### Added
|
|
45
|
+
|
|
46
|
+
- Hardened triage for large and incomplete GitHub responses: paginated files, commits, check runs, statuses, and repository tree; raw-diff fallback when the unified diff exceeds GitHub's size limit.
|
|
47
|
+
|
|
48
|
+
## [0.1.0] - 2026-08-18
|
|
49
|
+
|
|
50
|
+
### Added
|
|
51
|
+
|
|
52
|
+
- Phase 1 deterministic triage: blast-radius map, fixed risk rules, one-page Markdown report, stable JSON output, and the bundled GitHub Action.
|
|
53
|
+
- Phase 2 optional literate-diff explainer with strict output validation, secret redaction, and fail-closed behavior.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Contributing to diffly
|
|
2
|
+
|
|
3
|
+
Thanks for helping make pull-request triage deterministic. This guide covers what you need to get productive quickly.
|
|
4
|
+
|
|
5
|
+
## Development setup
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
git clone https://github.com/VIVAAN-DHAWAN/diffly-cli.git
|
|
9
|
+
cd diffly-cli
|
|
10
|
+
python -m venv .venv
|
|
11
|
+
. .venv/bin/activate
|
|
12
|
+
python -m pip install -e '.[dev]'
|
|
13
|
+
pytest -q
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
The CI matrix runs the suite on Python 3.10 through 3.13.
|
|
17
|
+
|
|
18
|
+
## Ground rules
|
|
19
|
+
|
|
20
|
+
- **Determinism is the product.** The same PR data must always produce the same flags and verdict. Never let heuristics, network state, or LLM prose change a verdict.
|
|
21
|
+
- **Fail closed.** When evidence is missing (truncated tree, unavailable checks), quarantine rather than assume success.
|
|
22
|
+
- **Keep the LLM sandboxed.** Generated explanations are clearly labeled, validated against a strict contract, redacted, and cannot influence `PASS`, `QUARANTINE`, or `BLOCK`. See [`docs/phase-2-contract.md`](docs/phase-2-contract.md).
|
|
23
|
+
- **Focused changes.** One behavior change per pull request, with regression tests.
|
|
24
|
+
|
|
25
|
+
## Pull-request checklist
|
|
26
|
+
|
|
27
|
+
1. Add or update tests for any behavior change.
|
|
28
|
+
2. Run `pytest -q` locally.
|
|
29
|
+
3. Update [`CHANGELOG.md`](CHANGELOG.md) under **Unreleased**.
|
|
30
|
+
4. If you changed user-facing behavior, update the README section that documents it.
|
|
31
|
+
5. Verify any new example commands against live public repositories — broken examples are bugs.
|
|
32
|
+
|
|
33
|
+
## Reporting bugs
|
|
34
|
+
|
|
35
|
+
Open an issue with the command you ran, the full output, your OS and Python version, and the repository/PR analyzed (public ones only). Run `diffly doctor` and include its output for environment problems.
|
|
36
|
+
|
|
37
|
+
## Security
|
|
38
|
+
|
|
39
|
+
Do not open public issues for security reports. Use [GitHub's security advisory form](https://github.com/VIVAAN-DHAWAN/diffly-cli/security/advisories/new). See [`SECURITY.md`](SECURITY.md).
|
diffly_cli-0.4.0/LICENSE
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
MIT License — diffly
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Vivaan Dhawan
|
|
4
|
+
|
|
5
|
+
================================================================================
|
|
6
|
+
PART 1 — THE LICENSE GRANT (standard MIT text)
|
|
7
|
+
================================================================================
|
|
8
|
+
|
|
9
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
10
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
11
|
+
in the Software without restriction, including without limitation the rights
|
|
12
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
13
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
14
|
+
furnished to do so, subject to the following conditions:
|
|
15
|
+
|
|
16
|
+
The above copyright notice and this permission notice shall be included in all
|
|
17
|
+
copies or substantial portions of the Software.
|
|
18
|
+
|
|
19
|
+
================================================================================
|
|
20
|
+
PART 2 — DEFINITIONS AND CLARIFICATIONS
|
|
21
|
+
================================================================================
|
|
22
|
+
|
|
23
|
+
These clarifications are part of this license. Where Part 1 and Part 2 could
|
|
24
|
+
be read differently, Part 1 controls; Part 2 explains intent.
|
|
25
|
+
|
|
26
|
+
1. "Software" means the diffly source code, its bundled GitHub Action, its
|
|
27
|
+
install scripts, its documentation, and any object code or distributions
|
|
28
|
+
built from them, in whole or in part.
|
|
29
|
+
|
|
30
|
+
2. "Contribution" means any work submitted to the project — including pull
|
|
31
|
+
requests, patches, and documentation — that is intentionally offered for
|
|
32
|
+
inclusion in the Software. By submitting a Contribution you agree it is
|
|
33
|
+
licensed under this same license, with no additional terms or conditions,
|
|
34
|
+
to the maximum extent permitted by law. You confirm you have the right to
|
|
35
|
+
license what you submit.
|
|
36
|
+
|
|
37
|
+
3. Verdicts are opinions, not guarantees. The PASS, QUARANTINE, BLOCK, and
|
|
38
|
+
related outputs produced by the Software are deterministic heuristics
|
|
39
|
+
applied at a point in time against data available at that moment. They are
|
|
40
|
+
review aids only. They do not certify correctness, security, safety,
|
|
41
|
+
fitness for production, compliance with any law, regulation, or standard,
|
|
42
|
+
or the absence of defects in any analyzed code, repository, or change.
|
|
43
|
+
You remain solely responsible for all decisions about the software you
|
|
44
|
+
review, merge, ship, or operate.
|
|
45
|
+
|
|
46
|
+
4. Network services. The Software may contact third-party services you direct
|
|
47
|
+
it to (for example the GitHub REST API) and, only when explicitly enabled
|
|
48
|
+
by you, an OpenAI-compatible model endpoint you configure. Those services
|
|
49
|
+
are governed by their own terms. The project authors neither operate those
|
|
50
|
+
services nor are party to your relationship with them.
|
|
51
|
+
|
|
52
|
+
5. Trademarks. This license grants no rights in the names "diffly",
|
|
53
|
+
"diffly-cli", or any related marks, logos, or trade dress, except as
|
|
54
|
+
strictly required for reasonable attribution or nominative fair use.
|
|
55
|
+
|
|
56
|
+
================================================================================
|
|
57
|
+
PART 3 — WARRANTY AND LIABILITY (extended statement)
|
|
58
|
+
================================================================================
|
|
59
|
+
|
|
60
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
61
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
62
|
+
FITNESS FOR A PARTICULAR PURPOSE, TITLE, NON-INFRINGEMENT, ACCURACY OF OUTPUT,
|
|
63
|
+
AND UNINTERRUPTED OR ERROR-FREE OPERATION. SOME JURISDICTIONS DO NOT ALLOW THE
|
|
64
|
+
EXCLUSION OF CERTAIN IMPLIED WARRANTIES, SO SOME OF THE ABOVE MAY NOT APPLY TO
|
|
65
|
+
YOU TO THE EXTENT LAW REQUIRES IT.
|
|
66
|
+
|
|
67
|
+
IN NO EVENT AND UNDER NO LEGAL THEORY — WHETHER IN CONTRACT, TORT (INCLUDING
|
|
68
|
+
NEGLIGENCE), STRICT LIABILITY, STATUTE, OR OTHERWISE — SHALL THE AUTHORS,
|
|
69
|
+
COPYRIGHT HOLDERS, OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
70
|
+
INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
71
|
+
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
72
|
+
DATA, PROFITS, GOODWILL, OR REPUTATION; BUSINESS INTERRUPTION; SECURITY
|
|
73
|
+
INCIDENTS; BUILD FAILURES; OR RELEASED DEFECTS) HOWEVER CAUSED AND ON ANY
|
|
74
|
+
THEORY OF LIABILITY, ARISING IN ANY WAY OUT OF OR IN CONNECTION WITH THE
|
|
75
|
+
SOFTWARE OR ITS USE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
76
|
+
|
|
77
|
+
TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THE TOTAL AGGREGATE
|
|
78
|
+
LIABILITY OF THE AUTHORS AND COPYRIGHT HOLDERS FOR ALL CLAIMS RELATING TO THE
|
|
79
|
+
SOFTWARE SHALL BE LIMITED TO THE GREATER OF ONE HUNDRED UNITED STATES DOLLARS
|
|
80
|
+
(USD 100) OR THE AMOUNT YOU PAID FOR THE SOFTWARE, WHICH BY DEFAULT IS ZERO.
|
|
81
|
+
|
|
82
|
+
================================================================================
|
|
83
|
+
PART 4 — GENERAL TERMS
|
|
84
|
+
================================================================================
|
|
85
|
+
|
|
86
|
+
1. Compliance with law. Your use of the Software must comply with applicable
|
|
87
|
+
export-control, sanctions, privacy, and other laws.
|
|
88
|
+
|
|
89
|
+
2. Severability. If any provision of this license is held unenforceable, it
|
|
90
|
+
will be modified to the minimum extent necessary, and the remaining
|
|
91
|
+
provisions stay in force.
|
|
92
|
+
|
|
93
|
+
3. No waiver. Failure to enforce any provision is not a waiver of it.
|
|
94
|
+
|
|
95
|
+
4. Termination. The licenses granted here terminate automatically if you
|
|
96
|
+
breach this license. They otherwise survive as long as the copyright law
|
|
97
|
+
of your jurisdiction requires, and are perpetual where permitted.
|
|
98
|
+
|
|
99
|
+
5. Entire agreement. This license is the entire agreement between you and the
|
|
100
|
+
copyright holders concerning the Software, superseding any other terms
|
|
101
|
+
communicated alongside copies of it.
|
|
102
|
+
|
|
103
|
+
6. Language. This license is written in English; translations are for
|
|
104
|
+
convenience only, and the English text controls.
|
|
105
|
+
|
|
106
|
+
THIS LICENSE FOLLOWS THE MIT LICENSE TEMPLATE AND ADDS CLARIFYING MATERIAL.
|
|
107
|
+
THE GRANT IN PART 1 REMAINS THE GOVERNING PERMISSION.
|
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: diffly-cli
|
|
3
|
+
Version: 0.4.0
|
|
4
|
+
Summary: Deterministic triage for large GitHub pull requests
|
|
5
|
+
Author: Vivaan Dhawan
|
|
6
|
+
License: MIT License — diffly
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2026 Vivaan Dhawan
|
|
9
|
+
|
|
10
|
+
================================================================================
|
|
11
|
+
PART 1 — THE LICENSE GRANT (standard MIT text)
|
|
12
|
+
================================================================================
|
|
13
|
+
|
|
14
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
15
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
16
|
+
in the Software without restriction, including without limitation the rights
|
|
17
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
18
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
19
|
+
furnished to do so, subject to the following conditions:
|
|
20
|
+
|
|
21
|
+
The above copyright notice and this permission notice shall be included in all
|
|
22
|
+
copies or substantial portions of the Software.
|
|
23
|
+
|
|
24
|
+
================================================================================
|
|
25
|
+
PART 2 — DEFINITIONS AND CLARIFICATIONS
|
|
26
|
+
================================================================================
|
|
27
|
+
|
|
28
|
+
These clarifications are part of this license. Where Part 1 and Part 2 could
|
|
29
|
+
be read differently, Part 1 controls; Part 2 explains intent.
|
|
30
|
+
|
|
31
|
+
1. "Software" means the diffly source code, its bundled GitHub Action, its
|
|
32
|
+
install scripts, its documentation, and any object code or distributions
|
|
33
|
+
built from them, in whole or in part.
|
|
34
|
+
|
|
35
|
+
2. "Contribution" means any work submitted to the project — including pull
|
|
36
|
+
requests, patches, and documentation — that is intentionally offered for
|
|
37
|
+
inclusion in the Software. By submitting a Contribution you agree it is
|
|
38
|
+
licensed under this same license, with no additional terms or conditions,
|
|
39
|
+
to the maximum extent permitted by law. You confirm you have the right to
|
|
40
|
+
license what you submit.
|
|
41
|
+
|
|
42
|
+
3. Verdicts are opinions, not guarantees. The PASS, QUARANTINE, BLOCK, and
|
|
43
|
+
related outputs produced by the Software are deterministic heuristics
|
|
44
|
+
applied at a point in time against data available at that moment. They are
|
|
45
|
+
review aids only. They do not certify correctness, security, safety,
|
|
46
|
+
fitness for production, compliance with any law, regulation, or standard,
|
|
47
|
+
or the absence of defects in any analyzed code, repository, or change.
|
|
48
|
+
You remain solely responsible for all decisions about the software you
|
|
49
|
+
review, merge, ship, or operate.
|
|
50
|
+
|
|
51
|
+
4. Network services. The Software may contact third-party services you direct
|
|
52
|
+
it to (for example the GitHub REST API) and, only when explicitly enabled
|
|
53
|
+
by you, an OpenAI-compatible model endpoint you configure. Those services
|
|
54
|
+
are governed by their own terms. The project authors neither operate those
|
|
55
|
+
services nor are party to your relationship with them.
|
|
56
|
+
|
|
57
|
+
5. Trademarks. This license grants no rights in the names "diffly",
|
|
58
|
+
"diffly-cli", or any related marks, logos, or trade dress, except as
|
|
59
|
+
strictly required for reasonable attribution or nominative fair use.
|
|
60
|
+
|
|
61
|
+
================================================================================
|
|
62
|
+
PART 3 — WARRANTY AND LIABILITY (extended statement)
|
|
63
|
+
================================================================================
|
|
64
|
+
|
|
65
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
66
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
67
|
+
FITNESS FOR A PARTICULAR PURPOSE, TITLE, NON-INFRINGEMENT, ACCURACY OF OUTPUT,
|
|
68
|
+
AND UNINTERRUPTED OR ERROR-FREE OPERATION. SOME JURISDICTIONS DO NOT ALLOW THE
|
|
69
|
+
EXCLUSION OF CERTAIN IMPLIED WARRANTIES, SO SOME OF THE ABOVE MAY NOT APPLY TO
|
|
70
|
+
YOU TO THE EXTENT LAW REQUIRES IT.
|
|
71
|
+
|
|
72
|
+
IN NO EVENT AND UNDER NO LEGAL THEORY — WHETHER IN CONTRACT, TORT (INCLUDING
|
|
73
|
+
NEGLIGENCE), STRICT LIABILITY, STATUTE, OR OTHERWISE — SHALL THE AUTHORS,
|
|
74
|
+
COPYRIGHT HOLDERS, OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
75
|
+
INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
76
|
+
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
77
|
+
DATA, PROFITS, GOODWILL, OR REPUTATION; BUSINESS INTERRUPTION; SECURITY
|
|
78
|
+
INCIDENTS; BUILD FAILURES; OR RELEASED DEFECTS) HOWEVER CAUSED AND ON ANY
|
|
79
|
+
THEORY OF LIABILITY, ARISING IN ANY WAY OUT OF OR IN CONNECTION WITH THE
|
|
80
|
+
SOFTWARE OR ITS USE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
81
|
+
|
|
82
|
+
TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THE TOTAL AGGREGATE
|
|
83
|
+
LIABILITY OF THE AUTHORS AND COPYRIGHT HOLDERS FOR ALL CLAIMS RELATING TO THE
|
|
84
|
+
SOFTWARE SHALL BE LIMITED TO THE GREATER OF ONE HUNDRED UNITED STATES DOLLARS
|
|
85
|
+
(USD 100) OR THE AMOUNT YOU PAID FOR THE SOFTWARE, WHICH BY DEFAULT IS ZERO.
|
|
86
|
+
|
|
87
|
+
================================================================================
|
|
88
|
+
PART 4 — GENERAL TERMS
|
|
89
|
+
================================================================================
|
|
90
|
+
|
|
91
|
+
1. Compliance with law. Your use of the Software must comply with applicable
|
|
92
|
+
export-control, sanctions, privacy, and other laws.
|
|
93
|
+
|
|
94
|
+
2. Severability. If any provision of this license is held unenforceable, it
|
|
95
|
+
will be modified to the minimum extent necessary, and the remaining
|
|
96
|
+
provisions stay in force.
|
|
97
|
+
|
|
98
|
+
3. No waiver. Failure to enforce any provision is not a waiver of it.
|
|
99
|
+
|
|
100
|
+
4. Termination. The licenses granted here terminate automatically if you
|
|
101
|
+
breach this license. They otherwise survive as long as the copyright law
|
|
102
|
+
of your jurisdiction requires, and are perpetual where permitted.
|
|
103
|
+
|
|
104
|
+
5. Entire agreement. This license is the entire agreement between you and the
|
|
105
|
+
copyright holders concerning the Software, superseding any other terms
|
|
106
|
+
communicated alongside copies of it.
|
|
107
|
+
|
|
108
|
+
6. Language. This license is written in English; translations are for
|
|
109
|
+
convenience only, and the English text controls.
|
|
110
|
+
|
|
111
|
+
THIS LICENSE FOLLOWS THE MIT LICENSE TEMPLATE AND ADDS CLARIFYING MATERIAL.
|
|
112
|
+
THE GRANT IN PART 1 REMAINS THE GOVERNING PERMISSION.
|
|
113
|
+
License-File: LICENSE
|
|
114
|
+
Keywords: blast-radius,cli,code-review,github,pull-request,tree-sitter
|
|
115
|
+
Classifier: Development Status :: 3 - Alpha
|
|
116
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
117
|
+
Classifier: Programming Language :: Python :: 3
|
|
118
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
119
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
120
|
+
Requires-Python: >=3.10
|
|
121
|
+
Requires-Dist: openai>=1.0
|
|
122
|
+
Requires-Dist: rich>=13.9
|
|
123
|
+
Requires-Dist: tree-sitter-language-pack>=1.10
|
|
124
|
+
Requires-Dist: tree-sitter>=0.25
|
|
125
|
+
Provides-Extra: dev
|
|
126
|
+
Requires-Dist: pytest>=8; extra == 'dev'
|
|
127
|
+
Requires-Dist: pyyaml>=6; extra == 'dev'
|
|
128
|
+
Description-Content-Type: text/markdown
|
|
129
|
+
|
|
130
|
+
<p align="center">
|
|
131
|
+
<img src="assets/logo.png" alt="diffly logo" width="140">
|
|
132
|
+
</p>
|
|
133
|
+
|
|
134
|
+
# ⚡ diffly
|
|
135
|
+
|
|
136
|
+
<p align="center">
|
|
137
|
+
<b>Your PR is 4,000 lines long. Nobody wants to review it.</b><br>
|
|
138
|
+
diffly reads it for you — files, symbols, checks, tests, blast radius —<br>
|
|
139
|
+
and hands you one page and one verdict: <b>PASS</b>, <b>QUARANTINE</b>, or <b>BLOCK</b>.
|
|
140
|
+
</p>
|
|
141
|
+
|
|
142
|
+
<p align="center">
|
|
143
|
+
<a href="https://github.com/VIVAAN-DHAWAN/diffly-cli/actions/workflows/ci.yml"><img src="https://img.shields.io/badge/CI-passing-brightgreen?style=for-the-badge&logo=githubactions" alt="CI"></a>
|
|
144
|
+
<a href="https://github.com/VIVAAN-DHAWAN/diffly-cli/releases/latest"><img src="https://img.shields.io/badge/release-v0.4.0-blue?style=for-the-badge" alt="Release"></a>
|
|
145
|
+
<a href="https://www.python.org/"><img src="https://img.shields.io/badge/python-3.10%2B-3776AB?style=for-the-badge&logo=python&logoColor=white" alt="Python 3.10+"></a>
|
|
146
|
+
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-green?style=for-the-badge" alt="License: MIT"></a>
|
|
147
|
+
</p>
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## Install
|
|
152
|
+
|
|
153
|
+
Pick whichever fits your setup:
|
|
154
|
+
|
|
155
|
+
**curl (recommended)**
|
|
156
|
+
```bash
|
|
157
|
+
curl -fsSL https://raw.githubusercontent.com/VIVAAN-DHAWAN/diffly-cli/main/install.sh | sh
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
**pip**
|
|
161
|
+
```bash
|
|
162
|
+
pip install diffly-cli
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
**uv**
|
|
166
|
+
```bash
|
|
167
|
+
uv tool install diffly-cli
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
**Homebrew**
|
|
171
|
+
```bash
|
|
172
|
+
brew install VIVAAN-DHAWAN/diffly-cli/diffly-cli
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
That's it. If `diffly` isn't found, add `~/.local/bin` to your `PATH` (curl/pip/uv) and open a new shell.
|
|
176
|
+
|
|
177
|
+
### Upgrading from pre-0.4.0
|
|
178
|
+
|
|
179
|
+
If you already have diffly installed but are on a version before 0.4.0 (which introduced the built-in update system), run the one-time upgrade script:
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
curl -fsSL https://raw.githubusercontent.com/VIVAAN-DHAWAN/diffly-cli/main/upgrade.sh | sh
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
This pulls in 0.4.0+, which has `diffly update` built in. From that point on, diffly will automatically check for new releases every time you run it and prompt you to update — no more manual upgrades needed.
|
|
186
|
+
|
|
187
|
+
## Updating
|
|
188
|
+
|
|
189
|
+
From 0.4.0 onwards, just run:
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
diffly update
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
Or simply start diffly normally — it will check for updates on launch and ask if you'd like to install the latest version. You can also choose to enable automatic updates so future versions install silently.
|
|
196
|
+
|
|
197
|
+
## Try it in 10 seconds
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
diffly pr https://github.com/astral-sh/ruff/pull/27808
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
Paste any pull-request URL — or run bare `diffly` for a guided flow. You'll get a keyboard-driven, one-page review: verdict, risk flags, checks, and a per-file blast-radius map. Arrow keys move, space toggles sections, Enter renders, `q` quits.
|
|
204
|
+
|
|
205
|
+

|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
## What diffly actually does
|
|
210
|
+
|
|
211
|
+
Large AI-generated pull requests are hard to review because file-by-file diffs hide what matters: which symbols changed, which tests cover them, whether dependencies moved, whether a security-sensitive file was touched. diffly makes the deterministic part of that review visible **before** any LLM gets involved.
|
|
212
|
+
|
|
213
|
+
It fetches the PR metadata, changed files, unified diff, commits, status checks, and repository tree; parses source changes with Tree-sitter; maps the blast radius; applies fixed risk rules; and emits a one-page Markdown report with a verdict.
|
|
214
|
+
|
|
215
|
+
<table>
|
|
216
|
+
<tr><td><b>One-page verdicts</b></td><td><code>PASS</code>, <code>QUARANTINE</code>, or <code>BLOCK</code> from fixed, documented rules. Same PR data in, same verdict out — every time.</td></tr>
|
|
217
|
+
<tr><td><b>Blast-radius map</b></td><td>Per file: status, additions/deletions, touched symbols, direct callers visible in changed hunks, and related test files discovered from the repository tree.</td></tr>
|
|
218
|
+
<tr><td><b>Risk flags</b></td><td>Auth/secrets touches, database changes, new dependencies, missing test coverage, failed or pending checks — each with severity and evidence.</td></tr>
|
|
219
|
+
<tr><td><b>Works offline</b></td><td><code>diffly local</code> triages git changes in any folder on disk — private, archived, or removed repositories included.</td></tr>
|
|
220
|
+
<tr><td><b>CI-native</b></td><td>Bundled GitHub Action posts one self-updating verdict comment on every PR. Stable JSON output for scripts.</td></tr>
|
|
221
|
+
<tr><td><b>Optional AI explainer</b></td><td>Bring your own OpenAI-compatible key for a generated narrative — sandboxed, redacted, strictly validated, and never allowed to change the verdict.</td></tr>
|
|
222
|
+
</table>
|
|
223
|
+
|
|
224
|
+
## Local mode — no GitHub required
|
|
225
|
+
|
|
226
|
+
Analyze git changes on your own disk. No token, no network:
|
|
227
|
+
|
|
228
|
+
```bash
|
|
229
|
+
diffly local # uncommitted working-tree changes in the current folder
|
|
230
|
+
diffly local ~/code/private-repo # any checkout — even repos deleted from GitHub
|
|
231
|
+
diffly local --base main # compare your branch against main instead
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
Untracked files are included, so brand-new work is never silently ignored. CI checks don't exist locally, so check-derived flags are skipped; everything else behaves exactly as it does for pull requests.
|
|
235
|
+
|
|
236
|
+
## GitHub Action
|
|
237
|
+
|
|
238
|
+
Add this to analyze every pull request automatically:
|
|
239
|
+
|
|
240
|
+
```yaml
|
|
241
|
+
name: Diffly
|
|
242
|
+
on: pull_request
|
|
243
|
+
permissions:
|
|
244
|
+
contents: read
|
|
245
|
+
pull-requests: write
|
|
246
|
+
jobs:
|
|
247
|
+
diffly:
|
|
248
|
+
runs-on: ubuntu-latest
|
|
249
|
+
steps:
|
|
250
|
+
- uses: VIVAAN-DHAWAN/diffly-cli@main
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
To enable the optional explainer in CI, add `DIFFLY_LLM_API_KEY: ${{ secrets.DIFFLY_LLM_API_KEY }}` under the step's `env`. Without a key, the Action runs deterministic-only.
|
|
254
|
+
|
|
255
|
+
## Everyday commands
|
|
256
|
+
|
|
257
|
+
```bash
|
|
258
|
+
diffly # guided wizard
|
|
259
|
+
diffly pr astral-sh/ruff 27808 # owner/repo + number
|
|
260
|
+
diffly pr https://github.com/astral-sh/ruff/pull/27808 # just paste the URL
|
|
261
|
+
diffly pr astral-sh/ruff 27808 --interactive # keyboard-driven review
|
|
262
|
+
diffly pr astral-sh/ruff 27808 --output triage.md
|
|
263
|
+
diffly pr astral-sh/ruff 27808 --json # stable JSON for scripts
|
|
264
|
+
diffly setup # guided tutorial
|
|
265
|
+
diffly doctor # environment diagnostics
|
|
266
|
+
diffly update # check for and install the latest release
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
For automation prefer `--json`: successful triage exits `0` regardless of verdict — enforce policy by reading the `verdict` field. Operational errors exit `2`.
|
|
270
|
+
|
|
271
|
+
### Optional AI explanation
|
|
272
|
+
|
|
273
|
+
```bash
|
|
274
|
+
export DIFFLY_LLM_API_KEY="your-key"
|
|
275
|
+
export DIFFLY_LLM_BASE_URL="https://api.openai.com/v1" # omit for the default endpoint
|
|
276
|
+
diffly pr OWNER/REPO NUMBER --explain
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
Default model is `gpt-5-mini`; override with `DIFFLY_LLM_MODEL` or `--llm-model`. The explainer sends bounded, redacted context, requires strict JSON output, rejects citations to files outside the changed-file set, and fails safely back to deterministic triage when anything is off.
|
|
280
|
+
|
|
281
|
+
## The verdict policy
|
|
282
|
+
|
|
283
|
+
| Verdict | Rule |
|
|
284
|
+
| --- | --- |
|
|
285
|
+
| **BLOCK** | A required check failed, or the PR touches authentication, credentials, secrets, or security-sensitive files. |
|
|
286
|
+
| **QUARANTINE** | Database schema/migrations, dependency changes, missing obvious test coverage for production files, or unavailable/pending checks. |
|
|
287
|
+
| **PASS** | No rule fired and observed checks passed. `SHIP` remains accepted as a legacy alias. |
|
|
288
|
+
|
|
289
|
+
Deliberately conservative: a verdict is a review gate, not a claim that a PR is correct or safe in every context.
|
|
290
|
+
|
|
291
|
+
## Real examples
|
|
292
|
+
|
|
293
|
+
Captured from live terminal sessions against public pull requests:
|
|
294
|
+
|
|
295
|
+
| Pull request | Files | Lines | Verdict | Why |
|
|
296
|
+
| --- | --- | --- | --- | --- |
|
|
297
|
+
| [`microsoft/vscode#330848`](demo/vscode-330848.md) | 25 | +2,557 / -251 | QUARANTINE | production files without obvious test coverage |
|
|
298
|
+
| [`kubernetes/kubernetes#141413`](demo/kubernetes-141413.md) | 41 | +708 / -740 | QUARANTINE | missing coverage + pending `tide` check |
|
|
299
|
+
| [`astral-sh/ruff#27808`](demo/ruff-27808.md) | 53 | +1,845 / -274 | BLOCK | `CodSpeed Performance Analysis` check failed |
|
|
300
|
+
|
|
301
|
+
Standalone screenshots: [vscode](assets/screenshots/vscode-330848.png) · [kubernetes](assets/screenshots/kubernetes-141413.png) · [ruff](assets/screenshots/ruff-27808.png)
|
|
302
|
+
|
|
303
|
+
Live AI-explainer reports (deterministic verdict preserved): [ruff phase 2](demo/ruff-27808-phase2.md) · [kubernetes phase 2](demo/kubernetes-141413-phase2.md)
|
|
304
|
+
|
|
305
|
+
## Current limitations
|
|
306
|
+
|
|
307
|
+
The Phase 2 explainer requires an OpenAI-compatible API key and never influences the verdict. Tree-sitter parsing covers symbols and direct calls visible in changed hunks, not a full repository-wide call graph. Test-coverage detection is heuristic (filenames + repository tree). Unavailable checks are quarantined rather than assumed passing. Model context is bounded and may truncate on very large PRs.
|
|
308
|
+
|
|
309
|
+
## Roadmap
|
|
310
|
+
|
|
311
|
+
- repository-wide symbol resolution and import-aware blast radius;
|
|
312
|
+
- configurable policy files for org-specific risk rules and thresholds;
|
|
313
|
+
- GitHub annotations and check-run output alongside the PR comment;
|
|
314
|
+
- baseline mode reporting only risks introduced vs the target branch;
|
|
315
|
+
- coverage-artifact-based test mapping;
|
|
316
|
+
- SARIF output for code-scanning integrations.
|
|
317
|
+
|
|
318
|
+
Details: [`docs/phase-2-contract.md`](docs/phase-2-contract.md) · [`docs/benchmarks.md`](docs/benchmarks.md)
|
|
319
|
+
|
|
320
|
+
## Development
|
|
321
|
+
|
|
322
|
+
```bash
|
|
323
|
+
git clone https://github.com/VIVAAN-DHAWAN/diffly-cli.git
|
|
324
|
+
cd diffly-cli
|
|
325
|
+
python -m venv .venv
|
|
326
|
+
. .venv/bin/activate
|
|
327
|
+
python -m pip install -e '.[dev]'
|
|
328
|
+
pytest -q
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
Keep changes focused, include regression tests, and record user-facing changes in [`CHANGELOG.md`](CHANGELOG.md). See [`CONTRIBUTING.md`](CONTRIBUTING.md).
|
|
332
|
+
|
|
333
|
+
## Security & privacy
|
|
334
|
+
|
|
335
|
+
Diffly talks to the GitHub API only for the repo and PR you point it at. Deterministic mode sends no code to any LLM. With `--explain`, bounded redacted context goes to your configured endpoint — read [`docs/phase-2-contract.md`](docs/phase-2-contract.md) before enabling it on sensitive repositories. Prefer environment variables over command-line tokens.
|
|
336
|
+
|
|
337
|
+
Report vulnerabilities privately via [GitHub security advisories](https://github.com/VIVAAN-DHAWAN/diffly-cli/security/advisories/new).
|
|
338
|
+
|
|
339
|
+
## License
|
|
340
|
+
|
|
341
|
+
Released under the [MIT License](LICENSE).
|