---
description: harness-submit 的8 步工作流详细步骤和执行日志记录格式。仅在执行提交流程时读取。
---

# harness-submit 检查清单

## P0 提交稳定性门禁（先读）

执行任何 commit 前必须遵循 `reference.md` 与 `../protocols/submit-protocol.md`：

- 提交方式只用固定三选项：commit+push / 仅本地 commit / 取消。
- commit message 必须写入 `.harness/changes/<change>/runtime/commit-message.txt`。
- 使用 `git commit -F`，禁止先英文 commit 再 amend。
- commit message 禁止 `Co-Authored-By`、`Generated by`、`AI generated`。
- blocking user confirmation 参数错误时不得自行绕过，必须改用固定模板重问。
- staged diff 是唯一提交依据。

### Wave-A 发布身份与环境边界

- [ ] 产品候选身份与归档治理身份分离：`productCommit`/`productTreeHash` 绑产品验证；`archiveCommit` 可晚于产品
- [ ] 进入 candidate CI / archive 前确认 product candidate CI 证据可被 `harness_archive status` 读取为 green
- [ ] 需要可写 DB/栈时走 `harness_environment` lease；禁止跨 change 默认可写共享


## 步骤 0：启动准备

确定变更名：用 Glob 搜索 `.harness/changes/*/plans/*-plan.md`（**排除 `.harness/archive/*/`**），读取 frontmatter 提取 `change-name`。默认最多一个未归档变更；如有多个，优先取最近修改的，或询问用户。

**读取 worktree.json 判定模式**：读取 `.harness/changes/<change-name>/meta/worktree.json`。`requested=true` → **worktree 模式**：submit 只本地 commit、不 push，commit 成功后**自动接续** checklist「worktree 合并流程」步骤 M0–M8（`/harness-merge` 为别名，可从 M0 重入）。`requested=false` → 主目录模式：正常 commit+push 主分支。

**读取 verification-ledger + post-test 变更分类**：

1. 通过 state layout resolver 读取权威 `evidence/verification-ledger.json`，记录 `diffHash` / `currentHead` / `unitTest` / `apiTest` 状态；split-v1 不得回退复制到 contract 目录
2. 执行 `harness_ledger.py diff-hash --repo . --base <baseCommit> --change-dir ".harness/changes/<change-name>" --json` 计算当前 diffHash；manifest 校验失败即停止，不得绕过后与 ledger 比对
3. 若 test 之后有代码变更（当前 diffHash ≠ test 完成时的 diffHash），按 7 类对 post-test diff 分类（见 `../protocols/ledger-protocol.md` 第六章），写入 ledger 的 `postTestClassification`
4. 行为性变更（BEHAVIORAL_SERVICE_CHANGE / API_CONTRACT_CHANGE / SQL_OR_MAPPER_CHANGE / SECURITY_OR_PERMISSION_CHANGE）→ **停止 submit**，提示先重跑 `/harness-execute` 相关场景
5. 非行为性变更（NON_BEHAVIORAL_CLEANUP / COMMENT_ONLY / TEST_ONLY）→ 可继续 submit，但后续验证按复用规则处理

**append `phase.start` 事件**（`harness_events.py append`；`note` 含 ledger diffHash、post-test 分类、验证策略）：

## 步骤 1：合并最新代码

> **分支名自动读取**：不硬编码 `master` 或 `main`，使用 `git rev-parse --abbrev-ref @{u}` 自动读取 upstream 分支。

**正常路径禁止 `git stash` / `stash pop`**。远端同步不在业务工作区执行；主目录与 worktree 模式统一由合并段的 `harness_integration.py` transaction 在隔离 integration worktree 内 fetch + merge：

```powershell
# 0. 自动读取 upstream 与目标分支（只读操作）
powershell.exe -Command "git -C '<项目路径>' rev-parse --abbrev-ref @{u}"

# 1. preflight：获取 integration lock + 写 journal/保护 ref
python harness/scripts/harness_integration.py preflight --change <change-name> --run-id <run-id> --feature-branch <feature> --target-branch <target> --temp-root <task-temp>

# 2. prepare：fetch + 从已提交 target 创建临时 integration worktree
python harness/scripts/harness_integration.py prepare --change <change-name> --run-id <run-id> --feature-branch <feature> --target-branch <target> --temp-root <task-temp>
```

