oss-maintainer-toolkit 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.
- oss_maintainer_toolkit-0.4.0/.github/workflows/publish.yml +30 -0
- oss_maintainer_toolkit-0.4.0/.github/workflows/test-action.yml +51 -0
- oss_maintainer_toolkit-0.4.0/.github/workflows/test.yml +28 -0
- oss_maintainer_toolkit-0.4.0/.gitignore +18 -0
- oss_maintainer_toolkit-0.4.0/LICENSE +21 -0
- oss_maintainer_toolkit-0.4.0/PKG-INFO +257 -0
- oss_maintainer_toolkit-0.4.0/README.md +219 -0
- oss_maintainer_toolkit-0.4.0/action.yml +99 -0
- oss_maintainer_toolkit-0.4.0/action_entrypoint.py +421 -0
- oss_maintainer_toolkit-0.4.0/examples/pr-triage.yml +34 -0
- oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/__init__.py +1 -0
- oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/analysis/__init__.py +0 -0
- oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/analysis/data_flow.py +304 -0
- oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/cli/__init__.py +0 -0
- oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/cli/main.py +494 -0
- oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/config.py +17 -0
- oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/cve/__init__.py +0 -0
- oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/cve/checker.py +189 -0
- oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/cve/parsers.py +94 -0
- oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/__init__.py +1 -0
- oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/audit_backlog.py +243 -0
- oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/audit_scorecard.py +207 -0
- oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/cache.py +99 -0
- oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/coaching.py +83 -0
- oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/config.py +103 -0
- oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/conflict_detection.py +104 -0
- oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/conflict_scorecard.py +65 -0
- oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/contributor_profiles.py +114 -0
- oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/contributor_scorecard.py +52 -0
- oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/dedup.py +114 -0
- oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/github_client.py +300 -0
- oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/heuristics.py +259 -0
- oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/ingest.py +145 -0
- oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/issue_cache.py +99 -0
- oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/issue_dedup.py +82 -0
- oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/issue_heuristics.py +210 -0
- oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/issue_ingest.py +127 -0
- oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/issue_pipeline.py +197 -0
- oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/issue_scorecard.py +86 -0
- oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/labeling.py +202 -0
- oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/labeling_scorecard.py +63 -0
- oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/linking.py +140 -0
- oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/linking_scorecard.py +73 -0
- oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/models.py +368 -0
- oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/pipeline.py +196 -0
- oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/providers.py +267 -0
- oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/review_routing.py +170 -0
- oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/review_routing_scorecard.py +54 -0
- oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/scorecard.py +86 -0
- oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/staleness.py +264 -0
- oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/staleness_scorecard.py +125 -0
- oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/vision.py +474 -0
- oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/vision_generation.py +384 -0
- oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/mcp/__init__.py +0 -0
- oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/mcp/__main__.py +5 -0
- oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/mcp/server.py +525 -0
- oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/models.py +79 -0
- oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/scanners/__init__.py +0 -0
- oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/scanners/patterns.py +194 -0
- oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/scanners/vulnerability_scanner.py +88 -0
- oss_maintainer_toolkit-0.4.0/pyproject.toml +67 -0
- oss_maintainer_toolkit-0.4.0/reports/openclaw-pr-body.md +120 -0
- oss_maintainer_toolkit-0.4.0/reports/openclaw-triage-2026-02-16.md +139 -0
- oss_maintainer_toolkit-0.4.0/reports/openclaw-triage-2026-02-18.json +258 -0
- oss_maintainer_toolkit-0.4.0/reports/openclaw-triage-2026-02-18.md +125 -0
- oss_maintainer_toolkit-0.4.0/scripts/triage_batch.py +612 -0
- oss_maintainer_toolkit-0.4.0/tests/__init__.py +0 -0
- oss_maintainer_toolkit-0.4.0/tests/conftest.py +12 -0
- oss_maintainer_toolkit-0.4.0/tests/fixtures/package_vulnerable.json +12 -0
- oss_maintainer_toolkit-0.4.0/tests/fixtures/requirements_vulnerable.txt +7 -0
- oss_maintainer_toolkit-0.4.0/tests/fixtures/sample_claude_response.json +11 -0
- oss_maintainer_toolkit-0.4.0/tests/fixtures/sample_clean.py +33 -0
- oss_maintainer_toolkit-0.4.0/tests/fixtures/sample_issue_metadata.json +36 -0
- oss_maintainer_toolkit-0.4.0/tests/fixtures/sample_pr_files.json +16 -0
- oss_maintainer_toolkit-0.4.0/tests/fixtures/sample_pr_metadata.json +30 -0
- oss_maintainer_toolkit-0.4.0/tests/fixtures/sample_taint.py +68 -0
- oss_maintainer_toolkit-0.4.0/tests/fixtures/sample_user.json +8 -0
- oss_maintainer_toolkit-0.4.0/tests/fixtures/sample_vision_document.yaml +16 -0
- oss_maintainer_toolkit-0.4.0/tests/fixtures/sample_vulnerable.py +74 -0
- oss_maintainer_toolkit-0.4.0/tests/test_action_badges.py +175 -0
- oss_maintainer_toolkit-0.4.0/tests/test_audit_backlog.py +253 -0
- oss_maintainer_toolkit-0.4.0/tests/test_coaching.py +273 -0
- oss_maintainer_toolkit-0.4.0/tests/test_conflict_detection.py +239 -0
- oss_maintainer_toolkit-0.4.0/tests/test_contributor_profiles.py +213 -0
- oss_maintainer_toolkit-0.4.0/tests/test_cve_checker.py +144 -0
- oss_maintainer_toolkit-0.4.0/tests/test_data_flow.py +66 -0
- oss_maintainer_toolkit-0.4.0/tests/test_gatekeeper_cache.py +86 -0
- oss_maintainer_toolkit-0.4.0/tests/test_gatekeeper_dedup.py +127 -0
- oss_maintainer_toolkit-0.4.0/tests/test_gatekeeper_github_client.py +209 -0
- oss_maintainer_toolkit-0.4.0/tests/test_gatekeeper_heuristics.py +260 -0
- oss_maintainer_toolkit-0.4.0/tests/test_gatekeeper_ingest.py +173 -0
- oss_maintainer_toolkit-0.4.0/tests/test_gatekeeper_pipeline.py +253 -0
- oss_maintainer_toolkit-0.4.0/tests/test_gatekeeper_providers.py +438 -0
- oss_maintainer_toolkit-0.4.0/tests/test_gatekeeper_scorecard.py +122 -0
- oss_maintainer_toolkit-0.4.0/tests/test_gatekeeper_vision.py +535 -0
- oss_maintainer_toolkit-0.4.0/tests/test_issue_cache.py +86 -0
- oss_maintainer_toolkit-0.4.0/tests/test_issue_dedup.py +128 -0
- oss_maintainer_toolkit-0.4.0/tests/test_issue_heuristics.py +258 -0
- oss_maintainer_toolkit-0.4.0/tests/test_issue_ingest.py +158 -0
- oss_maintainer_toolkit-0.4.0/tests/test_issue_pipeline.py +180 -0
- oss_maintainer_toolkit-0.4.0/tests/test_issue_scorecard.py +79 -0
- oss_maintainer_toolkit-0.4.0/tests/test_labeling.py +420 -0
- oss_maintainer_toolkit-0.4.0/tests/test_linking.py +270 -0
- oss_maintainer_toolkit-0.4.0/tests/test_mcp_server.py +48 -0
- oss_maintainer_toolkit-0.4.0/tests/test_openclaw_scenarios.py +409 -0
- oss_maintainer_toolkit-0.4.0/tests/test_review_routing.py +257 -0
- oss_maintainer_toolkit-0.4.0/tests/test_staleness.py +365 -0
- oss_maintainer_toolkit-0.4.0/tests/test_vision_generation.py +433 -0
- oss_maintainer_toolkit-0.4.0/tests/test_vulnerability_scanner.py +83 -0
- oss_maintainer_toolkit-0.4.0/vision_documents/openclaw.yaml +95 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
id-token: write
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
publish:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
environment: pypi
|
|
14
|
+
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
|
|
18
|
+
- name: Set up Python
|
|
19
|
+
uses: actions/setup-python@v5
|
|
20
|
+
with:
|
|
21
|
+
python-version: "3.11"
|
|
22
|
+
|
|
23
|
+
- name: Install build tools
|
|
24
|
+
run: pip install build
|
|
25
|
+
|
|
26
|
+
- name: Build package
|
|
27
|
+
run: python -m build
|
|
28
|
+
|
|
29
|
+
- name: Publish to PyPI
|
|
30
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
name: Self-test Action
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
branches: [master]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
pull-requests: write
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
self-test:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
steps:
|
|
15
|
+
- name: Checkout
|
|
16
|
+
uses: actions/checkout@v4
|
|
17
|
+
|
|
18
|
+
- name: Run Gatekeeper on this PR
|
|
19
|
+
id: gatekeeper
|
|
20
|
+
uses: ./
|
|
21
|
+
with:
|
|
22
|
+
github_token: ${{ secrets.GITHUB_TOKEN }}
|
|
23
|
+
post_comment: "true"
|
|
24
|
+
|
|
25
|
+
- name: Verify outputs
|
|
26
|
+
shell: bash
|
|
27
|
+
run: |
|
|
28
|
+
verdict="${{ steps.gatekeeper.outputs.verdict }}"
|
|
29
|
+
echo "Verdict: $verdict"
|
|
30
|
+
|
|
31
|
+
if [ -z "$verdict" ]; then
|
|
32
|
+
echo "::error::verdict output is empty"
|
|
33
|
+
exit 1
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
case "$verdict" in
|
|
37
|
+
fast_track|review_required|recommend_close)
|
|
38
|
+
echo "Valid verdict: $verdict"
|
|
39
|
+
;;
|
|
40
|
+
*)
|
|
41
|
+
echo "::error::Unexpected verdict value: $verdict"
|
|
42
|
+
exit 1
|
|
43
|
+
;;
|
|
44
|
+
esac
|
|
45
|
+
|
|
46
|
+
scorecard='${{ steps.gatekeeper.outputs.scorecard_json }}'
|
|
47
|
+
if [ -z "$scorecard" ]; then
|
|
48
|
+
echo "::error::scorecard_json output is empty"
|
|
49
|
+
exit 1
|
|
50
|
+
fi
|
|
51
|
+
echo "Scorecard JSON length: ${#scorecard}"
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
name: Tests
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [master]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [master]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
strategy:
|
|
13
|
+
matrix:
|
|
14
|
+
python-version: ["3.11", "3.12", "3.13"]
|
|
15
|
+
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
|
+
|
|
19
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
20
|
+
uses: actions/setup-python@v5
|
|
21
|
+
with:
|
|
22
|
+
python-version: ${{ matrix.python-version }}
|
|
23
|
+
|
|
24
|
+
- name: Install dependencies
|
|
25
|
+
run: pip install -e ".[dev,gatekeeper]"
|
|
26
|
+
|
|
27
|
+
- name: Run tests
|
|
28
|
+
run: pytest
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Pranay Om
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: oss-maintainer-toolkit
|
|
3
|
+
Version: 0.4.0
|
|
4
|
+
Summary: OSS Maintainer Toolkit — automated triage for PRs, issues, contributors, and review queues
|
|
5
|
+
Project-URL: Homepage, https://github.com/pranayom/oss-maintainer-toolkit
|
|
6
|
+
Project-URL: Repository, https://github.com/pranayom/oss-maintainer-toolkit
|
|
7
|
+
Project-URL: Issues, https://github.com/pranayom/oss-maintainer-toolkit/issues
|
|
8
|
+
Author: Pranay Om
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: dedup,gatekeeper,github,governance,issue-triage,maintainer,oss,pr-triage
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
20
|
+
Requires-Python: >=3.11
|
|
21
|
+
Requires-Dist: httpx>=0.25
|
|
22
|
+
Requires-Dist: mcp[cli]>=1.2.0
|
|
23
|
+
Requires-Dist: pydantic-settings>=2.0
|
|
24
|
+
Requires-Dist: pydantic>=2.0
|
|
25
|
+
Requires-Dist: rich>=13.0
|
|
26
|
+
Requires-Dist: typer>=0.9
|
|
27
|
+
Provides-Extra: dev
|
|
28
|
+
Requires-Dist: build>=1.0; extra == 'dev'
|
|
29
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
|
|
30
|
+
Requires-Dist: pytest>=7.0; extra == 'dev'
|
|
31
|
+
Requires-Dist: respx>=0.20; extra == 'dev'
|
|
32
|
+
Requires-Dist: twine>=5.0; extra == 'dev'
|
|
33
|
+
Provides-Extra: gatekeeper
|
|
34
|
+
Requires-Dist: numpy>=1.24; extra == 'gatekeeper'
|
|
35
|
+
Requires-Dist: pyyaml>=6.0; extra == 'gatekeeper'
|
|
36
|
+
Requires-Dist: sentence-transformers>=2.0; extra == 'gatekeeper'
|
|
37
|
+
Description-Content-Type: text/markdown
|
|
38
|
+
|
|
39
|
+
# OSS Maintainer Toolkit
|
|
40
|
+
|
|
41
|
+
Automated triage for PRs, issues, contributors, and review queues. A free GitHub Action and CLI built on a three-tier pipeline: embedding-based dedup, heuristic scoring, and optional LLM vision alignment.
|
|
42
|
+
|
|
43
|
+
**Every PR gets a verdict: `FAST_TRACK`, `REVIEW_REQUIRED`, or `RECOMMEND_CLOSE`.**
|
|
44
|
+
|
|
45
|
+
Tested on [OpenClaw](https://github.com/openclaw/openclaw) (3,368 open PRs): cut the maintainer review queue by 36% and found 6% duplicate PRs in 30 seconds. [See the full report.](https://gist.github.com/pranayom)
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Installation
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
# Core toolkit
|
|
53
|
+
pip install oss-maintainer-toolkit
|
|
54
|
+
|
|
55
|
+
# With PR triage / gatekeeper pipeline
|
|
56
|
+
pip install "oss-maintainer-toolkit[gatekeeper]"
|
|
57
|
+
|
|
58
|
+
# For development
|
|
59
|
+
pip install -e ".[dev,gatekeeper]"
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### CLI usage
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
maintainer assess --owner openclaw --repo openclaw --pr 18675 # PR triage
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### MCP server
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
python -m oss_maintainer_toolkit.mcp # start the MCP server
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## Quick Start (GitHub Action)
|
|
77
|
+
|
|
78
|
+
Copy this workflow into `.github/workflows/pr-triage.yml` in your repo:
|
|
79
|
+
|
|
80
|
+
```yaml
|
|
81
|
+
name: PR Triage
|
|
82
|
+
|
|
83
|
+
on:
|
|
84
|
+
pull_request:
|
|
85
|
+
types: [opened, synchronize, reopened]
|
|
86
|
+
|
|
87
|
+
permissions:
|
|
88
|
+
pull-requests: write
|
|
89
|
+
contents: read
|
|
90
|
+
|
|
91
|
+
jobs:
|
|
92
|
+
triage:
|
|
93
|
+
runs-on: ubuntu-latest
|
|
94
|
+
steps:
|
|
95
|
+
- uses: actions/checkout@v4
|
|
96
|
+
- uses: pranayom/oss-maintainer-toolkit@v1
|
|
97
|
+
with:
|
|
98
|
+
github_token: ${{ secrets.GITHUB_TOKEN }}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
That's it. Every new PR gets a scorecard comment with a verdict and flags.
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## How It Works
|
|
106
|
+
|
|
107
|
+
```
|
|
108
|
+
PR opened
|
|
109
|
+
|
|
|
110
|
+
v
|
|
111
|
+
[Tier 1: Embedding Dedup] — sentence-transformers, cosine similarity
|
|
112
|
+
| Duplicates -> RECOMMEND_CLOSE (stop)
|
|
113
|
+
v
|
|
114
|
+
[Tier 2: Heuristic Scoring] — 7 deterministic rules, weighted scoring
|
|
115
|
+
| Flagged -> REVIEW_REQUIRED (stop)
|
|
116
|
+
v
|
|
117
|
+
[Tier 3: Vision Alignment] — LLM compares PR against Vision Document (optional)
|
|
118
|
+
|
|
|
119
|
+
v
|
|
120
|
+
FAST_TRACK
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Tiers run strictly in sequence. Each tier is a gate — failures don't proceed to the next tier. This reserves LLM time for the minority of PRs where semantic judgment is actually useful.
|
|
124
|
+
|
|
125
|
+
### Tier 1 — Embedding Dedup (free, local)
|
|
126
|
+
Computes semantic embeddings for PR title + description + diff using `all-MiniLM-L6-v2`. Flags duplicates above a cosine similarity threshold (default: 0.90).
|
|
127
|
+
|
|
128
|
+
### Tier 2 — Heuristic Scoring (free, deterministic)
|
|
129
|
+
Seven rules scored against PR metadata:
|
|
130
|
+
|
|
131
|
+
| Rule | What it catches |
|
|
132
|
+
|---|---|
|
|
133
|
+
| `new_account` | GitHub account < 90 days old |
|
|
134
|
+
| `first_contribution` | No previously merged PRs on this repo |
|
|
135
|
+
| `sensitive_paths` | Changes to auth, credentials, CI/CD, extensions |
|
|
136
|
+
| `low_test_ratio` | Code added without proportional tests |
|
|
137
|
+
| `unjustified_deps` | Dependency changes without explanation |
|
|
138
|
+
| `large_diff_hiding` | Large PR with small sensitive changes buried in bulk |
|
|
139
|
+
| `temporal_clustering` | Multiple new-account PRs within a short window |
|
|
140
|
+
|
|
141
|
+
### Tier 3 — Vision Alignment (optional, $0 via OpenRouter)
|
|
142
|
+
Compares the PR diff against your project's Vision Document (a YAML file defining principles, anti-patterns, and focus areas). Uses OpenRouter free models. Requires an `OPENROUTER_API_KEY` (free at [openrouter.ai/keys](https://openrouter.ai/keys)).
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## Inputs
|
|
147
|
+
|
|
148
|
+
| Input | Required | Default | Description |
|
|
149
|
+
|---|---|---|---|
|
|
150
|
+
| `github_token` | Yes | — | GitHub token for API access (usually `secrets.GITHUB_TOKEN`) |
|
|
151
|
+
| `vision_document` | No | `""` | Path to YAML vision document (relative to repo root) |
|
|
152
|
+
| `openrouter_api_key` | No | `""` | OpenRouter API key for Tier 3 ($0 cost). Tier 3 skipped if not provided. |
|
|
153
|
+
| `openrouter_model` | No | `openai/gpt-oss-120b:free` | OpenRouter model for Tier 3 |
|
|
154
|
+
| `duplicate_threshold` | No | `0.9` | Cosine similarity threshold for duplicate detection |
|
|
155
|
+
| `suspicion_threshold` | No | `0.6` | Suspicion score threshold for flagging |
|
|
156
|
+
| `enforce_vision` | No | `false` | Enable Tier 3 vision alignment (set to `true` after reviewing your vision doc) |
|
|
157
|
+
| `post_comment` | No | `true` | Post scorecard as a PR comment |
|
|
158
|
+
|
|
159
|
+
## Outputs
|
|
160
|
+
|
|
161
|
+
| Output | Description |
|
|
162
|
+
|---|---|
|
|
163
|
+
| `verdict` | `FAST_TRACK`, `REVIEW_REQUIRED`, or `RECOMMEND_CLOSE` |
|
|
164
|
+
| `scorecard_json` | Full scorecard as JSON for downstream CI steps |
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## Vision Documents
|
|
169
|
+
|
|
170
|
+
A Vision Document is an optional YAML file that defines what your project is trying to be. It enables Tier 3, where an LLM evaluates whether a PR aligns with your project's direction.
|
|
171
|
+
|
|
172
|
+
Example structure:
|
|
173
|
+
|
|
174
|
+
```yaml
|
|
175
|
+
project: my-project
|
|
176
|
+
principles:
|
|
177
|
+
- name: "Security First"
|
|
178
|
+
description: "All changes touching auth or credentials require security review"
|
|
179
|
+
- name: "Test Everything"
|
|
180
|
+
description: "Every feature PR must include tests"
|
|
181
|
+
|
|
182
|
+
anti_patterns:
|
|
183
|
+
- "Adding dependencies without justification"
|
|
184
|
+
- "Modifying CI/CD without maintainer approval"
|
|
185
|
+
|
|
186
|
+
focus_areas:
|
|
187
|
+
- "src/auth/"
|
|
188
|
+
- "src/credentials/"
|
|
189
|
+
- ".github/"
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Place it at `.github/vision.yaml` and set `vision_document: ".github/vision.yaml"` in the action inputs.
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## Example Scorecard Comment
|
|
197
|
+
|
|
198
|
+
When the action runs on a PR, it posts a comment like:
|
|
199
|
+
|
|
200
|
+
> ## ⚠ PR Triage: **REVIEW REQUIRED**
|
|
201
|
+
>
|
|
202
|
+
> > First-time contributor modifying sensitive paths without tests.
|
|
203
|
+
>
|
|
204
|
+
> | Dimension | Score | Summary |
|
|
205
|
+
> |---|---|---|
|
|
206
|
+
> | Hygiene & Dedup | `++++++++--` 0.80 | No duplicates found |
|
|
207
|
+
> | Contributor Risk | `++++------` 0.40 | New account + sensitive paths |
|
|
208
|
+
>
|
|
209
|
+
> ### Flags
|
|
210
|
+
> - [**HIGH**] **Sensitive Paths**: PR modifies `src/auth/oauth.ts`, `src/credentials/store.ts`
|
|
211
|
+
> - [MEDIUM] **First Contribution**: No previously merged PRs from this author
|
|
212
|
+
> - [MEDIUM] **Low Test Ratio**: 245 lines added, 0 test lines
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## Roadmap
|
|
217
|
+
|
|
218
|
+
- **PR Triage** — Shipped (v0.3.0)
|
|
219
|
+
- **Issue Triage** — Dedup and classify issues
|
|
220
|
+
- **Issue-to-PR Linking** — Suggest which PRs address which issues
|
|
221
|
+
- **Label Automation** — Auto-classify PRs/issues into project label taxonomies
|
|
222
|
+
- **Contributor Profiles** — Track contribution patterns and reliability
|
|
223
|
+
- **Review Routing** — Suggest reviewers based on file ownership
|
|
224
|
+
- **Smart Stale Detection** — Semantic staleness (superseded, merged elsewhere, blocked)
|
|
225
|
+
- **Cross-PR Conflict Detection** — Surface PRs with overlapping file changes
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
## Evidence: OpenClaw Triage
|
|
230
|
+
|
|
231
|
+
We ran this tool against 100 of OpenClaw's 3,368 open PRs:
|
|
232
|
+
|
|
233
|
+
| Verdict | Count | Meaning |
|
|
234
|
+
|---|---|---|
|
|
235
|
+
| FAST_TRACK | 64 (64%) | Safe for quick review |
|
|
236
|
+
| REVIEW_REQUIRED | 30 (30%) | Flagged — needs human attention |
|
|
237
|
+
| RECOMMEND_CLOSE | 6 (6%) | Likely duplicate |
|
|
238
|
+
|
|
239
|
+
- Found 3 duplicate clusters (6 PRs) at 0.90 threshold
|
|
240
|
+
- 89% of PRs from first-time contributors
|
|
241
|
+
- 40% touch security-sensitive paths
|
|
242
|
+
- Extrapolated: ~200 closable duplicates in the full backlog
|
|
243
|
+
|
|
244
|
+
---
|
|
245
|
+
|
|
246
|
+
## Cost
|
|
247
|
+
|
|
248
|
+
$0. All tiers run for free:
|
|
249
|
+
- Tier 1: `sentence-transformers` on CPU (GitHub Actions runner)
|
|
250
|
+
- Tier 2: Pure Python rules
|
|
251
|
+
- Tier 3: OpenRouter free models (optional, free API key)
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
## License
|
|
256
|
+
|
|
257
|
+
MIT
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
# OSS Maintainer Toolkit
|
|
2
|
+
|
|
3
|
+
Automated triage for PRs, issues, contributors, and review queues. A free GitHub Action and CLI built on a three-tier pipeline: embedding-based dedup, heuristic scoring, and optional LLM vision alignment.
|
|
4
|
+
|
|
5
|
+
**Every PR gets a verdict: `FAST_TRACK`, `REVIEW_REQUIRED`, or `RECOMMEND_CLOSE`.**
|
|
6
|
+
|
|
7
|
+
Tested on [OpenClaw](https://github.com/openclaw/openclaw) (3,368 open PRs): cut the maintainer review queue by 36% and found 6% duplicate PRs in 30 seconds. [See the full report.](https://gist.github.com/pranayom)
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
# Core toolkit
|
|
15
|
+
pip install oss-maintainer-toolkit
|
|
16
|
+
|
|
17
|
+
# With PR triage / gatekeeper pipeline
|
|
18
|
+
pip install "oss-maintainer-toolkit[gatekeeper]"
|
|
19
|
+
|
|
20
|
+
# For development
|
|
21
|
+
pip install -e ".[dev,gatekeeper]"
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### CLI usage
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
maintainer assess --owner openclaw --repo openclaw --pr 18675 # PR triage
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### MCP server
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
python -m oss_maintainer_toolkit.mcp # start the MCP server
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Quick Start (GitHub Action)
|
|
39
|
+
|
|
40
|
+
Copy this workflow into `.github/workflows/pr-triage.yml` in your repo:
|
|
41
|
+
|
|
42
|
+
```yaml
|
|
43
|
+
name: PR Triage
|
|
44
|
+
|
|
45
|
+
on:
|
|
46
|
+
pull_request:
|
|
47
|
+
types: [opened, synchronize, reopened]
|
|
48
|
+
|
|
49
|
+
permissions:
|
|
50
|
+
pull-requests: write
|
|
51
|
+
contents: read
|
|
52
|
+
|
|
53
|
+
jobs:
|
|
54
|
+
triage:
|
|
55
|
+
runs-on: ubuntu-latest
|
|
56
|
+
steps:
|
|
57
|
+
- uses: actions/checkout@v4
|
|
58
|
+
- uses: pranayom/oss-maintainer-toolkit@v1
|
|
59
|
+
with:
|
|
60
|
+
github_token: ${{ secrets.GITHUB_TOKEN }}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
That's it. Every new PR gets a scorecard comment with a verdict and flags.
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## How It Works
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
PR opened
|
|
71
|
+
|
|
|
72
|
+
v
|
|
73
|
+
[Tier 1: Embedding Dedup] — sentence-transformers, cosine similarity
|
|
74
|
+
| Duplicates -> RECOMMEND_CLOSE (stop)
|
|
75
|
+
v
|
|
76
|
+
[Tier 2: Heuristic Scoring] — 7 deterministic rules, weighted scoring
|
|
77
|
+
| Flagged -> REVIEW_REQUIRED (stop)
|
|
78
|
+
v
|
|
79
|
+
[Tier 3: Vision Alignment] — LLM compares PR against Vision Document (optional)
|
|
80
|
+
|
|
|
81
|
+
v
|
|
82
|
+
FAST_TRACK
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Tiers run strictly in sequence. Each tier is a gate — failures don't proceed to the next tier. This reserves LLM time for the minority of PRs where semantic judgment is actually useful.
|
|
86
|
+
|
|
87
|
+
### Tier 1 — Embedding Dedup (free, local)
|
|
88
|
+
Computes semantic embeddings for PR title + description + diff using `all-MiniLM-L6-v2`. Flags duplicates above a cosine similarity threshold (default: 0.90).
|
|
89
|
+
|
|
90
|
+
### Tier 2 — Heuristic Scoring (free, deterministic)
|
|
91
|
+
Seven rules scored against PR metadata:
|
|
92
|
+
|
|
93
|
+
| Rule | What it catches |
|
|
94
|
+
|---|---|
|
|
95
|
+
| `new_account` | GitHub account < 90 days old |
|
|
96
|
+
| `first_contribution` | No previously merged PRs on this repo |
|
|
97
|
+
| `sensitive_paths` | Changes to auth, credentials, CI/CD, extensions |
|
|
98
|
+
| `low_test_ratio` | Code added without proportional tests |
|
|
99
|
+
| `unjustified_deps` | Dependency changes without explanation |
|
|
100
|
+
| `large_diff_hiding` | Large PR with small sensitive changes buried in bulk |
|
|
101
|
+
| `temporal_clustering` | Multiple new-account PRs within a short window |
|
|
102
|
+
|
|
103
|
+
### Tier 3 — Vision Alignment (optional, $0 via OpenRouter)
|
|
104
|
+
Compares the PR diff against your project's Vision Document (a YAML file defining principles, anti-patterns, and focus areas). Uses OpenRouter free models. Requires an `OPENROUTER_API_KEY` (free at [openrouter.ai/keys](https://openrouter.ai/keys)).
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## Inputs
|
|
109
|
+
|
|
110
|
+
| Input | Required | Default | Description |
|
|
111
|
+
|---|---|---|---|
|
|
112
|
+
| `github_token` | Yes | — | GitHub token for API access (usually `secrets.GITHUB_TOKEN`) |
|
|
113
|
+
| `vision_document` | No | `""` | Path to YAML vision document (relative to repo root) |
|
|
114
|
+
| `openrouter_api_key` | No | `""` | OpenRouter API key for Tier 3 ($0 cost). Tier 3 skipped if not provided. |
|
|
115
|
+
| `openrouter_model` | No | `openai/gpt-oss-120b:free` | OpenRouter model for Tier 3 |
|
|
116
|
+
| `duplicate_threshold` | No | `0.9` | Cosine similarity threshold for duplicate detection |
|
|
117
|
+
| `suspicion_threshold` | No | `0.6` | Suspicion score threshold for flagging |
|
|
118
|
+
| `enforce_vision` | No | `false` | Enable Tier 3 vision alignment (set to `true` after reviewing your vision doc) |
|
|
119
|
+
| `post_comment` | No | `true` | Post scorecard as a PR comment |
|
|
120
|
+
|
|
121
|
+
## Outputs
|
|
122
|
+
|
|
123
|
+
| Output | Description |
|
|
124
|
+
|---|---|
|
|
125
|
+
| `verdict` | `FAST_TRACK`, `REVIEW_REQUIRED`, or `RECOMMEND_CLOSE` |
|
|
126
|
+
| `scorecard_json` | Full scorecard as JSON for downstream CI steps |
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## Vision Documents
|
|
131
|
+
|
|
132
|
+
A Vision Document is an optional YAML file that defines what your project is trying to be. It enables Tier 3, where an LLM evaluates whether a PR aligns with your project's direction.
|
|
133
|
+
|
|
134
|
+
Example structure:
|
|
135
|
+
|
|
136
|
+
```yaml
|
|
137
|
+
project: my-project
|
|
138
|
+
principles:
|
|
139
|
+
- name: "Security First"
|
|
140
|
+
description: "All changes touching auth or credentials require security review"
|
|
141
|
+
- name: "Test Everything"
|
|
142
|
+
description: "Every feature PR must include tests"
|
|
143
|
+
|
|
144
|
+
anti_patterns:
|
|
145
|
+
- "Adding dependencies without justification"
|
|
146
|
+
- "Modifying CI/CD without maintainer approval"
|
|
147
|
+
|
|
148
|
+
focus_areas:
|
|
149
|
+
- "src/auth/"
|
|
150
|
+
- "src/credentials/"
|
|
151
|
+
- ".github/"
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Place it at `.github/vision.yaml` and set `vision_document: ".github/vision.yaml"` in the action inputs.
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
## Example Scorecard Comment
|
|
159
|
+
|
|
160
|
+
When the action runs on a PR, it posts a comment like:
|
|
161
|
+
|
|
162
|
+
> ## ⚠ PR Triage: **REVIEW REQUIRED**
|
|
163
|
+
>
|
|
164
|
+
> > First-time contributor modifying sensitive paths without tests.
|
|
165
|
+
>
|
|
166
|
+
> | Dimension | Score | Summary |
|
|
167
|
+
> |---|---|---|
|
|
168
|
+
> | Hygiene & Dedup | `++++++++--` 0.80 | No duplicates found |
|
|
169
|
+
> | Contributor Risk | `++++------` 0.40 | New account + sensitive paths |
|
|
170
|
+
>
|
|
171
|
+
> ### Flags
|
|
172
|
+
> - [**HIGH**] **Sensitive Paths**: PR modifies `src/auth/oauth.ts`, `src/credentials/store.ts`
|
|
173
|
+
> - [MEDIUM] **First Contribution**: No previously merged PRs from this author
|
|
174
|
+
> - [MEDIUM] **Low Test Ratio**: 245 lines added, 0 test lines
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## Roadmap
|
|
179
|
+
|
|
180
|
+
- **PR Triage** — Shipped (v0.3.0)
|
|
181
|
+
- **Issue Triage** — Dedup and classify issues
|
|
182
|
+
- **Issue-to-PR Linking** — Suggest which PRs address which issues
|
|
183
|
+
- **Label Automation** — Auto-classify PRs/issues into project label taxonomies
|
|
184
|
+
- **Contributor Profiles** — Track contribution patterns and reliability
|
|
185
|
+
- **Review Routing** — Suggest reviewers based on file ownership
|
|
186
|
+
- **Smart Stale Detection** — Semantic staleness (superseded, merged elsewhere, blocked)
|
|
187
|
+
- **Cross-PR Conflict Detection** — Surface PRs with overlapping file changes
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## Evidence: OpenClaw Triage
|
|
192
|
+
|
|
193
|
+
We ran this tool against 100 of OpenClaw's 3,368 open PRs:
|
|
194
|
+
|
|
195
|
+
| Verdict | Count | Meaning |
|
|
196
|
+
|---|---|---|
|
|
197
|
+
| FAST_TRACK | 64 (64%) | Safe for quick review |
|
|
198
|
+
| REVIEW_REQUIRED | 30 (30%) | Flagged — needs human attention |
|
|
199
|
+
| RECOMMEND_CLOSE | 6 (6%) | Likely duplicate |
|
|
200
|
+
|
|
201
|
+
- Found 3 duplicate clusters (6 PRs) at 0.90 threshold
|
|
202
|
+
- 89% of PRs from first-time contributors
|
|
203
|
+
- 40% touch security-sensitive paths
|
|
204
|
+
- Extrapolated: ~200 closable duplicates in the full backlog
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
## Cost
|
|
209
|
+
|
|
210
|
+
$0. All tiers run for free:
|
|
211
|
+
- Tier 1: `sentence-transformers` on CPU (GitHub Actions runner)
|
|
212
|
+
- Tier 2: Pure Python rules
|
|
213
|
+
- Tier 3: OpenRouter free models (optional, free API key)
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
## License
|
|
218
|
+
|
|
219
|
+
MIT
|