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.
Files changed (110) hide show
  1. oss_maintainer_toolkit-0.4.0/.github/workflows/publish.yml +30 -0
  2. oss_maintainer_toolkit-0.4.0/.github/workflows/test-action.yml +51 -0
  3. oss_maintainer_toolkit-0.4.0/.github/workflows/test.yml +28 -0
  4. oss_maintainer_toolkit-0.4.0/.gitignore +18 -0
  5. oss_maintainer_toolkit-0.4.0/LICENSE +21 -0
  6. oss_maintainer_toolkit-0.4.0/PKG-INFO +257 -0
  7. oss_maintainer_toolkit-0.4.0/README.md +219 -0
  8. oss_maintainer_toolkit-0.4.0/action.yml +99 -0
  9. oss_maintainer_toolkit-0.4.0/action_entrypoint.py +421 -0
  10. oss_maintainer_toolkit-0.4.0/examples/pr-triage.yml +34 -0
  11. oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/__init__.py +1 -0
  12. oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/analysis/__init__.py +0 -0
  13. oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/analysis/data_flow.py +304 -0
  14. oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/cli/__init__.py +0 -0
  15. oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/cli/main.py +494 -0
  16. oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/config.py +17 -0
  17. oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/cve/__init__.py +0 -0
  18. oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/cve/checker.py +189 -0
  19. oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/cve/parsers.py +94 -0
  20. oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/__init__.py +1 -0
  21. oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/audit_backlog.py +243 -0
  22. oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/audit_scorecard.py +207 -0
  23. oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/cache.py +99 -0
  24. oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/coaching.py +83 -0
  25. oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/config.py +103 -0
  26. oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/conflict_detection.py +104 -0
  27. oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/conflict_scorecard.py +65 -0
  28. oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/contributor_profiles.py +114 -0
  29. oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/contributor_scorecard.py +52 -0
  30. oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/dedup.py +114 -0
  31. oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/github_client.py +300 -0
  32. oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/heuristics.py +259 -0
  33. oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/ingest.py +145 -0
  34. oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/issue_cache.py +99 -0
  35. oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/issue_dedup.py +82 -0
  36. oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/issue_heuristics.py +210 -0
  37. oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/issue_ingest.py +127 -0
  38. oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/issue_pipeline.py +197 -0
  39. oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/issue_scorecard.py +86 -0
  40. oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/labeling.py +202 -0
  41. oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/labeling_scorecard.py +63 -0
  42. oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/linking.py +140 -0
  43. oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/linking_scorecard.py +73 -0
  44. oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/models.py +368 -0
  45. oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/pipeline.py +196 -0
  46. oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/providers.py +267 -0
  47. oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/review_routing.py +170 -0
  48. oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/review_routing_scorecard.py +54 -0
  49. oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/scorecard.py +86 -0
  50. oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/staleness.py +264 -0
  51. oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/staleness_scorecard.py +125 -0
  52. oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/vision.py +474 -0
  53. oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/gatekeeper/vision_generation.py +384 -0
  54. oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/mcp/__init__.py +0 -0
  55. oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/mcp/__main__.py +5 -0
  56. oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/mcp/server.py +525 -0
  57. oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/models.py +79 -0
  58. oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/scanners/__init__.py +0 -0
  59. oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/scanners/patterns.py +194 -0
  60. oss_maintainer_toolkit-0.4.0/oss_maintainer_toolkit/scanners/vulnerability_scanner.py +88 -0
  61. oss_maintainer_toolkit-0.4.0/pyproject.toml +67 -0
  62. oss_maintainer_toolkit-0.4.0/reports/openclaw-pr-body.md +120 -0
  63. oss_maintainer_toolkit-0.4.0/reports/openclaw-triage-2026-02-16.md +139 -0
  64. oss_maintainer_toolkit-0.4.0/reports/openclaw-triage-2026-02-18.json +258 -0
  65. oss_maintainer_toolkit-0.4.0/reports/openclaw-triage-2026-02-18.md +125 -0
  66. oss_maintainer_toolkit-0.4.0/scripts/triage_batch.py +612 -0
  67. oss_maintainer_toolkit-0.4.0/tests/__init__.py +0 -0
  68. oss_maintainer_toolkit-0.4.0/tests/conftest.py +12 -0
  69. oss_maintainer_toolkit-0.4.0/tests/fixtures/package_vulnerable.json +12 -0
  70. oss_maintainer_toolkit-0.4.0/tests/fixtures/requirements_vulnerable.txt +7 -0
  71. oss_maintainer_toolkit-0.4.0/tests/fixtures/sample_claude_response.json +11 -0
  72. oss_maintainer_toolkit-0.4.0/tests/fixtures/sample_clean.py +33 -0
  73. oss_maintainer_toolkit-0.4.0/tests/fixtures/sample_issue_metadata.json +36 -0
  74. oss_maintainer_toolkit-0.4.0/tests/fixtures/sample_pr_files.json +16 -0
  75. oss_maintainer_toolkit-0.4.0/tests/fixtures/sample_pr_metadata.json +30 -0
  76. oss_maintainer_toolkit-0.4.0/tests/fixtures/sample_taint.py +68 -0
  77. oss_maintainer_toolkit-0.4.0/tests/fixtures/sample_user.json +8 -0
  78. oss_maintainer_toolkit-0.4.0/tests/fixtures/sample_vision_document.yaml +16 -0
  79. oss_maintainer_toolkit-0.4.0/tests/fixtures/sample_vulnerable.py +74 -0
  80. oss_maintainer_toolkit-0.4.0/tests/test_action_badges.py +175 -0
  81. oss_maintainer_toolkit-0.4.0/tests/test_audit_backlog.py +253 -0
  82. oss_maintainer_toolkit-0.4.0/tests/test_coaching.py +273 -0
  83. oss_maintainer_toolkit-0.4.0/tests/test_conflict_detection.py +239 -0
  84. oss_maintainer_toolkit-0.4.0/tests/test_contributor_profiles.py +213 -0
  85. oss_maintainer_toolkit-0.4.0/tests/test_cve_checker.py +144 -0
  86. oss_maintainer_toolkit-0.4.0/tests/test_data_flow.py +66 -0
  87. oss_maintainer_toolkit-0.4.0/tests/test_gatekeeper_cache.py +86 -0
  88. oss_maintainer_toolkit-0.4.0/tests/test_gatekeeper_dedup.py +127 -0
  89. oss_maintainer_toolkit-0.4.0/tests/test_gatekeeper_github_client.py +209 -0
  90. oss_maintainer_toolkit-0.4.0/tests/test_gatekeeper_heuristics.py +260 -0
  91. oss_maintainer_toolkit-0.4.0/tests/test_gatekeeper_ingest.py +173 -0
  92. oss_maintainer_toolkit-0.4.0/tests/test_gatekeeper_pipeline.py +253 -0
  93. oss_maintainer_toolkit-0.4.0/tests/test_gatekeeper_providers.py +438 -0
  94. oss_maintainer_toolkit-0.4.0/tests/test_gatekeeper_scorecard.py +122 -0
  95. oss_maintainer_toolkit-0.4.0/tests/test_gatekeeper_vision.py +535 -0
  96. oss_maintainer_toolkit-0.4.0/tests/test_issue_cache.py +86 -0
  97. oss_maintainer_toolkit-0.4.0/tests/test_issue_dedup.py +128 -0
  98. oss_maintainer_toolkit-0.4.0/tests/test_issue_heuristics.py +258 -0
  99. oss_maintainer_toolkit-0.4.0/tests/test_issue_ingest.py +158 -0
  100. oss_maintainer_toolkit-0.4.0/tests/test_issue_pipeline.py +180 -0
  101. oss_maintainer_toolkit-0.4.0/tests/test_issue_scorecard.py +79 -0
  102. oss_maintainer_toolkit-0.4.0/tests/test_labeling.py +420 -0
  103. oss_maintainer_toolkit-0.4.0/tests/test_linking.py +270 -0
  104. oss_maintainer_toolkit-0.4.0/tests/test_mcp_server.py +48 -0
  105. oss_maintainer_toolkit-0.4.0/tests/test_openclaw_scenarios.py +409 -0
  106. oss_maintainer_toolkit-0.4.0/tests/test_review_routing.py +257 -0
  107. oss_maintainer_toolkit-0.4.0/tests/test_staleness.py +365 -0
  108. oss_maintainer_toolkit-0.4.0/tests/test_vision_generation.py +433 -0
  109. oss_maintainer_toolkit-0.4.0/tests/test_vulnerability_scanner.py +83 -0
  110. 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,18 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *$py.class
4
+ *.egg-info/
5
+ dist/
6
+ build/
7
+ .env
8
+ venv/
9
+ .venv/
10
+ .pytest_cache/
11
+ *.egg
12
+ .eggs/
13
+ *.so
14
+ .mypy_cache/
15
+ .mcp.json
16
+ mcp_stderr*.log
17
+ .gatekeeper_cache.db
18
+ *-tutorial.md
@@ -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
+ > ## &#x26A0; 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
+ > ## &#x26A0; 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