**Shell 安全规则（强制）**：
- 任何 git 命令被 hook 拒绝（`Denied` / `PreToolUse:Bash hook error`）→ 停止流程，不得宣称"拉取成功"
- transaction 各步骤状态以 journal 为唯一事实源；FAILED 步骤用 `recover` 续跑，不重复已完成副作用

merge 冲突或 `TARGET_MOVED` 时，参考 `reference.md` 的恢复清单；**禁止 `checkout --ours/--theirs`**。

## 步骤 2：最终验证（ledger 复用优先）

**先判断是否可复用 test 阶段验证**。读取 ledger 后，若**全部满足**：

- 当前 diffHash 与 ledger 一致（或 post-test 仅为非行为性清理）
- `unitTest.status=OK` 且 `apiTest.status=OK`
- postTestClassification ∈ {NON_BEHAVIORAL_CLEANUP, COMMENT_ONLY, TEST_ONLY, 无}
- 远端无新提交（步骤 1 pull 未引入他人提交）
- 用户未要求 `submit-full-verify`

→ **跳过重跑** 项目构建/测试命令，复用 ledger 结果，在执行日志标记 `🔁REUSED`，并在提交摘要写明"验证复用 test 阶段结果（diffHash=<...>）"。

**重跑触发条件**（任一满足则必须重跑）：

- 远端有新提交并完成 pull/rebase
- staged diff 与 ledger diffHash 不一致且属行为性变更
- post-test 修改属于行为性变更（已在步骤 0 拦截，此处兜底）
- test 报告缺失或失败
- 用户要求 `submit-full-verify`

重跑时只使用 harness-submit 自有确定性验证，不调用 Superpowers 合并/收尾流程：

```powershell
powershell.exe -NoProfile -Command "<项目构建命令>"
powershell.exe -NoProfile -Command "<项目测试命令>"
```

> **接口测试依赖编译产物时的重跑顺序**（通用）：若项目的接口测试执行器（如 in-process HTTP server runner）import 编译产物（build output）而非源码，重跑接口测试前**必须先跑构建命令**重新编译，否则接口测试测的是 post-test 改动前的旧产物，会漏检行为性变更。单元测试若通过别名/直指源码则不受影响，但接口测试执行器通常依赖独立编译产物——务必先编译再跑接口测试。

编译或测试失败 → 停止提交，提示用户修复。

**重跑后必须把结果写回 ledger** 的 `compile`/`unitTest` 项，并更新 `diffHash`/`currentHead`。

**提交前最终门禁**（步骤 2 末尾，commit 前强制，`unitTestFull` 模块级全量）——**只调 `can-reuse`，删除二次全量门禁**：

```powershell
python <skills-root>/scripts/harness_ledger.py can-reuse `
  --change-dir ".harness/changes/<change-name>" `
  --verification unitTestFull --scope module `
  --project . --profile-input unitTestFull `
  --command "<resolved commands.unitTestFull.command>" --json
```

- `--command` **按 profile key resolve**：读 `build-profile.json` 的 `commands.unitTestFull.command`（v2），或 `python <skills-root>/scripts/harness_profile.py resolve --project . --key unitTestFull --json` 取 resolved command。**禁止原样复制示例模块名**（命令按 profile key resolve，文档示例只展示 key）。
- `--profile-input unitTestFull` 从 `build-profile.json` 的 `verificationInputs.unitTestFull`（v2 由 `commands.unitTestFull.inputs` 派生）展开**依赖闭包**文件集，**禁止用仅含 staged 业务文件的 `--files` 快捷方式**冒充全量闭包。
- 增量 `unitTest`（scope=测试类）永远不能冒充 `unitTestFull` 门禁；ledger 只有 `unitTest` 时返回 `insufficient-evidence`。
- `reuse=true` → **不再执行二次全量测试**（删除与 coverage 冲突的二次门禁，spec §3.3）；仅 `reuse=false`（can-reuse 明确失败）时执行**同一 resolved verification**（profile `unitTestFull` 命令，模块级全量单元测试），成功后用**同一文件集、command、`scope=module`** 写回 ledger 的 `unitTestFull` 项，再继续步骤 3。
- profile 缺 `commands.unitTestFull` / `verificationInputs.unitTestFull` / glob 无匹配 / 结果为空 → 返回 `insufficient-evidence`（exit 0），仍须执行全量测试但**不允许缓存复用**，直到 profile 正确配置。

