商业产业 Hacker News AI 2026-08-09T15:25 正文 ok 457 words

人类 vs. AI:面向 Agent 编辑的基于 Diff 的文本行级归属追溯

英文标题:🔶 Human vs. AI – Diff-based line-level provenance for text under agentic editing

us-vs-them 是一个可作为库或 CLI 工具使用的方案,利用文本版本历史判断每一行内容由人类还是 Agent 创作或修改。它面向 Agent 编程和编辑场景,可帮助保护人类亲自撰写或修订的关键代码、README 开头等内容,避免后续 Agent 随意覆盖。该工具通过 Git 提交作者和简单 Diff 计算文本区间的“人类归属度”,以 0.00 至 1.00 的数值表示内容完全由 Agent、部分被 Agent 修改或完全由人类创作。对于开发者而言,这提供了一种无需在纯文本或 Markdown 中额外标记、即可管理人机协作编辑边界的机制。
打开原文相关 3 · 机会 0
media54.1 KB media120.1 KB

中文

面向 Agent 编辑的文本行级归属追溯——这一行是我们写的,还是它们写的?——从文本的版本历史中推导得出。可作为库或 CLI 工具使用。

替代文本

随着 Agent 编程和编辑的普及,内容归属成为一个重要问题。人类编写或编辑过的文本应被视为近乎神圣:Agent 应当保持谨慎,且必须有充分理由才去触碰它。另一方面,另一个 Agent 产出的粗制内容则完全可以随意处理。

一个使用场景是:你有一个主要通过 vibe coding 构建的应用,希望在其中某些代码区域明确表达自己的想法和所有权。你当然不希望下一个会话中的另一个 Agent 直接推平_这一段_代码。

另一个使用场景是 README.md:它最初由模型生成,而你重写了开头几段。Agent 可以自由重做或补充更靠后的部分,但在修改开头的任何内容前,确实应当再三考虑。

这一方案需要满足的主要约束是:不应要求为此专门给文本添加标记。应当原样支持无处不在的纯文本(Markdown)。

因此,唯一可利用的信息是:文本的每个新版本都由可识别的作者创建——要么是人类,要么是 Agent。

对给定文本进行评估后,输出是一组区间——机器生成文本“海洋”中由人类创作的行构成的“岛屿”。从技术上说,这基于简单的 diff,这也是算法开发的指导性隐喻。我们不希望只追踪单独每一行的作者归属,而是要追踪具有连贯意义的文本片段。因此,归属关系的合并、拆分与稀释都需要纳入考量,同时还要避免结果收敛为全是“海洋”或全是“岛屿”。

将 us-vs-them 作为 CLI 工具使用时,需要通过 bbin 在本地安装。

一个 Git 仓库本身就是带有归属标记的版本历史——按顺序记录文件的每个修订版本,以及做出该变更的作者。

在 Git 仓库内任意位置使用:

us-vs-them --ours dan@eighttrigrams.net README.md

将得到类似以下的列表:

1-3          0.00
4            1.00
5-7          0.00
8-20         0.46
21-164       0.00

其中,1.0 表示该区间完全由人类创作。
0.46 表示该区间最初由人类创作,但已在一定程度上被 Agent 修改。
0.00 表示完全由 Agent 创作。

参数如下:

--ours:这些是人类,其他所有人均被视为 Agent。

--theirs:这些是 Agent,其他所有人均被视为人类。

应将人数较少的一方作为参数指定。
同时传入两个参数将被拒绝。

了解其行为的最佳方式,是查看 caution_test.clj。

English / 原文

Line-level provenance for text under agentic editing — who wrote this line, us or them? — derived from a text's version history. Use it as library or as CLI tool.

alt

With agentic coding and editing, provenance becomes a pertinent question. Text a human wrote or edited should be considered close to sacred: an agent should be hesitant and have a very good reason to touch it. Slop another agent has produced, on the other hand, is completely up for grabs.

A use case for this: Take a mostly vibecoded app in which you want to establish some corners in the code where you want to assert your ideas and ownership. You surely don't want another agent bulldoze over this piece of code in the next session.

Another use case: the README.md, originally generated, where you rewrite the opening paragraphs. The agent should feel free to redo or append parts further downwards but should really think twice changing anything in the opener.

The main constraint under which this should work is that this should not require for text to be marked up specifically for that. Omnipresent plain text (markdown) should be supported as is.

The only thing to leverage then, is that each new version of a text is created under identifable authorship - of either a human or an agent.

The output of an evaluation over a given text is a set of ranges — "islands" of human-authored lines inside a "sea" of machine generated text. Technically based on simple diffing, this is the guiding metaphor for development of the algorithm. We don't want to track authorship of individual lines only, but of meaningfully coherent pieces of text. So joining, splitting apart, and dilution of authorship are behaviours to be factored in, also in such a manner that we don't converge in full sea or full island.

Using us-vs-them as CLI tool requires bbin for a local install.

A git repository is already a history of versions each carrying a provenance marker — every revision of the file, in order, with the author of the change that made it.

To use it anywhere inside a git repository:

us-vs-them --ours dan@eighttrigrams.net README.md

This yields a listing like

1-3          0.00
4            1.00
5-7          0.00
8-20         0.46
21-164       0.00

where 1.0 means fully human authored range.
0.46 means originally human authored range, modified by agents to a certain degree.
0.00 means fully agent authored.

Parameters are:

--ours: these are the humans, everonee else is considered an agent

--theirs: these are agents, everyone else is considered human

Name whichever side is the shorter list.
Passing both arguments at the same time will be rejected.

The best way to understand the behaviour is to have a look at caution_test.clj.