Easydict Agent 提交结果统一报告:基于 Git numstat 的确定性统计与回执契约实践
2026/9/23 5:14:03 网站建设 项目流程

Easydict Agent 提交结果统一报告:基于 Git numstat 的确定性统计与回执契约实践

【免费下载链接】Easydict一个简洁优雅的词典翻译 macOS App。开箱即用,支持离线 OCR 识别,支持有道词典,🍎 苹果系统词典,🍎 苹果系统翻译,OpenAI,Gemini,DeepL,Google,Bing,腾讯,百度,阿里,小牛,彩云和火山翻译。A concise and elegant Dictionary and Translator macOS App for looking up words and translating text.项目地址: https://gitcode.com/gh_mirrors/ea/Easydict

导读

本文围绕 Easydict 仓库中一次面向 Agent 工作流的工程治理改进展开:当 AI Agent(如 Codex)在本地自动执行git commitworktree分支集成后,如何向用户输出一份可复算、可核验、格式统一的提交结果回执。文中将完整拆解git-commitSkill 的提交后报告契约、基于 Git numstat 的确定性文本行统计脚本(含代码/文档互斥分类与二进制静默跳过规则),以及worktree-rebase-mergeSkill 如何复用该契约补充提交来源与集成状态。读完本文,你将掌握一套可迁移到任意 Git 仓库的"提交结果统一报告"设计:统计可复算、回执字段固定、多工作流不重复维护模板。


一、背景:为什么需要"统一提交结果报告"

在 Easydict 的 Agent 协作体系中,AI Agent 被授权在本地执行自动提交与分支集成。改进之前的痛点有两个:

  1. 信息被压缩:自动本地提交已经成功执行时,Agent 的最终回复可能只显示短哈希和标题,用户无法确认提交动作与完整提交内容;
  2. 跨工作流报告不一致worktree-rebase-merge另外维护了更严格的展示要求,导致同一个提交在两个工作流(普通提交 vs. worktree 集成)中呈现的报告详细程度不一致。

该问题的完整背景记录在 执行计划 与对应的 完成历史 中。其核心解法是:git-commitSkill 统一定义"成功提交后的用户可见结果",其他调用方(如 worktree 集成流程)只复用该契约,并补充各自的领域事实。

为什么不是简单"写长一点"?

背景中明确指出了根因——两套工作流各自维护展示模板,属于典型的"契约漂移"。如果只是把其中一套写得更详细,另一套仍然会退化为短哈希 + 标题。因此本次改进的核心设计原则是:

  • 唯一来源(single source of truth)git-commit是提交结果、统计数据和单提交实际信息的唯一格式来源;
  • 只读真实数据:所有回执字段必须来自 Git 真实对象(git rev-parsegit showgit status等),不允许 Agent 凭记忆或推断填写;
  • 可复算统计:变动统计由脚本从 Git 原始数据(numstat)计算,而非 Agent 主观估计。

二、任务契约:目标、边界与验收标准

执行计划为本次改进定义了严格的任务契约(原文档对应章节):

用户目标

统一提交后的用户可见结果,并增加总变动、代码变动和文档变动三组信息。

允许动作与修改路径

  • 修改仓库 Agent 指南、git-commitworktree-rebase-mergeSkill;
  • 增加统计脚本、行为测试、执行计划和完成历史;
  • 允许修改路径限定为:
    • .agents/skills/git-commit/(Skill 本体、脚本、测试、参考文档);
    • .agents/skills/worktree-rebase-merge/SKILL.md
    • docs/agents/repository-guide.md
    • 本执行计划和完成历史。

预期交付物

  1. 唯一提交后报告契约;
  2. 确定性文本行统计(可复算);
  3. 可复用的提交说明。

验收标准

统计可复算,行为测试和静态检查通过。

目标清单(原文档原文要点)

  • git-commit统一定义成功提交后的用户可见结果;
  • 明确区分本次创建提交复用源分支已有提交
  • 展示完整提交哈希、完整实际提交信息、工作树状态和 push 状态;
  • 展示可复算的总变动、代码变动和文档变动文本行数;
  • 静默忽略二进制文件,不在最终结果中显示二进制统计。

非目标(边界声明)

  • 不修改产品代码、构建配置或运行时资源;
  • 不改变 staging、commit、rebase、merge 和 push 的授权边界;
  • 不为单一案例复制第二套提交展示模板。

注意"非目标"的意义:这是一次纯粹的Agent 工作流 / 交付协议层治理,不触碰 Easydict 的 Swift/ObjC 产品代码。这也是后续验证环节明确"未运行xcodebuild"的原因。