**编译/测试成功必须有明确证据**：
- 构建命令输出必须包含构建成功证据（如 `BUILD SUCCESS` / `Finished` / exit code 0）
- 测试命令输出必须包含测试通过证据（如 `Tests run: N, Failures: 0` / `passed` / exit code 0）
- 命令被 hook 拒绝或 exit code 非 0 → 标记为 ❌ 失败，停止提交流程

**review 报告**（参考性）：如果 `.harness/changes/<change-name>/reports/review/review-report-*.md` 存在（旧路径 `reviews/` 兼容），可读取并展示摘要（如“review 报告：RED 高风险建议 N 个，YELLOW 中低风险建议 M 个，仅供参考”），但不得因 review 结果阻塞提交。

**review fixback**（参考性）：如果 `.harness/changes/<change-name>/reports/review/fixback-*.md` 存在，展示最新 fixback 摘要并提示“可回到 `/harness-execute --fixback` 处理”；除非 `review.strict-review-gate=true` 且存在 RED，否则不得阻塞提交。

## 步骤 3：.gitignore 检查 + 暂存业务文件 ⚠️ 强制阻断

### Ignored test 精确暂存

- [ ] 检查 `.harness/changes/<change-name>/evidence/test-tracking.json` 是否存在
- [ ] 存在时先执行 `python <skills-root>/scripts/harness_test_guard.py stage --project . --change-dir ".harness/changes/<change-name>" --json`；任一 manifest/path/hash/index 校验失败立即停止
- [ ] 用 `git diff --cached --name-only` 验证 guard 响应 `files` 中的每个精确路径均已暂存，且没有 guard 引入的额外路径；manifest 中已由 `HEAD` 跟踪且未变化的历史条目无需进入本次 cached diff
- [ ] 无 manifest 时禁止使用 `git add -f`；有 manifest 时也只允许 guard 内部的 exact force-add，**禁止全局 force-add**、目录级 force-add 和全局修改 `.gitignore`

提交前**强制检查 `.gitignore`** 是否包含 `.harness/`：

```powershell
powershell.exe -Command "Select-String -Path '<项目路径>\.gitignore' -Pattern '\.harness'"
```

如果未包含：
- **必须提醒用户**：`⚠️ .gitignore 未包含 .harness/，会导致 .harness/ 下文件被提交（含日志、报告、可能含敏感信息）`
- **默认不提交 .harness/ 下文件**：使用 blocking user confirmation 询问用户是否：
  1. 添加 .harness/ 到 .gitignore（推荐）
  2. 仅 stage 业务代码文件，不提交 .harness/
  3. 取消提交

