@erzhe/harness-kit 0.1.3 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +74 -20
- package/SPEC-v0.md +108 -18
- package/dist/harness-kit.cjs +10486 -4062
- package/package.json +4 -2
- package/skills/erzhe-harness-init/SKILL.md +113 -75
- package/skills/harness-check-loop/SKILL.md +65 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@erzhe/harness-kit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "AI-friendly repo harness: a manifest.yaml single source of truth that generates AGENTS.md / CLAUDE.md / Cursor rules and enforces invariants, contracts and drift via `harness-kit verify`.",
|
|
6
6
|
"keywords": [
|
|
@@ -48,12 +48,14 @@
|
|
|
48
48
|
"prepare": "pnpm build"
|
|
49
49
|
},
|
|
50
50
|
"dependencies": {
|
|
51
|
-
"commander": "^
|
|
51
|
+
"commander": "^13.1.0",
|
|
52
52
|
"fast-glob": "^3.3.3",
|
|
53
|
+
"picomatch": "^4.0.2",
|
|
53
54
|
"yaml": "^2.9.0"
|
|
54
55
|
},
|
|
55
56
|
"devDependencies": {
|
|
56
57
|
"@types/node": "^26.1.0",
|
|
58
|
+
"@types/picomatch": "^4.0.2",
|
|
57
59
|
"esbuild": "^0.28.1",
|
|
58
60
|
"tsx": "^4.22.5",
|
|
59
61
|
"typescript": "^6.0.3"
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: erzhe-harness-init
|
|
3
|
-
description: 给一个仓库接入 harness-kit —— 引导 agent
|
|
3
|
+
description: 给一个仓库接入 harness-kit —— 引导 agent 做仓库考古、保真迁移现有 agent 规则、把隐性工程知识翻译成 .agents/manifest.yaml,再用 sync/doctor/verify 和会话证据验证到绿。当用户说"给这个仓库配置 harness / 初始化 AI 脚手架 / 生成 AGENTS.md 契约层"时使用。
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# erzhe-harness-init
|
|
7
7
|
|
|
8
|
-
把**当前仓库**改造成 agent
|
|
8
|
+
把**当前仓库**改造成 agent 友好:保全既有规则,产出填好的 `.agents/manifest.yaml`,并让 `harness-kit doctor` healthy、`harness-kit verify` 退出码 0。
|
|
9
9
|
|
|
10
|
-
CLI
|
|
10
|
+
CLI 只负责机械骨架、确定性生成与门禁;**理解仓库、分析文档语义、运行 context review** 是 agent 的工作。
|
|
11
11
|
|
|
12
12
|
## 0. 定位 harness-kit 命令
|
|
13
13
|
|
|
@@ -17,89 +17,127 @@ CLI 只负责机械骨架 + 确定性门禁;**理解仓库、把隐性知识
|
|
|
17
17
|
- 已全局安装:`harness-kit`
|
|
18
18
|
- 在 harness-kit 仓内开发:`pnpm exec tsx src/cli.ts`
|
|
19
19
|
|
|
20
|
-
先跑一次 `--help`
|
|
20
|
+
先跑一次 `--help` 确认可用。全程用同一种方式,别混用版本。
|
|
21
21
|
|
|
22
|
-
## 1.
|
|
22
|
+
## 1. 首次接入前:全量盘点与保真
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
在任何 `init` / `sync` 或入口文件改写之前完成:
|
|
25
|
+
|
|
26
|
+
1. **做全仓文档清单**:盘点仓库内每一份现存的 `AGENTS.md`、`CLAUDE.md`(包括被 `.gitignore` 忽略但真实存在的嵌套入口),并递归追踪它们显式引用的每一份仓内文档。文档目录名不限;不以 `docs`、`knowledge`、`context` 等文件夹名做白名单。支持 Markdown 链接、`@path` 和带 `.md/.mdx/.markdown/.txt/.rst/.adoc/.asciidoc/.org` 扩展名的纯路径。Markdown 图片、普通代码和资产链接不是 guidance。
|
|
27
|
+
2. **先记录 legacy entry 的只读基线**:逐文件记录仓内路径、原始字节 hash、文件类型和 symlink target;不得格式化、改编码或归一化换行。下一节由 `init` 把这份事实落成 byte-preserving snapshot,不能靠复制粘贴重建。
|
|
28
|
+
3. **建立逐规则 preservation ledger**:原入口中的每条约束各占一行,记录来源定位、原意、新落点、保留/改写/删除状态及理由。不能把多条规则合并成一条来掩盖遗漏。
|
|
29
|
+
4. **业务文档原地保留**:不得移动、重命名或复制既有业务文档;直接以原路径注册。仓内 legacy snapshot 只保存 Harness 将实际接管的 managed entry;嵌套入口和引用文档仅在仓外私有审计 bundle 中留证。
|
|
30
|
+
|
|
31
|
+
每个注册到 `knowledge` 的条目都显式填写:
|
|
32
|
+
|
|
33
|
+
- `root: agents | repo`:`agents` 表示 `.agents/` 下由 agent 维护的知识,`repo` 表示留在仓库原路径的既有文档;目录名不决定 root。
|
|
34
|
+
- `authority: derived | policy | review`:`derived` 是可由代码、测试、本地配置推导的描述;`policy` 是规范性约束;`review` 是需要复核的材料。
|
|
35
|
+
- 对明确过时的 `derived` 描述,用代码、测试和本地配置证据**在原文件原地更新**。`policy` 文档约束代码,不能因当前实现不同就反向改掉政策。authority、含义或取舍存在语义歧义时,升级给用户决定,禁止自行猜测。
|
|
36
|
+
|
|
37
|
+
## 2. 铺骨架(若还没有 `.agents/`)
|
|
38
|
+
|
|
39
|
+
```sh
|
|
25
40
|
harness-kit init --repo .
|
|
26
41
|
```
|
|
27
42
|
|
|
28
|
-
生成 `.agents/{manifest.yaml, knowledge/, playbooks/, adoption.md}`
|
|
43
|
+
生成 `.agents/{manifest.yaml, knowledge/, playbooks/, adoption.md}` 骨架,并在 `.agents/adoption/legacy/` 保存 Harness 将接管的 **managed legacy entry**;每个 legacy entry 的 byte-preserving 快照还要绑定 mode 与索引。立刻逐项核对索引 hash / mode / symlink target 与第 1 步基线;不一致就停止,不能继续接管。adoption 父目录/index/snapshot 出现 symlink 时必须 fail closed。若并发导致索引事务失败,整个 init 仍算失败;错误里列出的 append-only snapshot 是保留给恢复审查的证据,不得自动删除或把它误判成已完成接管。已存在任一 scaffold 目标时普通 `init` 必须零写入拒绝;不得用 `--force` 绕过尚未保真的入口。
|
|
29
44
|
|
|
30
|
-
##
|
|
45
|
+
## 3. 仓库考古 → 填 manifest(核心)
|
|
31
46
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
-
|
|
35
|
-
- 能自动验证的就给命令(`enforcement`
|
|
36
|
-
- `AGENTS.md` 有体量预算(150 行 / 700 词)——细节沉到 `.agents
|
|
47
|
+
**纪律:**
|
|
48
|
+
|
|
49
|
+
- 不臆造。先用代码、测试、实际脚本和本地配置取证;只有语义歧义才问用户。
|
|
50
|
+
- 能自动验证的就给命令(`enforcement` / 契约 `snapshot`);验证不了的诚实标 `manual`,别假装能检查。
|
|
51
|
+
- `AGENTS.md` 有体量预算(150 行 / 700 词)——细节沉到 `.agents/` 或注册原地文档,manifest 只写精选。
|
|
37
52
|
|
|
38
53
|
按顺序逐块填 `.agents/manifest.yaml`(schema 见 harness-kit 的 `SPEC-v0.md`):
|
|
39
54
|
|
|
40
|
-
1. **identity**:读
|
|
41
|
-
2. **capabilities
|
|
42
|
-
3. **environment**:从 `.env.example
|
|
43
|
-
4. **contracts
|
|
44
|
-
5. **invariants**:从
|
|
45
|
-
6. **modules
|
|
46
|
-
|
|
47
|
-
|
|
55
|
+
1. **identity**:读 README、包/构建配置和顶层目录。填 `name`、一句话 `summary`、`scope_in` / `scope_out`、`upstream` / `downstream`。
|
|
56
|
+
2. **capabilities**:从真实 scripts、Makefile、justfile 和自动化配置提取 setup / build / test / dev / lint / release。实际运行或检查入口;长驻的标 `background: true`,有副作用的标 `mutating: true`。
|
|
57
|
+
3. **environment**:从 `.env.example`、配置和 README 抓关键环境变量。危险的标 `secret: true`、必需的标 `required: true`。
|
|
58
|
+
4. **contracts**:识别 HTTP、CLI、公共 API、proto/schema/IDL、事件等对外接口,尽量给打印当前接口指纹的 `snapshot` 命令。过滤注释/生成物噪音;含复杂引号、正则或管道时下沉到 `.agents/checks/<id>.sh`,脚本从仓库根运行并固定 `LC_ALL=C`。无法自动检查才写 `manual_verify`。
|
|
59
|
+
5. **invariants**:从 policy、现有 agent 入口和真实代码约定提炼“必须始终成立”的规则。能表达成 `enforcement` / `check` 就执行化,否则标 `manual: true`。
|
|
60
|
+
6. **modules + validation**:按真实模块边界填写 `role`、具体 `entry` 文件、上下游、`must_know`、`pitfalls`,并完成可执行影响面:
|
|
61
|
+
- 首次接入必须给真实生产面填写 `modules[].owns`、真实覆盖文件填写 `modules[].tests`、真实可运行 capability 填写 `modules[].checks`,再用 `validation.required_coverage` 覆盖真实生产根。
|
|
62
|
+
- 每个 `owns` / `tests` / `required_coverage` 正向 glob 写入前都要对仓库文件清单实际求值并确认命中;不得套用惯例路径、发明 glob 或使用 `!` 否定 glob。真实不存在的测试/检查要报 GAP,不能造一个来过门禁。
|
|
63
|
+
- `checks` 只能引用已声明、可终止、无副作用且亲自验证可运行的 capability 动词。用 `plan-checks` / `run-checks` 验证真实改动能选中预期模块、测试与检查。
|
|
64
|
+
- `test_touch` 按实际风险设为 `required | advisory | off`;公共接口、核心业务、安全边界优先 `required`,不能全仓拍脑袋一刀切。
|
|
65
|
+
7. **routing**:按常见改动类型写 `read`、`entry`、`dont_assume`、`verify`。`routing.verify` 是给 agent 读的最小提示;`modules.checks` 是供 `run-checks` 执行的 capability,别混用。
|
|
66
|
+
8. **knowledge**:把第 1 步的文档按 `root` / `authority` 注册;只新增代码推不出的领域知识、坑和决策,重要决策写 journal ADR。`binds` 必须是实际源文件,用于新鲜度检查。
|
|
67
|
+
|
|
68
|
+
## 4. 语义复核与首次接入盲审
|
|
69
|
+
|
|
70
|
+
完成仓库分析、manifest、knowledge 和 preservation ledger 后:
|
|
71
|
+
|
|
72
|
+
1. 由 **Agent 在分析之后**逐个记录已复核的 knowledge / module(两种 target 分开运行,并写具体证据):
|
|
73
|
+
```sh
|
|
74
|
+
harness-kit record-context-review --repo . --path <knowledge.path> --reason "<reviewed code/test/local-config evidence>"
|
|
75
|
+
harness-kit record-context-review --repo . --module <module.name> --reason "<reviewed entry and module boundaries>"
|
|
76
|
+
```
|
|
77
|
+
`record-context-review` 只记录已经完成的分析,**绝不能替代分析**,也不能由 `sync` 暗中代跑。
|
|
78
|
+
2. 先在真实仓运行一次普通 `harness-kit sync --repo .`,确认它**拒绝覆盖尚未接管的 legacy 入口**;如果直接写成功,按安全缺陷停止。不要为了过这一步手删、移动或改写真实入口。
|
|
79
|
+
3. 用 CLI 在仓库外生成不可直接激活的审计候选(输出目录必须不存在或为空):
|
|
80
|
+
```sh
|
|
81
|
+
harness-kit prepare-adoption --repo . --out <external-empty-candidate-dir>
|
|
82
|
+
```
|
|
83
|
+
bundle 会私有保存 managed legacy byte/mode/link 证据、所有嵌套入口与递归显式引用文档的 guidance 证据、manifest/index 证据和确定性生成候选(AGENTS/CLAUDE/reference/routing/modules),但**不会写真实入口或复制业务文档到仓内**。`sync` 仍然只根据 manifest 重生成确定性文件;它不分析仓库、不更新业务或 knowledge 文档、不决定规则语义。
|
|
84
|
+
4. 在宣布首次接入完成前,派一个**全新、独立的 agent/context 做 blind audit(盲审)**:先只给 bundle 内的 legacy 证据和生成候选,不给 preservation ledger、迁移结论或预期答案;让审计者独立枚举旧规则并检查每条是否保留,把报告写到仓库外,之后才与 ledger 对账。
|
|
85
|
+
5. 发现明确缺口时,审计者给 `fail`,当前 agent 自动修 manifest/knowledge/ledger、重新运行 context review,并用**新的空目录**重新 `prepare-adoption`,再交给新的独立上下文重审;旧 bundle/receipt 不得复用。**清晰缺口的修复和复审不找用户代劳**,循环到无明确缺口。
|
|
86
|
+
6. 只有规则含义、authority 或冲突取舍存在语义歧义时才升级给用户;得到决定后写入 ledger 并再次盲审。
|
|
87
|
+
7. **盲审通过后**,先把“声明通过”的报告绑定到这一版候选,再用同一对证据接管:
|
|
88
|
+
```sh
|
|
89
|
+
harness-kit record-adoption-audit --repo . --candidate <candidate-dir> --verdict pass --report <external-audit-report> --reason "<review result>" --out <external-receipt>
|
|
90
|
+
harness-kit sync --repo . --adopt-existing --candidate <candidate-dir> --audit <external-receipt>
|
|
91
|
+
```
|
|
92
|
+
apply 时 CLI 会重新发现并核对 live legacy、snapshot/index、guidance inventory/bytes/mode/topology、manifest、候选每个字节和报告 hash;任一变化都让回执 stale。receipt 的 `assurance=declared`、`independence=unverified` 只证明顺序和字节绑定,**不冒充 Agent 身份或语义判断质量**。没有精确 pass receipt 的裸 `--adopt-existing` 必须失败。以后入口已带 managed header,日常只用普通 `sync`。
|
|
93
|
+
|
|
94
|
+
## 5. 验证到绿
|
|
95
|
+
|
|
96
|
+
```sh
|
|
97
|
+
harness-kit doctor
|
|
98
|
+
harness-kit verify
|
|
99
|
+
```
|
|
48
100
|
|
|
49
|
-
|
|
101
|
+
- 路径不存在就修 manifest;impact glob 零命中就回到真实文件清单修正,不能扩大假 glob。
|
|
102
|
+
- 契约提示 baseline 未设置时,先确认当前接口符合 policy,再运行 `harness-kit accept-contract --repo .`;拿不准是否 breaking 就升级给用户,绝不静默 accept。
|
|
103
|
+
- 迭代到 `doctor` healthy、`verify` 退出码 0,且 GAPS 只剩确实无法自动执行的覆盖。
|
|
50
104
|
|
|
105
|
+
## 6. 自动安装有效的会话门禁并验证
|
|
106
|
+
|
|
107
|
+
作为首次接入收尾、在宣称完成之前,由 agent 完成下面的判断和安装,**不让用户选择项目 Hook 或用户分发器等实现方式**:
|
|
108
|
+
|
|
109
|
+
1. 只为当前真正使用的客户端安装 SessionStart/Stop hooks,并把 `claude`、`cursor` 或 `codex` 显式传给 `--agents`;不要因为 CLI 支持多个客户端就默认全装。
|
|
110
|
+
2. 运行 `git rev-parse --absolute-git-dir` 和 `git rev-parse --path-format=absolute --git-common-dir`。两个规范化路径相同就是普通 worktree;不同才是真正的 linked worktree。不能只看根目录 `.git` 是否为文件,因为 submodule 也是这种外观。
|
|
111
|
+
3. Claude Code、Cursor 和普通 worktree 里的 Codex 使用项目级安装,例如 `harness-kit install-hooks --repo . --stop --agents codex`。如果当前客户端是 Codex 且两个 Git 路径不同,直接使用安全 fallback:
|
|
112
|
+
|
|
113
|
+
```sh
|
|
114
|
+
harness-kit install-hooks --repo . --stop --agents codex --allow-user-dispatcher
|
|
51
115
|
```
|
|
52
|
-
harness-kit sync # manifest -> AGENTS.md / CLAUDE.md / routing.md / modules.md
|
|
53
|
-
harness-kit doctor # 补全度 / 引用路径 / 漂移 / 新鲜度 / 体量预算;按报告修
|
|
54
|
-
harness-kit verify # 门禁:跑不变量 + 契约 + 漂移,并列出 GAPS
|
|
55
|
-
```
|
|
56
116
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
2. 逐条处理:
|
|
85
|
-
- **生成物 drift**("AGENTS.md drifted, run sync")→ 直接 `harness-kit sync`。
|
|
86
|
-
- **knowledge 新鲜度告警**(绑定的源文件变了)→ 重新读那个源文件,判断知识是否真过时;过时就改 `.agents/knowledge/*` 或对应 manifest 字段再 sync。**没实质变化就别乱改**。
|
|
87
|
-
- **契约 drift**(snapshot 变了)→ 看对应代码改动:确属**有意**改接口(有需求 / commit 佐证)才 `harness-kit accept-contract --id <id>`;拿不准是否 breaking 就**别 accept**,标给人。
|
|
88
|
-
- **invariant 违规** → 按规则修代码;确认该规则已过时才动 manifest。
|
|
89
|
-
3. 全部处理完再 `verify` 到退出码 0。
|
|
90
|
-
4. **产出一份变更清单交给人 review(这是唯一的人工动作)**,至少含:
|
|
91
|
-
- 改了哪些 manifest 字段 / knowledge 文件,为什么;
|
|
92
|
-
- accept 了哪些契约、对应什么代码改动、是否 breaking;
|
|
93
|
-
- 哪些**没动**及原因。
|
|
94
|
-
|
|
95
|
-
**红线**:
|
|
96
|
-
- 契约 accept 必须有据可依且**必写进给人的清单**——绝不静默 auto-accept 对外接口变更。
|
|
97
|
-
- 拿不准就标 GAP 交人,别用幻觉填。
|
|
98
|
-
- 只修真漂移,别为了凑绿去改无关内容。
|
|
99
|
-
|
|
100
|
-
## 反模式(别做)
|
|
101
|
-
|
|
102
|
-
- ❌ 手写 `AGENTS.md` / `routing.md` / `modules.md`(它们是生成物,改 manifest)。
|
|
103
|
-
- ❌ 把整个代码库塞进 manifest —— 只放精选的"该看哪 + 为什么 + 别假设什么"。
|
|
104
|
-
- ❌ 为了消灭 GAPS 硬造检查 —— 查不了就诚实标 manual。
|
|
105
|
-
- ❌ 一上来全仓 grep 乱猜 —— 先按 routing 读该读的。
|
|
117
|
+
Codex fallback 会保留用户 Hook 源配置里的其他 Hook,只加入一对固定的 SessionStart/Stop 调度入口和一个版本化分发器;同时从项目 `.codex/hooks.json` 移除且只移除 Harness 自己的命令,第三方项目 Hook 原位保留。这样 linked worktree 始终只有用户分发器这一条 Harness 路径,不会因某个 Codex surface 又开始读取项目 Hook 而重复跑检查。当前 worktree 的登记放在它自己的 Git admin dir。未登记的仓库会直接不执行,登记存在但 runner、权限、路径或 hash 不一致则阻断。安装器遇到未知 JSON 结构、同名外来分发器或并发编辑时必须拒绝,agent 不得用 `--force` 猜测合并。
|
|
118
|
+
|
|
119
|
+
在 Orca 管理的 Codex 终端里,当前 `$CODEX_HOME` 是生成态运行时,Orca 会从系统 `~/.codex` 合并用户 Hook。安装器会自动识别这种环境并把 Harness 入口写到 `~/.codex` 源配置;agent 不得直接补丁当前运行时 `hooks.json`、Orca 管理脚本或私有 trust hash。安装后必须创建一个全新的 Orca Agent 会话,让宿主正常镜像源配置,再验证 evidence。
|
|
120
|
+
|
|
121
|
+
Codex 首次信任用户分发器时,agent 先用一句人话说明:“它不改业务代码,也不是共享 Git hook;只把已登记 worktree 的会话事件交回该仓库自己的门禁,其他仓库不执行。”宿主允许 agent 完成信任复核时自动完成;必须由 UI 确认时,只请用户批准安装器打印出的那一条精确 managed dispatcher,不抛给用户技术选型题。
|
|
122
|
+
|
|
123
|
+
随后启动一个**全新的 Agent 会话**,完成一次安全的验证闭环,再运行 `harness-kit evidence --repo . --json`。宿主支持创建会话/Agent(例如 Orca)时由当前 agent 自动创建和检查;不支持时才请用户重开一次会话。只有 evidence 明确记录该新会话的 SessionStart 基线、Stop 阶段 `run-checks + verify` 结果并且 `hookActive: true`,才能宣称 hooks 已生效。客户端未执行 hooks 时要报 GAP,并用任务开始 SHA 手动跑 `run-checks --base <sha>`,不能把默认 `no-change` 当证据。
|
|
124
|
+
|
|
125
|
+
原生 Git hooks(pre-commit / pre-push)是**可选且仅限确认安全时**的增强:不得覆盖既有 hooks,不得改变未知的团队工作流,也不能作为首次接入完成条件。**绝不要指示用户修改 CI。**
|
|
126
|
+
|
|
127
|
+
## 7. 日常维护 / 自愈
|
|
128
|
+
|
|
129
|
+
门禁发现 drift 后由 agent 处理,人只审查最终变更清单:
|
|
130
|
+
|
|
131
|
+
1. 生成物 drift → `sync`;它仍然只做确定性重生成。
|
|
132
|
+
2. `derived` knowledge stale → 重读绑定的代码/测试/本地配置,有明确证据才原地更新;`policy` 冲突则修代码,语义不清才问用户。
|
|
133
|
+
3. 契约 drift → 只有需求和代码证据都表明有意变更才 accept,并写进审查清单;否则升级。
|
|
134
|
+
4. invariant 违规 → 修代码;确认 policy 已变更后才能改规则。
|
|
135
|
+
5. 重跑 `record-context-review`(仅在分析完成后)、`run-checks` 和 `verify` 到绿,列出改了什么、证据、accept 的契约及未动项。
|
|
136
|
+
|
|
137
|
+
## 反模式
|
|
138
|
+
|
|
139
|
+
- 手写生成的 `AGENTS.md` / `CLAUDE.md` / `routing.md` / `modules.md`。
|
|
140
|
+
- 用 `sync` 或 `record-context-review` 冒充仓库分析。
|
|
141
|
+
- 移动/复制业务文档,或按目录名漏掉显式引用文档。
|
|
142
|
+
- 为了消灭 GAPS 发明 capability、glob 或检查。
|
|
143
|
+
- 跳过 legacy 快照、逐规则 ledger 或独立盲审。
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: harness-check-loop
|
|
3
|
+
description: 在一个已接入 harness-kit 的仓库里实现需求 / 修 bug 时的"实现 -> 验证"闭环。用 plan-checks 算影响面、run-checks 跑验收、按 gap 补齐,直到真正交付。当 agent 要开始写功能代码、或 stop 钩子拦下"未验证的交付"时使用。
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# harness-check-loop
|
|
7
|
+
|
|
8
|
+
一个 agent 在**已接入 harness-kit** 的仓库里实现需求 / 修 bug 的闭环。目标不是"跑通测试命令",而是**证明这次改动真的交付了**:影响面被覆盖、该补的用例补了、验收通过。
|
|
9
|
+
|
|
10
|
+
harness-kit 只提供确定性弹药,不替你判断功能对不对:
|
|
11
|
+
- `plan-checks` —— 按 `modules[].owns` 把改动映射到模块,算出该跑哪些 `checks`,并列出**诚实的 gap**(哪块没测、没碰测试、没命中任何模块…)。只算不跑。
|
|
12
|
+
- `run-checks` —— 把 `plan-checks` 选出的 **capability check** 真跑一遍,持久化 passed/failed/gaps/waivers;没有实际执行的 check 不能算绿。
|
|
13
|
+
- `verify` —— 再查 manifest、生成物、不变量和契约,和 `run-checks` 分工互补。
|
|
14
|
+
- **SessionStart + Stop 钩子**(若已 `install-hooks --stop`)会记住会话开始时的代码基线,并在你**每次尝试结束时**重跑两道门禁;会话中已经 commit 的改动也不会漏。
|
|
15
|
+
|
|
16
|
+
## 心法:两半闭环
|
|
17
|
+
|
|
18
|
+
改动可分两类,闭环方式不同:
|
|
19
|
+
|
|
20
|
+
- **改老代码 / 修老需求 / 改历史逻辑** → 影响面已有回归网。`plan-checks` 会算出命中的模块和它们的 `checks`,直接 `run-checks` 验收即可。
|
|
21
|
+
- **加新功能 / 新 feature** → 回归网里**还没有**覆盖它的用例。光跑老测试跑不出新功能对不对。你要**先补上验收这次新行为的用例**(让它先红后绿),再让它沉淀进回归网。
|
|
22
|
+
|
|
23
|
+
判断依据看 `plan-checks` 的 gap:`missing-test-touch` / `module-without-tests` 就是在告诉你"这块新行为还没有对应测试"。
|
|
24
|
+
|
|
25
|
+
## 闭环步骤
|
|
26
|
+
|
|
27
|
+
1. **定影响面**:动手前先
|
|
28
|
+
```
|
|
29
|
+
git rev-parse HEAD # 记为 task-start SHA;即使稍后 commit 也不会漏
|
|
30
|
+
harness-kit plan-checks --repo .
|
|
31
|
+
```
|
|
32
|
+
读三样:命中的模块、要跑的 checks、gap 列表。gap 的 `-> suggestion` 就是你的下一步。
|
|
33
|
+
2. **实现**:按 routing / modules.md 读该读的再改。改生产代码时,**同步改/补它 `tests` glob 覆盖的用例**——尤其新功能,用例要断言真实行为(请求参数、返回 response、状态与交互),不是只断言"没抛异常"。
|
|
34
|
+
3. **验收**:
|
|
35
|
+
```
|
|
36
|
+
harness-kit run-checks --repo . --base <task-start-sha>
|
|
37
|
+
harness-kit verify --repo .
|
|
38
|
+
```
|
|
39
|
+
- `run-checks` 为 `verified*`,且 `verify` 退出 0 → 交付达成,进第 5 步。
|
|
40
|
+
- 手动默认只看到 `no-change` 不能证明已经 commit 的任务;传第 1 步的 SHA。生命周期 hook 有自己的 SessionStart exact base,不受此限制。
|
|
41
|
+
- 有失败 / blocking gap → 进第 4 步。
|
|
42
|
+
4. **按证据收敛**(你自己闭环,别丢回给人):
|
|
43
|
+
- `check FAILED` → 读日志尾巴,定位并修,重跑。
|
|
44
|
+
- `missing-test-touch` → 在该模块 `tests` 里补覆盖本次改动的用例,重跑。
|
|
45
|
+
- `module-without-tests` → 该模块没有回归网:补 `tests` glob + 基础用例(参考模块的 `playbook`)。
|
|
46
|
+
- `unmapped-file` / `unmapped-required-file` → 改动落在没人 `owns/tests` 的文件:若属已有模块,补映射;若是新模块,补一张模块卡。required 范围不能静默跳过。
|
|
47
|
+
- `no-checks-selected` → 命中模块没声明 `checks`:补 `checks`(capability 动词)。
|
|
48
|
+
- `manual-base-required` → 工作区已干净但没有任务起点:用第 1 步记录的 SHA 重跑 `run-checks --base <sha>`。
|
|
49
|
+
- 真属于本次**非目标**的覆盖类 blocking gap(`missing-test-touch` / `module-without-tests` / `unmapped-required-file`),才用 `run-checks --waive <kind> --where <输出中的 scope> --reason <为什么>` 豁免。检查未跑、配置/Git 失败等不能豁免;豁免只绑定当前代码指纹,改代码后必须重新判断。
|
|
50
|
+
修完回第 3 步,直到 `run-checks` 退出码 0。
|
|
51
|
+
5. **交付**:用 `harness-kit evidence --repo .` 复核最终证据;手动流程里只有 `runChecksValid:true` 仍不完整,必须看到匹配的 `verifyPassed:true` 与整体 `valid:true`。若显示 `stale`,说明留证后代码又变了,回到第 3 步。只有两道门禁都绿了才算完;把改了什么、补了哪些用例、豁免了什么及原因写进交付说明。
|
|
52
|
+
|
|
53
|
+
## 拔高正确率的三根杠杆(闭环保证的是一致性,不是"意图全对"——用这些逼近意图)
|
|
54
|
+
|
|
55
|
+
- **先红后绿(bug 必做)**:修 bug 前先写一个能**复现该 bug 的失败用例**,确认它红;修完变绿。没见过红的绿,证明不了你真修好了。
|
|
56
|
+
- **独立复核**:实现者和验收者同一个大脑时最容易自我欺骗。让**另一个 agent / bugbot** 或另开一轮,只拿"需求 + diff"复核,别信你自己的一面之词。
|
|
57
|
+
- **看 diff 覆盖**:确认新增/改动的代码行真的被新用例执行到,而不是测了一堆无关的老路径。
|
|
58
|
+
|
|
59
|
+
## 红线
|
|
60
|
+
|
|
61
|
+
- ❌ 没跑 `run-checks` 就说"做完了"。stop 钩子会拦,别赌它不在。
|
|
62
|
+
- ❌ 为了消 gap 造假测试(`assert true`、把断言删了、无意义豁免)——那是把回归网变成安慰剂。
|
|
63
|
+
- ❌ 把 `run-checks` 的失败当噪音绕过去。红灯是"还没交付",不是"可选项"。
|
|
64
|
+
- ❌ 明明加了新行为却只跑老回归、不补新用例。
|
|
65
|
+
- ❌ 把手动 `no-change` 当成“已验收 commit”。它只说明当前工作区没差异,不知道任务从哪里开始。
|