context-infra 检查与复盘infra.guiming.net · 全内容自包含呈现 · 生成于 2026-07-21 16:28 UTC

workflow_version_evolution

Z3 全文↑ Z2 条目

道-方法 · 道层 skill 全文

← 返回道层 skill 索引 · 返回方法论区

本页是 <code>rules/skills/workflow_version_evolution.md</code> 的逐字投影(仅隐私清洗,零改写)。

时点提示:本页是仓内文件 rules/skills/workflow_version_evolution.md 的逐字投影(仅做隐私清洗:仓库根绝对路径→相对路径、家目录→~/;除此零改写)。若源文件后续有修订,以仓内真源为准。

Workflow: 版本演进 SOP

元数据

1. 这份 SOP 干什么

任何「对外承诺」(被读 / 被引用 / 被脚本依赖 / 必读约束)发生变化时,本 SOP 告诉你:

事件触发,agent 直接判定。不投票,不喂 JSON 模板,不列穷举清单。

2. 核心判据(只有一个问题)

「这次改完,下游有没有人或脚本必须跟着改自己?」

「大改」「小改」不是行数。1 行 YAML 反转可能是 X,500 行重排版可能不打。判的是下游负担。

「接口」不只是显式 API、CLI 参数、字段。长期可观察行为(INDEX 顺序、文件路径、reason 措辞惯例、目录结构)也算接口 — 下游已无声依赖,破坏即 X。

3. 事件分类(什么时候触发判定)

事件来自三种情境:

情境现场表现默认动作
调研写入在同一份调研/设计文档持续追加内容中间过程不定版;一轮调研闭环(结论收敛 / 决定继续 / 决定放弃)时定一版
新建文件创建一份新文件看是否被外部读/引用/校验 — 是则按 Y 处理。Schema 类例外:约束新生产方 = Y;强制既有消费方重新解析 = X
修改已发布文件改一份已被引用/必读的文件默认进入版本判定,按 §2 判 X/Y/不打。修改 = prompt 明确要求改/增/删;纯讨论 / 质疑 / 征询不算修改 → 不触发

「调研型 prompt」(请你调研 / 思考 / 提案 / 评估)本身不触发版本号。等真的产出落地、形成可被引用的产物时再定版。强主张原则但没要求当下写入已发布文件 → 不触发,等下一个真正写入的 prompt 来时再判

4. 文档类型 × 接口定义(查表速记)

每类对外承诺的「接口」是什么、X/Y 各对应什么:

类型「接口」是什么X 级(必须改)Y 级(兼容扩展)
代码(脚本/CLI/库)函数签名 / CLI 参数 / 配置 key / 错误码 / 副作用删参数、错误码反转、可逆变不可逆加可选参数、新导出函数、扩错误码
设计 / 规则文档核心结论 / 边界假设 / 强制约束(MUST)推翻原结论、约束语气从 SHOULD 变 MUST、删硬规则段新增约束不推翻原结论、补充论证
调研文档当前轮的最终结论新证据推翻原结论补充证据但结论不变
Skill 文档触发条件 / 步骤序列 / 输出格式 / 验收标准触发条件反转、必选步骤变可选/反之、删输出字段新增可选步骤、扩触发场景、补充验收维度
Schema(YAML/JSON/SQL DDL)字段、字段值代表的策略、约束(required/enum)删字段、字段值反转策略、required 加严、列删/改名加可选字段、扩 enum、新增表

INDEX / 路由文件按「设计 / 规则文档」处理。重排导航 = X,追加条目 = Y。

「设计/规则文档」典型样例包括 CLAUDE.md / AGENTS.md 的强制要求段、cron 表(config/CRONTAB.md)、Claude Code hook 配置(settings.json 的 hooks 段)、以及任何被 LLM 启动时必读的「配置即承诺」类文件。它们的接口是「读者必读的强约束 + 调度时机/参数」 —— 改一句话整体行为反转。形式上不一定是 Markdown,YAML / JSON 配置只要承担「LLM 必读」职责就归这一类。

记不清类型时,回到 §2 那一句话即可。

5. 现场(事件刚发生)

写入前(手上有 prompt 和计划,还没动 commit):

判一次预判 — 是 X 还是 Y 还是不打。预判记在 task 笔记或 todo 里。落地后回头核对:实际 diff 与预判一致吗?不一致就以 diff 为准。

写入后未 tag(commit 已落或 stop hook 已自动 commit):

版本号管理由独立 sub-agent 负责。主 agent 协调多个 sub-agent 完成任务时,最后派一个 version-manager sub-agent(用 Opus)按本 SOP 统一处理:

  1. 扫描本轮所有内容性 sub-agent 的产出(文件改动、commit message、changelog 里可能写入的版本号字样)
  2. 按本 SOP 事件分类 + 文档类型 + 等级判据校核每处
  3. 与本 SOP 不符就改(覆盖其他 sub-agent 的误改)
  4. 决定本轮是否打 git tag、tag 名、reason 三段

