From 9e8db6d8d15bb2b1df65f96c92c62c21107ef2b5 Mon Sep 17 00:00:00 2001 From: yanghl Date: Sat, 30 May 2026 08:16:37 +0800 Subject: [PATCH] feat(hooks): Stop 钩子自动续跑编码流程 + 去除 A 类人工停点 --- hooks/hooks.json | 13 +++++++++++++ hooks/scripts/auto-continue.sh | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ hooks/scripts/reset-stall-counter.sh | 16 ++++++++++++++++ skills/coding/fe-feature-brainstorm/SKILL.md | 2 +- skills/coding/fe-feature-plan/SKILL.md | 2 +- skills/coding/fe-feature-tdd/SKILL.md | 4 ++-- skills/coding/feature-brainstorm/SKILL.md | 2 +- skills/coding/feature-plan/SKILL.md | 2 +- skills/coding/feature-tdd/SKILL.md | 2 +- skills/coding/frontend-start/SKILL.md | 6 +++--- skills/coding/module-report/SKILL.md | 2 +- skills/coding/module-start/SKILL.md | 4 ++-- skills/coding/test-gate/SKILL.md | 4 ++-- skills/crosscut/coding-start/SKILL.md | 6 +++--- skills/crosscut/interrupt-check/SKILL.md | 2 +- skills/plan/db-init/SKILL.md | 14 +++++++------- skills/plan/downstream-gen/SKILL.md | 4 ++-- skills/plan/scope-lock/SKILL.md | 11 +++-------- skills/plan/skeleton-gen/SKILL.md | 22 +++++++--------------- 19 files changed, 134 insertions(+), 51 deletions(-) create mode 100755 hooks/scripts/auto-continue.sh create mode 100755 hooks/scripts/reset-stall-counter.sh diff --git a/hooks/hooks.json b/hooks/hooks.json index bdd90d0..ff16be1 100644 --- a/hooks/hooks.json +++ b/hooks/hooks.json @@ -6,6 +6,19 @@ "hooks": [ { "type": "command", "command": "\"${CLAUDE_PLUGIN_ROOT}\"/hooks/scripts/log-cross-module.sh" } ] + }, + { + "matcher": "", + "hooks": [ + { "type": "command", "command": "\"${CLAUDE_PLUGIN_ROOT}\"/hooks/scripts/reset-stall-counter.sh" } + ] + } + ], + "Stop": [ + { + "hooks": [ + { "type": "command", "command": "\"${CLAUDE_PLUGIN_ROOT}\"/hooks/scripts/auto-continue.sh" } + ] } ] } diff --git a/hooks/scripts/auto-continue.sh b/hooks/scripts/auto-continue.sh new file mode 100755 index 0000000..ab6572b --- /dev/null +++ b/hooks/scripts/auto-continue.sh @@ -0,0 +1,67 @@ +#!/usr/bin/env bash +# Stop 钩子:让 ERP workflow 在回合中途结束时自动续跑,除非命中「终止标记」或「防循环上限」。 +# +# 设计: +# 1. 终止标记 [ERP-HALT] —— 终止/硬护栏 skill(coding-start 全部完成、test-gate 红、 +# feature-tdd 路径护栏、interrupt-check 中断)会打印它。出现即放行停下。 +# 2. 防循环 —— 连续「无工具调用」的空转停止累加计数;达到上限放行停下。 +# 正常推进时由 PostToolUse 的 reset-stall-counter.sh 清零,故真流程不受限。 +# 3. 否则 —— block 并喂一句「继续推进」指令,用户无需手敲 continue。 +set -u + +INPUT="$(cat)" + +SENTINEL='[ERP-HALT]' +MAX_STALL=8 + +# —— 从 stdin JSON 取字段(不依赖 jq)—— +get_str() { + printf '%s' "$INPUT" \ + | sed -n "s/.*\"$1\"[[:space:]]*:[[:space:]]*\"\([^\"]*\)\".*/\1/p" \ + | head -n1 +} +TRANSCRIPT="$(get_str transcript_path)" +# 反转义 Windows 路径里的 \\ 与 \/ +TRANSCRIPT="${TRANSCRIPT//\\\\//}" +TRANSCRIPT="${TRANSCRIPT//\\//}" + +# 计数器文件(按会话 transcript 路径派生 key,避免多会话互相干扰) +KEY="$(printf '%s' "$TRANSCRIPT" | tr -cd 'A-Za-z0-9' | tail -c 40)" +[ -z "$KEY" ] && KEY="default" +CNT_FILE="${TMPDIR:-/tmp}/erp-autocont-$KEY" +SIZE_FILE="${TMPDIR:-/tmp}/erp-autosize-$KEY" + +allow_stop() { rm -f "$CNT_FILE" "$SIZE_FILE" 2>/dev/null; exit 0; } + +# 1) 终止标记出现在最近的 transcript 尾部 → 放行停下 +if [ -n "$TRANSCRIPT" ] && [ -f "$TRANSCRIPT" ]; then + if tail -c 16000 "$TRANSCRIPT" 2>/dev/null | grep -qF "$SENTINEL"; then + allow_stop + fi +fi + +# 2) 进展自复位(自包含,不依赖 PostToolUse):transcript 自上次停止以来显著增长 +# → 说明这一轮做了实质工作(工具调用 + 结果),清零空转计数。 +CUR_SIZE=0 +[ -n "$TRANSCRIPT" ] && [ -f "$TRANSCRIPT" ] && CUR_SIZE="$(wc -c < "$TRANSCRIPT" 2>/dev/null | tr -d ' ')" +case "$CUR_SIZE" in (''|*[!0-9]*) CUR_SIZE=0 ;; esac +LAST_SIZE=0 +[ -f "$SIZE_FILE" ] && LAST_SIZE="$(cat "$SIZE_FILE" 2>/dev/null || echo 0)" +case "$LAST_SIZE" in (''|*[!0-9]*) LAST_SIZE=0 ;; esac +echo "$CUR_SIZE" > "$SIZE_FILE" +if [ $((CUR_SIZE - LAST_SIZE)) -gt 4000 ]; then + rm -f "$CNT_FILE" 2>/dev/null +fi + +# 3) 防循环:连续空转停止达到上限 → 放行停下 +CNT=0 +[ -f "$CNT_FILE" ] && CNT="$(cat "$CNT_FILE" 2>/dev/null || echo 0)" +case "$CNT" in (''|*[!0-9]*) CNT=0 ;; esac +if [ "$CNT" -ge "$MAX_STALL" ]; then + allow_stop +fi +echo $((CNT + 1)) > "$CNT_FILE" + +# 3) 拦下停止 → 续跑 +printf '%s' '{"decision":"block","reason":"继续推进 ERP workflow:直接执行流程的下一步——若当前 skill 已结束,立即用 Skill 工具调用对应派发器(A 阶段 plan-start / B 阶段 coding-start)或链中的下一个 skill;不要输出收尾叙述、不要停下等用户输入。只有打印了 [ERP-HALT] 的终止/硬护栏点才应停下。"}' +exit 0 diff --git a/hooks/scripts/reset-stall-counter.sh b/hooks/scripts/reset-stall-counter.sh new file mode 100755 index 0000000..a58e028 --- /dev/null +++ b/hooks/scripts/reset-stall-counter.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash +# PostToolUse 钩子:任何工具调用都视为「有进展」,清零 auto-continue.sh 的空转计数。 +# 这样真正在推进的流程可无限续跑,只有「连续多次纯文字、零工具」的空转才会触发防循环上限。 +set -u + +INPUT="$(cat)" +TRANSCRIPT="$(printf '%s' "$INPUT" \ + | sed -n 's/.*"transcript_path"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' \ + | head -n1)" +TRANSCRIPT="${TRANSCRIPT//\\\\//}" +TRANSCRIPT="${TRANSCRIPT//\\//}" + +KEY="$(printf '%s' "$TRANSCRIPT" | tr -cd 'A-Za-z0-9' | tail -c 40)" +[ -z "$KEY" ] && KEY="default" +rm -f "${TMPDIR:-/tmp}/erp-autocont-$KEY" 2>/dev/null +exit 0 diff --git a/skills/coding/fe-feature-brainstorm/SKILL.md b/skills/coding/fe-feature-brainstorm/SKILL.md index d9a5707..3924c72 100644 --- a/skills/coding/fe-feature-brainstorm/SKILL.md +++ b/skills/coding/fe-feature-brainstorm/SKILL.md @@ -55,7 +55,7 @@ allowed-tools: Read Write Skill AskUserQuestion Glob Grep - 消费的后端端点(与 docs/05 对齐,按本 FE 的 `associated_reqs[]` 过滤) - 业务规则前端复刻清单(逐条,每条标注:规则描述 / 触发时机 / 报错文案 / 来源 REQ) - Design Tokens 引用清单(本 FE 用到的 `var(--color-*)` 名称) - - 文件已存在 → 征求用户确认后覆盖 + - 文件已存在 → 直接覆盖(spec 是 CC 内部产物,无需确认) 4. **Spec 自审**(inline 修,无须用户等待): - 所有顶级节非空 diff --git a/skills/coding/fe-feature-plan/SKILL.md b/skills/coding/fe-feature-plan/SKILL.md index ae0c9c2..9e746b3 100644 --- a/skills/coding/fe-feature-plan/SKILL.md +++ b/skills/coding/fe-feature-plan/SKILL.md @@ -56,7 +56,7 @@ allowed-tools: Read Write Grep Skill AskUserQuestion 5. **写 plan 到 `docs/superpowers/plans/-.md`**: - 按 `${CLAUDE_SKILL_DIR}/templates/fe-feature-plan-template.md` 渲染 - - 文件已存在 → 征求用户确认后覆盖 + - 文件已存在 → 直接覆盖(plan 是 CC 内部产物,无需确认) 6. **Plan 自审**(inline 修,无须用户等待): - 每个任务必须含 `test_file::test_name`、`impl_file`、完成标准 diff --git a/skills/coding/fe-feature-tdd/SKILL.md b/skills/coding/fe-feature-tdd/SKILL.md index aafadae..51ad834 100644 --- a/skills/coding/fe-feature-tdd/SKILL.md +++ b/skills/coding/fe-feature-tdd/SKILL.md @@ -13,8 +13,8 @@ allowed-tools: Read Write Edit Agent Skill Bash(git add *) Bash(git commit *) ## 路径护栏(前端阶段) -- 任务的 `impl_file` 路径若**不以** `frontend/`(或项目实际前端根目录,从 `docs/09-项目目录结构.md § 前端目录结构` 取)开头 → 硬停并打印:`fe-feature-tdd 不允许写非前端文件:。前端阶段任务的 impl_file 必须落在前端目录下。` -- 命中 `backend/` / `sql/` / `scripts/` → 同上硬停 +- 任务的 `impl_file` 路径若**不以** `frontend/`(或项目实际前端根目录,从 `docs/09-项目目录结构.md § 前端目录结构` 取)开头 → 硬停并打印:`fe-feature-tdd 不允许写非前端文件:。前端阶段任务的 impl_file 必须落在前端目录下。 [ERP-HALT]` +- 命中 `backend/` / `sql/` / `scripts/` → 同上硬停 `[ERP-HALT]` - 不允许在主会话直接 `pnpm playwright` / `pnpm test` / `pnpm e2e`,必须派发子会话 ## 执行步骤 diff --git a/skills/coding/feature-brainstorm/SKILL.md b/skills/coding/feature-brainstorm/SKILL.md index eb1bfd8..f7a3b91 100644 --- a/skills/coding/feature-brainstorm/SKILL.md +++ b/skills/coding/feature-brainstorm/SKILL.md @@ -43,7 +43,7 @@ allowed-tools: Read Write Skill AskUserQuestion Bash(mysql *) 3. **写 spec 到 `docs/superpowers/specs/-.md`**: - 按 `${CLAUDE_SKILL_DIR}/templates/feature-spec-template.md` 渲染 - 覆盖:goal / 输入输出 / 业务规则 / 约束 / schema / API 引用 / acceptance criteria - - 文件已存在 → 征求用户确认后覆盖 + - 文件已存在 → 直接覆盖(spec 是 CC 内部产物,无需确认) 4. **Spec 自审**(inline 修,无须用户等待): - **占位符扫描**:`TBD` / `TODO` / `【人工填写:】` / 含糊段 → 修(按"占位符规则"流程解决) diff --git a/skills/coding/feature-plan/SKILL.md b/skills/coding/feature-plan/SKILL.md index 57f12c5..2e2560f 100644 --- a/skills/coding/feature-plan/SKILL.md +++ b/skills/coding/feature-plan/SKILL.md @@ -56,7 +56,7 @@ allowed-tools: Read Write Grep Skill AskUserQuestion 5. **写 plan 到 `docs/superpowers/plans/-.md`**: - 按 `${CLAUDE_SKILL_DIR}/templates/feature-plan-template.md` 渲染 - - 文件已存在 → 征求用户确认后覆盖 + - 文件已存在 → 直接覆盖(plan 是 CC 内部产物,无需确认) 6. **Plan 自审**(inline 修,无须用户等待): - **占位符扫描**:按"占位符规则"清单逐项 grep;命中即修 diff --git a/skills/coding/feature-tdd/SKILL.md b/skills/coding/feature-tdd/SKILL.md index 093578e..18f9002 100644 --- a/skills/coding/feature-tdd/SKILL.md +++ b/skills/coding/feature-tdd/SKILL.md @@ -35,7 +35,7 @@ allowed-tools: Read Write Edit Agent Skill Bash(git add *) Bash(git commit *) - **绝不**在主会话直接跑 `./gradlew test` / `pnpm test` / `scripts/test.sh`,必须通过子会话 - **绝不**在主会话直接 `mysql -e "ALTER ..."`;业务 schema 改动一律走 `sql/migrations/V*.sql` 文件(只读查询 / 临时调试除外) - 每次 commit 必须含 `REQ-XXX-NNN` 标签;不混合无关改动到同一 commit -- **后端阶段路径硬护栏**:任务表里的 `impl_file` 路径以 `frontend/` 开头 → 硬停并打印 `feature-tdd 后端阶段不允许写前端代码:。请检查 plan 任务定义;UI 推迟到前端阶段(fe-feature-*)`,不再继续 TDD 循环 +- **后端阶段路径硬护栏**:任务表里的 `impl_file` 路径以 `frontend/` 开头 → 硬停并打印 `feature-tdd 后端阶段不允许写前端代码:。请检查 plan 任务定义;UI 推迟到前端阶段(fe-feature-*) [ERP-HALT]`,不再继续 TDD 循环 ## 参考 diff --git a/skills/coding/frontend-start/SKILL.md b/skills/coding/frontend-start/SKILL.md index b023a6c..62f61c5 100644 --- a/skills/coding/frontend-start/SKILL.md +++ b/skills/coding/frontend-start/SKILL.md @@ -19,7 +19,7 @@ allowed-tools: Read Write Edit Skill Glob Grep AskUserQuestion Bash(git branch * 读 docs/08 § 三 "功能:" 项: -- 已有 `- [ ] FE-NN ...` 或 `- [x] FE-NN ...` 行 → **加载**:逐行解析得 `fe_list[]`,每项 `{ fe_id, name, status, associated_reqs[], associated_prototypes[] }`。行格式不符 → 硬停打印问题行 +- 已有 `- [ ] FE-NN ...` 或 `- [x] FE-NN ...` 行 → **加载**:逐行解析得 `fe_list[]`,每项 `{ fe_id, name, status, associated_reqs[], associated_prototypes[] }`。行格式不符 → 硬停打印问题行 `[ERP-HALT]` - 仅有 HTML 注释占位(无 FE bullet)→ **推导**: 1. 读 `prototype/**/*.html` + `docs/01-需求清单/**/*.md` + `docs/05-API接口契约.md` 2. 以**业务功能**为单位拆分(同流程多屏可合 1 FE;一 HTML 多功能可拆多 FE;无 UI 的 REQ 不产生 FE)。每个 FE:`{ fe_id: FE-NN, name, associated_reqs[], associated_prototypes[] }`,prototype 路径可带 anchor 区分文件内多区域 @@ -35,12 +35,12 @@ allowed-tools: Read Write Edit Skill Glob Grep AskUserQuestion Bash(git branch * 读 § 三 `整体里程碑:` 字段并 `git tag -l 'milestone/frontend-phase'` 校验: -- 字段为 `milestone/frontend-phase` 且 tag 存在 → 打印"前端阶段已完成"并停(冗余保护,正常由 coding-start 拦掉) +- 字段为 `milestone/frontend-phase` 且 tag 存在 → 打印"前端阶段已完成 `[ERP-HALT]`"并停(冗余保护,正常由 coding-start 拦掉) - 否则(`—` 或 tag 不存在)→ 进入步骤 4 ### 步骤 4:切到 frontend-phase 分支 -目标分支 `frontend-phase`,分支管理逻辑同 module-start 步骤 3:已在 → 继续;存在 → checkout;不存在 → 切本地默认分支后 `git checkout -b frontend-phase`。任何错误硬停 + 诊断,不自动 stash / 覆盖。 +目标分支 `frontend-phase`,分支管理逻辑同 module-start 步骤 3:已在 → 继续;存在 → checkout;不存在 → 切本地默认分支后 `git checkout -b frontend-phase`。任何错误硬停 + 诊断,不自动 stash / 覆盖。`[ERP-HALT]` ### 步骤 5:识别已完成的 FE diff --git a/skills/coding/module-report/SKILL.md b/skills/coding/module-report/SKILL.md index a33dcdb..4089a8c 100644 --- a/skills/coding/module-report/SKILL.md +++ b/skills/coding/module-report/SKILL.md @@ -15,7 +15,7 @@ allowed-tools: Read Write Glob Grep Skill Bash(git diff *) Bash(git log *) Bash( - `module-` → `phase=backend`,`phase_id=` - `frontend-phase` → `phase=frontend`,`phase_id=frontend-phase` -- 其它分支 → 硬停 +- 其它分支 → 硬停 `[ERP-HALT]` ## 执行步骤 diff --git a/skills/coding/module-start/SKILL.md b/skills/coding/module-start/SKILL.md index b81692b..86454e4 100644 --- a/skills/coding/module-start/SKILL.md +++ b/skills/coding/module-start/SKILL.md @@ -26,7 +26,7 @@ allowed-tools: Read Write Skill Glob Grep Bash(git branch *) Bash(git checkout * 约束: - 模块完成 = `docs/08 § 二` 该模块 `里程碑:` 字段为 `milestone/` 且 `git tag -l` 能查到该 tag;二者任一缺失即视为未完成 -- 任何文件读取或解析失败 → 打印错误并停止 +- 任何文件读取或解析失败 → 打印错误并停止 `[ERP-HALT]` ### 步骤 2:找不到未完成后端模块的处理 @@ -43,7 +43,7 @@ allowed-tools: Read Write Skill Glob Grep Bash(git branch *) Bash(git checkout * - 该分支已存在但当前不在 → checkout 过去 - 该分支不存在 → 先把工作树切到本地默认分支(main 或 master,已由 milestone-tag 的本地 merge 累积所有已完成模块),作为新分支的干净 base,再 `git checkout -b` 创建模块分支 -任何错误(定位不到默认分支 / 切换前工作树脏 / checkout 失败)一律停下并打印诊断信息,不自动 stash、不强制覆盖。 +任何错误(定位不到默认分支 / 切换前工作树脏 / checkout 失败)一律停下并打印诊断信息,不自动 stash、不强制覆盖。`[ERP-HALT]` ### 步骤 4:计算已完成 REQ 集合 `done_reqs[]` diff --git a/skills/coding/test-gate/SKILL.md b/skills/coding/test-gate/SKILL.md index d1e8949..dfd2931 100644 --- a/skills/coding/test-gate/SKILL.md +++ b/skills/coding/test-gate/SKILL.md @@ -24,7 +24,7 @@ allowed-tools: Read Write Skill Agent Bash(git add *) Bash(git commit *) Bash(gi - `module-` → `phase=backend`,`phase_id=`,`command=./scripts/test.sh` - `frontend-phase` → `phase=frontend`,`phase_id=frontend-phase`;命令从 `docs/04-技术规范.md § 零 frontend.test_command` / `frontend.e2e_command` 拼接(缺失则 `pnpm test:ci && pnpm e2e:ci`) -- 其它分支 → 硬停打印 `test-gate 仅在 module-* 或 frontend-phase 分支可调用,当前 ` +- 其它分支 → 硬停打印 `test-gate 仅在 module-* 或 frontend-phase 分支可调用,当前 [ERP-HALT]` 1. 派发 Agent 子会话(general-purpose)运行上述 `command`,子会话只返回结构化 JSON(不输出描述文字): ```json @@ -47,7 +47,7 @@ allowed-tools: Read Write Skill Agent Bash(git add *) Bash(git commit *) Bash(gi ``` ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - [test-gate] ⚠️ 未通过 (phase=) + [test-gate] ⚠️ 未通过 (phase=) [ERP-HALT] 失败清单: <子会话 JSON 的 failed 摘要> 详细证据: docs/superpowers/module-reports/-test-gate.md diff --git a/skills/crosscut/coding-start/SKILL.md b/skills/crosscut/coding-start/SKILL.md index fe4cb42..8774b66 100644 --- a/skills/crosscut/coding-start/SKILL.md +++ b/skills/crosscut/coding-start/SKILL.md @@ -22,13 +22,13 @@ cat "${CLAUDE_PLUGIN_ROOT}/skills/crosscut/coding-start/banners/flow-overview.tx ### 步骤 1:确认 docs/08 存在 检查 `docs/08-模块任务管理.md` 存在。 -- 不存在 → 打印"⚠️ 项目尚未初始化,请先运行 `/erp-workflow:plan-start`"并停下。 +- 不存在 → 打印"⚠️ 项目尚未初始化,请先运行 `/erp-workflow:plan-start` `[ERP-HALT]`"并停下。 ### 步骤 2:Plan 完成性检查 读取 `docs/08-模块任务管理.md § 一`,判断 A0~A5 是否全部勾选(含子项)。 -- 任一未勾选 → 提示用户先运行 `/erp-workflow:plan-start` 完成 A 阶段,并停下 +- 任一未勾选 → 提示用户先运行 `/erp-workflow:plan-start` 完成 A 阶段并打印 `[ERP-HALT]`,停下 - 全部勾选 → 进入步骤 3 ### 步骤 3:后端完成性检查 + 派发 @@ -43,7 +43,7 @@ cat "${CLAUDE_PLUGIN_ROOT}/skills/crosscut/coding-start/banners/flow-overview.tx 读 `docs/08 § 三 整体里程碑:` 字段(并用 `git tag -l 'milestone/frontend-phase'` 校验): -- **`整体里程碑: milestone/frontend-phase` 且 tag 存在** → 前端已完成,打印 `所有阶段已完成(后端模块 + 前端阶段里程碑均已标记)`,结束本 skill。 +- **`整体里程碑: milestone/frontend-phase` 且 tag 存在** → 前端已完成,打印 `所有阶段已完成(后端模块 + 前端阶段里程碑均已标记) [ERP-HALT]`,结束本 skill。 - **`整体里程碑: —` 或 tag 不存在** → 前端未完成,打印 `[coding-start] 后端已完成、前端未完成 → 派发 frontend-start(写前端)`,立即用 Skill 工具调用 frontend-start(直接调用,**不要**先输出"已完成 / 接下来 / 请检查 / 等你确认"之类桥接叙述——会被解读为 turn 结束信号、害用户手敲 continue),本 skill 结束。 diff --git a/skills/crosscut/interrupt-check/SKILL.md b/skills/crosscut/interrupt-check/SKILL.md index 36de300..a7b0d8d 100644 --- a/skills/crosscut/interrupt-check/SKILL.md +++ b/skills/crosscut/interrupt-check/SKILL.md @@ -30,7 +30,7 @@ allowed-tools: Read Write Bash(mysql *) 1. 逐项核对 3 个中断条件。**全部未触发** → 输出 `interrupt-check: 通过`,结束。 2. **触发任一** → 按 `${CLAUDE_SKILL_DIR}/templates/interrupt-block-template.md` 渲染 Blocker 块,追加到当前 plan 文件(典型路径 `docs/superpowers/plans/-.md`;test-gate 场景下追加到本模块任一已有 plan 文件)。 -3. 向会话打印一句话摘要 + 指向 plan 文件路径,**停下**。 +3. 向会话打印一句话摘要 + 指向 plan 文件路径 + `[ERP-HALT]`,**停下**。 ## 参考 diff --git a/skills/plan/db-init/SKILL.md b/skills/plan/db-init/SKILL.md index 7b1a322..5a36e8e 100644 --- a/skills/plan/db-init/SKILL.md +++ b/skills/plan/db-init/SKILL.md @@ -66,8 +66,8 @@ bash "${CLAUDE_SKILL_DIR}/scripts/validate.sh" \ - `1` → **自主修正循环**(最多 3 轮,docs/03 是 SSoT 不动): 1. 解析 stderr 差异清单,修正 V1.sql 2. 重跑 validate.sh - 3. 退出 0 → 进入 B;退出 1 且本轮 < 3 → 回步骤 1;本轮 ≥ 3 仍失败 → 停下,打印最终残留差异 + 已尝试的 3 轮修正摘要,让用户介入 -- `2` → 用法错(V1 / docs 路径找不到),打印路径并停下 + 3. 退出 0 → 进入 B;退出 1 且本轮 < 3 → 回步骤 1;本轮 ≥ 3 仍失败 → 停下,打印最终残留差异 + 已尝试的 3 轮修正摘要,让用户介入 `[ERP-HALT]` +- `2` → 用法错(V1 / docs 路径找不到),打印路径并停下 `[ERP-HALT]` 完成后(V1 写入并通过 validate.sh 校验),用 `Edit` 在 `docs/08-模块任务管理.md` 中勾选: - ` - [ ] sql/migrations/V1__initial_schema.sql 已生成` @@ -77,7 +77,7 @@ bash "${CLAUDE_SKILL_DIR}/scripts/validate.sh" \ #### B.1 检查 .env.local 凭据 -用 `Glob` 检查 `.env.local` 是否存在;不存在 → 提示用户重新运行 A2 `skeleton-gen` 重建并停下。 +用 `Glob` 检查 `.env.local` 是否存在;不存在 → 提示用户重新运行 A2 `skeleton-gen` 重建并停下。`[ERP-HALT]` 用 `Bash` 加载并校验 5 个必填字段非空: @@ -89,7 +89,7 @@ for v in DB_HOST DB_PORT DB_USER DB_PASSWORD DB_SCHEMA; do done ``` -任一缺失 → 打印缺失字段名并停下,提示用户编辑 `.env.local` 后重跑。 +任一缺失 → 打印缺失字段名并停下,提示用户编辑 `.env.local` 后重跑。`[ERP-HALT]` #### B.2 验证 MySQL 连接 @@ -99,7 +99,7 @@ mysql -h"$DB_HOST" -P"$DB_PORT" -u"$DB_USER" -p"$DB_PASSWORD" -e "SELECT 1;" ``` - **成功** → 进入步骤 C -- **失败** → 打印具体错误(认证 / 主机不可达 / 端口拒接等),提示检查 `.env.local`,**停下**。 +- **失败** → 打印具体错误(认证 / 主机不可达 / 端口拒接等),提示检查 `.env.local`,**停下**。`[ERP-HALT]` 完成后,用 `Edit` 在 `docs/08-模块任务管理.md` 中勾选: - ` - [ ] .env.local 凭据已验证(mysql -e "SELECT 1" OK)` @@ -120,7 +120,7 @@ mysql -h"$DB_HOST" -P"$DB_PORT" -u"$DB_USER" -p"$DB_PASSWORD" "$DB_SCHEMA" \ < sql/migrations/V1__initial_schema.sql ``` -非零退出 → 报错停下,打印 mysql stderr。 +非零退出 → 报错停下,打印 mysql stderr。`[ERP-HALT]` 完成后,用 `Edit` 在 `docs/08-模块任务管理.md` 中勾选: - ` - [ ] setup-test-db.sh 防护通过 + DROP+CREATE + apply V1 已执行` @@ -135,7 +135,7 @@ EXPECTED=$(grep -c '^## `' docs/03-数据库设计文档.md) [ "$ACTUAL" = "$EXPECTED" ] || { echo "MISMATCH: actual=$ACTUAL expected=$EXPECTED"; exit 1; } ``` -行数不一致 → 报错停下;一致 → 进入步骤 D。 +行数不一致 → 报错停下 `[ERP-HALT]`;一致 → 进入步骤 D。 ### D. 勾选 docs/08 进度 + 进入 A5 diff --git a/skills/plan/downstream-gen/SKILL.md b/skills/plan/downstream-gen/SKILL.md index ffbf6f5..5961571 100644 --- a/skills/plan/downstream-gen/SKILL.md +++ b/skills/plan/downstream-gen/SKILL.md @@ -94,11 +94,11 @@ cp "${CLAUDE_SKILL_DIR}/templates/docs-10-header-template.md" docs/10-验收检 - **module_id 缺 docs/08 § 二** → 按步骤 D 规则渲染该模块 bullet(含 REQ 子项),按 `module_id` 字母序插入正确位置 - **module_id 缺 docs/02 § 二** → 重算该模块的 `req_order` 段(步骤 A 子流程),按拓扑序插入 docs/02 § 二 - 修复后重跑检查;通过 → 进入 2;3 轮仍失败 → 停下,打印最终残留差异 + 已尝试的 3 轮修复摘要让用户介入。 + 修复后重跑检查;通过 → 进入 2;3 轮仍失败 → 停下,打印最终残留差异 + 已尝试的 3 轮修复摘要让用户介入。`[ERP-HALT]` 2. **最终占位符扫描**(覆盖 Plan 阶段全部产出): - a. **`TBD` → 自动补齐**:Grep 搜索 `TBD(A3 自动补)` 和 `TBD(A5 自动补)`。有命中则就地补填(A3 残留 → 查 docs/03 填 `依赖表`;A5 残留 → 查 docs/05 按 REQ-ID 填 `依赖接口`),再 Grep 确认 0 命中;仍残留报错停下。 + a. **`TBD` → 自动补齐**:Grep 搜索 `TBD(A3 自动补)` 和 `TBD(A5 自动补)`。有命中则就地补填(A3 残留 → 查 docs/03 填 `依赖表`;A5 残留 → 查 docs/05 按 REQ-ID 填 `依赖接口`),再 Grep 确认 0 命中;仍残留报错停下。`[ERP-HALT]` b. **`【人工填写:...】` → QA 循环等用户补**: diff --git a/skills/plan/scope-lock/SKILL.md b/skills/plan/scope-lock/SKILL.md index 2e39871..62af289 100644 --- a/skills/plan/scope-lock/SKILL.md +++ b/skills/plan/scope-lock/SKILL.md @@ -47,7 +47,7 @@ cat "${CLAUDE_PLUGIN_ROOT}/skills/plan/scope-lock/banners/flow.txt" 0 命中后,用 `Edit` 在 `docs/08-模块任务管理.md` 中勾选: - ` - [ ] 项目概述已填写(CLAUDE.md § 🎯 项目概述)` -### B. 提示用户检查默认技术栈并等待 +### B. 默认技术栈(自动,无停顿) `docs/04-技术规范.md` 已由 A0 `project-init` 用模板复制(默认技术栈,见 `project-init/templates/docs-04-stack-template.md`)。本步骤让用户检查 / 调整 § 零。 @@ -64,16 +64,11 @@ cat "${CLAUDE_PLUGIN_ROOT}/skills/plan/scope-lock/banners/flow.txt" - 不需要的行直接删除(如纯后端项目删前端行) - 需要替换的技术直接改 - 需要新增的条目直接加行 - 改完后回来选择「继续」。 + (默认栈开箱即用;如需改,直接编辑该文件即可,流程不会在此等待。) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ``` -用 `AskUserQuestion` 询问: -- **question**: `技术栈检查完毕了吗?` - - 用户选择「继续」→ 进入步骤 C。 - - 用户选择「有疑问想先沟通」→ 回答用户问题后,再次弹出同样的 QA。 - -完成后,用 `Edit` 在 `docs/08-模块任务管理.md` 中勾选: +**不再弹窗等待。** 默认技术栈直接采用;若用户在本轮对话中已明确要求调整某项技术,就地用 `Edit` 改 docs/04 § 零,否则保持默认。随后用 `Edit` 在 `docs/08-模块任务管理.md` 中勾选,并直接进入步骤 C: - ` - [ ] 技术栈已确认(docs/04 § 零)` ### C. 提示用户填写需求清单并等待 diff --git a/skills/plan/skeleton-gen/SKILL.md b/skills/plan/skeleton-gen/SKILL.md index 65c19d9..ffe38e1 100644 --- a/skills/plan/skeleton-gen/SKILL.md +++ b/skills/plan/skeleton-gen/SKILL.md @@ -135,23 +135,15 @@ bash "${CLAUDE_SKILL_DIR}/scripts/merge-gitignore.sh" "${CLAUDE_SKILL_DIR}/templ > `.env.local` 的 DB 连接核对**不在此处停**,统一放到 E.4 最终闸门——等所有产出(docs / scripts / .env.local / .gitignore)都初始化完成后再停一次,避免「一生成就停」。 -#### E.4 验证 + QA 闸门(含 .env.local 连接核对) +#### E.4 验证闸门(自动,无停顿) -**这是 skeleton-gen 唯一的收尾停顿——所有产出(docs / scripts / .env.local / .gitignore)全部初始化完成后才在此停一次**,**严禁**在 `.env.local` 一生成(C.1)时就提前停。 +所有产出(docs / scripts / .env.local / .gitignore)初始化完成后在此自动校验放行,**不再弹窗等待**: -循环直到两条件**同时**满足: -(a) `Grep` 重新扫 8 路径,0 命中 -(b) 用户 `AskUserQuestion` 选「继续」 - -每次弹 QA 前重扫;有残留则打印残留位置清单(文件:行号 — 说明)+ 再弹 QA。 - -QA 横幅涵盖: -- 产出文件清单(docs/04 / 06 / 07 / 09 + scripts/*.sh + .env.local + .gitignore) -- 占位状态(N=0 或待填清单) -- **`.env.local` DB 连接核对**:用 `Bash`(`set -a; . .env.local; set +a`)读出后列出当前 `DB_HOST` / `DB_PORT` / `DB_USER` / `DB_SCHEMA` 的**值**;`DB_PASSWORD` / `JWT_SECRET` **只列字段名、不回显值**(凭据不进会话)。提示「默认连接开箱即用;若与本地 MySQL 不符,**现在直接编辑 `.env.local`** 再选『继续』(`cp -n` 不会覆盖你的修改,下一步 A4 db-init 会真正连库验证)」。 -- 两选项:「继续」/「有疑问先沟通」 - -通过后(N=0 且用户选「继续」),用 `Edit` 在 `docs/08-模块任务管理.md` 中勾选: +1. `Grep` 重扫 8 路径的占位符: + - 0 命中 → 进入 2。 + - 仍有残留 → 打印残留清单(文件:行号 — 说明)并停下 `[ERP-HALT]`(骨架产出不应残留占位符,属生成异常,修正后重跑)。 +2. **`.env.local` DB 连接信息(仅供参考,无需在此确认)**:用 `Bash`(`set -a; . .env.local; set +a`)列出 `DB_HOST` / `DB_PORT` / `DB_USER` / `DB_SCHEMA` 的**值**;`DB_PASSWORD` / `JWT_SECRET` **只列字段名、不回显**(凭据不进会话)。默认连接开箱即用;如与本地 MySQL 不符,可直接编辑 `.env.local`,下一步 A4 db-init 会真正连库验证(连不上会在 A4 报错停下)。 +3. 用 `Edit` 在 `docs/08-模块任务管理.md` 中勾选,并直接进入 F: - `- [ ] A2 骨架生成 — skeleton-gen` ### F. 进入 A3 -- libgit2 0.22.2