
一份一百四十行的政策被删到只剩十五行十月七日QGIS 把一份只有十五行的政策文件合进了主干。它删掉了原先一百四十行的 AI 工具使用政策只留下一句式的禁令。被替换的是同一年年初由 Even Rouault 起草的 QEP408那版政策的核心是人在回路。从人在回路到一律禁止中间只隔了八个月。新提案编号 QEP428作者是 QGIS 核心贡献者 Nyall Dawson。拉取请求号 387改动统计是增加七行、删除一百四十行。合入的时间戳落在十月七日晚上随后源分支被删除。十月十二日这条消息被顶上 Hacker News 首页拿下二百八十七分。到当天下午讨论串已经积累了二百九十五条评论。一条十五行的政策能引发这种体量的讨论说明争的从来不是 QGIS 本身。QGIS 是一套开源地理信息系统用 C 与 Python 写成历史超过二十年。它的贡献者里有大量来自测绘、遥感、城市规划与公共部门的工程师。这类用户既是使用者也是回馈者社区结构比纯互联网项目更紧密。所以当它决定关门时受到影响的是一整条职业化的贡献链路。禁令的两句话写了什么新政策的正文只有两句话第一句划定范围第二句写后果。第一句说qgis/qgis 仓库不接受任何由大模型、AI 或智能体协助产出的代码贡献。第二句说如果事后发现你用了 AI、LLM 或任何智能体工作流代码会被回滚贡献者权限会被制裁。关键词是「事后发现」它把举证责任放在维护者一侧也把时间窗口拉到合入之后。制裁手段写了两条代码回滚以及贡献者权限处置。文件头部的版本号是 2.0作者一栏从 Even Rouault 改成 QGIS 项目贡献者。日期一栏保留了二零二六年九月二十四日那是提案提交讨论的日子。联系人一栏从个人邮箱换成了 qgis.org 这个组织地址。这三处头部改动说明它不再是一份个人提案而是一份项目立场文件。被删掉的旧政策不是敷衍之作它有一百四十行结构完整。旧政策要求贡献者必须逐行读过并理解模型产出的代码再请维护者评审。它还要求贡献者能够在评审中回答关于自己改动的问题。透明性方面它要求用 Assisted-by 这类提交信息尾注标出工具使用情况。它明确禁止了未经人类批准、在项目空间里自行行动的智能体比如 GitHub 上的 claude。自动发布评论的评审机器人同样被禁除非人类留在回路里。旧政策甚至单列一节叫「提取性贡献」专门描述只索取不回馈的行为。那一节讨论了如何识别这类贡献以及为什么它们会消耗维护者的时间。它还建议新人从小改动起步先建立对自己判断力的信心。这些条款在文本层面几乎无懈可击问题出在文本之外。旧政策不是没写清楚是没人执行一位参与者在讨论里翻出了执行层面的账本。他说旧政策里设计的 extractive 标签从来没有被创建过。与此同时大约五十个拉取请求被打上了 AI Assisted 标记。这五十个里面约四十个最终没有合入主干就被关闭。还有若干请求连标记都没有直接在评审过程中被静默关掉。这组数字说明一件事标签体系先于流程崩溃了。标记本身成了负担而不是帮助评审者判断风险的工具。分类要求假设了贡献者会主动披露、维护者会主动归类。当提交量涨到某个阈值这两个假设会同时失效。Dawson 在回复里承认旧政策的那套流程在现实中并没有发生。他给出的理由是机器产出的内容流量远超人类评审者能认真消化的上限。这句话在另一位维护者 haubourg 的评论里被展开得更具体。haubourg 说来自外部贡献者的 AI 使用给维护者的肩膀压上了难以承受的压力。他描述了两个都不想要的结局未评审请求越堆越长或者代码在没被完整读懂的情况下合入。他提醒自由软件社区建立在人的网络之上。机构信任 QGIS是因为它们知道自己可以回馈可以雇人做支持、培训和功能开发。如果这个网络被稀释项目会失去欢迎人类贡献者所需的带宽。这段论证把禁令的动机从技术判断挪到了组织生存。它也是整场讨论里被点赞最多的一条评论四十五个赞成对四个反对。一条自述模型让我以为自己能修 QGIS讨论串里最有分量的一段话来自一位自称初级开发者的贡献者 Amalvir。他说自己正是这条政策的直接影响对象并且投了赞成票。他此前提交过两个由 AI 协助的回归修复请求用来定位缺陷原因并给出修复。他说当时没有意识到这样做会给本就脆弱的评审者社区造成伤害。他承认自己还没有能力修复 QGIS 这种复杂度项目里的缺陷。但模型给了他一种「这件事可以做」的错觉几轮对话之后缺陷看起来就修好了。他的原话是这样做破坏了评审者与贡献者之间的信任契约。那个契约的内容是你在这个项目里提交改动就说明你知道自己在做什么。他补充了第二层影响这一层很少有人讨论。当贡献变得如此容易使用 AI 的贡献者学到的东西很少甚至没有。他们无法在项目里积累能力也就永远没有希望成为评审者。结果是社区停滞维护者队伍得不到补充。这段自述把一个抽象争论还原成一条具体的成长路径被截断。它也让「禁止」这个动作有了可以辩护的动机。一位核心贡献者随后引用了这段话作为支持关门的关键理由。值得注意的是说这段话的人并不是被针对的对象而是自愿放弃工具的人。反对意见边界在哪里误伤有多大反对的声音同样具体而且大多不是关于要不要用 AI。一位参与者 kannes 先讲清立场他认为当前围绕 AI 的狂热在很多层面都是问题。但他想指出一些技术上的好处这些好处会被新政策一并禁掉。他列举的第一项是用模型在代码库里发现不那么明显的上下文。他强调模型经常出错但结果可以被人用来理解代码从而写出更好的贡献。第二项是把模型当成一个模拟评审者。把代码丢给它拿到一份清单丢掉无关部分再看剩下的是否指出了真问题。他把这种用法比作 IDE 里那个偶尔有用的助手能减少错误并提高稳健性。他担心「协助」和「使用」这两个词太宽会把孩子和洗澡水一起倒掉。他追问这份政策的意图到底是什么是减少维护者压力还是对 AI 表态。如果是后者他认为文本可以写得更清楚立场也可以更强。另一位参与者把边界问题问得更直接这包括议题内容、评论和请求描述吗。他得到的回答是安全公告这一块过去几乎全部由 AI 撰写。这说明同一条禁令在不同工作流上的实际边界并不一致。Even Rouault 用一个小号回复了「倒掉孩子」的质疑态度坦率。他说他们清楚可能会倒掉孩子但那个孩子可能本来就活不下来。他把这份提案称为一个权宜之计。他的理由是两年前的世界虽然不算好但至少没有今天这么糟。在完全理解后果之前没有理由放开。他判断也许要等这轮 AI 泡沫破裂才能看清什么算是公平的 AI 使用。另一条建议来自长期贡献者 adamjstewart他谈的是范围。他建议把文档、缺陷报告、讨论、请求描述和评论全部纳入管辖。他的理由是这些文字往往比代码本身更啰嗦也更具提取性。这条建议没有写进最终的两句话里但它指出了政策执行的一个盲区。Dawson 对范围的回答是把这次改动定性为一道暂时关上的门。他说这不会是一份刻在石头上的永久政策。他用的措辞是先关门等时机安全、讨论充分时再选择性地开一条缝。他点名了两个可能的开口把 AI 当作 IDE 自动补全的替代。以及把 AI 用于语言翻译。这两个场景都要按个案单独讨论不会一次性放开。他也解释了为什么要从最严格的一端起步。旧政策的执行失败被摆出来之后他的判断是项目已经因此失去至少一位价值极高的贡献者。投票、数字与分歧的形状提案在十月五日走完讨论期进入投票阶段。十月七日标签从 Voting 换成 Accepted随后合入主干。讨论串里有三十条对话参与者列表里出现十五个人。投票结果用表情写在页面上提案本身拿到六十九个赞成和十九个反对。haubourg 那段解释维护者压力的评论拿到四十五个赞成和四个反对。Amalvir 那段自述拿到十三个赞成和两个心形。赞成票里包括 Even Rouault 本人也就是旧政策的作者。他在投票评论里只写了一个加一。这些数字不能直接等同于社区共识但能说明分歧的形状。赞成的一方集中在维护者负担和社区可持续性上。反对的一方集中在边界模糊和技术好处被误伤上。两边的共同前提是评审者的注意力是稀缺资源。分歧只在于关门是不是保护这份注意力的正确手段。两版政策并排看把两版政策放在一起差异会变得很直观。下面这张表对比的是管辖对象、透明度要求和违规后果三个维度。维度QEP408旧人在回路QEP428新一律禁止管辖对象代码、提案、议题、安全漏洞、评论仓库内的代码贡献允许的使用人工逐行复核后可以提交不允许任何协助式产出透明度要求用 Assisted-by 尾注披露工具使用不再区分披露与不披露智能体行为禁止未经人类批准自行行动禁止任何智能体工作流违规后果评审阶段拒绝或要求重做代码回滚与贡献者权限处置文本规模约一百四十行两句话表格里最值得注意的一行是透明度要求。旧政策把披露当作核心机制新政策直接取消了这一层。取消披露的理由很直接如果使用本身就是违规披露就只剩下自证其罪的功能。把禁令写成钩子一个真跑过的 commit-msg 检查政策文本本身不执行任何检查它需要落到工具链上才有牙齿。最轻的一种落法是在提交信息这一层加一道钩子。下面这段 Python 脚本可以直接放进 .git/hooks/commit-msg。它读取 Git 传进来的提交信息文件路径逐行匹配被禁的尾注。匹配目标是 Assisted-by 尾注。它同时拦截把 Claude、Copilot、Codex、Gemini、Cursor 写进共同作者行的写法。命中任意一条就打印拒绝理由并返回非零退出码让这次提交失败。这段代码在本机真实跑过两次输出是确定的。第一次喂进去带 Assisted-by 的提交信息脚本打印拒绝行并返回退出码一。第二次喂进去只带 Refs 的正常提交信息脚本静默返回退出码零。#!/usr/bin/env python3 # .git/hooks/commit-msg import re import sys BANNED re.compile( rassisted-by:|co-authored-by:\s*(claude|copilot|codex|gemini|cursor), re.IGNORECASE, ) def main(path): text open(path, encodingutf-8, errorsreplace).read() hits [line.strip() for line in text.splitlines() if BANNED.search(line)] if not hits: return 0 print(QEP428: commit message carries an AI-assisted trailer, rejected) for line in hits: print( -, line) return 1 if __name__ __main__: sys.exit(main(sys.argv[1]))这段钩子只能拦住声明出来的工具使用拦不住隐瞒。它的价值在于把「必须披露」这条旧政策要求变成可执行的检查。而新政策把披露这一层整个拿掉了因为它不再区分披露与不披露。在禁令之下钩子的作用从确保透明变成提供事后追溯的线索。这也解释了为什么新政策把后果写成回滚与权限处置而不是要求补充说明。如果项目愿意还可以把检查扩展到共同作者行之外。例如扫描请求描述模板里的固定段落或者校验提交者签名与已知账号的对应关系。但这些手段都只能降低噪声不能替代评审者读懂代码这件事。关门的代价与开源治理的下一步把这件事只看成 QGIS 一家项目的选择会漏掉它真正的位置。过去一年里已经有一批开源项目在收紧 AI 贡献的口子。有的要求披露有的要求人类逐行负责有的直接禁止。LLVM 的政策是人在回路的代表文本要求贡献者对每一行负责并标注工具使用。GDAL 的 RFC 111 走了同一路线把披露与复核写进正式流程。QGIS 的特殊之处在于它先试过最温和的那一档然后退回了最严格的那一档。这条路径比单纯的禁令更有信息量因为它包含一次失败实验的结果。失败的关键指标不是有多少 AI 请求被提交而是有多少被认真评审。五十个标记、四十个关闭、一个从未创建的标签三个数字指向同一件事。流程设计假设了贡献者会主动披露、维护者会主动分类。当提交量涨到某个阈值两个假设同时失效。于是政策被迫从管理使用切换到禁止使用因为前者需要的人力更多。这也意味着禁令的可持续性取决于同一件事维护者的人力是否够用。关门降低了分类成本但把判断成本转移到了发现环节。事后发现的机制要求有人持续怀疑、持续核查这同样需要时间。Dawson 承诺的按个案开口是这个机制唯一的减压阀。如果开口的节奏由维护者随意掌握政策就会在边界上反复摇摆。如果开口需要公开的判据比如翻译场景与补全场景各自的门槛争议会小得多。对贡献者来说可操作的建议反而变简单了。在 QGIS 仓库里不要提交任何由模型生成或改写的代码包括看起来很小的修复。不要用模型生成请求描述或评论除非项目明确放开这一项。如果确实用了模型做理解或验证也把它留在本地不要让它出现在提交物里。把贡献规模压到自己能完全解释的程度这是旧政策里唯一没有被争议的建议。对维护者来说这次讨论提供了一份现成的风险清单。分类标签在提交量低的时候有效在提交量高的时候会先崩。更稳的做法是把披露要求绑在工具链上而不是绑在人的自觉上。提交信息钩子、签名验证、贡献者协议都可以承担一部分过滤。这也是整场讨论里唯一没有分歧的结论。模型的产出速度可以无限提升人类评审的注意力不能。所有治理设计最终都要回到这个不对称上。QGIS 选择用关门来缩小输入把不对称暂时拉回可控区间。这个选择会付出代价代价包括误伤那些只用模型做理解的贡献者。代价还包括短期内失去一部分愿意尝试新工具的新人。项目赌的是保住评审者网络比留住这部分新人更重要。这个赌注是否成立要等下一年的贡献者数量才能验证。在那之前这份十五行的政策就是 QGIS 给出的答案。它把问题从「怎么用好 AI」改写成「怎么保住人」。这个改写本身就是本轮事件最值得记录的部分。