放最后是为了让 version-manager 看到全貌;放中间会被后续 sub-agent 的改动绕过。单 agent 任务则主 agent 自己按 SOP 判定,不必派 version-manager。

按 §2 判一次。Y 级 agent 直接 git tag -a 0.Y -m "<reason>"。X 级也由 agent 自行判定并写清 reason;如果当前载体无法安全打 tag(例如文件未 commit、非 git 载体未落定、或工作区状态不支持),就在对应 VERSION_LOG / 调研报告 / todo 中记录 tag 建议和阻塞原因,等载体可用时由自动化或后续 agent 继续处理。

commit_subject 匹配 ^rescue:|^cleanup:.recovery|^chore.accumulated → 内容已在 session ref 里,合并到 main 不算新发布,不打版。

6. 后补(扫历史时)

后补不是上帝视角。看 git 历史 / session 记录给每个事件反推版本号时,按那个时间点的可见信息判 — 结合文件创建/修改时间 + 当时的 prompt + 当时的 diff + 当时其他文件状态判,把后续事件 mask 掉。不要用「我知道这方案后来真的实施了」反推「当时就该判 minor」。每个事件落到当时的「时间切片」里看,跨切片的因果不影响切片内的判定。这样保证时间一致性,避免用后果倒推动机。

发现一段历史完全没打版本号、要批量回填时走这套流程。

第一步:识别大改。按 §2 / §4 扫每个 commit 找 X 候选。这些是叙事骨架,每个独立打一个 tag。

第二步:合并近邻小改。剩下的小修补按下面规则聚类:

第三步:模糊时按低位归类。拿不准是 X 还是 Y → 先按 Y 打,reason 里点一句「可能为 X,按 Y 先归档并写明不确定点」。后补阶段重要的是叙事连贯,不是单点精确。

后补的输入可以是 commit subject + per-file numstat、用户当时 prompt 原文、changelog 笔记。任一够用即可,不强求格式。diff 行数用 per-file numstatgit show --numstat),不用 commit-total(避免无关文件被合算 — 实证教训:曾把 git_safety 2 行误判成 942 行)。

7. 等级与命名

等级:只有 X 和 Y 两级。无 patch、无 rc/beta、无模块子版本号。ZeroVer 期 X 永远 0,Y 单调递增。X-bump 事件由 reason 第一句承担语义(不真把 X 从 0 改 1)。脱离 ZeroVer 由人显式宣布 1.0,条件是本仓库之外的人或系统开始依赖。

命名(默认):仓库级一条主版本号线,载体是 git annotated tag。git tag -a 0.Y -m "<reason>"

非 git 载体:SQL DDL 文件、独立 Markdown 库、跨工具配置目录、纯文档项目等可把「git annotated tag」替换为载体原生承载方式(CHANGELOG 行 / 文件名后缀 _v0.7.md / schema 注释 / commit footer 等)。形式可换,等级语义(X/Y/不打)和 reason 三段写法不变

命名(例外)

跨项目一致X.Y 两级 + git annotated tag + reason 三段式 + 调研后缀约定,所有 zlxbjtu 个人项目都用这一套。换项目不换形式。

8. reason 三段写法

固定顺序,下游一眼能判:

<下游必须做什么>。<改了什么(接口层面)>。<为什么改>。

major 示例:

调 git 的自动化脚本要审视是否遵守"父 repo 不操作子 repo .git"。git_safety.md §4 新增「嵌套 git repo 边界」段,列出已知嵌套 repo 与边界契约。weclaude/ 嵌套 repo 的 .git 被父 repo 误识为 gitlink,破坏 stop hook 提交流程。

minor 示例:

调用方无需改动。tools/git/AGENT_GUIDE.md 新增 sandbox merge 章节,描述合并流程但不改既有约定。给新成员降低上手门槛。

9. 不写什么(负面清单)

为避免过度工程化,明确不做以下事:

10. 自检(打 tag 前过一遍)

  1. 这次变化触发了哪种事件(调研写入闭环 / 新建对外文件 / 修改已发布文件)?
  2. 涉及的文档落在 §4 哪一类,它的「接口」是什么,这次动了接口的哪部分?
  3. 下游必须改自己吗 → X / Y / 不打?
  4. reason 三段是否齐全?「下游必须做什么」是不是写在第一句?
  5. tag 名是仓库级 0.Y 还是调研后缀 0.Y-research-<topic>

5 个全 yes 就 git tag -a 走起。任一不确定 → 按低位归类(Y)+ reason 注明不确定点 + todo 加一条后续 agent 审查项。

11. EvolutionRecord 指针(2026-07-02 S6)

tools/evolution_workflow/record.pyEvolutionRecord.version_decision 只记录本 SOP 对该更新的 X / Y / none 结果、路径和理由;它不改变本 SOP 的判定语义,也不替代打 tag。若任务明确禁止 commit/tag/stage/push,仍可在 record 中写入 level: Ylevel: none 作为审计证据,但实际 tag 操作必须留待允许写 git metadata 的后续流程。


← 返回道层 skill 索引 · 返回方法论区