# Dev Workflow

> 存在测试用例的软件开发项目的核心功能开发循环（本地功能分支 + 测试用例开工门禁 + 全量测试 + 构建测试包给用户验收后合并回 main；全程本地、无 PR 无 CI，2026-09-07 起取代 PR + CI 版）。当用户在软件开发项目上要开发新功能、修 bug、修改核心功能代码，或提到开发工作流、dev-workflow、开分支、建分支、worktree、全量测试、测试用例、合并回 main、功能验收、超集时必须使用——即便项目本身是软件项目，也要先判断这次需求是不是核心开发（判断标准见第 0 步）。普通文件处理修改（文档、README、版本号 bump（/bump）、配置调整等不触碰核心功能代码、不涉及测试用例的杂事）不走本流程：直接在 main 上改 → git add → /commit。

- Skill: `xhqing/dev-workflow` (Agent Skill, multi-file: 4 files)
- Install (CLI): `npx skillmds@latest add xhqing/dev-workflow`
- Raw SKILL.md: https://api.skillmd.com/api/skills/xhqing/dev-workflow/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Productivity
- Author: xhqing (https://skillmd.com/u/xhqing)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/xhqing/dev-workflow

---


# 开发工作流：本地功能分支 + 测试用例门禁（核心开发专用）

核心逻辑：**main 必须永远绿，且 main 上的内容必须是用户验收过的**。所有核心改动（新功能、bug 修复）走「测试方供用例 → 本地功能分支开发 → 全量测试（机器门禁）→ 构建测试包给用户安装验收（人工门禁）→ 合并回 main」。两道门禁各管一层：机器门禁防「改 A 坏 B」的客观回归，人工门禁防「用例全绿但不是用户想要的样子」的主观偏差——用例是需求的机器翻译，翻译本身可能有漏（尤其界面、体验、文案这类难以完全用例化的维度），人在合并前把关补上这层。

2026-09-07 起远端 GitHub PR / CI 流程取消（存量仓库的 ci.yml 保留不动、不主动删），裁决全部本地化。三权分立不变：**用例定义权归测试 Agent（Hopper / TestEngineerAgent）**——需求先转成验收用例（用例先行），开发 Agent 不写用例、不改用例；**代码实现权归开发 Agent**——只改实现代码去满足用例，永远不反向改用例迁就实现；**结果裁决权**归两道门禁 + Hopper 事后归档验收。

**流程总览**（各步细节见正文与 references）：

1. 第 0 步：定性——这次需求是不是核心开发
2. 第 1 步：开工门禁——main 上必须有本次需求的未通过用例组
3. 第 2 步：建 worktree + 功能分支
4. 第 3 步：开发（用例目录只读、问题终止上报）
5. 第 4 步：对齐 main + 检查用例变更
6. 第 5 步：全量测试（机器门禁）
7. 第 6 步：构建测试包 + 用户验收（人工门禁）
8. 第 7 步：超集校验 + 合并回 main
9. 第 8 步：收尾（Hopper 归档、清理）

## 第 0 步：定性——这次需求是不是核心开发

项目是软件项目 ≠ 这次需求就是核心开发。每次触发先判断：**改动会不会触碰核心源代码的运行行为、应不应该由测试用例来覆盖**——是则走本流程；纯文档、README、版本号、配置、格式调整是杂事，main 直改（`git add` → `/commit`）。拿不准时**从严走本流程或直接问用户**，宁重勿漏——把核心改动当杂事直改进 main，等于绕过两道门禁。

混合需求（核心功能 + 顺带文档）正常走本流程：琐碎文件修改不作为分支的开发目标，但功能开发必须同步的文档（README、CHANGELOG）在分支上顺带改是允许的，不算违规。

## 第 1 步：开工门禁——main 上必须有本次需求的未通过用例组

以 **main 的最新提交**为基准检查（`git show main:test-cases/pending/` 之类，不能用脏工作区的状态冒充 main 状态）：`test-cases/` 目录结构齐全，且 `pending/` 下存在本次需求对应的用例组（`requirement.md` + 用例文件）。

不满足则**阻塞暂停，向用户汇报**：请用户找测试 Agent（Hopper）提供最新的测试用例和需求文档并同步进项目。开发 Agent 不自己补用例——这是用例定义权的边界。过渡期（Hopper 供用例能力就绪前）用户手工提供用例也走同一结构，流程不区分用例来源。

目录结构、权限、同步机制全貌见 `references/test-cases.md`（开工前读一次）。

## 第 2 步：建 worktree + 功能分支

```bash
cd <主仓库目录> && git switch main && git pull
git worktree add ../<仓库名>-<功能名> -b <分支名>    # 并行开发（推荐）
# 或不并行时：
git switch -c <分支名>
```

分支必须从最新 main 开出。分支命名收敛为 `feat/<功能>` / `fix/<缺陷>` + 小写短横线描述（如 `feat/model-picker`）——用例新增归测试方（开发 Agent 不再有 `test/` 前缀）、杂事走 main 直改（不再有 `chore/` 前缀）。一个分支只做一件事、只对应一个需求组。**用户说「切分支 / 新建分支」但未说明用途时，默认创建名为 `Test` 的分支**（用户 2026-09-06 立——快速试验场景不想每次起名，不追问用途；已存在未合并的 Test 分支时报告并让用户选择复用还是换名）。

**worktree 的价值**：多个功能（多个开发会话）并行时，同一目录里的改动、`git status`、测试运行会互相污染，分不清哪份改动属于哪个功能。每个功能独占一个 worktree 目录 + 分支，天然隔离。要点：

- worktree 目录放主仓库**同级**（`~/Developer/<仓库名>-<功能名>`），不要嵌套在主仓库内（会被视为未跟踪内容，容易误提交）；
- 每个 worktree 首次进入装依赖（`bun install --frozen-lockfile` / `npm ci`），node_modules 不共享；
- 写全局共享目标的命令（如安装到系统位置的 sync 类脚本）不要在多个 worktree 并行跑；
- 一个分支同一时刻只能存在于一个 worktree。

## 第 3 步：开发中的纪律

1. **用例目录只读 + 可运行，禁止增删改**：`test-cases/` 下的一切（用例、requirement.md）只能读和执行，不能新建、修改、删除、移动。运行用例需要的伴生文件（fixture 等）也由测试方提供，缺了不自己补——阻塞上报。唯一的豁免是测试运行自产的缓存（`__pycache__`、`.pytest_cache` 等），配合 .gitignore 兜底。本条已配套工具强制：跨端 hook（`~/.claude/hooks/test-cases-guard.py`，CC / ZCode / CodeBuddy / Trae 四端挂载）会直接拦截指向 `test-cases/` 的写操作（写入被 deny 时按提示走合规通道，不要绕过），见 `references/test-cases.md`。
2. **碰到用例或需求有问题 → 终止开发，向用户汇报**：具体问题（用例跑不起来、用例疑似断言错误、需求文档含糊不清、用例之间互相矛盾）+ 建议，请用户与测试 Agent 对齐需求后解决。绝不通过改用例来绕过问题——这是 LLM 的著名失败模式（改不动代码就放宽断言），本流程从结构上禁掉它。
3. **版本号不在功能分支 bump**：多个并行分支各自 bump 必然冲突，版本号递增由发版流程统一处理（`/bump` 在 main 上改齐）。
4. **CHANGELOG 条目写在自己的段落**：记录「为什么改 + 改了什么」；不同分支写的条目落在不同位置，git 能自动合并。避免和别的分支同时新建同一个版本标题。

## 第 4 步：对齐 main + 检查用例变更

功能开发完成后，把 main 合进当前分支（全仓库合并——包括 `test-cases/` 目录，测试方的用例更新会自然带进来，这正是要全量合并的原因）：

```bash
git merge main
```

merge 后**必查一件事**：diff 一下 `pending/` 里本次需求组的用例和 requirement.md 有没有在开发期间被测试方更新。变了就先重新对齐需求（必要时重新评估开发内容和改动范围），再进下一步——开发期间需求悄悄变了而实现还照旧，是隐性返工的最大来源。有冲突照常解决，解决结果会被下一步的全量测试覆盖验证。

## 第 5 步：全量测试（机器门禁）

在分支上本地跑项目全量测试：**项目原有单元测试 + `test-cases/` 验收用例全部**，加类型检查（如 `bun test` / `npm test` + `tsc --noEmit`，按项目技术栈）。

通过口径（三条，逐条判定）：

- `passed/` 目录的用例**必须全绿**——这是回归防护，一条都不能红；
- `pending/` 里**本次需求组**的用例必须全绿——这是增量目标；
- `pending/` 里**其它组**的用例不阻塞本次合并——它们本来就处于未完成状态，红着是合理的（对应别的还没做完的工作；只要本次改动没把它们从「红」变「更红」，就不归本次管）。

未通过目录里只有本次一组用例时（串行开发的常见情形），这个口径就等价于「全部通过」。

红灯是分支上的正常工作状态（不是事故——main 红才是事故），在分支上修到绿再走下一步。

## 第 6 步：构建测试包 + 用户验收（人工门禁）

全量测试通过后、合并回 main 之前：在 dev 的 worktree 里按项目发布工艺构建**测试版安装包**（vsce package、npm pack 等，按项目来），交给用户安装实测，用户按 `pending/<需求名>/requirement.md` 逐条核对验收。

验收不通过是一个循环，不是一个终点：实现不符合需求 → dev 上改 → **重新跑全量测试**（不是只跑改过的部分）→ 重新构建测试包 → 请用户复验；需求本身要变 → 走第 3 步第 2 条的通道（终止上报，用户找测试方改需求文档和用例、同步进来后重新对齐）。

构建与验收的完整规矩（测试版本标识、产物放 tmp/、不打 tag 不发 Release、与运行版隔离规则的关系）见 `references/acceptance.md`（进本步前读一次）。

## 第 7 步：超集校验 + 合并回 main

**窗口纪律**（合并前向用户提醒）：从「main merge 进 dev」那一刻起，到「dev merge 回 main」那一刻止，**main 不能有新提交、dev 也不能有新改动**——merge 回 main 的必须是跑过全量测试且用户验收过的那份提交，main 或 dev 任何一边动了，这个等价关系就断了。全量测试一绿、用户验收一过就立刻合并，窗口期越短越安全；有别的分支处在窗口期时，测试方的用例同步也避开或事后通知返工。

合并前先跑硬校验：

```bash
git merge-base --is-ancestor main dev && echo "超集成立，可以合并"
```

这条命令检查「main 的所有提交都在 dev 里」（dev ⊇ main）。**不成立说明 main 在窗口期动过**（用户手动改、别的分支合回去、测试方同步用例都算）——必须回第 4 步重新对齐、重跑全量测试，绿了之后看 main 新进的是什么：只是用例或文档 → 用户验收结论延续，直接合并；进了别的功能代码 → 请用户快速复验再合并。纪律管「尽量不破坏」，校验管「破坏了必然被发现」，两条腿缺一不可。

成立则在 main 上合并（超集成立时这是快进合并，main 的指针直接移到 dev 最新提交，**main 收到的树和测试过的树逐字节相同**——这是整个保证的物理基础）：

```bash
git switch main && git merge dev
```

超集纪律的完整论证（为什么窗口两边都不能动、并行分支怎么互相影响、「100% 没问题」的精确含义）见 `references/merge-discipline.md`（遇到窗口期被破坏、并行冲突时读）。

## 第 8 步：收尾

1. **汇报请测试方归档**：合并完成后向用户报告「已合并回 main，请让 Hopper 验收归档」。用例从 `pending/` 挪到 `passed/` 由测试方做（开发 Agent 对用例目录无写权限），这同时是 Hopper 的独立验收环节——放弃 CI 后，这是「第三方裁决」的替代。归档与同步细节见 `references/test-cases.md`。
2. **清理 worktree**：`cd <主仓库目录> && git worktree remove ../<仓库名>-<功能名>`（测试包产物放 worktree 的 tmp/ 下，随 worktree 一起清）。
3. **同步其它活着的 worktree**：本次功能合并进 main 后，把 main 合回其它还活着的分支（进各 worktree 目录 `git merge main`）——冲突在几行规模时解决，比拖到几百行轻松；分支活得越短，冲突窗口越小。
4. **push**：本流程不含 push——推远端走 `/commit`（用户自行 `git add` 后触发）或用户明确指示。

## git 授权边界（与全局纪律衔接）

**触发本 skill（用户要求开发核心功能）= 授权流程内的本地 git 操作**：`git worktree add` / `git switch -c` / `git merge main`（对齐）/ `git merge dev`（合并回 main）/ `git worktree remove`，以及本地测试与构建。**不含 push**——推送远端仍只走 `/commit`（用户自行 `git add` 后触发）或用户明确指示。dev merge 回 main 产生的 merge commit 是本流程的固有产物，属流程内授权，不走「commit 授权 = 用户主动 /commit」的入口（那条管的是暂存区提交，本流程不触碰暂存区）。

## references（按需加载）

- `references/test-cases.md` — 测试用例体系全貌：目录结构、Hopper 权威源与单向同步、权限与 hook 强制、归档机制。**第 1 步开工门禁前读。**
- `references/acceptance.md` — 测试包构建与人工验收的完整规矩。**第 6 步进验收前读。**
- `references/merge-discipline.md` — 超集纪律完整论证：窗口期、硬校验、并行分支、main 窗口期变动的返工口径。**第 7 步遇窗口期问题时读。**

