CI ran .gitea/ci/commit_message_lint.py, an independent reimplementation that parsed the type/emoji mapping out of docs/common/commit_message.md. Its scope pattern accepted fix(-a), fix(a-), fix(a--b) and fix(_), and it had no subject length check, so the gate that actually blocks merges enforced weaker rules than the Validation this skill reports. The CI entry is now a wrapper that locates the skill validator and delegates to it with no arguments; commit_policy.json becomes the only rule source and explanatory docs stop being a machine policy input. The validator also learns the workflow_run event, whose payload carries neither a PR title nor a before/after range. An upstream pull_request now validates <integration-branch>..head_sha instead of HEAD alone, taking the branch name from COMMIT_LINT_MAIN_BRANCH, and degrades to the upstream head commit with a WARN rather than guessing a base. Alongside: --help now documents the no-argument CI mode it had always supported silently, CI wiring detail moves to references/ci-wiring.md, and the description gains negative boundaries. test/test_commit_message_policy.py asserts policy/spec-table equality and uses ast to assert the CI entry imports no regex and reads no file, so a second implementation cannot reappear unnoticed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
181 lines
8.8 KiB
Markdown
181 lines
8.8 KiB
Markdown
---
|
||
name: commit-message
|
||
description: "当用户需要撰写或审查提交信息、检查已暂存改动、判断是否拆分提交,或使用 emoji 与提交类型(作用域)格式时使用。不用于交互式起草 PR 标题、发布说明或变更日志,不用于照原文执行用户已经给定的提交,也不用于诊断 CI 为什么失败(改用 gitea-fix-ci)。"
|
||
---
|
||
|
||
# Commit Message(提交信息)
|
||
|
||
## 概述
|
||
|
||
根据已暂存的差异生成符合仓库规范的提交信息建议。先确定当前有效的机器策略,
|
||
再判断一次提交的逻辑边界,并在展示任何候选信息前完成校验。
|
||
|
||
本 skill 自带可独立部署的机器资产:
|
||
|
||
- `references/commit_policy.json`:提交信息格式策略。
|
||
- `scripts/validate_commit_message.py`:候选信息和 CI 输入校验器。
|
||
- `references/ci-wiring.md`:把 validator 接到 CI 的方式与事件覆盖范围。
|
||
|
||
以包含本文件的目录作为 skill 根目录解析上述路径。不要假设存在 Playbook checkout、
|
||
仓库 `docs/` 目录或特定的当前工作目录。
|
||
|
||
validator 是提交信息规则的唯一实现。CI 入口只能调用它,不得自行实现校验,也不得
|
||
从说明性文档解析 type/emoji 等规则;说明性文档是给人读的,不是机器策略来源。
|
||
|
||
## 适用场景
|
||
|
||
以下情况使用本 skill:撰写提交信息、审查已暂存边界、判断是否拆分提交,或处理
|
||
`emoji/type(scope): subject` 格式。
|
||
|
||
交互式起草 PR 标题、发布说明、变更日志,以及执行用户已经明确给出的原文,不使用
|
||
本 skill。validator 的无参数 CI 模式可以把 `pull_request.title` 当作独立输入校验;
|
||
这不表示交互式 commit-message 工作流负责起草 PR 标题。
|
||
|
||
## 输入
|
||
|
||
- 暂存状态:`git status --short` 和 `git diff --cached`。
|
||
- 暂存内容指纹:
|
||
`git diff --cached --binary --no-ext-diff | git hash-object --stdin`。
|
||
- 未暂存状态,必须与已暂存差异分开检查。
|
||
- 适用的项目指引和机械约束,例如 hook、CI 或显式机器策略。
|
||
- 本 skill 目录中的 bundled policy 和 validator。
|
||
|
||
## 有效策略
|
||
|
||
validator 按以下固定优先级选择机器策略:
|
||
|
||
1. 命令行 `--policy <path>`。
|
||
2. 环境变量 `COMMIT_POLICY_PATH`。
|
||
3. 本文件旁的 `references/commit_policy.json`。
|
||
|
||
同时读取适用的项目指引、hook 和 CI 约束;它们用于发现冲突,但不会改变上述路径
|
||
优先级。需要让项目规则成为机器策略时,必须通过前两项之一显式选择对应 JSON。
|
||
policy 的 `emoji.requirement_env` 未设置时使用 `required_by_default`;设置成
|
||
非空 `false_values` 中任一值时关闭要求,设置成其它值时开启要求。空
|
||
`false_values` 属无效 policy。
|
||
|
||
显式机器策略与 bundled 默认值不一致时,必须在结果中说明。不要从说明性文件中
|
||
推断规则覆盖。bundled policy 缺失、损坏或版本不支持时,应报告部署错误,不能
|
||
悄悄退回到自行编造的 Conventional Commits 约定。
|
||
|
||
## 流程
|
||
|
||
1. **基线状态**
|
||
|
||
分别检查已暂存和未暂存改动,记录完整 cached diff 的上述指纹。如果没有任何
|
||
已暂存改动,停止并说明无法根据实际差异生成最终建议。只有用户明确要求时,才
|
||
可以提供基于未暂存内容的草稿。
|
||
|
||
2. **判断提交边界**
|
||
|
||
找出主要意图,以及保证该意图正确所必需的文件或 hunk。如果同一文件内存在多个
|
||
无关 hunk,也必须按 patch 边界拆分,不能只按文件归组。如果已暂存改动包含互不
|
||
相关的意图,按顺序列出拆分组并为每组给出独立信息。在用户明确选择不拆分前,
|
||
不要用一个主题掩盖多个意图。
|
||
|
||
3. **起草信息**
|
||
|
||
对单一意图给出一个具体建议。只有存在实质不同且均有效的 type 或 scope 解释时,
|
||
才增加备选项。只有在说明动机、影响、验证、任务链接或破坏性变更时,才添加正文
|
||
或 footer。
|
||
|
||
4. **校验候选信息**
|
||
|
||
使用 Python 3.10 或更高版本。根据本文件位置解析 skill 根目录,对每一个候选主题
|
||
以进程 API 的 `argv` 参数数组运行 validator:
|
||
|
||
```text
|
||
argv = [
|
||
"<python3>",
|
||
"<skill-root>/scripts/validate_commit_message.py",
|
||
"--subject",
|
||
"<candidate>",
|
||
]
|
||
```
|
||
|
||
路径和候选必须分别作为 argv 元素传入;禁止把候选拼接到 shell 命令字符串中。
|
||
Linux/macOS 通常使用 `python3`,Windows 使用当前环境可用的 Python 3 入口。
|
||
|
||
对提交信息文件可使用 `--message-file <path>`,但该模式只校验首行主题,不机械
|
||
校验 body/footer;结果中的 `Validation` 必须明确这一边界。如果项目指引要求使用
|
||
bundled policy 之外的策略,传入 `--policy <path>`;否则让 validator 使用随 skill
|
||
携带的 JSON。无参数的 CI 模式不能代替对新起草候选的 `--subject` 校验;其专用
|
||
约束见下文“CI 输入校验”。
|
||
|
||
5. **一致性复核**
|
||
|
||
最终确定前重新运行 `git status --short` 和 cached diff 指纹。任一结果发生变化时,
|
||
重新阅读差异、判断边界并重新校验候选信息;不要只比较文件名或 diff stat。
|
||
|
||
6. **🔴 CHECKPOINT · 🛑 STOP:等待执行授权**
|
||
|
||
明确标注结果是建议还是最终选择,然后停止。只有用户在审阅建议后明确授权具体
|
||
动作,才执行该动作:授权 `git commit` 不等于授权暂存或重组 index;授权调整
|
||
index 也不等于授权提交。未获得相应授权时,不运行 `git commit`,不暂存文件,
|
||
不修改 index。
|
||
|
||
## CI 输入校验
|
||
|
||
无参数运行 validator 即进入 CI 输入校验:从事件 payload 取回全部待校验主题,只有
|
||
未识别事件或本地调用才回退 `HEAD`。已识别事件缺失或损坏 payload 时必须失败;
|
||
shallow repository 一律失败;不能用可能截断的 payload `commits` 数组或计数字段
|
||
证明范围完整。
|
||
|
||
覆盖哪些事件、每种事件取回什么范围、以及可信编排要求见
|
||
`references/ci-wiring.md`。接线或排查前先运行
|
||
`validate_commit_message.py --help`,以脚本当前输出为事件覆盖范围的权威。
|
||
|
||
## 输出约定
|
||
|
||
以下固定字段名保留英文,以兼容已有调用方;字段内容使用中文:
|
||
|
||
单一意图必须包含:
|
||
|
||
- `Detected`:已暂存文件、主要意图,以及是否需要拆分。
|
||
- `Spec`:使用的 bundled 或显式机器策略,以及项目机械约束冲突。
|
||
- `Proposed`:一个已经校验通过的主题;确有必要时附正文或 footer。
|
||
- `Validation`:validator 命令及其结果。
|
||
- `Notes`:歧义、剩余风险或实质不同的备选解释。
|
||
|
||
多个意图必须包含 `Detected`、按顺序排列的 `Split` 分组以及 `Notes`。每个 `Split`
|
||
分组都必须包含:
|
||
|
||
- `Files/Hunks`:文件及具体 hunk/patch 边界;同一文件可出现在不同组。
|
||
- `Intent`:该组唯一的逻辑意图。
|
||
- `Spec`:该组候选使用的机器策略和冲突。
|
||
- `Proposed`:该组已经校验通过的独立主题。
|
||
- `Validation`:该组实际运行的 validator argv 和结果。
|
||
|
||
在用户明确选择不拆分前,不要给出合并后的 `Proposed`。任何组未校验通过时,不得
|
||
把整份拆分建议标为已验证。
|
||
|
||
## 危险信号(Red Flags)
|
||
|
||
出现以下任一情况时停止并纠正,不能继续生成最终建议或执行动作:
|
||
|
||
- **混淆 staged 与 unstaged**:用工作树 diff 代替 cached diff,或在无 staged diff
|
||
时把未暂存草稿标为最终 `Proposed`。
|
||
- **用摘要代替边界审查**:只看文件名或 diff stat,不读取完整 cached diff 和相关
|
||
hunk;同一文件中的无关意图因此被错误合并。
|
||
- **伪造校验完成**:仅手工检查格式,或运行无参数的 HEAD/CI 模式,却声称候选主题
|
||
已通过 validator。
|
||
- **忽略状态漂移**:cached diff 指纹或状态已变化,仍沿用旧意图判断和旧候选。
|
||
- **越权执行**:为了实现拆分而自行改 index,或把提交授权、暂存授权和 index 重组
|
||
授权视为同一个许可。
|
||
|
||
## 成功标准
|
||
|
||
- 建议准确描述当前已暂存差异,而不是猜测用户意图。
|
||
- 每个候选都使用 bundled 或显式选定的策略完成校验。
|
||
- 混合改动得到明确的拆分建议。
|
||
- 暂存状态或完整 cached diff 指纹变化会触发重新基线和重新判断。
|
||
- 未经明确授权,不执行提交、暂存或 index 写入。
|
||
|
||
## 失败处理
|
||
|
||
- 没有已暂存差异:说明限制,并停止生成最终的差异型信息。
|
||
- policy 或 validator 缺失/无效:报告部署或配置错误。
|
||
- 候选无效:报告 validator 原因,不把它标记为合规信息。
|
||
- 意图混合或无法判断:建议拆分并说明边界依据。
|
||
- 审查期间项目状态变化:重新执行基线和边界判断。
|