三、确定性变动统计:commit-change-stats.py 深度解析

本次改进的核心交付物之一是统计脚本 commit-change-stats.py。它只依赖Python 标准库 + Git CLI,不引入第三方依赖,因此可在任意具备 Python 3 与 Git 的机器上直接复算。

3.1 用法:单提交与多提交范围

单提交统计(默认HEAD,也可传入任意 revision):

python3 "<git-commit-skill-dir>/scripts/commit-change-stats.py" <full-commit-hash>

多提交范围统计(三圆点BASE...SOURCE集成区间):

python3 "<git-commit-skill-dir>/scripts/commit-change-stats.py" \ --range <target-commit>...<source-commit>

参数约束(源码parse_arguments,L166-L186):

  • revision为可选位置参数,默认HEAD
  • 使用--range时不允许再传位置参数,否则报错do not combine a positional revision with --range
  • --range强制使用BASE...SOURCE形式,两侧分别通过git rev-parse --verify <rev>^{commit}解析为完整对象 ID,非法 revision 会以非零退出码报错到 stderr。

3.2 数据来源:rename-aware numstat

脚本从 Git 获取原始变动数据(L85-L92):

  • 单提交:git show --format= --numstat -z --find-renames <revision>
  • 多提交范围:git diff --numstat -z --find-renames <base>...<source>

两个关键设计点:

  1. -zNUL 分隔:正确处理含空格、中文等特殊字符的文件路径(这是行为测试覆盖的边界之一);
  2. --find-renames重命名检测:numstat 输出中重命名记录的第一个字段为空,parse_numstat会跳过源路径字段、只取目标路径用于分类(L111-L116),因为"重命名后的目标路径"才是分类依据。

3.3 代码 / 文档互斥分类规则

is_documentation函数(L128-L141)定义文档类别的判定,使用PurePosixPath归一化路径并统一小写比较:

规则维度命中即归为docs
目录路径任意父目录名为docsdocumentation
固定文件名AGENTS.mdSKILL.md
文件名前缀readmechangelog开头(不区分大小写)
扩展名.md.mdx.rst.adoc

其余所有文本文件(源码、测试、构建/运行时配置、资源、Skill 脚本等)归为code。两条类别互斥且穷尽:总计必须严格等于code + docs之和,这是"可复算"的数学基础。

3.4 二进制静默跳过

Git numstat 对二进制文件记录为-(新增/删除字段均为-)。collect_stats在解析时遇到该标记直接continue(L150-L151),既不参与统计,也不出现在用户可见报告中——这与任务目标中"静默忽略二进制文件"完全一致。

3.5 稳定 JSON 输出

脚本最终输出一份sort_keys=Trueensure_ascii=False的稳定 JSON(L205-L218):

{ "code": { "deletions": 2, "files": 1, "insertions": 8, "net": 6 }, "docs": { "deletions": 13, "files": 4, "insertions": 60, "net": 47 }, "revision": "<full-commit-hash>", "scope": "commit", "total": { "deletions": 15, "files": 5, "insertions": 68, "net": 53 } }

每个类别包含files / insertions / deletions / net四个字段,net = insertions - deletions。JSON 输出保证了后续任何调用方(Agent、CI、脚本)都能以结构化方式消费统计结果,而非解析人类文本。

3.6 错误处理

所有 Git 调用失败(无效 revision、不可读变更集、格式异常的 numstat 记录)都会抛出ChangeStatsError,主函数打印error: <message>到 stderr 并返回退出码 1。这意味着:脚本失败时绝不编造统计——该约束同时写入报告契约("脚本失败或数字不一致时不编造统计")。


四、唯一提交后报告契约:reporting.md 与回执模板

统计脚本只解决"数字从哪来"的问题,而"回执长什么样"由 reporting.md 定义。

4.1 回执证据的采集(创建提交后)

报告契约要求创建提交后收集以下五项证据:

证据命令用途
完整哈希git rev-parse HEADCommit 字段
完整实际提交信息git show -s --format=%B HEAD实际提交信息区块
当前分支git branch --show-current分支字段
最终工作树状态git status --short工作树字段(干净 / 保留未提交变更)
变动统计commit-change-stats.py统计表

4.2 用户可见回执的固定字段

契约规定回执必须完整保留以下字段(中文任务使用中文标签,英文任务翻译标签但保留字段与顺序):