**git status 中如出现 .harness/changes/**：
```powershell
powershell.exe -Command "git -C '<项目路径>' status --porcelain | Select-String '\.harness'"
```
- 如果有匹配，必须只 stage 业务代码文件，**禁止 `git add -A`**
- 推荐 stage 方式：明确列出业务代码文件路径 `git add <file1> <file2> ...`

## 步骤 4：提交方式选择（固定三选项）

**worktree 模式（requested=true）**：固定为「仅本地 commit」，不展示「commit+push」选项；commit 完成后继续下方「worktree 合并流程」，跳过下方三选项询问。

`harness-submit` 不调用 Superpowers 呈现合并选项。只允许使用固定 blocking user confirmation 模板：

```text
本次变更已完成验证，请选择提交方式：

1. commit + push 到当前 upstream
2. 仅本地 commit，不 push
3. 取消提交
```

禁止在此步骤引入"创建 PR""丢弃所有变更""直接合并到主分支"等旧选项，避免 blocking user confirmation 参数错误和流程歧义。

## 步骤 5：展示提交摘要 + 确认 ⚠️ 强制阻断

展示完整的 commit message 和变更列表，等待用户确认。**不可跳过此步。**

**commit message 生成规则**：
- subject 只根据 `git diff --cached` 当前实际暂存的变更，或本次变更名生成
- **不得混入历史任务上下文**（如之前的 plan 描述、与本次 diff 无关的短语）
- 示例：本次 indicator 权限修复，正确 subject 应类似 `fix(indicator): 修复指标库列表组织权限过滤`，不得出现与本次 diff 无关的内容

**展示四项信息**（缺一不可）：

```powershell
# 1. 实际 staged 文件列表
powershell.exe -Command "git -C '<项目路径>' diff --cached --name-only"

# 2. diff stat
powershell.exe -Command "git -C '<项目路径>' diff --cached --stat"
```

格式：

```markdown
## 准备提交

### 1. 实际 Staged 文件列表
（基于 git diff --cached --name-only 的实际输出）
- src/.../业务代码文件
- test/.../测试代码文件

### 2. Diff Stat
 src/.../业务代码文件 | +12 -3
 test/.../测试代码文件 | +45 -0
 2 files changed, 57 insertions(+), 3 deletions(-)

### 3. Commit Message
<type>(<scope>): <中文描述>

- 变更点1
- 变更点2

### 4. 是否会 push
（根据本步骤提交方式选择：会推送到 origin/<branch> / 仅本地提交，不推送）

### 确认？
回复「是」→ 执行提交 | 回复「改」→ 修改 message | 回复「取消」→ 放弃
```

> Git 提交信息**不包含** `Co-Authored-By` 行（遵循项目 git-commit.md 规范）。


### 5.1 生成 commit-message.txt（强制）

在用户确认前，必须把完整中文 commit message 写入：

```text
.harness/changes/<change-name>/runtime/commit-message.txt
```

用 Write 工具或 PowerShell 创建文件。message 不得包含 `Co-Authored-By`、`Generated by`、`AI generated`。

用户确认时展示该文件完整内容；确认后步骤 6 必须使用：

```powershell
powershell.exe -NoProfile -Command "git -C '<项目路径>' commit -F '.harness/changes/<change-name>/runtime/commit-message.txt'"
```

不得使用 `git commit -m` 提交长中文 message，不得先提交英文再 amend。

## 步骤 6：执行 commit 和可选 push

**worktree 模式（requested=true）**：只执行下方 `git commit -F`，**不执行 push**；记录 local commit hash 后**继续 worktree 合并流程 M0**，不结束 submit。

用户确认后，根据步骤 4 的提交方式选择执行：

```powershell
powershell.exe -NoProfile -Command "git -C '<项目路径>' commit -F '.harness/changes/<change-name>/runtime/commit-message.txt'"
```

**记录 pre-pull local commit hash**：
```powershell
powershell.exe -Command "git -C '<项目路径>' rev-parse HEAD"
```
保存为 `<pre-pull-hash>` 用于后续比对。

**push 前的远程新提交检查（强制）**：

```powershell
# 拉取远程最新引用
powershell.exe -Command "git -C '<项目路径>' fetch"

# 检查远程是否有新提交（自上次 fetch 以来）
powershell.exe -Command "git -C '<项目路径>' log HEAD..@{u} --oneline"
```

**如果远程有新提交**（输出非空）：
- **不得直接 pull 后 push**
- 必须 pull/rebase 后**重新构建/测试**（ledger 复用条件被破坏，须重跑并写回 ledger）
- 验证通过后再 push
- 使用 blocking user confirmation 询问用户：
  ```
  远程有新提交（N 个），需要 pull/rebase 后重新验证：
  1. 重新验证（pull/rebase + 构建 + 测试）
  2. 停止 push（保留本地提交，等待用户后续处理）
  ```
- 如果用户选 2，必须停止 push，不得强行推送

**如果远程无新提交**（输出为空），可以直接 push：

```powershell
powershell.exe -Command "git -C '<项目路径>' push"
```

**push 成功必须有证据**：
- git push 输出包含 `To <remote>` 和实际推送范围（如 `<old-hash>..<new-hash>`）
- exit code 为 0
- 否则标记为 ❌ 推送失败 / 状态未知

**记录 final pushed hash**：
```powershell
powershell.exe -Command "git -C '<项目路径>' rev-parse HEAD"
```
保存为 `<final-pushed-hash>`。

**commit hash 双标注**：
- 如果 `<pre-pull-hash>` ≠ `<final-pushed-hash>`，在执行日志中分别记录：
  ```
  - **pre-pull local commit hash**: <pre-pull-hash>
  - **final pushed hash**: <final-pushed-hash>
  ```
- 后续 archive 阶段读取时以 `<final-pushed-hash>` 为准

不用 `--no-verify`、`--no-gpg-sign` 等跳过 hook 的参数。

## 步骤 7：收尾引导

**worktree 模式（requested=true）**：不清理 worktree，**直接继续下方「worktree 合并流程」**。

**主目录模式 Worktree 清理**：如果当前在 worktree 中，询问用户是否删除：
- 是 → 先确认分支已推送 origin，再 `git worktree remove` + `git branch -D`
- 否 → 保留

> ⚠️ `git worktree remove` 在 Windows 下常因残留 `node_modules` 等深嵌套 gitignored 文件失败（"Directory not empty"）。完整兜底方法（robocopy /MIR 清空 + .NET 删空目录、ExitWorktree 限制、PreToolUse hook 对 `/MIR` 的误判规避）见 `reference.md`「Worktree 清理兜底（Windows）」。

**产出归档引导**：展示 `.harness/changes/<change-name>/` 下的所有产出文件，询问用户：
- 保留 → 后续可运行 harness-archive 归档
- 归档 → 运行 harness-archive
- 清理 → 删除 `.harness/changes/<change-name>/` 目录

**append `phase.end` 事件**（submit 段；`note` 含结束时间、耗时、结果、final pushed hash、验证策略、摘要）：

---

## worktree 合并流程（integration transaction，M0–M7）

> worktree 模式 commit 成功后自动执行；用户仅说「合并分支」/`/harness-merge` 且已有本地 commit 时从 M0 重入。合并由 `harness_integration.py` transaction 执行：隔离 integration worktree + journal + 保护 ref + 精确清理。**禁止 `checkout --theirs/--ours`；正常路径禁止仓库级 stash。**

### P0 合并稳定性门禁

- 主分支名不硬编码，用 `git symbolic-ref --short refs/remotes/origin/HEAD` 读取
- push 只在主分支；worktree 分支不 push
- 所有 git 命令通过 `powershell.exe -Command "..."` 执行（transaction 脚本内部 git 调用除外）
- transaction 步骤状态以 `.harness/state/integration/<transaction-id>/journal.json` 为唯一事实源

### 步骤 M0：启动合并段

append `phase.start`（`--phase merge`；`note` 含 worktree 分支、主分支、ledger diffHash、验证策略；重入时 note 标注「重入 merge」）。

### 步骤 M1：preflight

```powershell
python harness/scripts/harness_integration.py preflight --change <change-name> --run-id <run-id> --feature-branch harness/<change-name> --target-branch <主分支> --temp-root <task-temp>
```

获取 integration lock、解析 base/feature head、写 journal 与保护 refs（`refs/harness/integration/<txn>/base|head`）。锁被其他 run 持有 → **停止**，不改动工作区与状态文件。

### 步骤 M2：prepare

```powershell
python harness/scripts/harness_integration.py prepare --change <change-name> --run-id <run-id> --feature-branch harness/<change-name> --target-branch <主分支> --temp-root <task-temp>
```

fetch 后从**已提交** target 创建临时 integration worktree；primary 的 staged/unstaged/untracked/ignored 与 mtime 均不被触碰。

### 步骤 M3：merge

```powershell
python harness/scripts/harness_integration.py merge --change <change-name> --run-id <run-id> --feature-branch harness/<change-name> --target-branch <主分支> --temp-root <task-temp>
```

- 方式固定 `--no-ff`；merge diff 出现其他 Change 的 contract/runtime 路径 → 结构化 `FOREIGN_CHANGE_PATHS` 拒绝
- 冲突 → step FAILED：**停下**，`git -C <integration-worktree> diff --name-only --diff-filter=U` 列冲突文件，提示用户手动解决；保护 refs 与 journal 保留
- 人工解决后以 `recover` 续跑；已完成步骤返回 REUSED，不重复 merge

### 步骤 M4：verify（组合态验证）

在 integration worktree 内执行验证命令；远端引入他人提交或 ledger 不可复用时必跑：

```powershell
python harness/scripts/harness_integration.py verify --change <change-name> --run-id <run-id> --feature-branch harness/<change-name> --target-branch <主分支> --temp-root <task-temp> --command "<resolved command>"
```

任一命令非零退出 → step FAILED，不进入 push。

**产品候选证据门槛**：

- 项目存在远端 CI：本地 push 只运行有界静态门槛，push 后必须取得当前候选 commit 的 CI 绿灯，才能归档或发布。
- 项目没有远端 CI：在候选 commit 对应的同一棵 tree 上完整执行 resolved check；成功后写本地候选收据。收据必须同时匹配时间、命令和 tree hash，不接受口头声明或旧提交结果。
- 不得在 pre-push 中无条件重复全量测试；失败后不自动重跑，先报告失败阶段与残留进程。

**写 check-ok marker**（`npm run check` exit 0 后强制；无 CI 项目以此作为产品候选绿灯证据）：

```powershell
node scripts/check-gate.mjs --write
```

### 步骤 M5：push

**硬门槛（eslint × feature worktree）**：integration / 主仓 `pre-push` 跑有界 `check:push` 时，eslint 不得把 sibling `.worktrees/<change>/` 当成第二工程根（双 `tsconfigRootDir`）。本仓以 `eslint.config.mjs` 的 `.worktrees/**` ignore 为准；若自定义 eslint 未 ignore，须先 `move_agent_to_root(<projectRoot>)` 再清 feature worktree，再 push。

```powershell
python harness/scripts/harness_integration.py push --change <change-name> --run-id <run-id> --feature-branch harness/<change-name> --target-branch <主分支> --temp-root <task-temp>
```

远端基线漂移 → `TARGET_MOVED` 结构化失败，不继续。成功后 journal `pushedHead` 即 `mergeFinalHash`。

若远端已确认 mergeCommit，但包装事务名与证据所属 Change 不同，导致
`LEDGER_SYNC_PENDING / LEDGER_MISSING`，必须显式指定真实证据归属后恢复：

```powershell
python harness/scripts/harness_integration.py recover --change <transaction-change> --evidence-change <evidence-change> --run-id <run-id> --feature-branch harness/<transaction-change> --target-branch <主分支> --temp-root <task-temp>
```

该覆盖只允许修复“默认同名台账缺失”的远端已确认事务；一旦 journal 已绑定证据
Change，后续传入不同值会 fail closed。目标台账的既有三项集成哈希必须精确匹配
本事务基线（或已匹配本次 mergeCommit），作为前序集成交接身份；禁止为包装事务
伪造空台账或覆盖其他历史 Change 的集成哈希。

### 步骤 M6：cleanup

```powershell
python harness/scripts/harness_integration.py cleanup --change <change-name> --run-id <run-id> --feature-branch harness/<change-name> --target-branch <主分支> --temp-root <task-temp>
```

- `git worktree remove --force` 精确路径 → 验证注销 → 临时分支 `branch -D` → （push 成功后）删除保护 refs → 释放 integration lock
- 清理只接受 journal 登记的精确 integrationRoot；仓库根、父目录、空路径、逃逸路径与其他 transaction 路径一律拒绝
- 失败保留 journal 与诊断证据，状态 🟡WARN，不得宣称清理完成
- 若存在 test-tracking manifest，确认其路径已由合并后的目标分支跟踪（`git ls-files --error-unmatch -- <exact-path>`），缺失即停止

**失败 txn 改走 abandon（勿强行 cleanup）**：

```powershell
python harness/scripts/harness_integration.py abandon --change <change-name> --run-id <run-id> --feature-branch harness/<change-name> --target-branch <主分支> --temp-root <task-temp>
```

仅当 push ≠ DONE 且 remote 不含 mergeCommit；清理 integration 产物后可换新 run-id 重开。push 成功 → `ABANDON_REFUSED`。

更新 `meta/worktree.json`：`created=false` + `removedAt`/`removedBy`/`removalNote`。

**删除 feature worktree 前（硬门槛）**：

1. 若 Agent root / cwd 落在待删 worktree → 先 `move_agent_to_root(<projectRoot>)`；目标为主仓，feature 分支已删则切 `main`/`master`，禁止 fetch 已不存在分支
2. 迁根失败 → **停止删除**
3. `assert_cleanup_safe(cleanupRoot, [.harness/changes/<id>, .harness/state/...], [.harness/archive])`；`CLEANUP_TOPOLOGY_REFUSED` → 停止

### 步骤 M7：更新 ledger + 收尾

ledger 顶层写入 `"mergeFinalHash": "<journal pushedHead>"`；经 `harness_gate.py close --phase merge` 关闭（禁止手工 phase.end）。

```markdown
## 合并完成 — <change-name>

- Merge commit: `<merge-commit-hash>`
- 主分支 push: ✅（<old>..<new> → origin/<主分支>）
- mergeFinalHash: `<merge-final-hash>`
- 验证策略: 🔁REUSED / 🔄已重跑
- worktree: 已清理（迁根后）
- 下一步: `/harness-archive`
```


## Wave-2 — 验证复用与 merge 面（H-9）

- [ ] 代码冻结后，同 identity 的 unitTestFull 须 can-reuse；禁止无 invalidationCode 整套重跑
- [ ] integration verify 会合并 profile mergeVerification.requiredOnMerge（若配置）
