name: coding-start
description: B 阶段(Coding)入口。先验证 Plan 已完成;按 docs/02 § 二 REQ 开发顺序清单扫描,对每个 REQ 所属模块用 docs/08 的 MR: 字段 + GitLab API state 判定是否完成——merged 跳过,— 或 opened/closed 选为当前模块并派发到 module-start。派发前自动探测默认分支(main / master)并 git checkout + pull --ff-only 保持 base 最新。
user-invocable: true
allowed-tools: Skill Read Glob Grep Bash(curl ) Bash(jq *) Bash(git branch *) Bash(git checkout *) Bash(git pull *) Bash(git status *) Bash(git symbolic-ref *) Bash(sed *) Bash(mkdir -p .tmp) Bash(rm -f .tmp/)
所有输出必须使用中文。
B 阶段(Coding)的入口分发器。
执行步骤
步骤 1:确认 docs/08 存在
检查 docs/08-模块任务管理.md存在。
- 不存在 → 打印"⚠️ 项目尚未初始化,请先运行
/erp-workflow:plan-start"并停下。
步骤 2:Plan 完成性检查
用 Grep 在 docs/08-模块任务管理.md 搜索 ^- \[ \] A[0-5](pattern 可以直接匹配父项未勾的情况;也可以用更宽的 ^[[:space:]]*- \[ \].*A[0-5] 覆盖子项)。
- 命中任一A 阶段未勾选 → 打印并停下: ``` ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ [coding-start] ⚠️ Plan 尚未完成
docs/08 § 一 还有未勾选项,请先运行: /erp-workflow:plan-start
继续 Plan 阶段直到 A5 下游文档生成完成,再回来运行 coding-start。 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
- 无命中 → Plan 已完成,进入步骤 3。
### 步骤 3:按 docs/02 REQ 序 + MR state 找当前模块
> `MR:` 字段 × GitLab API state 的三组合判定规则见 `CLAUDE.md § ✅ 模块完成判定规则 § 模块状态语义`。
1. 用 `Read` 读取 `docs/02-开发计划.md` 的 § 二;用 `Grep`(pattern `^\|\s*[0-9]+\s*\|\s*\*\*(REQ-[A-Z0-9]+-[0-9]+)\*\*\s*\|\s*(module_\w+)`,`-n`)抽取所有表格数据行,按行号升序得 `req_order[]`,每项含 `req_id` + `module_id`。
2. 若 `req_order` 为空 → 打印错误并**停下**(与原逻辑相同,略)。
3. **初始化模块完成缓存 `module_merged[module_id → bool]`**(空)。
4. 按序遍历 `req_order[]`:
- 若 `module_merged[module_id]` 已有缓存:
- `true` → 跳过本 REQ,继续下一个
- `false` → `current_module = module_id`,结束遍历,进入步骤 4
- 未缓存 → 读取 docs/08 § 二 该模块条目的 ` - MR:` 字段:
- `MR: —` → `module_merged[module_id] = false`;`current_module = module_id`,结束遍历
- `MR: !<iid>` → 先 `Bash`: `set -a; . ./.env.local; set +a` 加载凭据,然后**分步校验 HTTP 状态 + 返回条数 + state 枚举**(v3 API 用 iid 过滤列表):
```bash
mkdir -p .tmp
HTTP_CODE=$(curl -sS -o .tmp/mr.json -w '%{http_code}' \
--header "PRIVATE-TOKEN: ${GITLAB_TOKEN}" \
"${GITLAB_API_URL}/projects/${GITLAB_PROJECT_ID}/merge_requests?iid=<iid>")
```
**硬停条件**(触发任一则打印诊断横幅并**停下**,不派发;任何"查不到就假设未 merged"的静默处理都禁止):
1. `HTTP_CODE != 200`:API 不可达 / token 错 / URL 错
2. `HTTP_CODE == 200` 但 `jq 'length' .tmp/mr.json != 1`:docs/08 记了 `!<iid>` 但远程查不到对应 MR(数据不一致)
3. `state = jq -r '.[0].state' .tmp/mr.json` 不在 `{merged, opened, closed}` 三个合法值里
诊断横幅模板:
```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[coding-start] ⚠️ 无法确定 MR !<iid>(模块 <module_id>)的状态
原因: <HTTP <code> | 查不到 MR | state=<异常值>>
API : ${GITLAB_API_URL}/projects/${GITLAB_PROJECT_ID}
body: <jq -r '.message // .error // .' .tmp/mr.json | head -c 200>
请按下列顺序核查:
1. .env.local 的 GITLAB_TOKEN 是否有效(在 GitLab Profile → Private token 页检查)
2. GITLAB_API_URL 前缀 / v3 路径 / host 是否匹配你的 GitLab 部署
3. GITLAB_PROJECT_ID 是否是该项目的 URL-encoded 路径或数字 ID
4. docs/08 记的 iid 是否存在于 GitLab 项目的 MR 列表
修正后重跑 /erp-workflow:coding-start。
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
```
清理:`rm -f .tmp/mr.json`。
校验通过后按 state 分派:
- `merged` → `module_merged[module_id] = true`,跳过本 REQ
- `opened` / `closed` → `module_merged[module_id] = false`;`current_module = module_id`,结束遍历
5. 全遍历完仍无命中(所有模块都 merged) → 打印:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ [coding-start] ✅ 所有模块已完成
docs/02 § 二 清单中每个 REQ 所属模块的 MR 都已 merged。项目结束。
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
并**停下**。
6. 命中后:记录 `current_module` 的 `MR:` 字段值(`—` / `!<iid>-opened` / `!<iid>-closed` / `!<iid>-查不到`,用于步骤 5 横幅展示)。
### 步骤 4:探测默认分支 + 切回并同步远程(准备 module-start 切新分支的干净 base)
4.0 **探测默认分支**:
```bash
DEFAULT_BRANCH=$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's|refs/remotes/origin/||')
if [ -z "$DEFAULT_BRANCH" ]; then
# HEAD 未设置,回退:在 main / master 里取第一个实际存在的远程分支
DEFAULT_BRANCH=$(git branch -r --format='%(refname:short)' | grep -E '^origin/(main|master)$' | head -1 | sed 's|^origin/||')
fi
-
DEFAULT_BRANCH为空 → 打印错误并停下(既无origin/main也无origin/master,说明远程未就绪,提示用户先完成 Plan 的首次 push 或git remote set-head origin -a设置 HEAD)。
4.1 切回 + 同步:
-
Bash:git branch --show-current→current_branch。 -
若
current_branch != $DEFAULT_BRANCH:-
Bash:git status --porcelain;非空 → 打印: ``` ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ [coding-start] ⚠️ 当前分支 有未提交改动,无法切换到
请手工处理后重新运行 /erp-workflow:coding-start。 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
并**停下**。 - `Bash`: `git checkout "$DEFAULT_BRANCH"`。 -
-
Bash:git pull --ff-only origin "$DEFAULT_BRANCH"。- 失败(非 fast-forward / 网络 / 冲突)→ 打印错误横幅: ``` ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ [coding-start] ⚠️ 同步 失败
本地 无法 fast-forward 到 remote。请手工处理: git status git log ..origin/ # 远程领先的 commit git log origin/.. # 本地未推的 commit 修复后重新运行 /erp-workflow:coding-start。 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
并**停下**。
步骤 5:打印横幅并分发
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[coding-start]
阶段:B 编码
当前模块:<current_module>
MR 状态:<未建 | opened | closed | 查不到>
下一步:invoke module-start
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
然后立即用 Skill 工具调用 module-start。
分发前先调用
interrupt-check;触发中断则停在此不分发。
设计要点
-
完成判定直接读取
MR:字段 + GitLab API state(curl,PRIVATE-TOKEN头):MR 未 merge 前 docs/08 没有任何"已完成"标记;用户提前触发 coding-start 时,步骤 3 扫描到 MR opened 仍会选中当前模块,module-start 会git checkout module-<id>回到原分支继续,不会跳到下一模块。 - 每次派发前都 pull 默认分支:代码同步的同时,也保证 module-start 切出新分支时 base 新鲜。默认分支由步骤 4.0 探测(main 或 master),不硬编码。
参考
-
docs/02-开发计划.md § 二 开发顺序清单(分发追踪) -
docs/08-模块任务管理.md § 二(模块元数据,含MR:字段) -
CLAUDE.md(项目指令) -
plan-start(姊妹入口,A 阶段)