关于 greenlight
greenlight 是面向开源贡献者、AI 编码 Agent 和维护者的 GitHub 贡献协调工具,可在选题、提交前检查及 PR 分流中提供依据明确的判断。
主要功能
- 01检查 Issue 是否可贡献、已被认领或受门槛限制
- 02扫描并排序适合处理的 Issue
- 03检查仓库规则与贡献门槛
- 04本地运行 PR 检查并分析 CI
- 05追踪认领并识别重复 PR
适用场景
- 01开工前确认 Issue 是否已有进行中的 PR
- 02提交前运行测试、Lint 和仓库规范检查
- 03维护者筛查新 PR 和重复变更
- 04为贡献活动挑选可处理的 Issue
MCP 相关
通过 stdio 提供 MCP 服务,将 33 个工具开放给编码 Agent,涵盖 Issue 预检、PR 检查与贡献协调。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
9收录的工具列表 · 更新于 今天
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| issue_url | string | 是 | 完整的 GitHub issue URL,例如 https://github.com/owner/repo/issues/123 |
详细介绍
Greenlight
Greenlight 是开源贡献的前期准备与协调层:它是外部贡献者(越来越多是 AI Agent)与公共代码仓库维护者之间的软件,并能回答其他工具无法回答的问题。我能在这里贡献吗?这个议题是否已被人悄悄认领?这里有哪些规矩?还有谁在和我竞争?对维护者来说:是谁在大量涌入我的队列?哪些内容可以安全合并?
为什么需要这一层
跟着风险投资的资金流向,你就会发现它没有流向哪里。Cognition(Devin)融资约 20 亿美元,估值达 480 亿美元;Factory 融资 2 亿美元,估值达 50 亿美元,目的是在企业自己的代码仓库中运行自主编码 Agent。CodeRabbit 融资 8,800 万美元(估值接近 5.5 亿美元),Graphite 在被 Cursor 收购前完成了 5,200 万美元的 B 轮融资,Greptile 则完成了 2,500 万美元的 A 轮融资;它们审查的都是团队自己的拉取请求。OpenHands 是一个 Agent 运行时。每家获得融资的厂商都假定你身处组织内部。
没有人负责这条边界。没有获得风投支持的工具能回答外部贡献者的问题:我能在这里贡献吗?这个议题是否已被人悄悄认领?这个代码仓库有哪些门槛和 AI 政策?还有谁在和我竞争?也没有获得风投支持的工具能回答维护者的问题:这 30 个未关闭的 PR 中,哪些是重复的?谁认领了什么?哪些认领已经过期?哪些由 Agent 编写的 PR 可以安全合并?Greenlight 就是这一层,它是在每周通过实际贡献活动不断运行和打磨的。
问题所在
AI 让编写代码变得廉价。贡献协调如今成了瓶颈,而且会以具体、反复出现的方式出问题:
- 隐形竞争。 议题列表视图会误导人。在对 usebruno/bruno 进行的一次人工审核重点环节中,7 个看似有希望的议题里有 6 个已被悄悄认领,相关 PR 只显示在议题时间线中,列表视图和搜索结果中都看不到。你可能花上一个周末做的工作,早已被人完成。
- 门槛与禁令。 Greenlight 自己的 Agent 政策索引现在追踪 505 个代码仓库:其中 127 个(25%)设有贡献门槛,19 个明确禁止 Agent 贡献。整个代码仓库(nuxt、uv、Gradio、Activepieces)都对外部 PR 关上了大门。没人告诉你;规定写在 AGENTS.md 里。
- 重复的 AI PR。 多位贡献者(人类或 Agent)争相处理同一个议题时,维护者会收到三个内容重叠的 PR,却没有办法进行协调。GitHub 没有认领系统,只有评论。
- 四处散落的规矩。 CLA、DCO 签署、changeset、提交格式、申请分配。每个代码仓库都有自己的一套规矩,把它们藏在不同文件里,还会因为细枝末节拒绝你的 PR。
这些都是协调问题,不是编程问题。代码 Agent 越来越强,边界却越来越混乱。Greenlight 负责处理这条边界。
Greenlight 的功能
三个层次,从决策到解决,再到协调:
| 层次 | 回答的问题 | 旗舰命令 |
|---|---|---|
| 决策 | 这个问题该由我来处理吗?这个仓库值得我投入时间吗? | check、scan、friction、xray、racecheck、wave、preflight |
| 解决 | 我的 PR 会通过吗?哪里出了问题?接下来该做什么? | ci-prep、ci、review、brief、verify、autopilot、babysit、evidence |
| 协调 | 谁在做什么,由谁解决冲突? | claim(加上 Claim Protocol)、guard、radar、digest、passport |
- 决策。
check会读取问题、相关评论、关联和提及的 PR(时间线、搜索结果和评论引用),以及仓库规则,然后用通俗语言给出结论:GO、RISKY、TAKEN、GATED 或 STALE。scan会为仓库的未关闭问题排序,让你优先选择胜算较大的问题。friction会以 0 到 100 分评估实际合并 PR 的难度,每个门槛都会引用其证据来源文件。xray(Timeline X-Ray)会在你开始编写代码前,深入核查候选问题的时间线,发现隐藏的进行中 PR,包括由问题报告者提交的修复 PR;scan --deep会先将已被认领的问题降级,再展示列表。racecheck(Keyword Race Check)能发现 X-Ray 看不到的竞争:有未关闭 PR 修复了相同问题,却从未关联该问题。它会根据问题关键词(文件名、标识符、特征词)而不是链接来查找,并给出 RACE / SUSPECT / CLEAR 判定及引用的关键词证据;scan --deep和xray会自动调用它。v0.20.1 的精度改进确保它在真实仓库中保持准确:GitHub 标签名、URL 路径片段和仓库模板中的样板内容(通过对扫描的 PR 队列进行文档频率抑制)都不会被视为证据;基于术语判为 RACE 必须使用从标题提取的术语;共享的变更文件还必须有显著的共同命中,因此仅有相邻关系会判为 SUSPECT,而不是 RACE。wave可通过一条命令将 Agent Policy Index 转换为构建队列:筛选出胜算较大的未关闭仓库和经 X-Ray 核查的入门问题,并排除带行为门槛的问题。 - 解决。
ci-prep会在推送前于本地运行仓库自身的拉取请求检查(测试、lint、类型检查,以及变更日志、提交格式、DCO 等规范),避免本可避免的 CI 失败出现在维护者面前。ci会根据基分支历史,将未通过检查的 PR 分类为已有问题、可能由你引入的问题或外部阻塞因素。review会将每个审查讨论线程分类为可能是真问题、可能是噪声或需要决策,并起草回复。verify会如实报告你的更改对测试通过与失败情况的影响。autopilot会根据代码当前版本核实 Bot 的发现,并自行修复机械性问题(处理 DCO、重新合并冲突、格式化)。brief会为任意 PR 汇总一份经过核实的单屏简报:按领域和风险说明更改概况、根据基分支历史分类 CI 状态、依据证据将发现归类为真问题或误报、标明是否有测试证据(若没有则明确注明)、列出合并阻塞因素,并给出一句优先查看事项。babysit会监控你未关闭的 PR,并报告一份按优先级排列的行动清单。 - 协调。
claim会发布协议认领(含过期租约、公开队列、心跳;完整规范见protocol/SPEC.md),并提供通过--via-api使用托管应用客户端的选项。guard会为维护者分析收到的 PR:是否有竞争性修复、是否有先前认领、是否缺少必要材料,以及贡献者是否为首次参与。digest会报告仓库中的 PR 竞争、被他人认领的冲突、过期认领和分配门槛冲突。radar会扫描整个未关闭 PR 队列,根据证据将竞争或重复的 PR 分组,并建议保留哪个;它会明确标注这只是启发式结果,而非定论。passport会汇总贡献者已合并的工作和认领记录。
每个判定和每份报告都会引用证据:被引用的政策条款、认领评论 URL、PR 编号或失败的检查。任何结论都不会在缺少来源的情况下提出。
面向对象
- 贡献者(人类)。 在 issue 上花一晚之前,先运行
check。挑选要处理的任务时,运行scan。推送前,运行ci-prep。 - AI Agent 和编码工具。 运行一条命令(
init --agent claude-code,也支持 cursor、copilot、windsurf、cline),即可安装 MCP 配置和唯一一条行为规则:打开 PR 前先检查 Greenlight。Agent 最浪费 token 的情况,就是去修复已经有人接手的 issue;33 个 MCP 工具让整个引擎在运行过程中都能使用。 - 维护者。 对每个新收到的 PR 运行
guard,用radar扫描所有未关闭的任务队列,用digest进行每周分流,并通过下方路线图管理控制室:清理过期认领、执行策略、过滤 AI PR。
明确列出实证
- 1194 项测试全部通过,包括一个基于真实活动案例固定下来的测试夹具集(已被接手的 issue、内容不足的 PR 提及、先认领再通过的门槛、范围限定的认领、未完成交付的 issue、过期认领、暂停 PR 的工作流)。
- 在真实活动中使用过:该工具包已在数十个公开开源仓库中创建了 80 多个拉取请求。每项功能都源于一次真实贡献因缺少它而失败。
- 在受众常去的所有地方都可获取:npm(
@reneturcios/greenlight)、MCP Registry 和 GHCR(ghcr.io/cloudcorprecords/greenlight),另有 Docker 和直接 MCP stdio。 - 随附两个持续更新的数据集:贡献摩擦指数(
data/friction-index.json)和 Agent 策略指数(505 个仓库、127 个设有门槛、19 个禁止 Agent,发布于docs/policy.html);两者都基于真实活动实地工作构建,而非抓取得来的猜测。
看它如何运作

