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.
Files changed (63) hide show
  1. diffly_cli-0.4.0/.github/workflows/ci.yml +21 -0
  2. diffly_cli-0.4.0/.github/workflows/example-diffly.yml +10 -0
  3. diffly_cli-0.4.0/.github/workflows/publish.yml +48 -0
  4. diffly_cli-0.4.0/.gitignore +27 -0
  5. diffly_cli-0.4.0/CHANGELOG.md +53 -0
  6. diffly_cli-0.4.0/CONTRIBUTING.md +39 -0
  7. diffly_cli-0.4.0/LICENSE +107 -0
  8. diffly_cli-0.4.0/PKG-INFO +341 -0
  9. diffly_cli-0.4.0/README.md +212 -0
  10. diffly_cli-0.4.0/SECURITY.md +20 -0
  11. diffly_cli-0.4.0/action/format_comment.py +66 -0
  12. diffly_cli-0.4.0/action/post_comment.py +86 -0
  13. diffly_cli-0.4.0/action.yml +41 -0
  14. diffly_cli-0.4.0/assets/diffly-cli-demo.gif +0 -0
  15. diffly_cli-0.4.0/assets/logo.png +0 -0
  16. diffly_cli-0.4.0/assets/real-captures/kubernetes-141413.ansi +41 -0
  17. diffly_cli-0.4.0/assets/real-captures/ruff-27808.ansi +41 -0
  18. diffly_cli-0.4.0/assets/real-captures/vscode-330848.ansi +41 -0
  19. diffly_cli-0.4.0/assets/screenshots/kubernetes-141413.png +0 -0
  20. diffly_cli-0.4.0/assets/screenshots/ruff-27808.png +0 -0
  21. diffly_cli-0.4.0/assets/screenshots/vscode-330848.png +0 -0
  22. diffly_cli-0.4.0/demo/kubernetes-141413-phase2.md +389 -0
  23. diffly_cli-0.4.0/demo/kubernetes-141413.md +293 -0
  24. diffly_cli-0.4.0/demo/ruff-27808-phase2.md +469 -0
  25. diffly_cli-0.4.0/demo/ruff-27808.md +383 -0
  26. diffly_cli-0.4.0/demo/vscode-330848.md +201 -0
  27. diffly_cli-0.4.0/docs/audit-report.md +63 -0
  28. diffly_cli-0.4.0/docs/benchmarks.md +50 -0
  29. diffly_cli-0.4.0/docs/launch/reddit-opensource.md +32 -0
  30. diffly_cli-0.4.0/docs/launch/reddit-programming.md +32 -0
  31. diffly_cli-0.4.0/docs/launch/show-hn.md +30 -0
  32. diffly_cli-0.4.0/docs/launch/x-thread.md +44 -0
  33. diffly_cli-0.4.0/docs/live-model-catalog.json +1 -0
  34. diffly_cli-0.4.0/docs/phase-0-research.md +27 -0
  35. diffly_cli-0.4.0/docs/phase-2-contract.md +31 -0
  36. diffly_cli-0.4.0/docs/visual-verification.md +11 -0
  37. diffly_cli-0.4.0/homebrew/diffly-cli.rb +24 -0
  38. diffly_cli-0.4.0/install.sh +27 -0
  39. diffly_cli-0.4.0/pyproject.toml +40 -0
  40. diffly_cli-0.4.0/scripts/capture_real_sessions.sh +21 -0
  41. diffly_cli-0.4.0/scripts/discover_benchmarks.py +84 -0
  42. diffly_cli-0.4.0/scripts/render_real_captures.py +85 -0
  43. diffly_cli-0.4.0/scripts/run_benchmarks.py +101 -0
  44. diffly_cli-0.4.0/scripts/validate_action.py +11 -0
  45. diffly_cli-0.4.0/scripts/write_benchmarks_doc.py +83 -0
  46. diffly_cli-0.4.0/src/diffly_cli/__init__.py +3 -0
  47. diffly_cli-0.4.0/src/diffly_cli/__main__.py +6 -0
  48. diffly_cli-0.4.0/src/diffly_cli/astmap.py +121 -0
  49. diffly_cli-0.4.0/src/diffly_cli/cli.py +770 -0
  50. diffly_cli-0.4.0/src/diffly_cli/diffparse.py +117 -0
  51. diffly_cli-0.4.0/src/diffly_cli/explainer.py +227 -0
  52. diffly_cli-0.4.0/src/diffly_cli/github.py +181 -0
  53. diffly_cli-0.4.0/src/diffly_cli/local.py +151 -0
  54. diffly_cli-0.4.0/src/diffly_cli/models.py +68 -0
  55. diffly_cli-0.4.0/src/diffly_cli/redact.py +59 -0
  56. diffly_cli-0.4.0/src/diffly_cli/triage.py +142 -0
  57. diffly_cli-0.4.0/src/diffly_cli/update.py +161 -0
  58. diffly_cli-0.4.0/tests/test_action.py +113 -0
  59. diffly_cli-0.4.0/tests/test_explainer.py +125 -0
  60. diffly_cli-0.4.0/tests/test_local.py +141 -0
  61. diffly_cli-0.4.0/tests/test_regressions.py +212 -0
  62. diffly_cli-0.4.0/tests/test_triage.py +74 -0
  63. 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,10 @@
1
+ name: Diffly
2
+ on: pull_request
3
+ permissions:
4
+ contents: read
5
+ pull-requests: write
6
+ jobs:
7
+ diffly:
8
+ runs-on: ubuntu-latest
9
+ steps:
10
+ - uses: VIVAAN-DHAWAN/diffly-cli@main
@@ -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).
@@ -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
+ ![diffly-cli animated demonstration](assets/diffly-cli-demo.gif)
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).