提交结果 - 动作:已创建提交 - Commit:`<full-hash>` - 分支:`<branch>` - 提交后校验:`<validation-status>` - 工作树:`干净` or `保留未提交变更` - Push:未执行 变动统计 | 类别 | 文件数 | 新增行 | 删除行 | 净变动 | | --- | ---: | ---: | ---: | ---: | | 总计 | <files> | <insertions> | <deletions> | <signed-net> | | 代码 | <files> | <insertions> | <deletions> | <signed-net> | | 文档 | <files> | <insertions> | <deletions> | <signed-net> | 实际提交信息 ```text <exact output of git show -s --format=%B HEAD> ```

净变动的符号约定:正值+N、负值-N、零值0(无变化)。代码块中的提交信息必须与 Git 输出完全一致,不允许美化或改写。

4.3 完整回执示例

post-commit-report-example.md 给出了可直接替换占位符的完整示例,其中体现了三个值得注意的细节:

  1. 双语文案提交信息:Easydict 遵循 Angular 风格的双语提交(中文主体 + 英文标题区块),回执中的"实际提交信息"原样保留这一格式;
  2. 统计表与 JSON 对齐:示例中总计 5 文件 / +68 / -15 / 净 +53,恰好等于代码(1 文件 / +8 / -2 / 净 +6)与文档(4 文件 / +60 / -13 / 净 +47)之和,直观演示了"总计 = 代码 + 文档"的可复算约束;
  3. Push 边界git-commitSkill 明确不执行git push、rebase 或 merge(见 SKILL.md 任务与边界表),因此回执中 Push 恒为"未执行"。

4.4 与提交主流程的衔接

报告契约不是独立存在的,它位于 git-commit 提交主流程 的末尾环节:

起草消息 → 展示完整预览 → 写入任务专用消息文件 → 校验消息 → git commit -F <message-file> → 以新建完整 commit hash 做提交后一致性校验 → 删除消息文件 → 读取 reporting.md 按真实结果交付

其中"提交后一致性校验"用于确认 Git 实际写入的 message 与预览一致(防止 hook 改写或内容漂移)。校验失败时保留消息文件、不 amend、不声称交付完成,确保回执中的"提交后校验"字段真实可信。


五、worktree-rebase-merge:复用契约并补充集成事实

单提交场景的契约统一后,剩下的问题是:worktree 集成场景如何复用而不复制模板?worktree 集成回执 给出了分层答案。

5.1 两层回执结构

worktree 集成完成后的回执分为两层:

第一层:集成结果(由worktree-rebase-merge补充的领域事实)

  • 源分支、目标分支和目标 checkout;
  • 源提交数与集成模式:direct-commitexisting-target-worktreetemporary-target-worktree
  • Rebase、Merge 和 Push 的实际状态(直接提交时三者明确写"未执行");
  • 源/目标 worktree 的最终状态、临时 worktree 路径与清理结果;
  • 原始 detached commit、源分支是创建还是复用

第二层:提交回执(复用git-commit契约,不重新起草)

5.2 单提交与多提交的差异化处理

  • 恰好一个源提交:在集成结果后完整附加git-commit回执(含统计表和完整实际信息),但动作字段按提交来源改写:
    • created-this-run→ 写"已创建提交";
    • preexisting-source-commit→ 写"本次未创建新提交;合并的是源分支已有提交",提交后校验写"未执行(本次复用已有提交)",但仍保留完整 hash、统计、实际信息、最终状态和 Push。
  • 多个源提交:先列出每个完整 hash 和 subject,再调用git-commit汇报冻结范围并生成统计;因为范围没有单一提交信息,绝不用其中一条 message 代表整个范围

5.3 冻结范围的时间点

多提交统计有一个易踩的坑:如果目标分支在集成后已经前进,BASE...SOURCE范围可能读出空结果。因此契约规定:多提交统计使用"合并前冻结的目标 OID"与"rebase 后源 OID",避免目标已前进后读出空范围。这体现了整个设计对"可复算"的坚持——统计数字必须与用户看到的集成动作发生在同一时间点。

5.4 职责划分原则

git-commit是提交结果、统计和单提交实际 message 的唯一格式来源worktree-rebase-merge只补充集成事实。

这是整个方案的分层核心:展示层契约收敛到一个 Skill,领域层事实由各工作流自行补充,杜绝了"第二套提交展示模板"的出现(对应非目标中的第三条)。


六、行为测试与验证:用临时仓库验证真实输出

"确定性统计"不能只靠设计,必须有测试兜底。测试文件为 test_commit_change_stats.py,其特点是以Python 标准库unittest+ 临时 Git 仓库运行真实命令、校验真实输出,而非 mock。

执行方式:

python3 .agents/skills/git-commit/tests/test_commit_change_stats.py

6.1 测试覆盖的边界场景

结合完成历史与计划"进度"章节,6 个行为测试覆盖:

场景验证点
混合文件代码与文档分类互斥、总计 = 两类之和
分类规则目录、文件名、扩展名各维度的 docs 判定
重命名rename-aware 解析、目标路径分类正确
中文和空格路径-zNUL 分隔下路径解析正确
删除删除行统计与净变动符号
多提交区间--range聚合统计
空提交与无效 revision错误路径行为(非零退出码、不编造统计)

6.2 完整的验证清单

执行计划的"验证"章节列出了本次改进的完整验收证据:

  • 统计脚本 6 个行为测试全部通过;
  • Python 语法检查通过;
  • 统计脚本对真实历史提交试运行通过,代码、文档和总计可复算;
  • 两个 Skill 的报告字段、提交来源分类和 Push 边界通过静态检查;
  • git diff --check通过(无空白错误);
  • 未运行xcodebuild——因为未修改产品代码、测试或 Xcode 工程元数据(与"非目标"边界一致)。

七、决策记录:关键设计取舍

执行计划的"决策记录"沉淀了四条可复用的工程决策:

日期决策理由
2026-08-21代码与文档分类互斥,总计必须等于两类之和保证统计可复算、可审计
2026-08-21二进制 numstat 记录静默跳过,不进入用户可见报告避免噪声,聚焦文本变动
2026-08-21单提交集成复用git-commit报告;多提交集成报告完整提交列表和区间统计唯一契约 + 范围事实
2026-08-21统计脚本只依赖 Python 标准库和 Git,测试使用临时仓库验证真实输出零第三方依赖、零 mock、结果可信

八、在 Skill 资产体系中的定位

要理解这套 Skill 为何可以独立演进,需要知道 Easydict 的 Skill 资产管理策略(见 docs/agents/skills.md):

  • 外部仓库统一维护通用内容,skills-lock.json登记的目录是外部权威内容的完整项目快照,可离线读取和运行;
  • lock 记录来源、ref、入口路径和内容哈希,通过重算检查本地漂移;
  • 通用 Git、Review 和交付算法由受管 Skill维护,不通过本地修补或 fork 改写;Swift/Xcode、本地化和发布等项目政策则写入宿主规则。

git-commitworktree-rebase-merge属于来源基线tisfeng/skills(v0.6.3 采用范围中的六个 Skill 之二)。这套"唯一报告契约"的设计因此具备了跨项目复用的能力——任何引入该 Skill 的仓库都能获得相同的提交回执体验。


九、完成条件与归档

执行计划以明确的"完成条件"收尾,它们同时也是验收时的行为断言:

  1. 成功提交后不能再用短哈希和标题代替完整结果;
  2. 用户可见结果包含:完整哈希、完整消息、工作树、push 和三组文本变动统计;
  3. worktree 流程能够准确说明本次创建提交还是复用已有提交
  4. 计划已归档,并在docs/histories/记录结果。

对应的归档产物为 执行计划(状态completed,负责人 Codex,关联 Issue/PR 为 none)与 完成历史。其中完成历史额外记录了"设计意图":让git-commit成为单提交结果的唯一报告契约,避免调用工作流各自维护不一致的模板;文本行统计由可测试脚本从 Git 原始数据计算,worktree-rebase-merge只补充提交来源和集成状态。


十、总结:这套方案的可迁移价值

Easydict 的这次治理改进,本质上是把"AI Agent 交付结果"从不可控的自然语言变成了可复算、可审计的结构化协议。其可迁移到其他仓库/团队的要点可以归纳为三条:

  1. 契约收敛:所有调用方共享同一个回执契约与统计脚本,杜绝"每个工作流一套模板"的漂移;
  2. 数据只读真实:回执字段全部来自 Git 真实对象(rev-parse/show/status/ numstat),脚本失败或数字不一致时宁可报错也不编造;
  3. 职责分层:展示层(git-commit)与领域层(worktree-rebase-merge的集成事实)各司其职,单提交复用统一报告、多提交补充范围列表与区间统计。

对于正在构建 Agent 自动化交付体系(自动 commit、自动 PR、worktree 集成)的团队,本文中的分类规则、回执模板、冻结范围时间点与临时仓库测试方法,都可以直接作为设计参考。

【免费下载链接】Easydict一个简洁优雅的词典翻译 macOS App。开箱即用,支持离线 OCR 识别,支持有道词典,🍎 苹果系统词典,🍎 苹果系统翻译,OpenAI,Gemini,DeepL,Google,Bing,腾讯,百度,阿里,小牛,彩云和火山翻译。A concise and elegant Dictionary and Translator macOS App for looking up words and translating text.项目地址: https://gitcode.com/gh_mirrors/ea/Easydict

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询