59 秒演示:在真实仓库中检查真实 issue、AI 发现隐藏认领、发现禁止 Agent 的 GATED 状态、活动任务侦察,以及认领看护工具。完整解说视频。
安装
npx @reneturcios/greenlight check <issue-url>
设置 AI 编码工具并验证设置:
npx @reneturcios/greenlight init --agent claude-code # one-command MCP setup (cursor, copilot, windsurf, cline work too)
npx @reneturcios/greenlight doctor # checks Node version, token, GitHub quota, cache
或者从源代码安装:
npm install
npm run build
设置 GITHUB_TOKEN(经典个人访问令牌;访问公开仓库不需要任何权限范围),即可将 GitHub API 速率限制从每小时 60 次提高到 5000 次。Greenlight 会将 API 响应缓存到 ~/.cache/greenlight。
通过 npx @reneturcios/greenlight mcp(stdio)运行 MCP 服务,或者让 Agent 使用 greenlight 命令,并将 mcp 作为唯一参数。
使用 Docker 运行
Greenlight 也提供 GHCR 容器映像:ghcr.io/cloudcorprecords/greenlight。
将其用作 stdio MCP 服务:
docker run -i ghcr.io/cloudcorprecords/greenlight
可以在映像名称后传入任何 CLI 命令,替代默认的 mcp 参数:
docker run ghcr.io/cloudcorprecords/greenlight check <issue-url>
docker run ghcr.io/cloudcorprecords/greenlight --version
在 AI 编码工具中使用
运行一条命令即可完成设置:
npx @reneturcios/greenlight init --agent claude-code
(也支持 cursor、copilot、windsurf、cline;如需设置多个工具,可重复使用 --agent)。Init 会将 MCP 配置复制到项目中,并安装工作流指令片段,教会 Agent 唯一一条行为规则:打开 PR 前先检查 Greenlight。 更喜欢手动设置?integrations/ 集成包提供了可直接复制的 MCP 配置,以及相同的指令片段。然后通过“列出你的 MCP 工具”提示词进行验证;greenlight 服务包含 33 个工具(见下方列表)。
CLI
# One-command setup for your AI coding tool (cursor, copilot, windsurf, cline work too)
npx @reneturcios/greenlight init --agent claude-code
# Verify the setup: Node version, token, GitHub quota, cache (exit 1 when anything fails)
npx @reneturcios/greenlight doctor
# Help: overview, one command's flags, or the version
npx @reneturcios/greenlight help check
npx @reneturcios/greenlight --version
# Verdict for one issue
npx @reneturcios/greenlight check https://github.com/batrapulkit/squidbrake/issues/74
# [GO] batrapulkit/squidbrake#74
# Taint: tell the approver when an agent edits its own setup right after reading outside content
# - open, unassigned, no linked PRs, no claim signals, no blocking gates
# Rank a repo's starter issues, GO first (falls back to recent open
# unassigned issues when the repo does not use those labels; --no-fallback to opt out)
npx @reneturcios/greenlight scan PrefectHQ/fastmcp
# Deep-verify candidates against their timelines first (catches hidden in-flight PRs)
npx @reneturcios/greenlight xray usebruno/bruno --issues 8149,9319
npx @reneturcios/greenlight scan usebruno/bruno --deep
# Keyword race check: is an open PR already fixing this issue without
# ever linking it? (link-based checks cannot see it; exit 1 on RACE)
npx @reneturcios/greenlight racecheck sveltejs/kit 17465
# Scans stop on a wall-time budget (default 600s; override with --max-time <seconds>).
# A scan that hits the budget returns the results gathered so far, labeled partial:
# --json gains partial: true, partial_reason ("scan time budget 600s reached; evaluated
# K of M candidates"), evaluated, and candidates; the human output prints the results
# plus a "Partial scan:" line naming the budget. Partial scans still exit 0.
npx @reneturcios/greenlight scan PrefectHQ/prefect --max-time 300
# Friction score for a repo
npx @reneturcios/greenlight friction triggerdotdev/trigger.dev
# CI triage for a red PR: is each failing check yours or pre-existing?
npx @reneturcios/greenlight ci https://github.com/reticlehq/reticle/pull/1620
# [pre-existing] install-gate (windows-latest)
# same check failing on base: 2 of 3 recent base runs, last at 2026-10-14T10:00:00Z
# [external-blocker] Vercel - Authorization required
# check name matches the Vercel deploy/auth pattern; this failure is infrastructure, not the PR
# JSON output for scripting
npx @reneturcios/greenlight ci <pr-url> --json
# CI pre-flight: run a repo's own PR checks locally before pushing (exit 1 on NO-GO)
npx @reneturcios/greenlight ci-prep ~/work/bruno
# [PASS] tests (workflow ci, job build)
# [SKIPPED] publish (workflow release, job release) - publishes a package
# [PASS] convention: DCO sign-off
# Verdict: GO
# Review triage for a PR with review feedback: which comments need you?
npx @reneturcios/greenlight review https://github.com/n8n-io/n8n/pull/41235
# Verified review brief for any PR: change shape by area and risk, CI
# triaged against base-branch history, findings classified with evidence,
# test evidence present or explicitly marked absent, merge blockers, and
# a one-line look-at-this-first
npx @reneturcios/greenlight brief https://github.com/usebruno/bruno/pull/9569
# Brief: 4 files (+335/-11), 2 source + 2 tests
# CI: code checks green; external blockers named (fork workflows require maintainer approval)
# review: NO FINDINGS
# blockers: none
# lookFirst: No blockers or real findings. Start here: 2 source files carry the change.
# Campaign scout: rank repo targets, dedupe against the campaign file, append as SCOUTED
npx @reneturcios/greenlight scout --repos acme/widgets,acme/gadgets --campaign campaign.json --write
# Babysit your registered claims: linked, linked-dead, healthy-active, heartbeat-due, expiring, unlinked-stale, queue-lost
npx @reneturcios/greenlight babysit --claims-only
# A claim whose linked PR closed unmerged reads linked-dead, with a release
# prompt: the issue is free, but the stale marker needs an explicit release.
# Pacing: claim posts never trip GitHub's anti-spam flag
# Every post attempt is ledgered at ~/.greenlight/posting-ledger.json
# (timestamp, kind, target, outcome). Claim posts enforce a minimum
# interval (default 90s, jittered; GREENLIGHT_CLAIM_MIN_INTERVAL_S, or
# --min-interval) and a daily soft cap (default 25 per rolling day;
# GREENLIGHT_CLAIM_DAILY_CAP, 0 disables). A post that fails with a block
# or an uncertain network error is marked UNCONFIRMED; the tool re-reads
# the target against the API before ever posting to it again, so a
# "failed" post that actually landed is marked confirmed and never
# reposted. --force overrides any pacing refusal, and the override is
# ledgered. greenlight status shows your pacing posture.
npx @reneturcios/greenlight status https://github.com/owner/repo/issues/123
# Maintainer guard for an incoming PR: competing fix, prior claims, missing
# artifacts (changeset / DCO / CLA), first-time contributor. Renders markdown
# ready to post as one comment; Greenlight itself never posts.
npx @reneturcios/greenlight guard https://github.com/owner/repo/pull/123
# Greenlight guard: 1 thing to check
# - Missing release-note file (repo uses .changes/): expected .changes/123-slug.md
npx @reneturcios/greenlight guard <pr-url> --quiet # exit 3 when flagged, silent otherwise
# Duplicate/competing PR radar for the whole queue: clusters PRs fixing the
# same issue or touching the same files, with evidence and a suggested keep
# per cluster (always labeled a heuristic, never a verdict)
npx @reneturcios/greenlight radar usebruno/bruno --limit 100
# 100 open PRs scanned in 6 API calls: 3 competing clusters, 94 unclustered
# cluster (same issue #5011): #5016 "Fix: Param table UI breaks bug" ~ #5074 "fix: Param Table UI Breaks on resize" - suggested keep #5016 (heuristic)
# cluster (file overlap, 100% Jaccard in packages/): #3484 ~ #5747 - suggested keep #3484 (heuristic)
# Verified comment for a maintainer-only repo: the issue takes no outside
# PRs (inspector, servers), so the contribution is a detailed, verified
# comment. Assembles from your notes or a markdown file; sections you
# leave empty render as explicit gaps, never filler. Never posts.
npx @reneturcios/greenlight verify-comment https://github.com/modelcontextprotocol/inspector/issues/2723 \
--claim "TUI tests append to the developer's real ~/.mcp-inspector/auth.log" \
--env "modelcontextprotocol/inspector @ 3a4b5c6, 2026-10-15" \
--repro $'point HOME at a scratch dir\nrun: vitest run __tests__/App.test.tsx' \
--observed "155 lines appear in the scratch HOME's auth.log" \
--expected "test runs leave the developer's home directory untouched" \
--root-cause "clients/tui/__tests__/setup.ts does not isolate the log dir" \
--fix "per-test-file temp dir via fs.mkdtempSync, set MCP_INSPECTOR_LOG_DIR, remove on exit" \
--ran "vitest run __tests__/App.test.tsx: 130 passed" \
--by "@CloudCorpRecords"
# or: greenlight verify-comment <issue-url> --from-file notes.md
# Honest red-green test delta, in your repo checkout: runs the detected
# test command on a base worktree and your working tree, and reports what
# your change actually did: newly passing (fixed), newly failing (yours),
# still failing (pre-existing, not yours). Says "unverifiable" with the
# reason instead of guessing when it cannot run or parse.
cd your-repo && npx @reneturcios/greenlight verify --base origin/main
# exit 3 when new failures exist, 1 when unverifiable
# PR babysitter: one prioritized action list across your open PRs --
# needs you now, waiting on them, quiet. Reruns report what changed.
npx @reneturcios/greenlight babysit --mine --repos acme/widgets,acme/gadgets
# or: greenlight babysit --prs <url1>,<url2> --fail-on-action (exit 3 when action is needed)
# Verified PR evidence pack: guard + CI triage + review triage + protocol
# status of linked issues, in one markdown document where every claim
# cites its source. The test delta comes from a verify report you pass in.
npx @reneturcios/greenlight evidence https://github.com/acme/widgets/pull/42 --out EVIDENCE.md
# or: greenlight evidence <pr-url> --verify-json verify.json
# Contributor passport: protocol claims from the public Claim Ledger plus
# merged PRs from GitHub. No Ledger file yet? It says so plainly.
npx @reneturcios/greenlight passport CloudCorpRecords
# The proxy, for authenticated reads (60/hr anonymous -> 5000/hr token):
# reads GITHUB_TOKEN once at startup, attaches it server-side, binds
# 127.0.0.1 only, and refuses to start without a token.
export GITHUB_TOKEN=<your-classic-token> && greenlight proxy &
export GREENLIGHT_GITHUB_BASE_URL=http://127.0.0.1:8792 GITHUB_TOKEN=proxy
# Verify every link of a release chain (tag, commit, release, npm, registry)
npx @reneturcios/greenlight shipcheck <owner/repo> --version x.y.z
我们的审核实例:
batrapulkit/squidbrake#74得分为 GO:0 条评论,标记为 help wanted,没有认领,没有门槛。shadcn-labs/pdfcn#58得分为 RISKY(已认领标记):我们审核的当天就有志愿者请求分配任务。langchain-ai/langchain#41185得分为 TAKEN(认领竞争):仍处于“未分配”状态时,已有 3 位有力认领者。PrefectHQ/fastmcp#5718得分为 GATED:FastMCP 要求先分配任务,或添加“prs welcome”标签,才能提交 PR。triggerdotdev/trigger.dev#5016得分为 GATED:未经背书的作者提交的 PR 会被自动关闭,必须先申请背书。
MCP 服务
同一引擎也通过 stdio 向编码 Agent(Claude、Cursor、Cline)开放。切入点:Agent 浪费的 token 大多用于修复已被接手的问题。让 Agent 在编写代码前先检查问题。
{
"mcpServers": {
"greenlight": {
"command": "npx",
"args": ["-y", "@reneturcios/greenlight", "mcp"],
"env": { "GITHUB_TOKEN": "your-token" }
}
}
}
工具(33 个):
check_issue- 单个问题 URL 的评估结果scan_repo- 对仓库中待处理问题排序,GO 优先(先选带标签的入门问题,若无则选近期未分配的待处理问题;deep: true会先对候选问题进行时间线透视)xray_issues- 时间线透视:根据时间线深度核验候选问题(隐藏的进行中 PR、报告者自行提交的修复 PR、评论中的声明);逐个问题给出 GO / RISKY / TAKEN,并附上 PR 证据racecheck_issue- 单个问题的关键词竞速检查:查找修复同一问题但从未链接该问题的待处理 PR(如 sveltejs/kit #17465 与 PR #17453 的情况);逐个 PR 引用匹配到的关键词,并给出 RACE / SUSPECT / CLEARrepo_friction- 仓库的摩擦评分wave_queue- 一次调用构建队列:从 Agent Policy Index 中筛选有胜算的待处理仓库,对入门问题进行透视(CLEAR / RISKY / TAKEN),排除行为门槛,并跳过你已有待处理 PR 的仓库verify- 针对已检出的仓库,诚实呈现基准版本与当前版本的测试差异(先检查失败项,绝不只报原始数量)shipcheck- 发布就绪检查:GitHub release、npm 版本、注册表记录和 GHCR 标签;逐项给出 GO / NO-GOpassport- GitHub 登录名对应的贡献者通行证:账本资料、已合并 PR 数量、信誉比率bounty_check- 单个问题的悬赏有效性分类:有效平台、无法核实的声明或已失效平台claim_issue- 由评估结果控制的问题认领评论(除非execute: true,否则仅试运行)prep_issue- 检查 Fork 和分支,并根据仓库已学习到的约定生成本地 PREP.md 清单(除非execute: true,否则仅试运行)open_pr- 从 Fork 分支创建 PR,并处理 DCO(除非execute: true,否则仅试运行)ci_prep- 推送前在本地运行仓库自身的 PR 检查(结果为 NO-GO 时退出码为 1)ci_triage- 将 PR 上的每项失败检查分类为已有问题、可能由你引起、无法确定(并说明倾向)或外部阻塞;依据基准分支近期的检查历史进行比较review_triage- 对你 PR 的审查反馈进行分类:每项发现都标为可能属实 / 可能是噪声 / 需要决定,并附原因和回复草稿(绝不会将人类评审标为噪声;只生成草稿,不会发布)pr_brief- 任意 PR 的已核实审查简报:按领域 / 风险分组的文件、根据基准分支历史进行的 CI 分类、有证据支持的真实 / 误报发现分类、测试证据(若不存在则明确标注)、合并阻塞项,以及一句「优先查看此项」提示(绝不编造发现)guard_pr- 维护者侧对新收到的 PR 进行分析:竞争性修复、非作者提出的先前认领、缺失的材料(changeset / DCO / CLA)、首次贡献者。返回可直接用于评论的 Markdown(绝不发布)repo_digest- 仓库级维护者报告:PR 竞速及先认领仲裁、他人已认领的冲突、过期认领、分配门槛冲突、被分流流程暂扣的问题(绝不发布)pr_radar- 维护者侧的重复 / 竞争 PR 雷达:将仓库的待处理 PR 聚类为竞争组(目标问题相同,或变更文件高度重叠),为每组提供证据并建议保留项(始终标注为启发式判断,绝非定论;绝不发布)claim_status- 单个问题的 Claim Protocol 预检:由谁认领、认领期限、排队者、竞争 PR、门槛,以及仓库是否遵守该协议preflight- 一次调用即可获得结论:claim_status 加仓库摩擦摘要verify_comment- 为仅限维护者操作的仓库起草已核实发现评论(仅起草,绝不发布)babysit_prs- 监控待处理 PR 并生成一份按优先级排序的操作清单(现在需要你处理、等待对方处理、暂时无事),与已存储的水位线进行差异比较;同时监控 my-claims 注册表(已关联、活跃且状态良好、需要发送心跳、即将过期、未关联且过期、队列中丢失)evidence_pack- 单个 PR 的已核实 PR 证据包:guard 评估结果、CI 分类、审查分类、已关联问题的协议状态,以及每项认领及其来源scout_campaign- 活动模式:为仓库目标排序,与活动文件去重,并在 API 预算耗尽后恢复my_claims- 认领注册表:已关联、活跃且状态良好、需要发送心跳、即将过期、未关联且过期、队列中丢失sync_campaign- 根据 API 实际状态协调本地跟踪数据(偏差、状态不匹配、过期认领)campaign_portfolio- 一屏式活动摘要:统计数量、按状态分类的认领、待处理队列、偏差数量autopilot_report- 按 PR 分类反馈(只读;核验机器人发现、分类 CI,并将机械性修复列为计划)api_status- 托管认领 API 状态claim_via_api- 通过托管认领 API 认领问题heartbeat_via_api- 通过托管认领 API 发送心跳 在本地运行:npm run dev(MCP 入口是src/index.ts;CLI 是src/cli.ts)。
评分方式
判定引擎是确定性的(不使用 LLM),并按以下顺序检查:
- 已关闭的问题:TAKEN(绝不可认领)。
- 有任何受指派人:TAKEN。
- 有一个关联的开放 PR,且该 PR 会关闭此问题:TAKEN。仅仅提及问题编号的 PR(例如 pdfcn 的 PR #91,它会关闭 #70,但在正文中列出了相关问题)只会添加
weak-pr-mention标记,并将原本为 GO 的判定降级为 RISKY。如果问题被标记为某个已关闭且已完成问题的重复项:判定为 RISKY,并添加duplicate-of-closed标记(工作已经交付;若重复项目标仍开放,则仅添加带其 URL 的duplicate-of-open警告)。 - 有两个或更多强认领者:TAKEN(认领竞争)。
- 有一个新的强认领,且针对整个问题(未满 45 天):判定为 RISKY,并添加
claimed标记。若新的认领只针对问题的一部分(“接手剩余的 fallback 需求”):判定为 RISKY,并添加claimed和partial-claim标记;原因需指出认领者及其认领范围,绝不判定为 TAKEN。 - 有一个超过 45 天、且没有关闭 PR 的强认领:判定为 RISKY,并添加
stale_claim标记。认领者可能已经放弃,但无法确定。过时的部分认领也按相同方式处理。超过 180 天且没有关闭 PR 的认领则视为衰减:通过stale-signal标记披露,并给出降低权重的原因,但本身绝不会阻止认领(两条很久以前的认领不再构成认领竞争,单条很久以前的认领也不再降低干净问题的评级)。 - 有硬性门槛(指派、背书、仅限协作者、暂停非应邀 PR、工作流自动关闭外部 PR),且无人被指派:GATED。最后两种情况来自 CONTRIBUTING 中的说明(“已暂停非应邀拉取请求”)以及对
.github/workflows中自动关闭外部 PR 的工作流的扫描。 - 180 天或更久没有活动:STALE。
- 软性“先认领”门槛(仓库要求贡献者开始工作前先评论,例如 pdfcn):绝不判定为 GATED;它会将原本为 GO 的判定最高限制为 RISKY,并附带说明,降级方式与弱 PR 提及相同。
- 其他情况:GO。
- 非作者评论中提及的开放 PR,且其标题或正文提到了问题编号:会将原本为 GO 的判定降级为 RISKY,并添加
comment-mentioned-pr标记(“可能已经涵盖此问题的一部分”)。这两种情况都不会导致 TAKEN;只有会关闭问题的 PR 才会如此。修复公告评论("/attempt #N"命令,或“已为……提交修复,见 ”这类说明,通常会链接到相关仓库中的 PR)也会按相同方式降级,但会使用自己的原因并引用 PR URL,同时添加attempt-linked-pr标记,即使该 PR 从未提及此问题。/attempt评论也会登记为强认领。 - 部分已解决:提及问题编号的已合并 PR(通过评论提及或关联),或表明部分工作已经交付的维护者评论(“由 #905 完成了一半,因此仍保持开放以处理 B 部分”,“已在 v3.1.0 中发布”,且旁边提及该问题)。仅给出 GO 会掩盖需要限定范围的工作,因此会添加
partially-addressed标记,并将原本为 GO 的判定最高限制为 RISKY,原因示例:“此问题已有部分内容交付(PR #905,已合并);请将工作范围限定为剩余部分”。绝不判定为 TAKEN。 摩擦分从 100 开始,扣除各项门槛的权重(需完成指派 −25、需担保 −35、仅限协作者 −50、暂停非主动 PR −40、范围受限的暂停 −20、外部 PR 自动关闭 −50、先讨论 −10、先认领 −5、CLA/DCO 各 −5、检测到行为门槛 −20);在可计算时,根据外部 PR 合并率以及审核和响应时间进行调整;对于开放的 good-first-issue,最多加 +10。未知信号保持为 null 并跳过,绝不猜测。当经典入门标签的数量恰好为 0 时,摩擦分会在标签数量旁显示一个仅供参考的候选估算值(在更广泛的入门标签集合中查找开放且未指派的问题,例如 "beginner friendly"、"easy"、"first-timers-only");此估算值绝不计分,也不会并入标签数量。确切公式见src/friction.ts。
行为门槛不是政策文件,而是根据维护者的实际做法判断。friction 会遍历已关闭 PR 列表,直到找到最近 12 个月内已关闭但未合并的 15 个 PR(超出时间范围的已关闭 PR 会被排除;如果最新关闭的 PR 本身也早于时间范围上限,则会附上“信号过时”说明),然后读取维护者一侧的评论,以查找拒绝 AI 的证据(提及 AI 并带有拒绝措辞、明确使用 "AI slop" 之类的短语,或提及已援引的 "AI policy";而 "AI-assisted PRs are welcome" 等欢迎 AI 的表述会抑制该信号)。两个独立 PR 即可判定仓库存在行为门槛;单个较弱信号会作为警告保留,单个明确的拒绝短语则足以独立触发检测。friction --json 会将其报告在顶层 behavioral_gate 字段中(包括 detected、strength、threshold、包含 PR 编号、引文和 URL 的 evidence,以及 notes);该字段是规范位置,signals.behavioralGate 则作为相同镜像保留,以兼容索引流水线。重新基线等索引流水线会读取规范字段,以重新归类书面政策未作说明、但实际做法带有敌意的仓库。API 调用成本上限为 48 次:最多调用 3 次列表接口以收集 15 个已关闭但未合并的 PR,再为每个 PR 最多获取 3 个证据页面(issue 评论、审核、审核评论);使用 --no-behavioral 可跳过此项。
friction --lite 是规范的轻量摩擦度计算方式:仅考虑政策门槛。它会获取政策来源(根目录、.github/ 和 docs/ 下的 CONTRIBUTING 变体、AGENTS.md、CLAUDE.md 和 AI_POLICY.md,以及组织级 AI_POLICY.md),从中解析门槛,应用 detectRepoPolicy 检测到的仅限协作者推送策略(目前不调用 API),并按精确的文档公式计算分数:从 100 开始,加上门槛权重(使用相同的 GATE_WEIGHTS),然后将结果限制在 [0, 100]。它会跳过行为门槛检测、合并速度(以及其中的外部 PR 合并率项)、首次审核和问题响应时间,以及 good-first-issue 加分:所有结果信号都保持为 null 并跳过,绝不猜测;signals.note 的值为 "lite",报告中则包含 lite: true。gates 和 score 字段的结构与完整摩擦分相同,因此 Agent Policy Index 扫描器可以将 --lite 用作统一的轻量摩擦分实现,而不必自行维护一套实现。
每份摩擦报告(轻量和完整)还包含 policy_provenance:针对每个探测过的政策来源,记录其已读取、不存在或获取失败,从此不会再把“没有政策文件”和“政策获取失败”混为一谈(此前两者显示相同)。在人类可读的输出中,这会呈现为一行摘要,例如:policy sources: 2 read (CONTRIBUTING.md, AGENTS.md), 3 absent, 0 fetch errors。
wave 可通过一条命令将 Agent Policy Index 转换为构建队列:使用现有的 xray 引擎对符合条件的开源仓库进行检查,这些仓库须有外部贡献者合并占比、星标数区间和入门问题(结果为 CLEAR / RISKY / TAKEN,并列出竞争中的 PR);排除检测到行为门槛的仓库,跳过你已提交未关闭 PR 的仓库;当核心 API 预算低于下限(默认 800)或触发搜索限流时,运行会停止并标记部分结果。支持人类可读输出和 --json;每个阶段都会报告所用的 API 调用次数。默认按可胜任度排序候选项(先看外部贡献者合并占比,再看阻碍程度,最后看星标数);--sort stars 可恢复旧的排序方式。
有一种范围限定的接收暂停(“not accepting pull requests that add new formatting options”),它属于独立的门槛类型(scoped_prs_paused),造成的阻碍程度只有全面暂停的一半,也不会直接决定判定结果:check 和 scan 会标记此类暂停,并将结果上限设为 RISKY,同时引用被拒绝的范围。
Autopilot 会持续维护分支健康看板:每个 PR 的可合并状态、mergeable_state、基础 SHA 和落后提交数都会在运行之间保存在其状态中,显示在报告输出里,并包含在 autopilot_report MCP 工具中(branch_health、branch_board)。
还有四个可由 Agent 调用的 CLI 命令会作为 MCP 工具提供:verify(如实对比基础版本与头部版本的测试变化)、shipcheck(发布、npm、注册表和 GHCR 就绪情况)、passport(基于声明记录的贡献者档案)和 bounty(单个问题的赏金活跃度)。
Agent 政策门槛与分诊暂缓
政策文件会从仓库实际存放的位置读取:仓库根目录、.github/ 和 docs/ 中的 AGENTS.md、CLAUDE.md、CONTRIBUTING.md 和 AI_POLICY.md(每个文件名只取首次命中),以及组织级的 .github/AI_POLICY.md。两种门槛类型会解析 Agent 规则:
agents_banned是硬性门槛:禁止自主 Agent 贡献的仓库会被判为 GATED,并以引用的政策原文作为证据;除非使用--force,否则claim会像处理 TAKEN 一样拒绝该仓库。agents_disclosure是标记,不会改变判定结果:对于要求使用 AI 前缀或披露的仓库,prep和check会给出具体的必要操作。
机器人分诊通知(“wait until maintainers remove the triage or approval label before opening a pull request”)或分诊标签会将问题标记为暂缓:check 会指出暂缓原因,并将原本为 GO 的判定上限设为 RISKY,附加 triage-hold 标记(不会变为 TAKEN);scan 会将暂缓的问题排在无阻碍问题之后。暂缓问题属于未来工作,而非当前工作。
可选的 AI 认领检测
模式匹配层无法识别所有人类表达“我来处理”的方式(有一次,它漏掉了真实问题中的一句“I'm looking into contributing a fix here”)。设置 FIREWORKS_API_KEY 后,check 会增加一道可选的复核:由 Fireworks 的低成本模型读取符合条件的评论(排除机器人和问题作者,与模式匹配使用相同的评论集合),并标记模式匹配漏掉的认领意向表述。
治理规则很明确:
- 默认关闭。 未设置密钥时不会发起调用,输出与仅使用模式匹配引擎时逐字节一致。
- 模式匹配优先,成本更低。 只有在模式匹配未发现强烈认领信号时,才会运行 AI 检测。
- 只添加标记,不改变判定。 AI 标记会添加
llm-claim标记,并以准确引文作为证据;如果原判定为 GO,则会降级为 RISKY。它永远不会判为 TAKEN,也不会覆盖 GATED。判定结果仍保持确定性。 - 不允许编造证据。 引文必须是评论正文中的精确子字符串;否则会在影响判定前被丢弃。
- 失败时静默处理。 超时、非 200 响应或无法解析的回复都不会返回信号,也不会将错误传入
check流程。分类结果会按评论 ID 和模型 ID 缓存,因此重复检查不会产生额外成本。
greenlight doctor 会报告该层是否已配置(绝不会显示密钥)。
自动化
Greenlight 将其作者手动完成的贡献流程自动化。作者曾为四个真实 PR(shadcn-labs/pdfcn #92-#95)手动完成整个流程:给出判定、发表评论认领、创建 fork 分支并发起 PR,同时全程考虑 DCO。
# 1. Claim the issue: verdict first, comment shaped by the repo's gates
greenlight claim https://github.com/shadcn-labs/pdfcn/issues/65
# 2. Prepare: fork/branch check (learning the repo's branch convention) plus a PREP.md checklist
greenlight prep https://github.com/shadcn-labs/pdfcn/issues/65 --dir /tmp/prep65
# 3. Open the PR from your fork branch (verifies DCO sign-off on DCO repos)
greenlight pr https://github.com/shadcn-labs/pdfcn/issues/65 --branch feat/quarterly-report-block
安全默认设置,而且这是一个特性:
- 默认试运行。 三个命令都会准确打印将要发布或创建的内容,然后退出。除非使用
--yes(CLI)或execute: true(MCP),否则不会发布或创建任何内容。 - 写入需要令牌。 无需令牌即可执行读取操作。写入操作需要
GITHUB_TOKEN(或GH_TOKEN);若未设置,命令会打印一条明确指出环境变量名称的错误,然后以非零状态退出。 - 由判定结果控制。 除非使用
--force,否则claim会拒绝 TAKEN 或 STALE 判定;对于必须获得背书的仓库,则会直接拒绝(背书无法自动化)。对于必须先分配任务的仓库,会改为发送任务分配请求,而非发布意向评论;对于必须先认领的仓库(开始工作前先评论),则会发布标准意向评论,满足这一流程要求。 - 根据仓库调整分支名称。
prep会读取近期已关闭 PR 的头部分支,并遵循占主导地位的命名惯例(pdfcn 的feat/<slug>-block),同时仍会显示默认名称feat/<slug>-<number>。 - 考虑 DCO。 对于采用 DCO 的仓库,
pr会验证分支上的每个提交是否都包含Signed-off-by:行;若有提交缺少该行,命令会列出这些提交并拒绝继续。 - 根据仓库调整准备流程。
prep还会了解仓库的贡献流程要求,并将其纳入 PREP.md 检查清单:存在哪些项目规则文件、这些文件要求使用什么验证命令(例如pnpm verify)、仓库是否从.changes/目录汇总变更日志、根目录package.json中有哪些脚本,以及近期提交是否遵循 Conventional Commits。约束性规则越来越多地写在AGENTS.md而非 CONTRIBUTING 中,prep 也会读取这些文件。
工具集
Greenlight 是一个面向开源贡献工作的四工具生命周期的入口,所有工具均发布在同一个 npm 作用域下,并彼此打通:
- gatefile(
npx @reneturcios/gatefile extract owner/repo)会提取仓库的贡献门槛,并将其保存到已提交的contribution-gates.json文件中。Greenlight 可直接读取此文件:运行greenlight check <issue-url> --gates-file contribution-gates.json,或在该文件位于工作目录时自动读取。这样只需回答一次门槛问题,即可重复使用,而无需每次都从文本中重新推导。 - greenlight 可给出判定、扫描、认领、准备并发起 PR(即本工具)。
- claimcheck(
npx @reneturcios/claimcheck claims owner/repo)会监控已认领的问题,发现认领过期,以及已完成的修复仍留在 fork 上的情况;这是已认领工作悄无声息地中断的两种原因。 - prwatch(
npx @reneturcios/prwatch attention --user you)会按你当前需要处理的事项,对你发起的开放 PR 进行分流:评审讨论串、未通过的检查、冲突以及评审者未回应。
每个工具都提供 CLI 和 MCP 服务(<tool> mcp)。
摩擦指数
data/friction-index.json 是一个已检入且持续扩充的评分仓库数据集。它最初包含我们于 2026-10-13 手动审核过的 MCP/AI 生态项目(FastMCP、trigger.dev、langchain、deepagents、openclaw、squidbrake、reticle、pdfcn、chatflow-agent,以及三个 MCP SDK 仓库)。运行 npm run index 可重新生成该数据集。
标记为 hand-verified 2026-10-13 的条目来自手动阅读仓库的实际政策和问题追踪器。标记为 live 的条目则是从实时项目规则文件(CONTRIBUTING 的各种变体、AGENTS.md、CLAUDE.md)解析而来。每项门槛都会记录其证据来源文件。计算得出的结果字段(合并率、评审耗时)会保持为 null,直至我们能够如实计算;绝不伪造。
已发布页面(cloudcorprecords.github.io/greenlight)还提供 Agent Policy Index:对 505 个仓库的贡献门槛和 AI 政策进行评估,并为每个条目引用证据。没有其他人发布过这份索引。
开发
npm test # tsx --test, includes fixture tests that reproduce our real verdicts
npm run build
发布检查清单
每次升级版本都必须更新以下所有内容,否则发布的内容会过时:
package.json版本package-lock.json版本server.json:顶层的version、npm 包的version,以及 OCI 的identifier标签。该标签必须与包版本一致 (ghcr.io/cloudcorprecords/greenlight:<version>);如果标签不一致,test/packaging.test.ts会导致构建失败src/index.ts版本examples/guard-workflow.yml固定的版本- 测试套件通过后,运行
npm run readme:count,以便根据实际运行结果重新生成 README 中的测试数量,切勿手动填写 (如果未记录此步骤,test/packaging.test.ts会导致构建失败)
路线图
明确标记:这些功能尚未发布。(v0.15.0 将两项路线图功能纳入产品:radar 用于聚类重复或相互竞争的 PR,brief 则为任意 PR 提供经过验证的评审简报。)
- 维护者控制室。
guard按 PR 运行,radar对队列进行聚类(两者均已发布);控制室是在此基础上构建的托管式仓库专属界面:清理过期认领,支持一键申请释放认领;提供首次贡献者风险说明和每周维护者摘要。引擎组件已经就绪;产品需要将其整合并提供托管服务。 - 策略执行包。 仓库总是在重复制定相同的规则(必须提供 changeset、必须提供发布说明、DCO、AI 披露)。一种基于
gatefile输出构建的策略包格式,让维护者只需在一个文件中启用策略包,即可由 Action 以相同的引用证据风格强制执行。 - 防御 AI PR 泛滥。 要过滤,而不是禁止:由
guard对传入 PR 的认领合理性、复现证据和测试差异进行评分,让维护者既能接纳优质 Agent 提交的工作,又能过滤垃圾内容。活动数据(拒绝的认领、诚实验证、证据包)就是验证依据。 - 认领仲裁即服务。 两项认领、一个队列、公开排序、维护者可覆盖:实时仲裁相互竞争的认领,这是维护者无法自行构建的功能。
- 在 github.com 上以内嵌方式为问题评分的浏览器扩展。
- 已搁置修复的检测和自动提醒:扫描 Fork,查找引用未关闭问题的分支,并在满足门槛时发送提醒。
完整的发布历史见 CHANGELOG.md。
许可证
MIT。请参阅 LICENSE。
由 Rene Turcios 构建——一位在 SF 公开开发的氛围编程者 / Agent 原生开发者。如果 Greenlight 为你省下了一个周末,请为此仓库点星,并关注 @CloudCorpRecords,了解下一个工具。
这一系列工具:prwatch · claimcheck · gatefile · hookcheck · injectcheck · actionpin——均已发布到 npm,包名位于 @reneturcios/ 命名空间下,并收录于官方 MCP Registry。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。