@hunter-harness/workflow-harness 0.2.71 → 0.2.73
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/harness/bundles/general/claude-code/.harness-build.json +1 -1
- package/harness/bundles/general/claude-code/harness-archive/SKILL.md +3 -3
- package/harness/bundles/general/claude-code/harness-codebase-map/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/harness-knowledge-ingest/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/harness-plan/SKILL.md +14 -10
- package/harness/bundles/general/claude-code/harness-plan/checklist.md +49 -9
- package/harness/bundles/general/claude-code/harness-plan/reference.md +83 -33
- package/harness/bundles/general/claude-code/harness-pull/SKILL.md +2 -2
- package/harness/bundles/general/claude-code/harness-push/SKILL.md +2 -2
- package/harness/bundles/general/claude-code/harness-review/SKILL.md +3 -3
- package/harness/bundles/general/claude-code/harness-run/SKILL.md +5 -5
- package/harness/bundles/general/claude-code/harness-run/checklist.md +4 -1
- package/harness/bundles/general/claude-code/harness-run/reference.md +3 -3
- package/harness/bundles/general/claude-code/harness-submit/SKILL.md +3 -3
- package/harness/bundles/general/claude-code/harness-sync/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/harness-test/SKILL.md +3 -3
- package/harness/bundles/general/claude-code/scripts/harness_context.py +270 -0
- package/harness/bundles/general/claude-code/scripts/harness_gate.py +71 -2
- package/harness/bundles/general/claude-code/scripts/harness_test_guard.py +8 -5
- package/harness/bundles/general/codebuddy/.harness-build.json +1 -1
- package/harness/bundles/general/codebuddy/harness-archive/SKILL.md +3 -3
- package/harness/bundles/general/codebuddy/harness-codebase-map/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/harness-knowledge-ingest/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/harness-plan/SKILL.md +14 -10
- package/harness/bundles/general/codebuddy/harness-plan/checklist.md +49 -9
- package/harness/bundles/general/codebuddy/harness-plan/reference.md +83 -33
- package/harness/bundles/general/codebuddy/harness-pull/SKILL.md +2 -2
- package/harness/bundles/general/codebuddy/harness-push/SKILL.md +2 -2
- package/harness/bundles/general/codebuddy/harness-review/SKILL.md +3 -3
- package/harness/bundles/general/codebuddy/harness-run/SKILL.md +5 -5
- package/harness/bundles/general/codebuddy/harness-run/checklist.md +4 -1
- package/harness/bundles/general/codebuddy/harness-run/reference.md +3 -3
- package/harness/bundles/general/codebuddy/harness-submit/SKILL.md +3 -3
- package/harness/bundles/general/codebuddy/harness-sync/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/harness-test/SKILL.md +3 -3
- package/harness/bundles/general/codebuddy/scripts/harness_context.py +270 -0
- package/harness/bundles/general/codebuddy/scripts/harness_gate.py +71 -2
- package/harness/bundles/general/codebuddy/scripts/harness_test_guard.py +8 -5
- package/harness/bundles/general/codex/.harness-build.json +1 -1
- package/harness/bundles/general/codex/harness-archive/SKILL.md +3 -3
- package/harness/bundles/general/codex/harness-codebase-map/SKILL.md +1 -1
- package/harness/bundles/general/codex/harness-knowledge-ingest/SKILL.md +1 -1
- package/harness/bundles/general/codex/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/general/codex/harness-plan/SKILL.md +14 -10
- package/harness/bundles/general/codex/harness-plan/checklist.md +49 -9
- package/harness/bundles/general/codex/harness-plan/reference.md +83 -33
- package/harness/bundles/general/codex/harness-pull/SKILL.md +2 -2
- package/harness/bundles/general/codex/harness-push/SKILL.md +2 -2
- package/harness/bundles/general/codex/harness-review/SKILL.md +3 -3
- package/harness/bundles/general/codex/harness-run/SKILL.md +5 -5
- package/harness/bundles/general/codex/harness-run/checklist.md +4 -1
- package/harness/bundles/general/codex/harness-run/reference.md +3 -3
- package/harness/bundles/general/codex/harness-submit/SKILL.md +3 -3
- package/harness/bundles/general/codex/harness-sync/SKILL.md +1 -1
- package/harness/bundles/general/codex/harness-test/SKILL.md +3 -3
- package/harness/bundles/general/codex/scripts/harness_context.py +270 -0
- package/harness/bundles/general/codex/scripts/harness_gate.py +71 -2
- package/harness/bundles/general/codex/scripts/harness_test_guard.py +8 -5
- package/harness/bundles/general/cursor/.harness-build.json +1 -1
- package/harness/bundles/general/cursor/harness-archive/SKILL.md +3 -3
- package/harness/bundles/general/cursor/harness-codebase-map/SKILL.md +1 -1
- package/harness/bundles/general/cursor/harness-knowledge-ingest/SKILL.md +1 -1
- package/harness/bundles/general/cursor/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/general/cursor/harness-plan/SKILL.md +14 -10
- package/harness/bundles/general/cursor/harness-plan/checklist.md +49 -9
- package/harness/bundles/general/cursor/harness-plan/reference.md +83 -33
- package/harness/bundles/general/cursor/harness-pull/SKILL.md +2 -2
- package/harness/bundles/general/cursor/harness-push/SKILL.md +2 -2
- package/harness/bundles/general/cursor/harness-review/SKILL.md +3 -3
- package/harness/bundles/general/cursor/harness-run/SKILL.md +5 -5
- package/harness/bundles/general/cursor/harness-run/checklist.md +4 -1
- package/harness/bundles/general/cursor/harness-run/reference.md +3 -3
- package/harness/bundles/general/cursor/harness-submit/SKILL.md +3 -3
- package/harness/bundles/general/cursor/harness-sync/SKILL.md +1 -1
- package/harness/bundles/general/cursor/harness-test/SKILL.md +3 -3
- package/harness/bundles/general/cursor/scripts/harness_context.py +270 -0
- package/harness/bundles/general/cursor/scripts/harness_gate.py +71 -2
- package/harness/bundles/general/cursor/scripts/harness_test_guard.py +8 -5
- package/harness/bundles/java/claude-code/.harness-build.json +1 -1
- package/harness/bundles/java/claude-code/harness-apidoc/SKILL.md +3 -3
- package/harness/bundles/java/claude-code/harness-archive/SKILL.md +3 -3
- package/harness/bundles/java/claude-code/harness-codebase-map/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-knowledge-ingest/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-package/SKILL.md +3 -3
- package/harness/bundles/java/claude-code/harness-plan/SKILL.md +14 -10
- package/harness/bundles/java/claude-code/harness-plan/checklist.md +49 -9
- package/harness/bundles/java/claude-code/harness-plan/reference.md +83 -33
- package/harness/bundles/java/claude-code/harness-pull/SKILL.md +2 -2
- package/harness/bundles/java/claude-code/harness-push/SKILL.md +2 -2
- package/harness/bundles/java/claude-code/harness-review/SKILL.md +3 -3
- package/harness/bundles/java/claude-code/harness-run/SKILL.md +5 -5
- package/harness/bundles/java/claude-code/harness-run/checklist.md +1 -1
- package/harness/bundles/java/claude-code/harness-submit/SKILL.md +3 -3
- package/harness/bundles/java/claude-code/harness-sync/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-test/SKILL.md +3 -3
- package/harness/bundles/java/claude-code/scripts/harness_context.py +270 -0
- package/harness/bundles/java/claude-code/scripts/harness_gate.py +71 -2
- package/harness/bundles/java/claude-code/scripts/harness_test_guard.py +8 -5
- package/harness/bundles/java/codebuddy/.harness-build.json +1 -1
- package/harness/bundles/java/codebuddy/harness-apidoc/SKILL.md +3 -3
- package/harness/bundles/java/codebuddy/harness-archive/SKILL.md +3 -3
- package/harness/bundles/java/codebuddy/harness-codebase-map/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-knowledge-ingest/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-package/SKILL.md +3 -3
- package/harness/bundles/java/codebuddy/harness-plan/SKILL.md +14 -10
- package/harness/bundles/java/codebuddy/harness-plan/checklist.md +49 -9
- package/harness/bundles/java/codebuddy/harness-plan/reference.md +83 -33
- package/harness/bundles/java/codebuddy/harness-pull/SKILL.md +2 -2
- package/harness/bundles/java/codebuddy/harness-push/SKILL.md +2 -2
- package/harness/bundles/java/codebuddy/harness-review/SKILL.md +3 -3
- package/harness/bundles/java/codebuddy/harness-run/SKILL.md +5 -5
- package/harness/bundles/java/codebuddy/harness-run/checklist.md +1 -1
- package/harness/bundles/java/codebuddy/harness-submit/SKILL.md +3 -3
- package/harness/bundles/java/codebuddy/harness-sync/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-test/SKILL.md +3 -3
- package/harness/bundles/java/codebuddy/scripts/harness_context.py +270 -0
- package/harness/bundles/java/codebuddy/scripts/harness_gate.py +71 -2
- package/harness/bundles/java/codebuddy/scripts/harness_test_guard.py +8 -5
- package/harness/bundles/java/codex/.harness-build.json +1 -1
- package/harness/bundles/java/codex/harness-apidoc/SKILL.md +3 -3
- package/harness/bundles/java/codex/harness-archive/SKILL.md +3 -3
- package/harness/bundles/java/codex/harness-codebase-map/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-knowledge-ingest/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-package/SKILL.md +3 -3
- package/harness/bundles/java/codex/harness-plan/SKILL.md +14 -10
- package/harness/bundles/java/codex/harness-plan/checklist.md +49 -9
- package/harness/bundles/java/codex/harness-plan/reference.md +83 -33
- package/harness/bundles/java/codex/harness-pull/SKILL.md +2 -2
- package/harness/bundles/java/codex/harness-push/SKILL.md +2 -2
- package/harness/bundles/java/codex/harness-review/SKILL.md +3 -3
- package/harness/bundles/java/codex/harness-run/SKILL.md +5 -5
- package/harness/bundles/java/codex/harness-run/checklist.md +1 -1
- package/harness/bundles/java/codex/harness-submit/SKILL.md +3 -3
- package/harness/bundles/java/codex/harness-sync/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-test/SKILL.md +3 -3
- package/harness/bundles/java/codex/scripts/harness_context.py +270 -0
- package/harness/bundles/java/codex/scripts/harness_gate.py +71 -2
- package/harness/bundles/java/codex/scripts/harness_test_guard.py +8 -5
- package/harness/bundles/java/cursor/.harness-build.json +1 -1
- package/harness/bundles/java/cursor/harness-apidoc/SKILL.md +3 -3
- package/harness/bundles/java/cursor/harness-archive/SKILL.md +3 -3
- package/harness/bundles/java/cursor/harness-codebase-map/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-knowledge-ingest/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-package/SKILL.md +3 -3
- package/harness/bundles/java/cursor/harness-plan/SKILL.md +14 -10
- package/harness/bundles/java/cursor/harness-plan/checklist.md +49 -9
- package/harness/bundles/java/cursor/harness-plan/reference.md +83 -33
- package/harness/bundles/java/cursor/harness-pull/SKILL.md +2 -2
- package/harness/bundles/java/cursor/harness-push/SKILL.md +2 -2
- package/harness/bundles/java/cursor/harness-review/SKILL.md +3 -3
- package/harness/bundles/java/cursor/harness-run/SKILL.md +5 -5
- package/harness/bundles/java/cursor/harness-run/checklist.md +1 -1
- package/harness/bundles/java/cursor/harness-submit/SKILL.md +3 -3
- package/harness/bundles/java/cursor/harness-sync/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-test/SKILL.md +3 -3
- package/harness/bundles/java/cursor/scripts/harness_context.py +270 -0
- package/harness/bundles/java/cursor/scripts/harness_gate.py +71 -2
- package/harness/bundles/java/cursor/scripts/harness_test_guard.py +8 -5
- package/harness/manifests/general/claude-code.json +22 -22
- package/harness/manifests/general/codebuddy.json +22 -22
- package/harness/manifests/general/codex.json +22 -22
- package/harness/manifests/general/cursor.json +22 -22
- package/harness/manifests/java/claude-code.json +23 -23
- package/harness/manifests/java/codebuddy.json +23 -23
- package/harness/manifests/java/codex.json +23 -23
- package/harness/manifests/java/cursor.json +23 -23
- package/hunter-workflow-family.json +5 -5
- package/package.json +1 -1
|
@@ -21,7 +21,7 @@ disallowed-tools:
|
|
|
21
21
|
- Bash(awk *)
|
|
22
22
|
- Bash(curl *)
|
|
23
23
|
---
|
|
24
|
-
<!-- generated by harness_deploy.py; core=
|
|
24
|
+
<!-- generated by harness_deploy.py; core=d79ae315e929446c; overlay=none; agent=claude-code; do not edit -->
|
|
25
25
|
# harness-archive — 变更归档
|
|
26
26
|
|
|
27
27
|
## Purpose
|
|
@@ -57,9 +57,9 @@ disallowed-tools:
|
|
|
57
57
|
## 统一读取协议
|
|
58
58
|
|
|
59
59
|
1. **`.harness/changes/<change-name>/` 是唯一真相源** — 所有输入从该目录读取,产物写入对应子目录
|
|
60
|
-
2. **change-name 优先从 frontmatter 读取** — `spec/*-design.md`、`plans/*-plan.md` 的 YAML `change-name`
|
|
60
|
+
2. **change-name 优先从 frontmatter 读取** — `plans/*-design.md`、`spec/*-design.md`、`plans/*-plan.md` 的 YAML `change-name`
|
|
61
61
|
3. **frontmatter 缺失时兼容旧格式** — 从路径推断,标记 `🟡 legacy-plan`,不失败
|
|
62
|
-
4. **
|
|
62
|
+
4. **design** — 设计真相源按序取第一个存在的:`plans/<change>-design.md`(v2 发布产物,哈希绑定)→ `spec/<change>-design.md`(legacy 手写)。两份**同时存在**时以 `plans/` 为准,并记 `🟡 WARN 设计文档双份`——v2 发布的那份才受完整性门禁保护,读手写的那份等于绕过校验
|
|
63
63
|
5. **plan** — 任务真相源:`plans/<change>-plan.md`
|
|
64
64
|
6. **implementation-detail** — 自适应执行参考;legacy 缺失 🟡WARN,不阻断
|
|
65
65
|
7. **test-scenarios** — 测试真相源:`plans/<change>-test-scenarios.md`
|
|
@@ -20,7 +20,7 @@ disallowed-tools:
|
|
|
20
20
|
- Bash(awk *)
|
|
21
21
|
- Bash(curl *)
|
|
22
22
|
---
|
|
23
|
-
<!-- generated by harness_deploy.py; core=
|
|
23
|
+
<!-- generated by harness_deploy.py; core=d79ae315e929446c; overlay=none; agent=claude-code; do not edit -->
|
|
24
24
|
# harness-codebase-map — 代码库地图
|
|
25
25
|
|
|
26
26
|
## Purpose
|
|
@@ -8,7 +8,7 @@ disallowed-tools:
|
|
|
8
8
|
- Bash(git *)
|
|
9
9
|
- Bash(curl *)
|
|
10
10
|
---
|
|
11
|
-
<!-- generated by harness_deploy.py; core=
|
|
11
|
+
<!-- generated by harness_deploy.py; core=d79ae315e929446c; overlay=none; agent=claude-code; do not edit -->
|
|
12
12
|
# harness-knowledge-ingest
|
|
13
13
|
|
|
14
14
|
知识 ingest 完全由 Hunter Platform 负责。归档完成时,客户端生成一个确定性 ZIP;
|
|
@@ -8,7 +8,7 @@ disallowed-tools:
|
|
|
8
8
|
- Bash(git *)
|
|
9
9
|
- Bash(curl *)
|
|
10
10
|
---
|
|
11
|
-
<!-- generated by harness_deploy.py; core=
|
|
11
|
+
<!-- generated by harness_deploy.py; core=d79ae315e929446c; overlay=none; agent=claude-code; do not edit -->
|
|
12
12
|
# harness-knowledge-query
|
|
13
13
|
|
|
14
14
|
项目知识以 Hunter Platform 的服务端索引为唯一真源。客户端只提交查询并消费结果:
|
|
@@ -21,7 +21,7 @@ disallowed-tools:
|
|
|
21
21
|
- Bash(awk *)
|
|
22
22
|
- Bash(curl *)
|
|
23
23
|
---
|
|
24
|
-
<!-- generated by harness_deploy.py; core=
|
|
24
|
+
<!-- generated by harness_deploy.py; core=d79ae315e929446c; overlay=none; agent=claude-code; do not edit -->
|
|
25
25
|
# harness-plan — 需求规划
|
|
26
26
|
|
|
27
27
|
## Purpose
|
|
@@ -39,9 +39,9 @@ disallowed-tools:
|
|
|
39
39
|
## 统一读取协议
|
|
40
40
|
|
|
41
41
|
1. **`.harness/changes/<change-name>/` 是唯一真相源** — 所有输入从该目录读取,产物写入对应子目录
|
|
42
|
-
2. **change-name 优先从 frontmatter 读取** — `spec/*-design.md`、`plans/*-plan.md` 的 YAML `change-name`
|
|
42
|
+
2. **change-name 优先从 frontmatter 读取** — `plans/*-design.md`、`spec/*-design.md`、`plans/*-plan.md` 的 YAML `change-name`
|
|
43
43
|
3. **frontmatter 缺失时兼容旧格式** — 从路径推断,标记 `🟡 legacy-plan`,不失败
|
|
44
|
-
4. **
|
|
44
|
+
4. **design** — 设计真相源按序取第一个存在的:`plans/<change>-design.md`(v2 发布产物,哈希绑定)→ `spec/<change>-design.md`(legacy 手写)。两份**同时存在**时以 `plans/` 为准,并记 `🟡 WARN 设计文档双份`——v2 发布的那份才受完整性门禁保护,读手写的那份等于绕过校验
|
|
45
45
|
5. **plan** — 任务真相源:`plans/<change>-plan.md`
|
|
46
46
|
6. **implementation-detail** — 自适应执行参考;legacy 缺失 🟡WARN,不阻断
|
|
47
47
|
7. **test-scenarios** — 测试真相源:`plans/<change>-test-scenarios.md`
|
|
@@ -84,14 +84,15 @@ disallowed-tools:
|
|
|
84
84
|
|
|
85
85
|
| 阶段 | 动作 |
|
|
86
86
|
|------|------|
|
|
87
|
-
| 0 |
|
|
88
|
-
| 0.5 |
|
|
89
|
-
| 0.
|
|
87
|
+
| 0 | git status;脏工作区 → baseline 隔离 + `decision`,不询问。环境体检并入 0.5 的引导命令,不再单独跑 doctor |
|
|
88
|
+
| 0.5 | 先定英文 `change-name`(kebab-case,`^[a-z0-9]+(-[a-z0-9]+)*$`)与一次性中文展示标题(建议 6~24 个可见字符,保留必要产品名),然后**一条命令完成引导**:<br>`python <skills-root>/scripts/harness_context.py bootstrap-plan --project . --change <cn> --executor <tool> --title "<中文标题>" --json`<br>它按序做完 doctor → 建 change 骨架 → prepare → state capture(首次把当时 HEAD 固定为不可变 `changeBase`)→ classify(落 `meta/gate-policy.json`)→ 生成合规 `plan_<uuid>` run-id 并追加 `phase.start`,返回紧凑摘要:`runId`/`attempt`/`tier`/`defaultPhases`/`conditionalPhases`/`requiredValidations`/`changeBase`/`head`/`executionRoot`。**重跑复用同一 run-id、不重复写 `phase.start`**(换 run-id 会让 finalize 按生命周期身份 fail-closed)。finalizer 必须复用该 `runId`/`attempt` |
|
|
89
|
+
| 0.5b | 仅在引导失败需要单步排查时用等价分解——**每条的参数都是必填,少一个就是白跑一轮**:<br>`harness_runtime.py doctor --project . --change-dir ".harness/changes/<cn>" --agent <claude-code\|codebuddy\|codex\|cursor> --json`<br>`harness_context.py prepare --project . --change <cn> --phase plan --executor <tool> --title "<中文标题>" --json`<br>`harness_state.py capture --project . --change-dir ".harness/changes/<cn>" --json`<br>`harness_gate.py classify --change <cn> --stage plan --json`<br>`harness_events.py append --change-dir ".harness/changes/<cn>" --phase plan --type phase.start --run-id plan_<uuid> --attempt 1`<br>⚠️ `--change-dir` 一律是 `.harness/changes/<cn>`(状态目录),**不是** prepare 返回的 `executionRoot`(代码执行根,无 worktree 时等于项目根)——填错会把 gate-policy/events 写到项目根 |
|
|
90
|
+
| 0.6 | 用引导返回的 `tier`/`defaultPhases`/`requiredValidations` 生成 `plannedPhases`,向用户用中文说明可选阶段;确认后运行 `harness_context.py configure-plan --project . --change <cn> --phases "plan,run,...,archive" --operator <tool> --reason "<中文原因>" --json`。无 Git 或不需要提交时不得加入 `submit`;快速迭代默认 `plan,run,archive`。省略项由脚本写入 `skippedPhases`,不得伪造阶段事件 |
|
|
90
91
|
| 1 | 直接执行一次 `npx hunter-harness knowledge query "<用户需求原文>" --limit 10 --json`。这是唯一执行入口,不扫描技能目录、不查找其他脚本;失败记 `issue` 并继续,不建立本地索引或离线回退 |
|
|
91
92
|
| 2 | 歧义优先检查 + 复杂度分级;先确认会改变实现方向的语义歧义 |
|
|
92
93
|
| 3 | 按复杂度执行有预算的代码探索;简单修复不得扩散到无关模块 |
|
|
93
94
|
| 4 | **设计审批包** blocking user confirmation;确认事件早于 approved 设计文档和 `meta/worktree.json` |
|
|
94
|
-
| 5–6 |
|
|
95
|
+
| 5–6 | **v2(默认)**:任务与场景只沉淀进 `meta/plan-evidence-input.json`(自然输入,字段定稿时点见 `reference.md` 阶段 8 v2 表);`plans/*.md` 四份由 finalize 派生,**不得手写**——手写的会被派生渲染覆盖,只是白写。**legacy**:才手写 plan + implementation-detail + test-scenarios → `plans/` |
|
|
95
96
|
| 7.5 | 仅 `--adversarial` 对抗评审 |
|
|
96
97
|
| 8 | **v2 路径(新 change 优先)**:`npx hunter-harness plan evidence-pack --input <meta/plan-evidence-input.json> --output <meta/plan-evidence.json>`,再 `npx hunter-harness plan finalize --input <meta/plan-evidence.json>`;exit 0 且 `code:"PLAN_FINALIZED"` 即发布完成(契约见 `reference.md` 阶段 8 v2 路径)。**legacy 路径**:自然输入不完整(如缺真实审批记录)时才在临时产物集上运行 `harness_plan_finalize.py finalize`,随后立即运行 `verify`;成功后把 finalizer 返回的绝对 `receiptPath` 原样传给 `harness_context.py close`,`--to-phase` 必须取 `plannedPhases` 中 plan 的真实后继,不得写死。写 append-only handoff receipt;不得手写占位路径;原子发布、派生清单计数对账、完整生命周期、render → `checklist.md` |
|
|
97
98
|
|
|
@@ -114,16 +115,19 @@ change-name 范围变更 → 提示重命名或记 🟡WARN(→ `reference.md`
|
|
|
114
115
|
| 规则 | 要点 |
|
|
115
116
|
|------|------|
|
|
116
117
|
| 产物路径 | 只写 `.harness/changes/<cn>/`;禁止 superpowers 输入 |
|
|
118
|
+
| 设计真相源 | **v2** = `plans/<cn>-design.md`(finalize 派生、哈希绑定、八 target 之一);**legacy** = `spec/<cn>-design.md`。同一 change 只有一份设计权威,禁止两处并存导致漂移;下游读取顺序见 `shared/read-protocol.md` |
|
|
117
119
|
| Change 标题 | 首次 Plan 同时确定英文 `change-name` 与中文展示标题;英文名保持目录和机器标识不变,中文标题由 `prepare --title` 持久化,后续阶段只复用、不重新生成 |
|
|
118
120
|
| 阶段计划 | Plan 必须持久化 `plannedPhases`;固定从 plan 开始、以 archive 结束。Test、Review、Submit、Package、API 文档可按项目策略省略;高风险必需项只能转为“提前结束且不可发布”,不得伪装通过 |
|
|
119
121
|
| 产品边界 | `ownership.productPaths` 必须覆盖计划会修改的源文件、测试文件和构建入口;只写目录前缀或精确文件,禁止 `**` 通配。finalize 前对照任务表补齐,避免归档阶段才发现边界缺口 |
|
|
120
122
|
| 空目录 | 不得为“预留目录”生成 `.gitkeep`;只有产品明确需要跟踪空目录时才能创建,并在计划中说明业务原因 |
|
|
121
|
-
| 设计审批包 | 一次 blocking user confirmation 含 worktree(读 `harness.json` `defaultWorktree
|
|
123
|
+
| 设计审批包 | 一次 blocking user confirmation 含 worktree(读 `harness.json` `defaultWorktree`)。必须同时展示 **in_scope 与 out_of_scope 两个列表**——只展示"做什么"会让范围误判活到发布之后,代价是整份计划 republish |
|
|
124
|
+
| 引用即追问 | 需求引用了外部设计文档章节(贴段落、指 `### Bn`、说"之前设计的时候如…")时,阶段 2 必须确认该章节是否纳入本次范围,落到 in_scope 或 out_of_scope;引用 ≠ 纳入,也 ≠ 排除 |
|
|
122
125
|
| 阶段 8 | 二选一且不得混用:**v2** = `hunter-harness plan finalize`(证据包 → 八 target + journal committed + plan-events.ndjson);**legacy** = 六项标准产物先进入 staging,仅 finalizer 校验成功后发布并写唯一 `phase.end`/log,随后 `verify` 确认 start/end、收据完整覆盖六项标准产物、哈希、全部任务表和非空场景清单一致。失败均不得手工补终态 |
|
|
123
126
|
| 发布后改产物 | 用 `harness_plan_finalize.py republish --run-id <全新> --reason "<why>"` 一次完成(新 attempt + 换收据 + 重新派生 manifest)。重跑 `finalize` 会报 `PLAN_FINALIZATION_HASH_CONFLICT`;**绝不手改 `meta/scenario-manifest.json`**(派生物,手改必致 `ARTIFACT_HASH_DRIFT`)→ `reference.md`「发布后修订计划」 |
|
|
124
|
-
| v2 输入骨架 | 不要猜 `plan-evidence-input.json`
|
|
127
|
+
| v2 输入骨架 | 不要猜 `plan-evidence-input.json` 结构:`npx hunter-harness plan evidence-pack --print-template` 给出**一个字不改就能通过 evidence-pack** 的骨架(结构合法;`change_key`/`run_id` 仍须换成真实身份才能 finalize),逐项替换即可。结构不符时命令返回 `PLAN_EVIDENCE_INPUT_INVALID`,带 `field_path` 与 `problems[]`(缺失/多余键、枚举取值)——按 problems 改完重跑;**不得**为找契约去反编译 `dist/bin.js` 或翻 npx 缓存。带不了 `<>` 的占位字段与硬约束清单 → `reference.md` 阶段 8 v2 路径 |
|
|
125
128
|
| Plan 结束 | **禁止**询问执行模式;只提示 `/harness-run` |
|
|
126
129
|
| 知识查询 | 阶段 1 失败不得假装已读历史,也不得改用本地索引或其他执行入口 |
|
|
130
|
+
| 读命令输出 | `--json` 输出是完整结构,**不得**接 `\| tail -N` / `\| head -N` 后据此判断——截断的 JSON 解析不了,只会逼出一次补读。输出太长时读命令写下的文件(classify → `meta/gate-policy.json`),或用 `bootstrap-plan` 的紧凑摘要 |
|
|
127
131
|
| 歧义优先检查 | 否定、对比、动作对象或范围存在多种合理解释时,最小取证后先给推荐理解并一次一问;确认前不深挖错误方向 |
|
|
128
132
|
| 简单修复探索预算 | 预计不超过 2 个代码文件、且不涉及认证/安全/迁移/并发/API 契约重设时,最多 1 次合并 CodeGraph 查询 + 1 次定向补查、1 个用户澄清问题;无关发现只记非阻断说明 |
|
|
129
133
|
| 精简产物 | 简单修复只保留实现所需的设计、任务、边界和测试;禁止在 spec/plan/detail/scenarios 中重复同一背景和结论 |
|
|
@@ -141,7 +145,7 @@ change-name 范围变更 → 提示重命名或记 🟡WARN(→ `reference.md`
|
|
|
141
145
|
|
|
142
146
|
## 交互白名单
|
|
143
147
|
|
|
144
|
-
1. **设计审批包**(阶段 4):设计 + 场景表 + worktree + change-name
|
|
148
|
+
1. **设计审批包**(阶段 4):设计 + **范围(做什么/不做什么)** + 场景表 + worktree + change-name
|
|
145
149
|
2. **decision-grilling**(阶段 2/3 澄清):语义歧义或高风险业务裁决(一次一问)
|
|
146
150
|
|
|
147
151
|
## 执行日志
|
|
@@ -12,9 +12,12 @@ description: harness-plan 的阶段检查清单和覆盖检查列表。仅在执
|
|
|
12
12
|
|
|
13
13
|
**判定**:stdout 为空 → ✅ 继续;stdout 非空 → baseline 隔离 + `decision`(note 含变更文件列表);Bash 被拒 → PowerShell 重试。
|
|
14
14
|
|
|
15
|
-
## 阶段 0.5
|
|
15
|
+
## 阶段 0.5:一次性引导与知识查询
|
|
16
16
|
|
|
17
|
-
- [ ]
|
|
17
|
+
- [ ] 定好 change-name(kebab-case)与中文展示标题后,运行一次 `harness_context.py bootstrap-plan --project . --change <cn> --executor <tool> --title "<中文标题>" --json`
|
|
18
|
+
- [ ] 引导返回 `code:"PLAN_BOOTSTRAPPED"`,记下 `runId`/`attempt`/`tier`/`defaultPhases`/`changeBase`;后续 finalize 必须复用同一 `runId`/`attempt`
|
|
19
|
+
- [ ] 不再手工生成 run-id、不再单独跑 doctor/prepare/capture/classify/append;需要单步排查时才用 SKILL.md 阶段 0.5b 的等价分解
|
|
20
|
+
- [ ] 引导失败时按返回的 `code` 处理(`PROJECT_ROOT_INVALID` → 该项目未 init),**不得**跳过引导直接写产物
|
|
18
21
|
- [ ] 项目已绑定平台时执行一次远端 knowledge `query`;不另跑前置 sync,不创建本地索引
|
|
19
22
|
- [ ] 查询失败追加 `issue`,不得回退本地 archive/SQLite、重跑“sync + query”循环或假装已读取历史
|
|
20
23
|
|
|
@@ -22,6 +25,7 @@ description: harness-plan 的阶段检查清单和覆盖检查列表。仅在执
|
|
|
22
25
|
|
|
23
26
|
- [ ] 否定、对比、动作对象、范围或保留/删除关系不存在未确认的多义解释
|
|
24
27
|
- [ ] 若存在歧义,仅完成最小取证后一次一问,并给出推荐理解
|
|
28
|
+
- [ ] **需求里引用了外部设计文档/章节(贴了段落、给了 `xxx.md` 的 `### Bn` 小节、说"之前设计的时候如…")时,必须确认该章节本次是否纳入**——引用不等于纳入,也不等于排除。把它列进 `in_scope` 或 `out_of_scope` 后再进入阶段 4;漏判会导致计划发布后整体作废重来(republish),是本流程最贵的返工
|
|
25
29
|
- [ ] 简单修复探索预算:最多 1 次合并 CodeGraph 查询 + 1 次定向补查、1 个澄清问题
|
|
26
30
|
- [ ] 无关发现只记非阻断 `issue`,未扩展当前方案或问题列表
|
|
27
31
|
|
|
@@ -65,16 +69,21 @@ description: harness-plan 的阶段检查清单和覆盖检查列表。仅在执
|
|
|
65
69
|
**展示内容**:
|
|
66
70
|
|
|
67
71
|
1. 设计摘要 + 关键证据 + 风险 + 变更清单
|
|
68
|
-
2.
|
|
69
|
-
3.
|
|
70
|
-
4.
|
|
71
|
-
5.
|
|
72
|
+
2. **本次做什么(in_scope)/ 本次不做什么(out_of_scope)** — 两个列表都必须显式列出,不得只展示"做什么"。用户看到"不做"清单才有机会当场纠正范围误判;`out_of_scope` 为空时写"无",不得省略该行。这两个列表随后原样进入 `plan-evidence-input.json` 的 `intent` 与 `approval.content`(两处必须集合相等)
|
|
73
|
+
3. 测试场景表摘要 + 8 维度覆盖检查
|
|
74
|
+
4. worktree 选项(是/否,含推荐理由)
|
|
75
|
+
5. change-name(自动生成,可修改)
|
|
76
|
+
6. 确认进入任务拆分
|
|
72
77
|
|
|
73
|
-
|
|
78
|
+
确认后立即追加 decision 事件,并写入 `meta/worktree.json`。设计文档按路径分流:
|
|
79
|
+
|
|
80
|
+
- **v2**:审批内容写进 `meta/plan-evidence-input.json` 的 `approval.content`(含 `approver_id`),
|
|
81
|
+
`plans/<change>-design.md` 由 finalize 从审批内容派生——**不要**手写它,手写的会被覆盖
|
|
82
|
+
- **legacy**:写 `spec/<change>-design.md`(含下方 frontmatter)
|
|
74
83
|
|
|
75
84
|
- [ ] 确认事件早于 approved 设计文档;未获确认时不得先落盘 `status: approved`
|
|
76
85
|
|
|
77
|
-
设计文档必须包含 frontmatter:
|
|
86
|
+
legacy 设计文档必须包含 frontmatter:
|
|
78
87
|
```yaml
|
|
79
88
|
---
|
|
80
89
|
change-name: <change-name>
|
|
@@ -209,6 +218,37 @@ source: harness-plan
|
|
|
209
218
|
|
|
210
219
|
> **缺任一文件 → ❌FAIL,不得宣称 plan 完成。**
|
|
211
220
|
|
|
221
|
+
> **先认路径再对表**:v2 与 legacy 的完整性口径不同,混用会得出错误结论。
|
|
222
|
+
|
|
223
|
+
### v2 路径(新 change 默认)
|
|
224
|
+
|
|
225
|
+
- [ ] 只手写 `meta/plan-evidence-input.json`;`plans/*.md` 由 finalize 派生,**不得**手写后再被覆盖
|
|
226
|
+
- [ ] `evidence-pack` 返回 `code:"PLAN_EVIDENCE_PACK_BUILT"`;结构报错按 `field_path`/`problems[]` 修正后重跑
|
|
227
|
+
- [ ] `finalize` exit 0 且 `code:"PLAN_FINALIZED"`
|
|
228
|
+
- [ ] 八 target 齐全:`plans/` ×4(design / implementation-detail / plan / test-scenarios)+ `meta/` ×4(gate-policy / implementation-checkpoints / scenario-manifest / worktree)
|
|
229
|
+
- [ ] `meta/publication-journals/<op>.json` 的 `state === "committed"`
|
|
230
|
+
- [ ] `meta/plan-events.ndjson` 含 `artifact_published` 与 `phase_ended` 两类终态事件
|
|
231
|
+
- [ ] 以上任一缺失都不得手工补写;回到对应阶段改自然输入后重跑
|
|
232
|
+
|
|
233
|
+
| 文件(v2) | 必须存在 | 检查结果 |
|
|
234
|
+
|------|:---:|:---:|
|
|
235
|
+
| `.harness/changes/<change>/meta/plan-evidence-input.json` | ✅ | □ |
|
|
236
|
+
| `.harness/changes/<change>/plans/<change>-design.md` | ✅ | □ |
|
|
237
|
+
| `.harness/changes/<change>/plans/<change>-plan.md` | ✅ | □ |
|
|
238
|
+
| `.harness/changes/<change>/plans/<change>-implementation-detail.md` | ✅ | □ |
|
|
239
|
+
| `.harness/changes/<change>/plans/<change>-test-scenarios.md` | ✅ | □ |
|
|
240
|
+
| `.harness/changes/<change>/meta/gate-policy.json` | ✅ | □ |
|
|
241
|
+
| `.harness/changes/<change>/meta/worktree.json` | ✅ | □ |
|
|
242
|
+
| `.harness/changes/<change>/meta/implementation-checkpoints.json` | ✅ | □ |
|
|
243
|
+
| `.harness/changes/<change>/meta/scenario-manifest.json`(非空且计数一致) | ✅ | □ |
|
|
244
|
+
| `.harness/changes/<change>/meta/publication-journals/<op>.json`(committed) | ✅ | □ |
|
|
245
|
+
| `.harness/changes/<change>/meta/plan-events.ndjson` | ✅ | □ |
|
|
246
|
+
| `.harness/changes/<change>/events.ndjson` | ✅ | □ |
|
|
247
|
+
|
|
248
|
+
> v2 过渡期**不写** `meta/plan-finalization.json` 与 `logs/execution-log.md`;缺这两项不算失败,不得为凑表手工补。
|
|
249
|
+
|
|
250
|
+
### legacy 路径(自然输入不完整时的回退)
|
|
251
|
+
|
|
212
252
|
- [ ] 所有待发布产物先写入 staging,不直接覆盖正式 change 目录
|
|
213
253
|
- [ ] 执行 `harness_plan_finalize.py finalize --change-dir ... --staging-dir ... --change ... --run-id <plan-run-id> --attempt <attempt> --json`;身份必须与本次 `phase.start` 完全相同
|
|
214
254
|
- [ ] finalizer 返回 `ok=true`、`artifactsHash`、绝对 `receiptPath` 与稳定 `artifactRef=meta/plan-finalization.json`;重复执行返回 `idempotent=true`
|
|
@@ -220,7 +260,7 @@ source: harness-plan
|
|
|
220
260
|
- [ ] 禁止在 finalizer 之前手工追加成功 `phase.end`
|
|
221
261
|
- [ ] context close 的 `--artifact` 只传 finalizer 原样返回的 `receiptPath` 或 `artifactRef`,不得猜测、拼接或使用 `<plan-finalization>` 占位文本
|
|
222
262
|
|
|
223
|
-
|
|
|
263
|
+
| 文件(legacy) | 必须存在 | 检查结果 |
|
|
224
264
|
|------|:---:|:---:|
|
|
225
265
|
| `.harness/changes/<change>/spec/<change>-design.md` | ✅ | □ |
|
|
226
266
|
| `.harness/changes/<change>/plans/<change>-plan.md` | ✅ | □ |
|
|
@@ -104,11 +104,16 @@ description: harness-plan 的需求提取模板、任务拆分规则、测试场
|
|
|
104
104
|
|
|
105
105
|
> **本阶段是强制检查点。** 先展示设计审批包,收到确认并追加 decision 事件后,才能落盘 `status: approved` 的设计文档并进入阶段 6(任务拆分)。设计方向正确后再细化任务,避免基于错误理解拆分无效任务。
|
|
106
106
|
|
|
107
|
-
|
|
107
|
+
**用户确认后必须立即追加 decision 事件**,然后按路径分流落盘:
|
|
108
108
|
|
|
109
|
-
|
|
109
|
+
| 路径 | 审批内容去哪 | 设计文档 |
|
|
110
|
+
|------|------------|---------|
|
|
111
|
+
| **v2**(默认) | `meta/plan-evidence-input.json` 的 `approval.content` + `approver_id` | `plans/<change-name>-design.md`,由 finalize 从审批内容派生——**不要手写**,手写的会被派生渲染覆盖 |
|
|
112
|
+
| **legacy** | 直接写文档 | `.harness/changes/<change-name>/spec/<change-name>-design.md`(不存在则不得进入阶段 6) |
|
|
110
113
|
|
|
111
|
-
|
|
114
|
+
**设计文档路径规则**:禁止保存到 `docs/superpowers/specs/` 作为正式产物;`/harness-plan` 不运行时调用 Superpowers。同一 change 不得同时存在 `plans/` 与 `spec/` 两份设计——v2 发布的那份才受完整性门禁保护。
|
|
115
|
+
|
|
116
|
+
### 设计文档模板(legacy 路径手写时使用;v2 由 finalize 派生,此模板仅作内容清单参考)
|
|
112
117
|
|
|
113
118
|
```markdown
|
|
114
119
|
---
|
|
@@ -181,15 +186,19 @@ source: harness-plan
|
|
|
181
186
|
|
|
182
187
|
### 产物结构
|
|
183
188
|
|
|
184
|
-
推荐结构:
|
|
185
|
-
|
|
186
189
|
```
|
|
187
190
|
.harness/changes/<change-name>/plans/
|
|
191
|
+
├── <change-name>-design.md # 设计(v2 由 finalize 派生)
|
|
188
192
|
├── <change-name>-plan.md # harness 简洁任务表,run 默认读取
|
|
189
193
|
├── <change-name>-implementation-detail.md # 原生自适应详细执行参考,run 补充读取
|
|
190
194
|
└── <change-name>-test-scenarios.md # 测试场景表
|
|
191
195
|
```
|
|
192
196
|
|
|
197
|
+
> **v2 路径下这四份都是派生产物**:唯一手写的是 `meta/plan-evidence-input.json`。
|
|
198
|
+
> 阶段 6 的任务拆分结果直接填进它的 `structured_input.tasks`,阶段 7 的场景填 `structured_input.scenarios`——
|
|
199
|
+
> 同一份内容不要先写成 Markdown 再誊进 JSON,finalize 会用派生渲染覆盖手写的 Markdown。
|
|
200
|
+
> 下面的 Markdown 格式说明用于**理解字段语义**与 legacy 路径手写。
|
|
201
|
+
|
|
193
202
|
### 计划文件 frontmatter(必须)
|
|
194
203
|
|
|
195
204
|
```yaml
|
|
@@ -284,10 +293,12 @@ status: approved
|
|
|
284
293
|
.harness/changes/<change-name>/backups/
|
|
285
294
|
```
|
|
286
295
|
|
|
287
|
-
3.
|
|
288
|
-
-
|
|
296
|
+
3. **保存设计文档**:
|
|
297
|
+
- **v2**:不手写文档;把审批内容填进 `meta/plan-evidence-input.json` 的 `approval.content`,
|
|
298
|
+
`plans/<change-name>-design.md` 由 finalize 派生(frontmatter 也由渲染器写)
|
|
299
|
+
- **legacy**:保存到 `.harness/changes/<change-name>/spec/<change-name>-design.md`
|
|
289
300
|
|
|
290
|
-
设计文档 frontmatter 格式:
|
|
301
|
+
legacy 设计文档 frontmatter 格式:
|
|
291
302
|
```yaml
|
|
292
303
|
---
|
|
293
304
|
change-name: <change-name>
|
|
@@ -299,14 +310,17 @@ status: approved
|
|
|
299
310
|
|
|
300
311
|
> 如果 frontmatter 缺失,后续 run/test/review/submit/archive 不得依赖模型猜测 change-name。
|
|
301
312
|
|
|
302
|
-
4.
|
|
313
|
+
4. **初始化结构化事件**:由阶段 0.5 的 `harness_context.py bootstrap-plan` 一次完成——它生成合规的 `<plan-run-id>`(`plan_<uuid>` 形状,必须小写字母开头:v2 identity 规则,裸 UUID 有 10/16 概率数字开头被拒)、`<attempt>`(首次为 `1`)并追加 `phase.start`,重跑复用同一身份不重复写事件。finalizer 必须复用引导返回的 `runId`/`attempt`,否则 verify 会按生命周期身份 fail-closed。同一次 plan 尝试内不得改变身份。执行日志在 `phase.end` 时由完整事件流渲染,任何阶段都不得直接用 Write/Edit 维护该投影。
|
|
303
314
|
|
|
304
|
-
5.
|
|
305
|
-
-
|
|
306
|
-
|
|
307
|
-
-
|
|
315
|
+
5. **保存计划文件**:
|
|
316
|
+
- **v2**:不手写;任务填 `structured_input.tasks`、场景填 `structured_input.scenarios`,
|
|
317
|
+
`plans/` 下四份 Markdown 全部由 finalize 派生
|
|
318
|
+
- **legacy**:手写并保存到(含 YAML frontmatter,含 change-name)
|
|
319
|
+
- `.harness/changes/<change-name>/plans/<change-name>-plan.md`(简洁任务表)
|
|
320
|
+
- `.harness/changes/<change-name>/plans/<change-name>-implementation-detail.md`(自适应详细执行参考)
|
|
321
|
+
- `.harness/changes/<change-name>/plans/<change-name>-test-scenarios.md`(测试场景表)
|
|
308
322
|
|
|
309
|
-
计划文件 frontmatter 格式:
|
|
323
|
+
legacy 计划文件 frontmatter 格式:
|
|
310
324
|
```yaml
|
|
311
325
|
---
|
|
312
326
|
change-name: <change-name>
|
|
@@ -327,23 +341,27 @@ status: approved
|
|
|
327
341
|
|
|
328
342
|
## 阶段 8:结束前产物完整性检查 ⚠️ 强制
|
|
329
343
|
|
|
330
|
-
> **缺任一文件 → ❌FAIL,不得宣称 plan
|
|
331
|
-
|
|
332
|
-
| 文件 |
|
|
333
|
-
|
|
334
|
-
| `.harness/changes/<change>/
|
|
335
|
-
| `.harness/changes/<change>/plans/<change>-
|
|
336
|
-
| `.harness/changes/<change>/
|
|
337
|
-
| `.harness/changes/<change>/plans/<change>-
|
|
338
|
-
| `.harness/changes/<change>/
|
|
339
|
-
| `.harness/changes/<change>/
|
|
340
|
-
| `.harness/changes/<change>/meta/
|
|
341
|
-
| `.harness/changes/<change>/meta/
|
|
342
|
-
| `.harness/changes/<change>/meta/
|
|
343
|
-
| `.harness/changes/<change>/
|
|
344
|
-
| `.harness/changes/<change>/
|
|
345
|
-
|
|
346
|
-
|
|
344
|
+
> **缺任一文件 → ❌FAIL,不得宣称 plan 完成。先认清走的是 v2 还是 legacy——两条路径的必需文件集不同,拿 legacy 的表去查 v2 会得出假失败。**
|
|
345
|
+
|
|
346
|
+
| 文件 | v2 | legacy |
|
|
347
|
+
|------|:---:|:---:|
|
|
348
|
+
| `.harness/changes/<change>/meta/plan-evidence-input.json` | ✅ | — |
|
|
349
|
+
| `.harness/changes/<change>/plans/<change>-design.md` | ✅(派生) | — |
|
|
350
|
+
| `.harness/changes/<change>/spec/<change>-design.md` | — | ✅ |
|
|
351
|
+
| `.harness/changes/<change>/plans/<change>-plan.md` | ✅(派生) | ✅ |
|
|
352
|
+
| `.harness/changes/<change>/plans/<change>-implementation-detail.md` | ✅(派生) | ✅ |
|
|
353
|
+
| `.harness/changes/<change>/plans/<change>-test-scenarios.md` | ✅(派生) | ✅ |
|
|
354
|
+
| `.harness/changes/<change>/meta/gate-policy.json` | ✅ | ✅ |
|
|
355
|
+
| `.harness/changes/<change>/meta/worktree.json` | ✅ | ✅ |
|
|
356
|
+
| `.harness/changes/<change>/meta/implementation-checkpoints.json` | ✅ | ✅ |
|
|
357
|
+
| `.harness/changes/<change>/meta/scenario-manifest.json` | ✅ | ✅ |
|
|
358
|
+
| `.harness/changes/<change>/meta/publication-journals/<op>.json`(committed) | ✅ | — |
|
|
359
|
+
| `.harness/changes/<change>/meta/plan-events.ndjson` | ✅ | — |
|
|
360
|
+
| `.harness/changes/<change>/meta/plan-finalization.json` | — | ✅ |
|
|
361
|
+
| `.harness/changes/<change>/logs/execution-log.md` | — | ✅ |
|
|
362
|
+
| `.harness/changes/<change>/events.ndjson` | ✅ | ✅ |
|
|
363
|
+
|
|
364
|
+
legacy 的 `plan-finalization.json.files` 必须完整列出 design、plan、implementation-detail、test-scenarios、gate-policy、worktree 六项标准输入。`verify` 对缺项、重复项、越界路径以及 symlink/junction/reparse point 一律 fail-closed;不得通过删减收据文件集后重算哈希来绕过完整性检查。
|
|
347
365
|
|
|
348
366
|
### 阶段 8 v2 路径(结构化证据包流程,新 change 优先)
|
|
349
367
|
|
|
@@ -363,8 +381,32 @@ npx hunter-harness plan finalize --input .harness/changes/<cn>/meta/plan-evidenc
|
|
|
363
381
|
> ```bash
|
|
364
382
|
> npx hunter-harness plan evidence-pack --print-template > .harness/changes/<cn>/meta/plan-evidence-input.json
|
|
365
383
|
> ```
|
|
366
|
-
>
|
|
367
|
-
>
|
|
384
|
+
> **骨架一个字不改就能通过 `evidence-pack`**(回归测试冻结这条不变量),所以可以先跑一次确认链路通,再逐项替换。
|
|
385
|
+
> 注意这只保证结构合法:`finalize` 还要求 `change_key` 与 `run_id` 是本次真实身份,占位值过不了发布。
|
|
386
|
+
> 自由文本字段用 `<...>` 占位,替换完 grep 一次 `<` 自检有无遗漏。`--print-template` 不读写任何文件,只打到 stdout。
|
|
387
|
+
|
|
388
|
+
**带不了 `<>` 的占位字段**(受枚举/哈希/命名约束,grep `<` 查不出来,必须逐个确认):
|
|
389
|
+
|
|
390
|
+
| 字段 | 模板占位值 | 换成什么 |
|
|
391
|
+
|------|-----------|---------|
|
|
392
|
+
| `change_key` | `replace-with-change-name` | 真实 change-name(kebab-case:`^[a-z0-9]+(-[a-z0-9]+)*$`) |
|
|
393
|
+
| `context.run_id` | `plan_replace-with-your-plan-run-id` | 阶段 0.5 生成、`phase.start` 已用的**同一个** plan-run-id |
|
|
394
|
+
| `evidence_sources[].content_hash` | `sha256:deadbeef…` | 证据源内容的真实 sha256(校验器显式拒绝全 0) |
|
|
395
|
+
| `risk_signals` | `["production_code"]` | classify 实际返回的信号 |
|
|
396
|
+
|
|
397
|
+
**容易踩的硬约束**(违反时命令会给 `field_path`,不必再猜):
|
|
398
|
+
|
|
399
|
+
- `structured_input.scenarios` **至少 3 条**——八维度缺项由命令补 `not_applicable`,但场景总数不能少于 3
|
|
400
|
+
- `intent.acceptance_examples` 2~5 条,`approval.content.acceptance_examples` 3~7 条 → 取 3 条同时满足
|
|
401
|
+
- `key_alternatives` / `invariants` / `failure_behaviors` / `compatibility_boundaries` 各至少 1 条
|
|
402
|
+
- `intent.in_scope`/`out_of_scope` 与 `approval.content` 同名字段必须**集合相等**
|
|
403
|
+
- tasks 只写 `task_id/objective/affected_paths/owner_phase`,六个 refs 数组由命令接线;多写 `cluster`/`title` 这类键会因精确键集被拒
|
|
404
|
+
- scenarios 只写 `scenario_id/title/acceptance/coverage_dimension/execution_level/evidence_requirements/risk_level`(+可选 `verification_command`);`priority`/`test_file` 这类计划表列不属于本输入
|
|
405
|
+
- `machine.worktree_policy` ∈ `project_default | required | forbidden`(没有 `none`)
|
|
406
|
+
|
|
407
|
+
> **结构错了怎么读报错**:命令在边界返回 `code:"PLAN_EVIDENCE_INPUT_INVALID"`(`stage:"boundary"`),
|
|
408
|
+
> `field_path` 指向第一处问题,`problems[]` 逐条给 `missing_keys`/`unexpected_keys`/`message`。
|
|
409
|
+
> 按 `problems` 改完重跑即可——**不需要**去反编译 `dist/bin.js` 或翻 npx 缓存找校验器。
|
|
368
410
|
|
|
369
411
|
| 字段 | 内容 | 定稿阶段 |
|
|
370
412
|
|------|------|:---:|
|
|
@@ -380,6 +422,14 @@ npx hunter-harness plan finalize --input .harness/changes/<cn>/meta/plan-evidenc
|
|
|
380
422
|
| `context` | project_id/run_id/branch_name/attempt(复用 plan-run-id 与 attempt) | 0.5 |
|
|
381
423
|
| `expected_baseline` | 首次发布 `{state:"absent", manifest_hash:null, generation:0}` | 8 |
|
|
382
424
|
|
|
425
|
+
> ⚠️ **已知缺口:v2 派生的 `meta/scenario-manifest.json` 目前喂不了 run/test 门禁。**
|
|
426
|
+
> 它是 artifact 包装体,每条场景只有 `scenario_id/coverage_dimension/execution_level/
|
|
427
|
+
> evidence_requirements/risk_level/task_refs/requirement_refs`;而门禁按
|
|
428
|
+
> `id/priority/requiredEvidenceKind/ownerPhase/executableTestId/testFile/testTitle`
|
|
429
|
+
> 判定哪些场景需要 ledger 证据。缺 `priority` 与 `requiredEvidenceKind` 时"必需场景"会算成空集,
|
|
430
|
+
> 所以门禁**明确报 `SCENARIO_MANIFEST_V2_UNSUPPORTED` 并列出 `missingFields`,绝不静默放行**。
|
|
431
|
+
> 需要 ledger 证据闭环的变更,在 v2 场景契约补齐这些字段前请走 legacy 路径。
|
|
432
|
+
|
|
383
433
|
- **证据包**(`plan-evidence.json`)是命令推导的产物(trusted/publication/context/baseline),不得手改;任何字段变化必须改自然输入后重跑 evidence-pack。
|
|
384
434
|
- **成功语义**:finalize exit 0 且 `code:"PLAN_FINALIZED"`。落盘事实 = 八 target(plans/*.md ×4 + meta/*.json ×4)+ `meta/publication-journals/<op>.json`(状态 committed)+ `meta/plan-events.ndjson`(artifact_published/phase_ended)。确定性门失败 exit 1 且 `code:"PLAN_FINALIZE_DETERMINISTIC_FAILED"` 附 findings——此时必须回到对应阶段修正规划内容,**不得**手改证据包或 staged 内容绕过。
|
|
385
435
|
- **验证**:journal `state==="committed"` + 八 target 存在 + plan-events.ndjson 含两类终态事件;不得手工补写任何一项。
|
|
@@ -21,7 +21,7 @@ disallowed-tools:
|
|
|
21
21
|
- Bash(awk *)
|
|
22
22
|
- Bash(curl *)
|
|
23
23
|
---
|
|
24
|
-
<!-- generated by harness_deploy.py; core=
|
|
24
|
+
<!-- generated by harness_deploy.py; core=d79ae315e929446c; overlay=none; agent=claude-code; do not edit -->
|
|
25
25
|
# harness-pull — 从 Hunter Platform 下拉与恢复
|
|
26
26
|
|
|
27
27
|
## Purpose
|
|
@@ -34,7 +34,7 @@ disallowed-tools:
|
|
|
34
34
|
|
|
35
35
|
## 前置条件
|
|
36
36
|
|
|
37
|
-
-
|
|
37
|
+
- 远端同步已配置:优先读环境变量 `HUNTER_REMOTE_SYNC_URL`、`HUNTER_REMOTE_SYNC_TOKEN`、`HUNTER_REMOTE_SYNC_ACTOR_ID`;缺失字段回退到 `hunter-harness connect` 写入的 `.harness/credentials.local.yaml`(含 actor_id;旧绑定缺该字段时 CLI 经 key-info 自动补全并写回)。两者都缺时 CLI 固定 fail closed(`PUSH_PULL_CLI_UNAVAILABLE`)。
|
|
38
38
|
- 分支文件恢复必须显式 `--scope branch_files --branch <来源分支>`;归档不出现在常规下拉范围(单个归档 ZIP 经 Platform 变更记录单独下载)。
|
|
39
39
|
|
|
40
40
|
## 交互流程
|
|
@@ -21,7 +21,7 @@ disallowed-tools:
|
|
|
21
21
|
- Bash(awk *)
|
|
22
22
|
- Bash(curl *)
|
|
23
23
|
---
|
|
24
|
-
<!-- generated by harness_deploy.py; core=
|
|
24
|
+
<!-- generated by harness_deploy.py; core=d79ae315e929446c; overlay=none; agent=claude-code; do not edit -->
|
|
25
25
|
# harness-push — 上传到 Hunter Platform
|
|
26
26
|
|
|
27
27
|
## Purpose
|
|
@@ -34,7 +34,7 @@ disallowed-tools:
|
|
|
34
34
|
|
|
35
35
|
## 前置条件
|
|
36
36
|
|
|
37
|
-
-
|
|
37
|
+
- 远端同步已配置:优先读环境变量 `HUNTER_REMOTE_SYNC_URL`、`HUNTER_REMOTE_SYNC_TOKEN`、`HUNTER_REMOTE_SYNC_ACTOR_ID`;缺失字段回退到 `hunter-harness connect` 写入的 `.harness/credentials.local.yaml`(含 actor_id;旧绑定缺该字段时 CLI 经 key-info 自动补全并写回)。两者都缺时 CLI 固定 fail closed(`PUSH_PULL_CLI_UNAVAILABLE`),**不得**改用旧 HTTP fallback 或手工 API 调用。
|
|
38
38
|
- 归档上传只选择已写入 outbox 的确定性包(阶段 06 产物);不存在可复用包时提示先完成本地归档,**不得**在 Push 内隐式补做 finalize/重建 ZIP。
|
|
39
39
|
|
|
40
40
|
## 交互流程
|
|
@@ -22,7 +22,7 @@ disallowed-tools:
|
|
|
22
22
|
- Bash(curl *)
|
|
23
23
|
- Bash(codegraph *)
|
|
24
24
|
---
|
|
25
|
-
<!-- generated by harness_deploy.py; core=
|
|
25
|
+
<!-- generated by harness_deploy.py; core=d79ae315e929446c; overlay=none; agent=claude-code; do not edit -->
|
|
26
26
|
# harness-review — 代码审查
|
|
27
27
|
|
|
28
28
|
## Purpose
|
|
@@ -49,9 +49,9 @@ disallowed-tools:
|
|
|
49
49
|
## 统一读取协议
|
|
50
50
|
|
|
51
51
|
1. **`.harness/changes/<change-name>/` 是唯一真相源** — 所有输入从该目录读取,产物写入对应子目录
|
|
52
|
-
2. **change-name 优先从 frontmatter 读取** — `spec/*-design.md`、`plans/*-plan.md` 的 YAML `change-name`
|
|
52
|
+
2. **change-name 优先从 frontmatter 读取** — `plans/*-design.md`、`spec/*-design.md`、`plans/*-plan.md` 的 YAML `change-name`
|
|
53
53
|
3. **frontmatter 缺失时兼容旧格式** — 从路径推断,标记 `🟡 legacy-plan`,不失败
|
|
54
|
-
4. **
|
|
54
|
+
4. **design** — 设计真相源按序取第一个存在的:`plans/<change>-design.md`(v2 发布产物,哈希绑定)→ `spec/<change>-design.md`(legacy 手写)。两份**同时存在**时以 `plans/` 为准,并记 `🟡 WARN 设计文档双份`——v2 发布的那份才受完整性门禁保护,读手写的那份等于绕过校验
|
|
55
55
|
5. **plan** — 任务真相源:`plans/<change>-plan.md`
|
|
56
56
|
6. **implementation-detail** — 自适应执行参考;legacy 缺失 🟡WARN,不阻断
|
|
57
57
|
7. **test-scenarios** — 测试真相源:`plans/<change>-test-scenarios.md`
|
|
@@ -22,7 +22,7 @@ disallowed-tools:
|
|
|
22
22
|
- Bash(curl *)
|
|
23
23
|
- Bash(codegraph *)
|
|
24
24
|
---
|
|
25
|
-
<!-- generated by harness_deploy.py; core=
|
|
25
|
+
<!-- generated by harness_deploy.py; core=d79ae315e929446c; overlay=none; agent=claude-code; do not edit -->
|
|
26
26
|
# harness-run — 需求编码
|
|
27
27
|
|
|
28
28
|
## Purpose
|
|
@@ -37,7 +37,7 @@ disallowed-tools:
|
|
|
37
37
|
|
|
38
38
|
## 前置条件
|
|
39
39
|
|
|
40
|
-
- `spec/*-design.md
|
|
40
|
+
- 设计文档(`plans/*-design.md` 优先,回退 `spec/*-design.md`)与 `plans/*-plan.md`(含 frontmatter)存在且已审批
|
|
41
41
|
- 读 `meta/worktree.json`:`requested=true` 时 worktree 须存在或 run 负责创建
|
|
42
42
|
|
|
43
43
|
## Worktree 门禁
|
|
@@ -60,9 +60,9 @@ disallowed-tools:
|
|
|
60
60
|
## 统一读取协议
|
|
61
61
|
|
|
62
62
|
1. **`.harness/changes/<change-name>/` 是唯一真相源** — 所有输入从该目录读取,产物写入对应子目录
|
|
63
|
-
2. **change-name 优先从 frontmatter 读取** — `spec/*-design.md`、`plans/*-plan.md` 的 YAML `change-name`
|
|
63
|
+
2. **change-name 优先从 frontmatter 读取** — `plans/*-design.md`、`spec/*-design.md`、`plans/*-plan.md` 的 YAML `change-name`
|
|
64
64
|
3. **frontmatter 缺失时兼容旧格式** — 从路径推断,标记 `🟡 legacy-plan`,不失败
|
|
65
|
-
4. **
|
|
65
|
+
4. **design** — 设计真相源按序取第一个存在的:`plans/<change>-design.md`(v2 发布产物,哈希绑定)→ `spec/<change>-design.md`(legacy 手写)。两份**同时存在**时以 `plans/` 为准,并记 `🟡 WARN 设计文档双份`——v2 发布的那份才受完整性门禁保护,读手写的那份等于绕过校验
|
|
66
66
|
5. **plan** — 任务真相源:`plans/<change>-plan.md`
|
|
67
67
|
6. **implementation-detail** — 自适应执行参考;legacy 缺失 🟡WARN,不阻断
|
|
68
68
|
7. **test-scenarios** — 测试真相源:`plans/<change>-test-scenarios.md`
|
|
@@ -78,7 +78,7 @@ disallowed-tools:
|
|
|
78
78
|
|
|
79
79
|
## Workflow 概要
|
|
80
80
|
|
|
81
|
-
0. 加载上下文:普通 Run 先 `harness_context.py prepare --
|
|
81
|
+
0. 加载上下文:普通 Run 先 `harness_context.py prepare --project . --change <id> --phase run --executor <tool> --json`(`--project` 必填,漏了直接 argparse 报错),再 **`harness_context.py begin --project . --change <id> --phase run --executor <tool> --json`** 校验交接,最后运行 **`harness_gate.py begin --phase run --change <id>`**。<br>**交接凭证不必手工补**:v2 计划的 `plan finalize` 不写 context 事务,`prepare` 会在检测到 committed 的 `meta/publication-journals/*.json` 时自动补录 `plan → run` 凭证(凭证带 `bootstrapSource=plan_publication_journal` 留痕)。仍报 `HANDOFF_REQUIRED`/`LEGACY_BOOTSTRAP_REQUIRED` 说明**没有**这份发布证据——回到 plan 阶段确认发布是否真的完成,**不得**自己拼 `classify + configure-plan + close` 造凭证。`harness_gate.py` 会从当前已安装适配器自动识别 skills root;只有执行复制到别处的脚本时才显式传 `--skills-root`。`--fixback` 不得拼装这些底层步骤,必须只调用一次 `harness_fixback.py launch-review --project . --change <id> --change-dir <change-dir> --executor <tool> --skills-root <skills-root> --product-identity <当前产品身份> --json`:该命令会先筛选结构化评审项,再原子选择 Fixback 分支、确认上下文、取得 Run 门禁并创建已填充批次。返回 `FIXBACK_NOTHING_TO_APPLY` 时直接报告“本轮评审没有需要执行的代码修复”并停止;返回阻塞码时按 `recoveryAction` 停止,不搜索实现、不试探其他参数、不创建空批次。禁止手写 `events.ndjson` / `phase.end`。已连接平台时 begin 会 best-effort 补传事件,失败只告警。
|
|
82
82
|
0.5. **测试基础设施探测**(先写 `CHECKING`,四项证据齐备后再结论)→ `reference.md` Step 0.5;测试基线已由上一步 gate begin 内部建立,不得再次执行 guard begin
|
|
83
83
|
1. **变更簇 TDD** — `protocols.md` `run-tdd-protocol`;批量 RED/GREEN;按需 `change-cluster-review-protocol`(高风险 + reviewer 预检可用)
|
|
84
84
|
2. 构建验证 + **仅**通过 `harness_ledger.py record` 写 ledger(禁止 Write/Edit `verification-ledger.json`);若本阶段创建/删除了清单、锁文件、源码根或改变技术栈,最后一次产品编辑后、写账本与关门前必须执行 `harness_preflight.py detect --project . --json` 刷新 build profile。`record --project . --profile-input <key>` 会对缺失/陈旧 profile 自动检测并从同一 target 推导 scope、coverage、规范命令和输入闭包;不得再手填另一套身份。`diff-hash --change-dir` 纳入 ignored tests → `reference.md` Step 2c
|
|
@@ -29,7 +29,7 @@ description: harness-run 的执行检查清单。仅在编码执行时读取。
|
|
|
29
29
|
- [ ] 读取并执行 `meta/worktree.json`:如果 `requested=true` 必须创建/切换 worktree,创建失败则停止或询问用户改为主目录;禁止静默降级
|
|
30
30
|
- [ ] **读取计划文件(主任务源)**:`.harness/changes/<change>/plans/<change>-plan.md` — 获取任务列表和依赖关系
|
|
31
31
|
- [ ] **读取详细计划(补充参考)**:`.harness/changes/<change>/plans/<change>-implementation-detail.md`(新版必需;legacy 缺失时 🟡WARN)
|
|
32
|
-
- [ ] **读取设计文档**:`.harness/changes/<change>/spec/<change>-design.md
|
|
32
|
+
- [ ] **读取设计文档**:`.harness/changes/<change>/plans/<change>-design.md`(v2);不存在时回退 `spec/<change>-design.md`(legacy)— 获取核心设计决策和不变项
|
|
33
33
|
- [ ] **读取测试场景表**:`.harness/changes/<change>/plans/<change>-test-scenarios.md` — 获取与当前任务相关的测试场景
|
|
34
34
|
- [ ] **读取验证账本**:通过 context 返回的 `executionRoot` 读取 `evidence/verification-ledger.json`(如存在)— 复用已有 compile/unitTest 结果
|
|
35
35
|
- [ ] **读取任务状态**:`.harness/changes/<change>/evidence/run-task-status.md`(如存在)— 恢复上次运行状态
|
|
@@ -39,7 +39,10 @@ description: harness-run 的执行检查清单。仅在编码执行时读取。
|
|
|
39
39
|
- [ ] 检查构建配置完整性(worktree 中确认构建配置文件存在,如 Java 的 `.mvn/maven.config`、`settings.xml`,前端的 `package.json`/lockfile 等)
|
|
40
40
|
- [ ] 依赖模块预安装(worktree 中检查上游依赖是否已安装,如 Java 的 `mvn install`、前端的 `npm install`/lockfile 等)
|
|
41
41
|
- [ ] 代码探索优先用 `codegraph_explore`,仅在返回不完整时补充 Read
|
|
42
|
+
- [ ] `harness_context.py prepare/begin` 均带 `--project .` 与 `--change <id>`(缺 `--project` 会被 argparse 直接拒)
|
|
43
|
+
- [ ] 交接凭证缺失时**不自行拼造**:v2 计划由 `prepare` 依据 committed 发布 journal 自动补录;仍报 `HANDOFF_REQUIRED`/`LEGACY_BOOTSTRAP_REQUIRED` 即代表发布证据不存在,回 plan 阶段查,不得用 `classify + configure-plan + close` 现编凭证
|
|
42
44
|
- [ ] `harness_gate.py begin --phase run` 已返回 Plan handoff 校验通过并自动 append `phase.start`;不得手工写事件绕过
|
|
45
|
+
- [ ] 门禁报 `SCENARIO_MANIFEST_V2_UNSUPPORTED` 时按 `missingFields` 回规划阶段补齐场景字段后重新发布;**不得**手改 `meta/scenario-manifest.json`(派生产物,手改必致哈希漂移)
|
|
43
46
|
|
|
44
47
|
### 步骤 0.1:执行模式(无询问)
|
|
45
48
|
|
|
@@ -19,7 +19,7 @@ description: harness-run 的编译失败策略表、TDD循环详细步骤和编
|
|
|
19
19
|
|
|
20
20
|
## 前置条件
|
|
21
21
|
|
|
22
|
-
-
|
|
22
|
+
- 设计文档存在:`plans/<change-name>-design.md`(v2)或 `spec/<change-name>-design.md`(legacy,含完整 frontmatter),按 `shared/read-protocol.md` 的顺序取第一个
|
|
23
23
|
- `.harness/changes/<change-name>/plans/<change-name>-plan.md` 存在(含完整 frontmatter)
|
|
24
24
|
- `.harness/changes/<change-name>/plans/<change-name>-test-scenarios.md` 存在
|
|
25
25
|
- `.harness/changes/<change-name>/plans/<change-name>-implementation-detail.md`(新版必需,legacy 缺失时 🟡WARN)
|
|
@@ -90,7 +90,7 @@ requested=true + path missing
|
|
|
90
90
|
2. **读取并执行 worktree 决策**:读取 `.harness/changes/<change-name>/meta/worktree.json`。如果 `requested=false`,在主目录执行;如果 `requested=true` 且 worktree 存在,必须 cd 到该 worktree;如果 `requested=true` 且 worktree 不存在,必须创建 worktree,创建失败则停止或询问用户是否改为主目录执行。禁止静默降级。
|
|
91
91
|
3. **读取计划文件(主任务源)**:`.harness/changes/<change-name>/plans/<change-name>-plan.md` → 获取任务列表和依赖关系
|
|
92
92
|
4. **读取详细计划(补充参考)**:`.harness/changes/<change-name>/plans/<change-name>-implementation-detail.md`(新版必需,legacy 缺失时 🟡WARN)→ 获取自适应执行参考
|
|
93
|
-
5. **读取设计文档**:`.harness/changes/<change-name>/spec/<change-name>-design.md
|
|
93
|
+
5. **读取设计文档**:`.harness/changes/<change-name>/plans/<change-name>-design.md`(v2 发布产物)→ 不存在时回退 `spec/<change-name>-design.md`(legacy)→ 获取核心设计决策和不变项
|
|
94
94
|
6. **读取测试场景表**:`.harness/changes/<change-name>/plans/<change-name>-test-scenarios.md` → 获取测试真相源
|
|
95
95
|
7. **读取验证账本**:通过 state layout resolver 定位 `evidence/verification-ledger.json`(如存在)→ 复用已有 compile/unitTest 结果
|
|
96
96
|
8. **读取任务状态**:`.harness/changes/<change-name>/evidence/run-task-status.md`(如存在)→ 恢复上次运行状态
|
|
@@ -113,7 +113,7 @@ requested=true + path missing
|
|
|
113
113
|
|
|
114
114
|
```
|
|
115
115
|
检查逻辑:
|
|
116
|
-
1. 读取 .harness/changes/<change-name>/spec/<change-name>-design.md
|
|
116
|
+
1. 读取 .harness/changes/<change-name>/plans/<change-name>-design.md(不存在则回退 spec/<change-name>-design.md)
|
|
117
117
|
2. 读取 .harness/changes/<change-name>/plans/<change-name>-plan.md
|
|
118
118
|
3. 读取 .harness/changes/<change-name>/plans/<change-name>-implementation-detail.md(legacy 缺失时 🟡WARN)
|
|
119
119
|
4. 读取 .harness/changes/<change-name>/plans/<change-name>-test-scenarios.md
|