@reneturcios/greenlight 0.14.0 → 0.15.0
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.
- package/README.md +140 -212
- package/dist/brief.d.ts +94 -0
- package/dist/brief.js +283 -0
- package/dist/brief.js.map +1 -0
- package/dist/cli.js +66 -0
- package/dist/cli.js.map +1 -1
- package/dist/help.js +22 -0
- package/dist/help.js.map +1 -1
- package/dist/index.js +28 -0
- package/dist/index.js.map +1 -1
- package/dist/radar.d.ts +84 -0
- package/dist/radar.js +370 -0
- package/dist/radar.js.map +1 -0
- package/package.json +1 -1
- package/server.json +2 -2
package/README.md
CHANGED
|
@@ -1,62 +1,58 @@
|
|
|
1
1
|
# Greenlight
|
|
2
2
|
|
|
3
|
-
Greenlight
|
|
3
|
+
**Greenlight is the pre-flight and coordination layer for open-source contribution: the software that stands between an outside contributor (increasingly an AI agent) and the maintainers of a public repo, and answers the questions no other tool answers. Can I contribute here at all? Is this issue secretly taken? What are the house rules? Who else is racing me? And for maintainers: who is flooding my queue, and what is safe to merge?**
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Why this layer exists
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Follow the venture money and you will see where it is not going. Cognition (Devin) raised about $2B at a $48B valuation, and Factory raised $200M at a $5B valuation, to run autonomous coding agents *inside* enterprises' own repos. CodeRabbit raised $88M (valued near $550M), Graphite raised a $52M Series B before being acquired by Cursor, and Greptile raised a $25M Series A, all reviewing a team's *own* pull requests. OpenHands is an agent runtime. Every funded player assumes you are inside the org.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
Nobody owns the boundary. No VC-backed tool answers the outside contributor's questions: can I contribute here, is this issue secretly taken, what are this repo's gates and AI policies, who else is racing me. And no VC-backed tool answers the maintainer's questions: which of these 30 open PRs are duplicates, who is claiming what, which claims have gone stale, which agent-written PRs are safe to merge. Greenlight is that layer, built from running real contribution campaigns through it every week.
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
## Use Greenlight inside your AI coding tool
|
|
11
|
+
## The problem
|
|
14
12
|
|
|
15
|
-
|
|
13
|
+
AI made code cheap. Contribution coordination is now the bottleneck, and it breaks in specific, repeatable ways:
|
|
16
14
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
* **Hidden competition.** Issue list views lie. In a hand-vetted focus session on usebruno/bruno, 6 of 7 promising issues were secretly taken by PRs visible only in the issues' timelines, not in the list view or search results. You can spend a weekend on work that was already done.
|
|
16
|
+
* **Gates and bans.** Greenlight's own Agent Policy Index now tracks 505 repos: 127 of them (25%) carry contribution gates, and 19 ban agent contributions outright. Whole repos (nuxt, uv, Gradio, Activepieces) have closed their doors to outside PRs entirely. Nobody told you; it was in AGENTS.md.
|
|
17
|
+
* **Duplicate AI PRs.** When several contributors (human or agent) race the same issue, maintainers get three overlapping PRs and no way to arbitrate. GitHub has no claim system, only comments.
|
|
18
|
+
* **House rules everywhere.** CLAs, DCO sign-off, changesets, commit formats, assignment requests. Every repo invents its own, hides them in different files, and rejects your PR on the technicality.
|
|
20
19
|
|
|
21
|
-
|
|
20
|
+
These are coordination problems, not coding problems. The code agents keep getting better; the boundary keeps getting messier. Greenlight works the boundary.
|
|
22
21
|
|
|
23
|
-
##
|
|
24
|
-
|
|
25
|
-
You find an issue that looks perfect. You code all evening. Then one of these happens:
|
|
22
|
+
## What Greenlight does
|
|
26
23
|
|
|
27
|
-
|
|
28
|
-
* The repo wanted you to ask first. Your pull request gets closed because the maintainers require contributors to request assignment or get a vouch (a recommendation from someone they know) before anyone may open a PR, and nobody told you.
|
|
29
|
-
* Your commits get rejected on a technicality. The repo requires a "Signed-off-by" line on every commit (called DCO sign-off, short for Developer Certificate of Origin) or an entry in its changelog folder, and you find out after you push.
|
|
24
|
+
Three layers, from decide to solve to coordinate:
|
|
30
25
|
|
|
31
|
-
|
|
26
|
+
| Layer | Question it answers | Flagship commands |
|
|
27
|
+
|---|---|---|
|
|
28
|
+
| **Decide** | Is this issue mine to take? Is this repo worth my time? | `check`, `scan`, `friction`, `xray`, `preflight` |
|
|
29
|
+
| **Solve** | Will my PR pass? What broke? What do I do next? | `ci-prep`, `ci`, `review`, `brief`, `verify`, `autopilot`, `babysit`, `evidence` |
|
|
30
|
+
| **Coordinate** | Who is working on what, and who resolves conflicts? | `claim` (+ Claim Protocol), `guard`, `radar`, `digest`, `passport` |
|
|
32
31
|
|
|
33
|
-
|
|
32
|
+
* **Decide.** `check` reads an issue, its comments, linked and mentioned PRs (timeline plus search plus comment references), and the repo's rules, then answers in plain words: GO, RISKY, TAKEN, GATED, or STALE. `scan` ranks a repo's open issues so you pick a winnable one first. `friction` scores a repo 0 to 100 on how hard it really is to get a PR merged, with every gate quoting the file its evidence came from. `xray` (Timeline X-Ray) deep-verifies candidates against their issue timelines before you write a line, catching hidden in-flight PRs including reporter-owned fix PRs; `scan --deep` demotes anything taken before it shows you the list.
|
|
33
|
+
* **Solve.** `ci-prep` runs a repo's own pull-request checks locally before you push (tests, lint, typecheck, plus conventions like changesets, commit format, DCO), so avoidable CI failures never appear in front of a maintainer. `ci` triages red PRs into pre-existing vs likely-yours vs external-blocker against base-branch history. `review` classifies every review thread as likely-real, likely-noise, or needs-decision and drafts your replies. `verify` reports the honest red-green test delta of your change. `autopilot` verifies bot findings against the code at head and fixes the mechanical items (DCO surgery, conflict re-merges, formatting) itself. `brief` assembles a verified one-screen brief for any PR: change shape by area and risk, CI triaged against base-branch history, findings classified real vs false-positive with evidence, test evidence present or explicitly marked absent, merge blockers, and a one-line look-at-this-first. `babysit` watches your open PRs and reports one prioritized action list.
|
|
34
|
+
* **Coordinate.** `claim` posts a protocol claim (expiring lease, public queue, heartbeats; full spec in [`protocol/SPEC.md`](protocol/SPEC.md)), with a hosted app client option via `--via-api`. `guard` analyzes an incoming PR for a maintainer: competing fix, prior claims, missing artifacts, first-time contributor. `digest` reports a repo's PR races, claimed-by-other conflicts, stale claims, and assignment-gate conflicts. `radar` scans the whole open-PR queue and clusters competing or duplicate PRs with evidence per cluster and a suggested keep, labeled a heuristic, never a verdict. `passport` renders a contributor's merged work plus claim record.
|
|
34
35
|
|
|
35
|
-
|
|
36
|
+
Every verdict and every report cites its evidence: the quoted policy line, the claim comment URL, the PR number, the failing check. Nothing is asserted without a source.
|
|
36
37
|
|
|
37
|
-
|
|
38
|
-
2. **Claim the right way.** It drafts the claim comment in the form the repo's rules actually want: a plain "I'll work on this" where that is enough, an assignment request where the repo requires one, or a refusal where a vouch is needed (no tool can vouch for you). It never posts without your say-so.
|
|
39
|
-
3. **Prep your workspace with the repo's own rules.** It sets up your fork and branch, then writes a checklist that includes what it learned from the repo itself: the house-rules files, the verify command they insist on, whether the repo wants a changelog entry, and how its commits are styled.
|
|
40
|
-
4. **Open the PR only when the basics pass.** It checks the branch is really ahead of the repo, and on repos that require DCO sign-off it verifies every commit carries the Signed-off-by line before it opens the pull request.
|
|
38
|
+
## Who it is for
|
|
41
39
|
|
|
42
|
-
|
|
40
|
+
* **Contributors (human).** Run `check` before you spend an evening on an issue. Run `scan` when you are picking what to work on. Run `ci-prep` before you push.
|
|
41
|
+
* **AI agents and coding tools.** One command (`init --agent claude-code`, also cursor, copilot, windsurf, cline) installs the MCP config plus the one behavior rule: check Greenlight before opening a PR. Agents waste the most tokens fixing already-taken issues; 27 MCP tools make the whole engine available mid-run.
|
|
42
|
+
* **Maintainers.** `guard` on each incoming PR, `radar` across the whole open queue, `digest` for the weekly triage, and the roadmap below for the control room: stale-claim sweeps, policy enforcement, AI-PR filtering.
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
* You want to know if an issue is really still yours to finish, or whether someone quietly claimed part of it in a comment.
|
|
46
|
-
* A repo's rules are unclear and you want to see them summarized before you start.
|
|
47
|
-
* You claimed something a while ago and want to know if that claim still counts.
|
|
48
|
-
* You are picking between several repos or issues and want the most winnable one first.
|
|
44
|
+
## Proof, stated plainly
|
|
49
45
|
|
|
50
|
-
|
|
46
|
+
* 965 tests, all passing, including a fixture corpus pinned to real campaign cases (a taken issue, a weak PR mention, claim-first gates, scoped claims, half-shipped issues, stale claims, paused-PR workflows).
|
|
47
|
+
* Dogfooded on real campaigns: the toolkit has authored 80+ pull requests across dozens of public open-source repos. Every feature exists because a real contribution died without it.
|
|
48
|
+
* Distributed everywhere the audience already looks: npm (`@reneturcios/greenlight`), the MCP Registry, and GHCR (`ghcr.io/cloudcorprecords/greenlight`), plus Docker and direct MCP stdio.
|
|
49
|
+
* Two living datasets ship with it: the Contribution Friction Index (`data/friction-index.json`) and the Agent Policy Index (505 repos, 127 gated, 19 agent bans, published at `docs/policy.html`), both built from real campaign field work, not scraped guesses.
|
|
51
50
|
|
|
52
|
-
|
|
51
|
+
## Watch it work
|
|
53
52
|
|
|
54
|
-
|
|
55
|
-
2. **Repo friction scores** (0-100, 100 = easiest): contribution gates parsed from CONTRIBUTING variants plus house-rules files (`AGENTS.md`, `CLAUDE.md`), with each gate recording which file its evidence came from (assignment-first, vouch, CLA, DCO, discussion-first, comment-first, collaborators-only, paused unsolicited PRs, external PRs auto-closed by workflow), plus outcome signals where computable.
|
|
56
|
-
3. **Scan mode**: rank a repo's open good-first-issue / help-wanted issues by verdict so a contributor (or agent) picks a winnable one first. Falls back to recent open unassigned issues when a repo has no labeled starter issues.
|
|
57
|
-
4. **Contribution automation**: `claim`, `prep`, and `pr` commands (plus matching MCP tools) that run the pipeline after the verdict. All writes are dry-run by default and need a token plus an explicit go flag.
|
|
53
|
+

|
|
58
54
|
|
|
59
|
-
|
|
55
|
+
*The 59-second demo: real issue checks on real repos, an AI-caught hidden claim, a GATED agent ban, campaign scouting, and the claims babysitter. [Full narrated video](docs/assets/greenlight-demo.mp4).*
|
|
60
56
|
|
|
61
57
|
## Install
|
|
62
58
|
|
|
@@ -99,16 +95,15 @@ docker run ghcr.io/cloudcorprecords/greenlight check <issue-url>
|
|
|
99
95
|
docker run ghcr.io/cloudcorprecords/greenlight --version
|
|
100
96
|
```
|
|
101
97
|
|
|
102
|
-
##
|
|
98
|
+
## Use it inside your AI coding tool
|
|
103
99
|
|
|
104
|
-
|
|
100
|
+
One command sets it up:
|
|
105
101
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
4. **prwatch** (`npx @reneturcios/prwatch attention --user you`) triages your open PRs by what needs you right now: review threads, failing checks, conflicts, reviewer silence.
|
|
102
|
+
```bash
|
|
103
|
+
npx @reneturcios/greenlight init --agent claude-code
|
|
104
|
+
```
|
|
110
105
|
|
|
111
|
-
|
|
106
|
+
(also `cursor`, `copilot`, `windsurf`, `cline`; repeat `--agent` for more than one). Init copies the MCP config into your project and installs the workflow instruction snippet that teaches your agent the one behavior rule: **check Greenlight before it opens a PR.** Prefer doing it by hand? The [`integrations/`](integrations/README.md) drop-in pack has ready-to-copy MCP configs plus the same snippets. Then verify with a "list your MCP tools" prompt; the greenlight server carries 27 tools (see the list below).
|
|
112
107
|
|
|
113
108
|
## CLI
|
|
114
109
|
|
|
@@ -164,6 +159,18 @@ npx @reneturcios/greenlight ci-prep ~/work/bruno
|
|
|
164
159
|
# Review triage for a PR with review feedback: which comments need you?
|
|
165
160
|
npx @reneturcios/greenlight review https://github.com/n8n-io/n8n/pull/41235
|
|
166
161
|
|
|
162
|
+
# Verified review brief for any PR: change shape by area and risk, CI
|
|
163
|
+
# triaged against base-branch history, findings classified with evidence,
|
|
164
|
+
# test evidence present or explicitly marked absent, merge blockers, and
|
|
165
|
+
# a one-line look-at-this-first
|
|
166
|
+
npx @reneturcios/greenlight brief https://github.com/usebruno/bruno/pull/9569
|
|
167
|
+
|
|
168
|
+
# Brief: 4 files (+335/-11), 2 source + 2 tests
|
|
169
|
+
# CI: code checks green; external blockers named (fork workflows require maintainer approval)
|
|
170
|
+
# review: NO FINDINGS
|
|
171
|
+
# blockers: none
|
|
172
|
+
# lookFirst: No blockers or real findings. Start here: 2 source files carry the change.
|
|
173
|
+
|
|
167
174
|
# Campaign scout: rank repo targets, dedupe against the campaign file, append as SCOUTED
|
|
168
175
|
npx @reneturcios/greenlight scout --repos acme/widgets,acme/gadgets --campaign campaign.json --write
|
|
169
176
|
|
|
@@ -185,10 +192,6 @@ npx @reneturcios/greenlight babysit --claims-only
|
|
|
185
192
|
# ledgered. greenlight status shows your pacing posture.
|
|
186
193
|
npx @reneturcios/greenlight status https://github.com/owner/repo/issues/123
|
|
187
194
|
|
|
188
|
-
# [likely-real] interpolation drops `__proto__` (packages/bruno-cli/src/runner/interpolate-vars.js:42)
|
|
189
|
-
# why: anchor matches: the comment's quoted token Object.assign({}, params) is present in the anchored hunk
|
|
190
|
-
# draft reply: Good catch. Fixed in <next commit>: ...
|
|
191
|
-
|
|
192
195
|
# Maintainer guard for an incoming PR: competing fix, prior claims, missing
|
|
193
196
|
# artifacts (changeset / DCO / CLA), first-time contributor. Renders markdown
|
|
194
197
|
# ready to post as one comment; Greenlight itself never posts.
|
|
@@ -198,6 +201,15 @@ npx @reneturcios/greenlight guard https://github.com/owner/repo/pull/123
|
|
|
198
201
|
# - Missing release-note file (repo uses .changes/): expected .changes/123-slug.md
|
|
199
202
|
npx @reneturcios/greenlight guard <pr-url> --quiet # exit 3 when flagged, silent otherwise
|
|
200
203
|
|
|
204
|
+
# Duplicate/competing PR radar for the whole queue: clusters PRs fixing the
|
|
205
|
+
# same issue or touching the same files, with evidence and a suggested keep
|
|
206
|
+
# per cluster (always labeled a heuristic, never a verdict)
|
|
207
|
+
npx @reneturcios/greenlight radar usebruno/bruno --limit 100
|
|
208
|
+
|
|
209
|
+
# 100 open PRs scanned in 6 API calls: 3 competing clusters, 94 unclustered
|
|
210
|
+
# cluster (same issue #5011): #5016 "Fix: Param table UI breaks bug" ~ #5074 "fix: Param Table UI Breaks on resize" - suggested keep #5016 (heuristic)
|
|
211
|
+
# cluster (file overlap, 100% Jaccard in packages/): #3484 ~ #5747 - suggested keep #3484 (heuristic)
|
|
212
|
+
|
|
201
213
|
# Verified comment for a maintainer-only repo: the issue takes no outside
|
|
202
214
|
# PRs (inspector, servers), so the contribution is a detailed, verified
|
|
203
215
|
# comment. Assembles from your notes or a markdown file; sections you
|
|
@@ -222,7 +234,7 @@ npx @reneturcios/greenlight verify-comment https://github.com/modelcontextprotoc
|
|
|
222
234
|
cd your-repo && npx @reneturcios/greenlight verify --base origin/main
|
|
223
235
|
# exit 3 when new failures exist, 1 when unverifiable
|
|
224
236
|
|
|
225
|
-
# PR babysitter: one prioritized action list across your open PRs
|
|
237
|
+
# PR babysitter: one prioritized action list across your open PRs --
|
|
226
238
|
# needs you now, waiting on them, quiet. Reruns report what changed.
|
|
227
239
|
npx @reneturcios/greenlight babysit --mine --repos acme/widgets,acme/gadgets
|
|
228
240
|
# or: greenlight babysit --prs <url1>,<url2> --fail-on-action (exit 3 when action is needed)
|
|
@@ -236,6 +248,15 @@ npx @reneturcios/greenlight evidence https://github.com/acme/widgets/pull/42 --o
|
|
|
236
248
|
# Contributor passport: protocol claims from the public Claim Ledger plus
|
|
237
249
|
# merged PRs from GitHub. No Ledger file yet? It says so plainly.
|
|
238
250
|
npx @reneturcios/greenlight passport CloudCorpRecords
|
|
251
|
+
|
|
252
|
+
# The proxy, for authenticated reads (60/hr anonymous -> 5000/hr token):
|
|
253
|
+
# reads GITHUB_TOKEN once at startup, attaches it server-side, binds
|
|
254
|
+
# 127.0.0.1 only, and refuses to start without a token.
|
|
255
|
+
export GITHUB_TOKEN=<your-classic-token> && greenlight proxy &
|
|
256
|
+
export GREENLIGHT_GITHUB_BASE_URL=http://127.0.0.1:8792 GITHUB_TOKEN=proxy
|
|
257
|
+
|
|
258
|
+
# Verify every link of a release chain (tag, commit, release, npm, registry)
|
|
259
|
+
npx @reneturcios/greenlight shipcheck <owner/repo> --version x.y.z
|
|
239
260
|
```
|
|
240
261
|
|
|
241
262
|
Real examples from our vetting:
|
|
@@ -246,82 +267,6 @@ Real examples from our vetting:
|
|
|
246
267
|
* `PrefectHQ/fastmcp#5718` scores **GATED**: FastMCP requires assignment or a "prs welcome" label before a PR.
|
|
247
268
|
* `triggerdotdev/trigger.dev#5016` scores **GATED**: unvouched-author PRs are auto-closed, a vouch request goes first.
|
|
248
269
|
|
|
249
|
-
## How scoring works
|
|
250
|
-
|
|
251
|
-
The verdict engine is deterministic (no LLM) and checks, in order:
|
|
252
|
-
|
|
253
|
-
1. Closed issue: **TAKEN** (never landable).
|
|
254
|
-
2. Any assignee: **TAKEN**.
|
|
255
|
-
3. An open linked PR that **closes** the issue: **TAKEN**. A PR that merely mentions the issue number (like pdfcn PR #91, which closes #70 but lists sibling issues in its body) only adds a `weak-pr-mention` flag and downgrades an otherwise-GO verdict to **RISKY**. Marked a duplicate of an issue closed as completed: **RISKY** with the `duplicate-of-closed` flag (the work already shipped; a still-open duplicate target only adds a `duplicate-of-open` warning with its URL).
|
|
256
|
-
4. Two or more strong claimants: **TAKEN** (claim race).
|
|
257
|
-
5. One strong fresh whole-issue claim (under 45 days): **RISKY** with the `claimed` flag. A fresh claim scoped to part of the issue ("taking the remaining fallback ask"): **RISKY** with `claimed` + `partial-claim` flags and a reason naming the claimer and the scope, never TAKEN.
|
|
258
|
-
6. One strong claim older than 45 days with no closing PR: **RISKY** with the `stale_claim` flag. The claimant probably walked away, but nobody knows for sure. Stale scoped claims get the same treatment.
|
|
259
|
-
7. A hard gate (assignment, vouch, collaborators-only, paused unsolicited PRs, external PRs auto-closed by workflow) with nobody assigned: **GATED**. The last two come from CONTRIBUTING language (\"paused unsolicited pull requests\") and a scan of `.github/workflows` for close-external-PR automation.
|
|
260
|
-
8. No activity for 180+ days: **STALE**.
|
|
261
|
-
9. A soft claim-first gate (the repo asks contributors to comment before starting, like pdfcn): never **GATED**; it caps an otherwise-GO verdict at **RISKY** with a note, the same downgrade shape as a weak PR mention.
|
|
262
|
-
10. Otherwise: **GO**.
|
|
263
|
-
11. An open PR referenced in a non-author comment whose title/body mentions the issue number: downgrades an otherwise-GO verdict to **RISKY** with the `comment-mentioned-pr` flag ("may already cover part of this issue"). Neither can produce **TAKEN**; only closing PRs do that. Fix-announcement comments ("/attempt #N" commands or "Submitted fix for ... in <PR url>" narratives, often linking PRs in sibling repos) get the same downgrade under their own reason quoting the PR URL, with the `attempt-linked-pr` flag, even when the PR never names the issue. `/attempt` comments also register as strong claims.
|
|
264
|
-
12. **Partially-addressed**: merged PRs that reference the issue number (comment-mentioned or linked), or maintainer comments signaling part of the work already shipped ("Half addressed by #905, leaving this open for half B", "Shipped in v3.1.0" next to the issue reference). A plain **GO** hides the scoping work this needs, so the flag `partially-addressed` is added, an otherwise-GO verdict is capped at **RISKY** with a reason like "part of this issue already shipped (PR #905, merged); scope your work to what remains". Never **TAKEN**.
|
|
265
|
-
|
|
266
|
-
Claim detection scans comments for explicit claim phrases, in-progress signals ("fix ready", "PR incoming", "opened a PR"), and soft offers ("happy to fix", "take a look at this one"). Bot authors are ignored, as are issue reporters unless they announce a ready fix. Soft claims now carry their comment date, so the verdict can show how old they are (the `weak-claim` flag, warning only). Scoped claims ("taking the remaining fallback ask", "claiming this half") are recorded as partial: a fresh partial claim downgrades an otherwise-GO verdict to RISKY with a reason naming the claimer and the scope, never TAKEN. PR references (#NNN) in non-author comments are cross-checked against the PR API: an open referenced PR that mentions the issue downgrades GO to RISKY with the `comment-mentioned-pr` flag, and a merged one feeds rule 12 above.
|
|
267
|
-
|
|
268
|
-
### Optional AI claim detection
|
|
269
|
-
|
|
270
|
-
The pattern layer cannot know every way a human says "I'm taking this" (one evening it missed "I'm looking into contributing a fix here" on a real issue). Set `FIREWORKS_API_KEY` and `check` gains an optional second pair of eyes: a cheap Fireworks model reads the eligible comments (bots and the issue author excluded, same pool as the patterns) and flags statements of intent the patterns missed.
|
|
271
|
-
|
|
272
|
-
The governance is plain:
|
|
273
|
-
|
|
274
|
-
- **Off by default.** No key, no calls, output byte-identical to the pattern-only engine.
|
|
275
|
-
- **Patterns stay primary and cheaper.** The AI only runs when they found no strong claim.
|
|
276
|
-
- **Flags, never verdicts.** An AI flag adds the `llm-claim` flag with the exact quote as evidence and downgrades an otherwise-GO verdict to **RISKY**. It can never produce **TAKEN** and never overrides **GATED**. Verdicts stay deterministic.
|
|
277
|
-
- **No invented evidence.** The quote must be an exact substring of the comment body; anything else is dropped before it can reach the verdict.
|
|
278
|
-
- **Failures are silent.** A timeout, a non-200 response, or an unparseable reply returns no signal, never an error into the check path. Classifications are cached by comment id and model id, so repeat checks cost nothing.
|
|
279
|
-
|
|
280
|
-
Cost on the default model (`accounts/fireworks/models/glm-5p3-flash`): one issue check costs well under a tenth of a cent. Override the model with `GREENLIGHT_LLM_MODEL` and the endpoint with `GREENLIGHT_LLM_BASE_URL`. `greenlight doctor` reports whether the layer is configured (the key is never printed).
|
|
281
|
-
|
|
282
|
-
### v0.9.3: the tool learns its gates
|
|
283
|
-
|
|
284
|
-
The Agent Policy Index field work kept finding agent bans Greenlight itself missed, so the detection learned them instead of working around them:
|
|
285
|
-
|
|
286
|
-
- **Policy files are read where repos actually keep them.** `AGENTS.md`, `CLAUDE.md`, `CONTRIBUTING.md`, and `AI_POLICY.md` are now probed at the repo root, in `.github/`, and in `docs/` (first hit per filename wins), plus the org-level `.github/AI_POLICY.md`, probed once per org and cached. Root-only reading had called tailwindcss, reveal.js, and AFFiNE "no policy" while their CONTRIBUTING sat one directory away.
|
|
287
|
-
- **Nine real bans are now detected, each pinned by a regression fixture:** immich, home-assistant (via its AI_POLICY.md), zed, meilisearch, mastodon (via the org policy), astral-sh/ruff and astral-sh/uv (via the org policy), stanfordnlp/dspy, kedro-org/kedro, and alacritty. Matching is done on the whole file with whitespace and markdown emphasis normalized, so line-wrapped prose no longer slips through.
|
|
288
|
-
- **Scoped bans dual-class instead of collapsing.** A ban aimed at one kind of agent operation (TypeScript's "bulk, agent-driven contributions", ppt-master's "purely AI-generated PRs submitted without human review") now surfaces as both `agents_banned` for autonomous operation and `agents_disclosure` for the human-led path. An explicit prohibition (nuxt, ripgrep, zed) still stands on its own, and explicit welcome or waiver language (hyperframes welcomes AI help and waives disclosure) never reads as a ban.
|
|
289
|
-
- **Friction JSON states its units.** `friction --json` now carries `outsider_merge_share` (0 to 1 fraction) and `outsider_merge_share_pct` (0 to 100), plus `signals.externalPRMergeRate_pct` next to the existing fraction field. The human-readable output is unchanged.
|
|
290
|
-
|
|
291
|
-
### v0.13.0: Timeline X-Ray
|
|
292
|
-
|
|
293
|
-
`greenlight xray` deep-verifies candidate issues against their GitHub timelines: the linked-PR walk (timeline + search) with linkStrength scoring, reporter-owned-PR detection, and a lazy comment-claim scan, at ~4 API calls per issue. `scan --deep` demotes anything the x-ray finds taken before presenting results. New MCP tool `xray_issues`; `scan_repo` gains `deep`. Born from a Bruno focus session where 6 of 7 hand-vetted issues turned out to be secretly taken by timeline-only PRs.
|
|
294
|
-
|
|
295
|
-
### v0.12.0: the Claim Protocol GitHub App client
|
|
296
|
-
|
|
297
|
-
One command claims now: `greenlight claim <issue-url> --via-api` posts through the hosted claim API instead of handing you a comment to paste. `greenlight auth login` runs the GitHub device flow once and stores the token in your OS keychain (or `~/.greenlight/api-token` at 0600 when no keychain is available); `--token` / `GREENLIGHT_API_TOKEN` covers scripts. Before any `--via-api` write, the client checks whether the Greenlight Claims app is installed on the repo: installed means the claim goes through the app backend (durable state recorded via webhooks); not installed means the current direct-API comment path with a printed one-line note saying so. The downgrade is never silent. The flow is honest end to end: a hosted status read runs the TAKEN pre-flight (refuses on another holder unless `--queue-ok`), the posted comment is verified by re-reading the status, and a 401 re-runs the device flow once before printing the manual steps. `greenlight release --via-api` and `greenlight heartbeat --via-api` cover the rest of the lifecycle. The MCP server grows to 23 tools with `api_status`, `claim_via_api`, and `heartbeat_via_api` (all report-mode-safe).
|
|
298
|
-
|
|
299
|
-
### v0.11.0: Autopilot
|
|
300
|
-
|
|
301
|
-
Open PRs were dying between babysit sweeps: a bot review sitting unanswered, a CI failure on the PR's own code, a drifted branch, a missing DCO trailer. Autopilot closes that loop. `greenlight autopilot` (report-only by default, `--apply` to fix) collects reviews, comments, and check results per open PR, verifies bot findings against the code at head (REAL, FALSE_POSITIVE with quoted counter-evidence, or NEEDS_HUMAN), and triages CI failures as introduced vs pre-existing against the base branch. The mechanical items fix themselves: DCO gaps get message-only surgery with byte-identical trees, merge conflicts resolve only when provably mechanical (lockfiles regenerated, changelogs unioned, version or counter bumps), and formatting pushes only when the diff is whitespace-only. Everything else becomes a plan, never a speculative edit. Fixes land on your fork branch with Rene's sign-off, respect the capability ledger's blocked repos, and replies queue as drafts behind the comment block instead of posting. Also exposed as the read-only `autopilot_report` MCP tool.
|
|
302
|
-
### v0.10.1: never again hardening
|
|
303
|
-
|
|
304
|
-
Three failures on 2026-10-18, each paid for in full, each now structurally impossible to repeat:
|
|
305
|
-
|
|
306
|
-
- **`greenlight shipcheck` verifies every link of a release chain.** A v0.9.3 ship report once claimed a git commit that did not exist: the tag pointed at a nonexistent object while npm and the registry were genuinely fine, and every verification step checked the package and the listing but never the git links. `shipcheck <owner/repo> --version x.y.z` checks all of them: the tag ref resolves, the commit object exists, package.json at the tag carries the version, the GitHub release exists, npm shows the version, and the MCP Registry shows it active. It exits non-zero naming the broken link, so a CI gate can run it after every publish. Reads only.
|
|
307
|
-
- **The capability ledger remembers what the account can do.** actualbudget/actual blocked PR creation (422 "user is blocked") and modelcontextprotocol/typescript-sdk 404'd it despite a valid fork; both were discovered only after full builds were done. Every claim and PR-creation outcome the tool observes is now recorded in `~/.greenlight/capabilities.json` with a timestamp and an evidence string, so the lesson is paid for once.
|
|
308
|
-
- **`greenlight preflight` is the reads-only go/no-go before a build.** It checks the fork exists with the right parent, reports KNOWN-BLOCKED with the recorded evidence when the ledger holds a structural block, summarizes the repo's policy gates, and with `--base` and `--files` flags each file's blob at the build base against the current upstream head, flagging DRIFTED files by name (actual #7333's upstream moved on the exact file the fix touched, discovered at open time). `scout` now excludes ledger-blocked repos before spending any API budget, naming the recorded reason.
|
|
309
|
-
|
|
310
|
-
### v0.10.0: multi-agent campaign management
|
|
311
|
-
|
|
312
|
-
Campaigns are no longer one agent: several agents now open PRs in parallel threads, and the tool's local memory only knew about PRs this process created. v0.10.0 makes the whole board visible and the shared limits safe:
|
|
313
|
-
|
|
314
|
-
- **`greenlight sync` reconciles local tracking with API truth.** It pulls the authoritative census (`author:<login> type:pr`) and reports drift: PRs the registry never saw (another agent opened them), state mismatches (the registry says open, the API says merged), and stale claims with no linked PR after `--stale-days` (default 7). `--tracker <csv|json>` diffs a tracker file too; `--write` upserts the registry's known-PRs section. Reads only, never posts.
|
|
315
|
-
- **`greenlight babysit --account` watches the whole account.** Instead of only locally-known PRs, the portfolio comes from the author census, so PRs opened by other agents or machines get the same needs-you-now triage. Without the flag, behavior is unchanged.
|
|
316
|
-
- **The posting ledger is multi-agent.** Every entry now carries an `agent` field (`GREENLIGHT_AGENT_ID` when set, otherwise `<hostname>:<pid>`), the daily soft cap and claim cadence are enforced against the combined ledger, and a lock file guards read-modify-write so concurrent processes cannot race past the cap. Set `GREENLIGHT_AGENT_ID` per agent (for example `worker-a`, `cron-scan`) to see who posted what.
|
|
317
|
-
- **`greenlight portfolio` is the one-screen summary:** census counts, claims by state, the pending posting queue (unconfirmed posts plus unlinked claims), and the drift count. Human text or `--json`. The same surface is exposed as the `sync_campaign` and `campaign_portfolio` MCP tools.
|
|
318
|
-
|
|
319
|
-
### v0.3.4: never race blind
|
|
320
|
-
|
|
321
|
-
One evening, five of twelve claimed issues were already taken. The races were not in the comments: they were in the issue timelines, where GitHub records PRs that reference the issue even when their bodies never say "closes #N". So `check` now reads the timeline. An open cross-referenced PR caps the verdict at **TAKEN** with the PR URL and title quoted. A merged one adds a "the issue may already be fixed, verify what shipped" note instead, capped at **RISKY**, because a merged PR can fix only part of an issue. Also new: emoji-proof fix-announcement matching ("Opened #NNN", "🤖 ..." prefixes), bounty-liveness warnings (dead platforms like Algora are named, unverified bounties are flagged, and bounties never raise a verdict), and a `possibly-server-side` warning when the issue's quoted error text does not exist anywhere in the repo. The `friction` command gains one more line when computable: the share of recent merged PRs written by outsiders and the median time to merge, straight from the API.
|
|
322
|
-
|
|
323
|
-
Friction score starts at 100 and subtracts gate weights (assignment -25, vouch -35, collaborators-only -50, paused unsolicited PRs -40, external PRs auto-closed -50, discussion-first -10, claim-first -5, CLA/DCO -5 each), adjusts for external PR merge rate and review/response times when computable, and adds up to +10 for open good-first-issues. Unknown signals stay null and are skipped, never guessed. See `src/friction.ts` for the exact formula.
|
|
324
|
-
|
|
325
270
|
## MCP server
|
|
326
271
|
|
|
327
272
|
The same engine is exposed over stdio for coding agents (Claude, Cursor, Cline). The wedge: agents waste the most tokens fixing already-taken issues. Have the agent pre-flight the issue before writing code.
|
|
@@ -338,117 +283,83 @@ The same engine is exposed over stdio for coding agents (Claude, Cursor, Cline).
|
|
|
338
283
|
}
|
|
339
284
|
```
|
|
340
285
|
|
|
341
|
-
Tools:
|
|
286
|
+
Tools (27):
|
|
342
287
|
|
|
343
288
|
* `check_issue` - verdict for one issue URL
|
|
344
289
|
* `scan_repo` - rank a repo's open issues, GO first (label-tagged starter issues, falling back to recent open unassigned issues; `deep: true` timeline-x-rays the candidates first)
|
|
290
|
+
* `xray_issues` - Timeline X-Ray: deep-verify candidate issues against their timelines (hidden in-flight PRs, reporter-owned fix PRs, comment claims); GO / RISKY / TAKEN per issue with PR evidence
|
|
345
291
|
* `repo_friction` - friction score for a repo
|
|
346
292
|
* `claim_issue` - verdict-gated claim comment (dry run unless `execute: true`)
|
|
347
293
|
* `prep_issue` - fork and branch check plus a local PREP.md checklist with the repo's learned conventions (dry run unless `execute: true`)
|
|
348
294
|
* `open_pr` - DCO-aware PR opening from a fork branch (dry run unless `execute: true`)
|
|
295
|
+
* `ci_prep` - run a repo's own PR checks locally before pushing (exit 1 on NO-GO)
|
|
349
296
|
* `ci_triage` - classify each failing check on a PR as pre-existing, likely-yours, indeterminate (with a stated lean), or external-blocker, by comparing against the base branch's recent check history
|
|
350
297
|
* `review_triage` - triage the review feedback on your PR: each finding classified likely-real / likely-noise / needs-decision with its reason and a reply draft (humans are never called noise; drafts only, nothing posted)
|
|
298
|
+
* `pr_brief` - verified review brief for any PR: files grouped by area/risk, CI triage against base-branch history, findings classified real vs false-positive with evidence, test evidence present or explicitly marked absent, merge blockers, and a one-line look-at-this-first (never invents findings)
|
|
351
299
|
* `guard_pr` - maintainer-side analysis of an incoming PR: competing fix, prior claims by someone other than the author, missing artifacts (changeset / DCO / CLA), first-time contributor. Returns comment-ready markdown (never posts).
|
|
352
300
|
* `repo_digest` - repo-level maintainer report: PR races with first-claim arbitration, claimed-by-other conflicts, stale claims, assignment-gate conflicts, triage-held issues (never posts).
|
|
301
|
+
* `pr_radar` - maintainer-side duplicate/competing PR radar: clusters a repo's open PRs into competing sets (same target issue, or high changed-file overlap) with evidence per cluster and a suggested keep (always labeled a heuristic, never a verdict; never posts).
|
|
353
302
|
* `claim_status` - Claim Protocol pre-flight for one issue: who holds it, until when, who is queued, competing PRs, gates, whether the repo honors the protocol
|
|
354
303
|
* `preflight` - the one-call answer: claim_status plus the repo friction summary
|
|
355
304
|
* `verify_comment` - draft the verified-finding comment for maintainer-only repos (draft only, never posts)
|
|
356
305
|
* `babysit_prs` - watch open PRs and get the one prioritized action list (needs you now, waiting on them, quiet), diffed against stored watermarks; also watches the my-claims registry (linked, healthy-active, heartbeat-due, expiring, unlinked-stale, queue-lost)
|
|
357
306
|
* `evidence_pack` - the Verified PR evidence pack for one PR: guard verdict, CI triage, review triage, protocol status of linked issues, every claim citing its source
|
|
358
|
-
* `
|
|
307
|
+
* `scout_campaign` - campaign mode: rank repo targets, dedupe against the campaign file, resume on API-budget exhaustion
|
|
308
|
+
* `my_claims` - the claims registry: linked, healthy-active, heartbeat-due, expiring, unlinked-stale, queue-lost
|
|
309
|
+
* `sync_campaign` - reconcile local tracking with API truth (drift, state mismatches, stale claims)
|
|
310
|
+
* `campaign_portfolio` - one-screen campaign summary: census counts, claims by state, pending queue, drift count
|
|
311
|
+
* `autopilot_report` - per-PR feedback classification (read-only; verify bot findings, triage CI, mechanical fixes as plans)
|
|
312
|
+
* `api_status` - hosted claim API status
|
|
313
|
+
* `claim_via_api` - claim through the hosted claim API
|
|
314
|
+
* `heartbeat_via_api` - heartbeat through the hosted claim API
|
|
359
315
|
|
|
360
316
|
Run it locally: `npm run dev` (MCP entry is `src/index.ts`; CLI is `src/cli.ts`).
|
|
361
317
|
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
Field work in October surfaced two repos publishing agent rules outside CONTRIBUTING (nuxt/nuxt's AGENTS.md bans autonomous-agent contributions outright; actualbudget/actual's AI policy requires an `[AI]` prefix plus a disclosure sentence), a fleet of mastra issues all carrying bot triage notices that scored GO with no gate kind for the hold, and two explicit soft claims the scan path missed because it ran the deterministic verdict alone. v0.9.0 closes all three gaps, then turns the campaign workflow into one command.
|
|
365
|
-
|
|
366
|
-
**Agent-policy gates.** Gate loading already reads AGENTS.md and CLAUDE.md as house-rule sources; two new gate kinds now parse them. `agents_banned` is a hard gate: a repo that bans autonomous-agent contributions scores GATED, with the quoted policy line as evidence, and `claim` refuses it like TAKEN unless `--force` (a human must still open the PR). `agents_disclosure` is a flag, never a verdict change: repos that require an `[AI]` prefix and an AI disclosure get concrete required actions from `prep` and `check`. Repos with neither policy produce byte-identical output to before.
|
|
367
|
-
|
|
368
|
-
**Triage hold.** A bot triage notice ("wait until maintainers remove the triage or approval label before opening a pull request") or a triage label (`needs triage`, `pending triage`, ...) marks an issue as held: `check` names the hold and caps an otherwise-GO verdict at RISKY with flag `triage-hold` (never TAKEN), scan demotes held issues below clean ones, and `digest` lists held issues per repo in their own section, the watch list for claims that may clear tomorrow.
|
|
369
|
-
|
|
370
|
-
**Claim AI on the default path.** `scan` now runs the same per-issue pipeline as `check`: legacy verdict, the optional Fireworks claim-intent layer when `FIREWORKS_API_KEY` is set, merged with the Claim Protocol. The 30-day classification cache (comment id + model) is shared across check, scan, and claim, and the layer's governance holds everywhere: flags only downgrade GO to RISKY via the `llm-claim` flag, never TAKEN, never overriding GATED; every flag carries an exact-substring quote; a failed classification round caches nothing.
|
|
371
|
-
|
|
372
|
-
**Claims babysitting.** When `claim` actually posts, the claim (issue URL, repo, number, posted_at, eta-days) is recorded into `~/.greenlight/my-claims.json`; `greenlight claim --register <issue-url>` records claims posted by other means. `babysit` gains a claims section (and `--claims-only`): each registered claim is bucketed by its live protocol status into linked (PR open, fine), healthy-active, heartbeat-due (no activity and the lease past half), expiring (lease under 48h), unlinked-stale (no PR after 72h), or queue-lost (someone ahead completed or the claim was superseded). Claims that complete retire from the registry with a note.
|
|
373
|
-
|
|
374
|
-
**Campaign scout mode.** `greenlight scout --repos o/r,... --campaign campaign.json --write` turns a repo list into ranked campaign targets: the scan pipeline per repo, issues already in the campaign file dropped in ANY status, survivors ranked by `30*verdictWeight (GO=2, RISKY=1) + 0.25*friction + 20*outsideMergeShare + 15/(1+medianMergeDays/14) + 5*freshness`, appended as `SCOUTED` with verdict and evidence summary. `--budget N` caps GitHub API calls (default 300); on budget hit the campaign file keeps a resume cursor and the scout exits cleanly, and a rerun resumes where it stopped. `--repos-file` takes one owner/repo per line.
|
|
375
|
-
|
|
376
|
-
```bash
|
|
377
|
-
greenlight scout --repos acme/widgets,acme/gadgets --campaign campaign.json --write
|
|
378
|
-
greenlight babysit --claims-only
|
|
379
|
-
```
|
|
380
|
-
|
|
381
|
-
### v0.9.1: the trust patch
|
|
382
|
-
|
|
383
|
-
A full day of dogfooding at portfolio scale (43 open PRs) found five fidelity problems, all fixed here. No new features, no new surface area beyond the repair.
|
|
384
|
-
|
|
385
|
-
**Babysit speed and honest failures.** Per-PR fetching is now parallel with a bounded concurrency (default 5, `--concurrency N` to override): a 15-PR sweep drops from ~9 minutes toward ~2. Each PR's reads get 2 attempts with a short backoff; a PR that still cannot be observed lands in a new `Could not check (transient)` section with its error kind (`transient` vs `usage`), never in needs-you or waiting, and its watermark is untouched so the next run reports it as if this run never happened.
|
|
386
|
-
|
|
387
|
-
**Guard flag subjects.** Every guard flag now carries a `subject`: `pr` (this PR's own diff, e.g. missing artifacts), `issue` (one of the PR's linked issues, e.g. a competing fix, with a canonical `owner/repo#N` `issueRef`), or `repo` (repo-wide signal). Babysit raises needs-you only for subject `pr`, and for subject `issue` when the issue is the PR's own linked issue; everything else collects into a `Repo notes` section, informational only. Field case: a babysit run on actual #9250 once reported "17 new things: Competing fix for #123" that belonged to other PRs in the repo; that shape now produces zero needs-you items from guard.
|
|
388
|
-
|
|
389
|
-
**Claim registry import.** `greenlight claim --import --ledger-user <github-login>` fetches the public Claim Ledger and imports every active or linked claim by that user into `~/.greenlight/my-claims.json`; `greenlight claim --import --urls <issue-url,...>` backfills manually. Re-imports dedupe; retired states are skipped.
|
|
390
|
-
|
|
391
|
-
**The proxy, shipped.** `greenlight proxy` starts the localhost forwarder that lifts you from the 60/hr anonymous quota to the 5000/hr authenticated budget: it reads `GITHUB_TOKEN` (or `GH_TOKEN`) once at startup, attaches it server-side, ignores incoming Authorization headers, binds 127.0.0.1 only, and refuses to start without a token. `greenlight doctor` now names the proxy as the remedy when you are unauthenticated.
|
|
392
|
-
|
|
393
|
-
**MCP parity.** Two new tools bring the server to 17: `scout_campaign` (campaign mode over MCP) and `my_claims` (the claims-bucketing half of the babysitter).
|
|
394
|
-
|
|
395
|
-
```bash
|
|
396
|
-
export GITHUB_TOKEN=<your-classic-token> && greenlight proxy &
|
|
397
|
-
export GREENLIGHT_GITHUB_BASE_URL=http://127.0.0.1:8792 GITHUB_TOKEN=proxy
|
|
398
|
-
greenlight claim --import --ledger-user <your-login>
|
|
399
|
-
greenlight babysit --concurrency 5
|
|
400
|
-
```
|
|
401
|
-
|
|
402
|
-
### v0.6.0: the babysitter, the autopilot, and the trust layer
|
|
403
|
-
|
|
404
|
-
**PR Babysitter.** `greenlight babysit` (or the `babysit_prs` MCP tool) is the answer to 34 open PRs and no time to watch them. Point it at PR URLs, or let it discover your open PRs across repos (`--mine --repos`), and it runs CI triage, review triage, and the guard on each one, diffs against stored watermarks, and prints one prioritized list: *needs you now* first (new likely-real review findings, CI newly failing on your code, merge conflicts, new guard flags, checks stuck over 2 hours), then *waiting on them* (checks still running, CI green with no feedback yet), then *quiet* (a PR that merged or closed retires from the watch with its resolution noted). The first run has no watermarks, so it says so and shows the full picture. Exit 0 always (cron-friendly); `--fail-on-action` gives exit 3 when the needs-you-now list is non-empty.
|
|
405
|
-
|
|
406
|
-
**Maintainer Autopilot.** The guard Action can now act, not just report — but only when the maintainer opts in. An `autopilot` section in `.greenlight-guard.json` carries a label map (check id to label name, e.g. `"protocol-claim": "claim-conflict"`) and a nudge toggle. The guard computes label decisions over severity-flag findings and ready-to-copy stale-claim nudge lines for 14+ day claims with no other open PR; it never applies anything itself. The Action applies the decided labels with the Actions token (creating labels that do not exist yet; failures degrade to warnings, never a failed run), and the nudge lines ride inside the single guard comment for the maintainer to post on the issue. Autopilot never closes PRs, never merges, and never posts beyond the one guard comment. `greenlight guard <pr-url> --labels-dry-run` shows exactly what it would do.
|
|
407
|
-
|
|
408
|
-
**Evidence pack and passport.** `greenlight evidence <pr-url>` (or the `evidence_pack` MCP tool) assembles the Verified PR evidence pack: guard verdict, CI triage, review triage, and Claim Protocol status of the linked issues, in one markdown document where every claim cites its source — the check run, the review anchor, the claim comment URL. The test-suite delta is included only when you hand it a `greenlight verify --json` report; the pack never runs suites itself and says so when the report is missing. And `greenlight passport <github-login>` renders the contributor passport: protocol claims from the public Claim Ledger (active, queued, the completed-vs-expired honor record, the over-cap flag) plus merged PRs from GitHub — the trust layer the Claim Protocol was always heading toward.
|
|
409
|
-
|
|
410
|
-
### v0.3.5: CI triage (solve-first)
|
|
411
|
-
|
|
412
|
-
The first solve-side command. On a red PR, `ci` fetches the PR's base and head, collects the failing check runs (with the first failure lines from annotations when it can), and builds the same checks' history from the twelve most recent base-branch commits. Each failing check gets one line with its class and the evidence: `pre-existing` (same check failing on base, with counts and the last failure time), `likely-yours` (failing on head, passing on base, and the PR touches files that relate to the check), `indeterminate` (no base signal to compare), or `external-blocker` (Vercel/Netlify/deploy-preview auth failures, infrastructure not the PR). Indeterminate checks always state their lean: not touching the check's area leans pre-existing, touching it leans yours, with the reason spelled out. A verdict line closes it out: ALL PRE-EXISTING, HAS LIKELY-YOURS, INDETERMINATE, or NO FAILURES.
|
|
413
|
-
|
|
414
|
-
### v0.3.7: prep hardening (solve-first)
|
|
415
|
-
|
|
416
|
-
The third solve-side upgrade, to `greenlight prep`. The checklist now starts with the exact signing path the repo demands (CLA Assistant with its signature phrase, a repo-specific CLA bot's signing page, or DCO with `git commit -s`) and the release-note artifact it owes (`.changeset/`, `.changes/<issue>-slug.md`, towncrier fragments, or a CHANGELOG note). Before anything else, it runs the fix-lives-here check: the v0.3.4 server-side signal plus a satellite-repo hint that fires only on tight textual evidence, warning prominently when the fix may not be buildable from this repo. A house-rules block closes it out: claim style, PR title convention, draft-first norm, and the test command, each with its source file.
|
|
417
|
-
|
|
418
|
-
### v0.3.9: the maintainer guard
|
|
318
|
+
## How scoring works
|
|
419
319
|
|
|
420
|
-
|
|
320
|
+
The verdict engine is deterministic (no LLM) and checks, in order:
|
|
421
321
|
|
|
422
|
-
|
|
322
|
+
1. Closed issue: **TAKEN** (never landable).
|
|
323
|
+
2. Any assignee: **TAKEN**.
|
|
324
|
+
3. An open linked PR that **closes** the issue: **TAKEN**. A PR that merely mentions the issue number (like pdfcn PR #91, which closes #70 but lists sibling issues in its body) only adds a `weak-pr-mention` flag and downgrades an otherwise-GO verdict to **RISKY**. Marked a duplicate of an issue closed as completed: **RISKY** with the `duplicate-of-closed` flag (the work already shipped; a still-open duplicate target only adds a `duplicate-of-open` warning with its URL).
|
|
325
|
+
4. Two or more strong claimants: **TAKEN** (claim race).
|
|
326
|
+
5. One strong fresh whole-issue claim (under 45 days): **RISKY** with the `claimed` flag. A fresh claim scoped to part of the issue ("taking the remaining fallback ask"): **RISKY** with `claimed` + `partial-claim` flags and a reason naming the claimer and the scope, never TAKEN.
|
|
327
|
+
6. One strong claim older than 45 days with no closing PR: **RISKY** with the `stale_claim` flag. The claimant probably walked away, but nobody knows for sure. Stale scoped claims get the same treatment.
|
|
328
|
+
7. A hard gate (assignment, vouch, collaborators-only, paused unsolicited PRs, external PRs auto-closed by workflow) with nobody assigned: **GATED**. The last two come from CONTRIBUTING language ("paused unsolicited pull requests") and a scan of `.github/workflows` for close-external-PR automation.
|
|
329
|
+
8. No activity for 180+ days: **STALE**.
|
|
330
|
+
9. A soft claim-first gate (the repo asks contributors to comment before starting, like pdfcn): never **GATED**; it caps an otherwise-GO verdict at **RISKY** with a note, the same downgrade shape as a weak PR mention.
|
|
331
|
+
10. Otherwise: **GO**.
|
|
332
|
+
11. An open PR referenced in a non-author comment whose title/body mentions the issue number: downgrades an otherwise-GO verdict to **RISKY** with the `comment-mentioned-pr` flag ("may already cover part of this issue"). Neither can produce **TAKEN**; only closing PRs do that. Fix-announcement comments ("/attempt #N" commands or "Submitted fix for ... in <PR url>" narratives, often linking PRs in sibling repos) get the same downgrade under their own reason quoting the PR URL, with the `attempt-linked-pr` flag, even when the PR never names the issue. `/attempt` comments also register as strong claims.
|
|
333
|
+
12. **Partially-addressed**: merged PRs that reference the issue number (comment-mentioned or linked), or maintainer comments signaling part of the work already shipped ("Half addressed by #905, leaving this open for half B", "Shipped in v3.1.0" next to the issue reference). A plain **GO** hides the scoping work this needs, so the flag `partially-addressed` is added, an otherwise-GO verdict is capped at **RISKY** with a reason like "part of this issue already shipped (PR #905, merged); scope your work to what remains". Never **TAKEN**.
|
|
423
334
|
|
|
424
|
-
|
|
335
|
+
Friction score starts at 100 and subtracts gate weights (assignment -25, vouch -35, collaborators-only -50, paused unsolicited PRs -40, external PRs auto-closed -50, discussion-first -10, claim-first -5, CLA/DCO -5 each), adjusts for external PR merge rate and review/response times when computable, and adds up to +10 for open good-first-issues. Unknown signals stay null and are skipped, never guessed. See `src/friction.ts` for the exact formula.
|
|
425
336
|
|
|
426
|
-
|
|
427
|
-
# Who holds this issue, until when, who is queued, which PRs compete
|
|
428
|
-
greenlight status https://github.com/ComposioHQ/composio/issues/4668
|
|
337
|
+
### Agent-policy gates and triage holds
|
|
429
338
|
|
|
430
|
-
|
|
431
|
-
# optional plan/eta lines, and the protocol footer (--plan, --eta-days)
|
|
432
|
-
greenlight claim <issue-url> --plan "reproduce then fix" --eta-days 5
|
|
433
|
-
```
|
|
339
|
+
Policy files are read where repos actually keep them: `AGENTS.md`, `CLAUDE.md`, `CONTRIBUTING.md`, and `AI_POLICY.md` at the repo root, in `.github/`, and in `docs/` (first hit per filename wins), plus the org-level `.github/AI_POLICY.md`. Two gate kinds parse agent rules:
|
|
434
340
|
|
|
435
|
-
|
|
341
|
+
* `agents_banned` is a hard gate: a repo that bans autonomous-agent contributions scores **GATED**, with the quoted policy line as evidence, and `claim` refuses it like TAKEN unless `--force`.
|
|
342
|
+
* `agents_disclosure` is a flag, never a verdict change: repos that require an AI prefix or disclosure get concrete required actions from `prep` and `check`.
|
|
436
343
|
|
|
437
|
-
|
|
344
|
+
A bot triage notice ("wait until maintainers remove the triage or approval label before opening a pull request") or a triage label marks an issue as held: `check` names the hold and caps an otherwise-GO verdict at **RISKY** with the `triage-hold` flag (never TAKEN), and `scan` demotes held issues below clean ones. Held issues are future pipeline, not current work.
|
|
438
345
|
|
|
439
|
-
|
|
346
|
+
## Optional AI claim detection
|
|
440
347
|
|
|
441
|
-
|
|
348
|
+
The pattern layer cannot know every way a human says "I'm taking this" (one evening it missed "I'm looking into contributing a fix here" on a real issue). Set `FIREWORKS_API_KEY` and `check` gains an optional second pair of eyes: a cheap Fireworks model reads the eligible comments (bots and the issue author excluded, same pool as the patterns) and flags statements of intent the patterns missed.
|
|
442
349
|
|
|
443
|
-
The
|
|
350
|
+
The governance is plain:
|
|
444
351
|
|
|
445
|
-
|
|
352
|
+
- **Off by default.** No key, no calls, output byte-identical to the pattern-only engine.
|
|
353
|
+
- **Patterns stay primary and cheaper.** The AI only runs when they found no strong claim.
|
|
354
|
+
- **Flags, never verdicts.** An AI flag adds the `llm-claim` flag with the exact quote as evidence and downgrades an otherwise-GO verdict to **RISKY**. It can never produce **TAKEN** and never overrides **GATED**. Verdicts stay deterministic.
|
|
355
|
+
- **No invented evidence.** The quote must be an exact substring of the comment body; anything else is dropped before it can reach the verdict.
|
|
356
|
+
- **Failures are silent.** A timeout, a non-200 response, or an unparseable reply returns no signal, never an error into the check path. Classifications are cached by comment id and model id, so repeat checks cost nothing.
|
|
446
357
|
|
|
447
|
-
|
|
358
|
+
`greenlight doctor` reports whether the layer is configured (the key is never printed).
|
|
448
359
|
|
|
449
360
|
## Automation
|
|
450
361
|
|
|
451
|
-
Greenlight
|
|
362
|
+
Greenlight automates the contribution pipeline its author ran by hand
|
|
452
363
|
for four real PRs (shadcn-labs/pdfcn #92-#95): verdict, claim comment, fork
|
|
453
364
|
branch, and opening the PR, with DCO awareness throughout.
|
|
454
365
|
|
|
@@ -485,17 +396,30 @@ Safety defaults, and this is a feature:
|
|
|
485
396
|
* **Repo-aware prep.** `prep` also learns the repo's contribution rituals
|
|
486
397
|
for the PREP.md checklist: which house-rules files exist, the verify
|
|
487
398
|
command they insist on (like `pnpm verify`), whether the repo assembles
|
|
488
|
-
its changelog from a `.changes/` directory, which root package.json
|
|
489
|
-
|
|
399
|
+
its changelog from a `.changes/` directory, which root package.json scripts
|
|
400
|
+
exist, and whether recent commits follow Conventional Commits.
|
|
490
401
|
Binding rules increasingly live in `AGENTS.md` rather than CONTRIBUTING,
|
|
491
402
|
and prep reads those too.
|
|
492
403
|
|
|
404
|
+
## The toolkit
|
|
405
|
+
|
|
406
|
+
Greenlight is the front door of a four-tool lifecycle for open-source contribution work, all published under the same npm scope and cross-wired:
|
|
407
|
+
|
|
408
|
+
1. **gatefile** (`npx @reneturcios/gatefile extract owner/repo`) extracts a repo's contribution gates into a committed `contribution-gates.json`. Greenlight consumes that file directly: `greenlight check <issue-url> --gates-file contribution-gates.json`, or automatically when the file sits in the working directory, so gates are answered once and reused instead of re-derived from prose.
|
|
409
|
+
2. **greenlight** verdicts, scans, claims, prep, and PR opening (this tool).
|
|
410
|
+
3. **claimcheck** (`npx @reneturcios/claimcheck claims owner/repo`) watches claimed issues for stale claims and finished fixes parked on forks, the two ways claimed work silently dies.
|
|
411
|
+
4. **prwatch** (`npx @reneturcios/prwatch attention --user you`) triages your open PRs by what needs you right now: review threads, failing checks, conflicts, reviewer silence.
|
|
412
|
+
|
|
413
|
+
Each tool is a CLI and an MCP server (`<tool> mcp`).
|
|
414
|
+
|
|
493
415
|
## The friction index
|
|
494
416
|
|
|
495
417
|
`data/friction-index.json` is a checked-in, growing dataset of scored repos. It starts with the MCP/AI ecosystem we hand-vetted on 2026-10-13 (FastMCP, trigger.dev, langchain, deepagents, openclaw, squidbrake, reticle, pdfcn, chatflow-agent, and the three MCP SDK repos). Regenerate it with `npm run index`.
|
|
496
418
|
|
|
497
419
|
Entries labeled `hand-verified 2026-10-13` come from reading the repos' actual policies and issue trackers by hand. Entries labeled `live` were parsed from live house-rules files (CONTRIBUTING variants, AGENTS.md, CLAUDE.md). Each gate records which file its evidence came from. Computed outcome fields (merge rates, review times) stay `null` until we can compute them honestly, never fabricated.
|
|
498
420
|
|
|
421
|
+
The published page ([cloudcorprecords.github.io/greenlight](https://cloudcorprecords.github.io/greenlight/)) adds the Agent Policy Index: 505 repos evaluated for contribution gates and AI policies, with quoted evidence per entry. Nobody else publishes this map.
|
|
422
|
+
|
|
499
423
|
## Development
|
|
500
424
|
|
|
501
425
|
```bash
|
|
@@ -503,14 +427,18 @@ npm test # tsx --test, includes fixture tests that reproduce our real verdict
|
|
|
503
427
|
npm run build
|
|
504
428
|
```
|
|
505
429
|
|
|
506
|
-
## Roadmap
|
|
430
|
+
## Roadmap
|
|
431
|
+
|
|
432
|
+
Clearly marked: these are not shipped yet. (v0.15.0 moved two roadmap items into the product: `radar` is duplicate/competing PR clustering, and `brief` is the verified review brief for any PR.)
|
|
433
|
+
|
|
434
|
+
* **Maintainer control room.** `guard` works per PR and `radar` clusters the queue (both shipped); the control room is the hosted per-repo surface built on top: stale-claim sweeps with one-click release requests, first-time-contributor risk notes, and a weekly maintainer digest. The engine pieces exist; the product is the assembly plus hosting.
|
|
435
|
+
* **Policy enforcement packs.** Repos keep inventing the same rules (changeset required, release note required, DCO, AI disclosure). A policy-pack format (built from `gatefile` output) that a maintainer adopts in one file, enforced by the Action with the same quoted-evidence style.
|
|
436
|
+
* **AI PR volume defense.** The filter, not the ban: `guard` scoring incoming PRs for claim legitimacy, repro evidence, and test deltas, so maintainers can keep the door open to good agent work while filtering spam. The campaign data (refused claims, honest verify, evidence packs) is the proof set.
|
|
437
|
+
* **Claim arbitration as a service.** Two claims, one queue, public ordering, maintainer override: live arbitration of competing claims, the piece maintainers cannot build themselves.
|
|
438
|
+
* Browser extension that scores issues inline on github.com.
|
|
439
|
+
* Parked-fix detection and auto-nudges: scan forks for branches referencing open issues and nudge when the gate is satisfied.
|
|
507
440
|
|
|
508
|
-
|
|
509
|
-
* Claim-to-PR prep scaffolding: emit the per-repo work order (house rules, CLA method and link, changeset conventions, fork/branch names) from one `prep` pass
|
|
510
|
-
* Browser extension that scores issues inline on github.com
|
|
511
|
-
* Hosted dashboard of the friction index, refreshed on a schedule
|
|
512
|
-
* Maintainer GitHub Action that auto-labels claim comments
|
|
513
|
-
* Parked-fix detection and auto-nudges: scan forks for branches referencing open issues and nudge when the gate is satisfied
|
|
441
|
+
Full release history lives in [`CHANGELOG.md`](CHANGELOG.md).
|
|
514
442
|
|
|
515
443
|
## License
|
|
516
444
|
|