Commit 981f6aceb41952b9b41ee6f4624b88ef50d52515

Authored by zichun
1 parent e559870b

refactor: B 阶段改用本地里程碑 tag,移除 git 远程/MR

- mr-create → milestone-tag:本地 merge 进默认分支 + 打 milestone/<id> tag,完成后自动回调 coding-start(无人工闸门)
- 移除 push/GitLab MR/API:删 deny-no-verify hook、derive-gitlab 脚本、pre-push 模板,env-local 去 GITLAB_*
- 完成判定改为 docs/08「里程碑」字段 + git tag -l;README/CLAUDE-template/状态语义同步
- 删除空 skills/internal 目录,skill 计数 27→25
- docs-04 § 一 新增 1.1 规则(后端通用约定)占位,由 skeleton-gen E 填写
Showing 36 changed files with 248 additions and 822 deletions
.claude-plugin/plugin.json
1 { 1 {
2 "name": "erp-workflow", 2 "name": "erp-workflow",
3 - "description": "ERP 项目全流程框架:阶段 A 计划(一次性) + 阶段 B 编码(模块循环 + 功能循环),含完整 skill 流水线 + 守门 hook + 软规则留痕。专为后端 Spring Boot + 前端 React + MySQL 8 的 ERP/管理类系统设计。", 3 + "description": "ERP 项目全流程框架:阶段 A 计划(一次性) + 阶段 B 编码(模块循环 + 功能循环),含完整 skill 流水线 + 守门 hook + 软规则留痕。",
4 "version": "0.1.0", 4 "version": "0.1.0",
5 - "skills": ["./skills/plan", "./skills/coding", "./skills/crosscut", "./skills/internal"] 5 + "skills": ["./skills/plan", "./skills/coding", "./skills/crosscut"]
6 } 6 }
README.md
@@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
2 2
3 Claude Code 插件:ERP / 后端管理系统全流程开发框架。 3 Claude Code 插件:ERP / 后端管理系统全流程开发框架。
4 4
5 -把"从零到 N 个模块上线 + 前端整体阶段"的整个流程固化成 **27 个 skill + 2 个 agent + 2 个 hook + 44 份模板**,让 CC 在 schema 演化用 Flyway migration、需求可追溯、人工审核可控的前提下推进编码。后端按模块循环依次提交 MR,所有后端 merged 后进入前端整体阶段(以项目根 `prototype/` 静态 HTML mockup 为页面权威)。 5 +把"从零到 N 个模块上线 + 前端整体阶段"的整个流程固化成 **25 个 skill + 2 个 agent + 1 个 hook + 41 份模板**,让 CC 在 schema 演化用 Flyway migration、需求可追溯、纯本地 git 的前提下推进编码。后端按模块循环依次打里程碑 tag,所有后端模块打里程碑后进入前端整体阶段(以项目根 `prototype/` 静态 HTML mockup 为页面权威)。
6 6
7 ## 这个插件做什么 7 ## 这个插件做什么
8 8
@@ -27,15 +27,15 @@ Claude Code 插件:ERP / 后端管理系统全流程开发框架。 @@ -27,15 +27,15 @@ Claude Code 插件:ERP / 后端管理系统全流程开发框架。
27 27
28 B-后端(按模块循环) 28 B-后端(按模块循环)
29 功能循环:Brainstorm → Plan → TDD → Verify → Review 29 功能循环:Brainstorm → Plan → TDD → Verify → Review
30 - 模块循环:本地测试闸门 → 写模块报告 → 创建 GitLab MR → ⏸ 用户 Approve+Merge → 下次 coding-start 自动扫描 MR 状态为 merged → 下一模块 30 + 模块循环:本地测试闸门 → 写模块报告 → 本地 merge 进默认分支 + 打 milestone/<id> tag → 自动回 coding-start → 下一模块
31 31
32 - ↓ 后端全部 merged 32 + ↓ 后端全部打里程碑
33 33
34 - B-前端(整体阶段,1 个 MR 34 + B-前端(整体阶段,1 个里程碑 tag
35 入口门禁:检查项目根 prototype/ 至少含 1 个 *.html mockup(缺失则 AskUserQuestion 提示用户补齐) 35 入口门禁:检查项目根 prototype/ 至少含 1 个 *.html mockup(缺失则 AskUserQuestion 提示用户补齐)
36 - FE 拆分:AI 自主推导功能清单(业务功能粒度,与 HTML 文件数无关)写入 docs/08 § 三;已有则加载——无人工审阅断点(人工只在 MR Approve+Merge 处介入) 36 + FE 拆分:AI 自主推导功能清单(业务功能粒度,与 HTML 文件数无关)写入 docs/08 § 三;已有则加载——无人工审阅断点(全程无人工介入)
37 FE 循环(每个 FE-NN):fe-feature-brainstorm → -plan → -tdd → -verify → -review 37 FE 循环(每个 FE-NN):fe-feature-brainstorm → -plan → -tdd → -verify → -review
38 - 收尾:test-gate(phase=frontend) → module-report(phase=frontend) → mr-create(分支 frontend-phase)→ ⏸ 用户 Approve+Merge → 全部完成 38 + 收尾:test-gate(phase=frontend) → module-report(phase=frontend) → milestone-tag(分支 frontend-phase)→ 全部完成
39 39
40 ⚙️ 后台守门:占位符未填 / 中断触发 / 跨模块改动未记录 40 ⚙️ 后台守门:占位符未填 / 中断触发 / 跨模块改动未记录
41 ``` 41 ```
@@ -66,7 +66,7 @@ Claude Code 插件:ERP / 后端管理系统全流程开发框架。 @@ -66,7 +66,7 @@ Claude Code 插件:ERP / 后端管理系统全流程开发框架。
66 ``` 66 ```
67 /erp-workflow:coding-start 67 /erp-workflow:coding-start
68 ``` 68 ```
69 - Plan 全部完成后由你显式触发。`coding-start` 是阶段分发权威——每次入口都重新扫描 docs/08 § 二/§ 三 + GitLab API state,按当前进度决定派发: 69 + Plan 全部完成后由你显式触发。`coding-start` 是阶段分发权威——每次入口都重新扫描 docs/08 § 二/§ 三 里程碑字段 + 本地 git tag,按当前进度决定派发:
70 70
71 **路由规则(coding-start 真值表,只做分发)**: 71 **路由规则(coding-start 真值表,只做分发)**:
72 72
@@ -76,19 +76,19 @@ Claude Code 插件:ERP / 后端管理系统全流程开发框架。 @@ -76,19 +76,19 @@ Claude Code 插件:ERP / 后端管理系统全流程开发框架。
76 | `true` | `false` | `frontend-start`(写前端) | 76 | `true` | `false` | `frontend-start`(写前端) |
77 | `true` | `true` | 打印"所有阶段已完成",停下 | 77 | `true` | `true` | 打印"所有阶段已完成",停下 |
78 78
79 - GitLab API HTTP 非 200 / 查不到 / state 非法 → 停下报错(绝不静默假设未 merged)。 79 + docs/08 里程碑字段与 `git tag -l` 不一致(字段填了但 tag 不存在,或反之)→ 停下报错(绝不静默假设完成状态)。
80 80
81 **后端阶段(module-start 内,单一职责)**: 81 **后端阶段(module-start 内,单一职责)**:
82 - - 切到 `module-<id>` 分支,跑功能循环(feature-brainstorm → ... → feature-review)→ 全 approve → test-gate → module-report → mr-create → ⏸ 人工 Approve+Merge → 用户重跑 coding-start,coding-start 再次路由 82 + - 切到 `module-<id>` 分支,跑功能循环(feature-brainstorm → ... → feature-review)→ 全 approve → test-gate → module-report → milestone-tag(本地 merge + 打 tag)→ 自动回 coding-start 再次路由
83 83
84 **前端阶段(frontend-start 内,自带前置门禁)**: 84 **前端阶段(frontend-start 内,自带前置门禁)**:
85 - 步骤 1:prototype/ 门禁(≥ 1 个 *.html,缺失则 AskUserQuestion 提示用户补齐 → 停下) 85 - 步骤 1:prototype/ 门禁(≥ 1 个 *.html,缺失则 AskUserQuestion 提示用户补齐 → 停下)
86 - 步骤 2:准备 FE 清单(无审阅断点)。§ 三 占位则 AI 扫 prototype + docs/01 + docs/05 自主推导 FE 业务功能清单写入 § 三(每个 FE 标注关联 REQ + 关联原型;FE 数与 HTML 文件数无关);§ 三 已有则直接加载 86 - 步骤 2:准备 FE 清单(无审阅断点)。§ 三 占位则 AI 扫 prototype + docs/01 + docs/05 自主推导 FE 业务功能清单写入 § 三(每个 FE 标注关联 REQ + 关联原型;FE 数与 HTML 文件数无关);§ 三 已有则直接加载
87 - - 步骤 4-8:MR state 判定 → 切 `frontend-phase` 分支 → 跑 fe-feature 循环(fe-feature-brainstorm → ... → fe-feature-review,专用 `fe-code-reviewer` agent 做 7 维 review)→ 全 approve → test-gate(frontend) → module-report(frontend) → mr-create(docs/08 § 三 整体 MR)→ ⏸ 人工 Approve+Merge 87 + - 步骤 3-7:里程碑 tag 判定 → 切 `frontend-phase` 分支 → 跑 fe-feature 循环(fe-feature-brainstorm → ... → fe-feature-review,专用 `fe-code-reviewer` agent 做 7 维 review)→ 全 approve → test-gate(frontend) → module-report(frontend) → milestone-tag(docs/08 § 三 整体里程碑)→ 自动回 coding-start → 全部完成
88 88
89 - `docs/08 § 二` 每后端模块占一行 bullet,`§ 三` 是前端阶段整体段,完成信号统一由 MR merged state 判定。 89 + `docs/08 § 二` 每后端模块占一行 bullet,`§ 三` 是前端阶段整体段,完成信号统一由本地 `git tag -l 'milestone/<id>'` 判定。
90 90
91 -4. **中途恢复**:任何时候运行对应入口命令——根据 Plan § 一 checkbox、§ 二 各后端模块 MR state、§ 三 前端整体 MR state 跳到当前该做的事。 91 +4. **中途恢复**:任何时候运行对应入口命令——根据 Plan § 一 checkbox、§ 二 各后端模块里程碑 tag、§ 三 前端整体里程碑 tag 跳到当前该做的事。
92 92
93 ## 目录结构 93 ## 目录结构
94 94
@@ -98,26 +98,24 @@ erp-workflow-plugin/ @@ -98,26 +98,24 @@ erp-workflow-plugin/
98 │ └── plugin.json # 插件清单,声明 skills 四个子目录 98 │ └── plugin.json # 插件清单,声明 skills 四个子目录
99 ├── README.md # 本文档 99 ├── README.md # 本文档
100 ├── hooks/ 100 ├── hooks/
101 -│ ├── hooks.json # hook 注册表(2 个 hook)  
102 -│ └── scripts/*.sh # 2 个 hook 脚本 101 +│ ├── hooks.json # hook 注册表(1 个 hook)
  102 +│ └── scripts/*.sh # 1 个 hook 脚本
103 ├── agents/ 103 ├── agents/
104 │ ├── superpower-code-reviewer.md # 后端 code-reviewer agent(feature-review 调用) 104 │ ├── superpower-code-reviewer.md # 后端 code-reviewer agent(feature-review 调用)
105 │ └── fe-code-reviewer.md # 前端专用 reviewer(fe-feature-review 调用,硬编码 7 维 review) 105 │ └── fe-code-reviewer.md # 前端专用 reviewer(fe-feature-review 调用,硬编码 7 维 review)
106 └── skills/ 106 └── skills/
107 ├── plan/ # 阶段 A:6 个一次性规划 skill 107 ├── plan/ # 阶段 A:6 个一次性规划 skill
108 ├── coding/ # 阶段 B:15 个 skill = 9 个后端模块/功能循环 + frontend-start + 5 个 fe-feature-* 108 ├── coding/ # 阶段 B:15 个 skill = 9 个后端模块/功能循环 + frontend-start + 5 个 fe-feature-*
109 - ├── crosscut/ # 横切:2 个入口 + 1 中断守门 + 1 留痕 skill  
110 - └── internal/ # superpowers 本地 fork:2 个无门 brainstorming / writing-plans 109 + └── crosscut/ # 横切:2 个入口 + 1 中断守门 + 1 留痕 skill
111 ``` 110 ```
112 111
113 -## Hook 清单(2 个,全部在 hooks/hooks.json 注册) 112 +## Hook 清单(1 个,在 hooks/hooks.json 注册)
114 113
115 | Hook | 脚本 | 事件 | 触发条件 | 作用 | 114 | Hook | 脚本 | 事件 | 触发条件 | 作用 |
116 |---|---|---|---|---| 115 |---|---|---|---|---|
117 -| 拒绝 no-verify | `deny-no-verify.sh` | PreToolUse / Bash | CC 尝试 `git push --no-verify` | 硬拦截,强制 `.githooks/pre-push` 生效 |  
118 -| 跨模块改动留痕 | `log-cross-module.sh` | PostToolUse / Edit \| Write | 当前处于 `module-*` 分支 且 编辑目标路径落在 `docs/08 § 二` 中**非当前模块**的 path 范围内(无论目标模块 MR 是否已 merged) | 把改动追加为 `TBD(CC 补)` 存根到 `<current_module>-cross-module.md`;通过 `additionalContext` 软提示 CC 调 `cross-module-log` skill **自主推断**补「原因 / 影响评估」两列。即时性由 CC 自己决定;**最迟在 `module-report` § ⑦ 硬闸门处**(TBD 未清空会阻断模块完成报告),保证模块完成前所有 TBD 必被 CC 填实 | 116 +| 跨模块改动留痕 | `log-cross-module.sh` | PostToolUse / Edit \| Write | 当前处于 `module-*` 分支 且 编辑目标路径落在 `docs/08 § 二` 中**非当前模块**的 path 范围内(无论目标模块是否已打里程碑) | 把改动追加为 `TBD(CC 补)` 存根到 `<current_module>-cross-module.md`;通过 `additionalContext` 软提示 CC 调 `cross-module-log` skill **自主推断**补「原因 / 影响评估」两列。即时性由 CC 自己决定;**最迟在 `module-report` § ⑦ 硬闸门处**(TBD 未清空会阻断模块完成报告),保证模块完成前所有 TBD 必被 CC 填实 |
119 117
120 -## Skill 清单(27 个) 118 +## Skill 清单(25 个)
121 119
122 ### Plan 阶段(6 个,`skills/plan/`) 120 ### Plan 阶段(6 个,`skills/plan/`)
123 121
@@ -125,7 +123,7 @@ erp-workflow-plugin/ @@ -125,7 +123,7 @@ erp-workflow-plugin/
125 |---|---|---|---| 123 |---|---|---|---|
126 | A0 | `project-init` | • 依赖检查(`mysql` 在 PATH,缺失则尝试自动安装)<br>• 空目录初始化:`cp` 模板创建 CLAUDE.md / docs/01/index.md / docs/08<br>• `git init` | `plan-start` | 124 | A0 | `project-init` | • 依赖检查(`mysql` 在 PATH,缺失则尝试自动安装)<br>• 空目录初始化:`cp` 模板创建 CLAUDE.md / docs/01/index.md / docs/08<br>• `git init` | `plan-start` |
127 | A1 | `scope-lock` | • 引导填项目概述 / 技术栈 / 需求索引<br>• 按 `docs/01-需求清单/<module>/{_module.md, REQ-*.md}` 子目录结构生成 REQ 卡片骨架(CC 起草 req_id / title / goal / rules / constraints / acceptance;输入 / 输出 各含一句简述 + N 张示例字段表(输入 8 列 / 输出 3 列),全部原样复制自模板,由人工按业务编辑;`依赖表 / 依赖接口` 留 `TBD(A3/A5 自动补)`)<br>• **停下**等人工审阅 + 改输入 / 输出,审阅完毕用 `/plan-start` 恢复续进 A2 | A0 | 125 | A1 | `scope-lock` | • 引导填项目概述 / 技术栈 / 需求索引<br>• 按 `docs/01-需求清单/<module>/{_module.md, REQ-*.md}` 子目录结构生成 REQ 卡片骨架(CC 起草 req_id / title / goal / rules / constraints / acceptance;输入 / 输出 各含一句简述 + N 张示例字段表(输入 8 列 / 输出 3 列),全部原样复制自模板,由人工按业务编辑;`依赖表 / 依赖接口` 留 `TBD(A3/A5 自动补)`)<br>• **停下**等人工审阅 + 改输入 / 输出,审阅完毕用 `/plan-start` 恢复续进 A2 | A0 |
128 -| A2 | `skeleton-gen` | • 生成架构文档:docs/04 § 一+ / docs/06 / docs/07 / docs/09<br>• 生成工具脚本:scripts/*.sh、.githooks/pre-push、.env.local<br>• 创建 `sql/migrations/` 空目录(Flyway 准备)<br>• 合并 .gitignore(逐行判重) | `plan-start` | 126 +| A2 | `skeleton-gen` | • 生成架构文档:docs/04 § 一+ / docs/06 / docs/07 / docs/09<br>• 生成工具脚本:scripts/*.sh、.env.local<br>• 创建 `sql/migrations/` 空目录(Flyway 准备)<br>• 合并 .gitignore(逐行判重) | `plan-start` |
129 | A3 | `db-design-gen` | • 从 docs/01 REQ 卡片正向设计 `docs/03-数据库设计文档.md`(schema SSoT)<br>• 回填 REQ 卡片依赖表(`TBD(A3 自动补)` → 实际表名)<br>• **停下**等人工审阅 docs/03,审阅完毕用 `/plan-start` 恢复续进 A4 | A2 | 127 | A3 | `db-design-gen` | • 从 docs/01 REQ 卡片正向设计 `docs/03-数据库设计文档.md`(schema SSoT)<br>• 回填 REQ 卡片依赖表(`TBD(A3 自动补)` → 实际表名)<br>• **停下**等人工审阅 docs/03,审阅完毕用 `/plan-start` 恢复续进 A4 | A2 |
130 | A4 | `db-init` | • LLM 解析 docs/03 → `sql/migrations/V1__initial_schema.sql`(DDL only)<br>• **5 维度全量校验** DDL ↔ docs/03(表名 / 列名+列序 / 类型+nullable+默认值 / 索引名 / FK 名),fail-closed<br>• 验证 MySQL 连接<br>• 调 `scripts/setup-test-db.sh` 复用三层防护(与 B 阶段 test.sh 共用)→ DROP+CREATE 空库<br>• apply V1 + `SHOW TABLES` 行数自检 | A3 | 128 | A4 | `db-init` | • LLM 解析 docs/03 → `sql/migrations/V1__initial_schema.sql`(DDL only)<br>• **5 维度全量校验** DDL ↔ docs/03(表名 / 列名+列序 / 类型+nullable+默认值 / 索引名 / FK 名),fail-closed<br>• 验证 MySQL 连接<br>• 调 `scripts/setup-test-db.sh` 复用三层防护(与 B 阶段 test.sh 共用)→ DROP+CREATE 空库<br>• apply V1 + `SHOW TABLES` 行数自检 | A3 |
131 | A5 | `downstream-gen` | • 一次性生成 docs/02 / docs/05 / docs/06 § 三 / docs/10<br>• 回填 REQ 卡片依赖接口(`TBD(A5 自动补)` → 实际 endpoint)<br>• 追加模块清单到 docs/08 § 二<br>• 最终占位符扫描(TBD 自动补 + `【人工填写:】` QA 循环)<br>• 打印 Plan 完成横幅并**停下**(不自动进 B) | A4 | 129 | A5 | `downstream-gen` | • 一次性生成 docs/02 / docs/05 / docs/06 § 三 / docs/10<br>• 回填 REQ 卡片依赖接口(`TBD(A5 自动补)` → 实际 endpoint)<br>• 追加模块清单到 docs/08 § 二<br>• 最终占位符扫描(TBD 自动补 + `【人工填写:】` QA 循环)<br>• 打印 Plan 完成横幅并**停下**(不自动进 B) | A4 |
@@ -138,10 +136,10 @@ erp-workflow-plugin/ @@ -138,10 +136,10 @@ erp-workflow-plugin/
138 /erp-workflow:coding-start ← 用户每次手动触发;阶段分发器(只做分发) 136 /erp-workflow:coding-start ← 用户每次手动触发;阶段分发器(只做分发)
139 137
140 │ ① Plan 完成校验(docs/08 § 一 A0~A5) 138 │ ① Plan 完成校验(docs/08 § 一 A0~A5)
141 - │ ② 后端完成性检查(§ 二 + GitLab state 139 + │ ② 后端完成性检查(§ 二 + git tag
142 │ ├ 未完成 → 立即派发 module-start,结束 140 │ ├ 未完成 → 立即派发 module-start,结束
143 │ └ 已完成 → 继续 ③ 141 │ └ 已完成 → 继续 ③
144 - │ ③ 前端完成性检查(§ 三 整体 MR + state 142 + │ ③ 前端完成性检查(§ 三 整体里程碑 + tag
145 │ ├ 已完成 → 打印"所有阶段已完成",结束 143 │ ├ 已完成 → 打印"所有阶段已完成",结束
146 │ └ 未完成 → 派发 frontend-start,结束 144 │ └ 未完成 → 派发 frontend-start,结束
147 145
@@ -155,11 +153,10 @@ erp-workflow-plugin/ @@ -155,11 +153,10 @@ erp-workflow-plugin/
155 │ │ request-changes (=5) → 停下(升级给人) 153 │ │ request-changes (=5) → 停下(升级给人)
156 │ │ 154 │ │
157 │ │ 本模块所有 REQ approve: 155 │ │ 本模块所有 REQ approve:
158 - │ │ test-gate(phase=backend) → module-report → mr-create  
159 - │ │ (docs/08 § 二 写 MR iid) 156 + │ │ test-gate(phase=backend) → module-report → milestone-tag
  157 + │ │ (本地 merge 进默认分支 + 打 milestone/<id>,写 docs/08 § 二)
160 │ │ 158 │ │
161 - │ └─ ⏸ 停下等人工 Approve + Merge  
162 - │ (合并后用户重跑 coding-start → coding-start 再次路由) 159 + │ └─ 自动回 coding-start → 再次路由(无人工介入)
163 160
164 ├─ 后端完成 & 前端完成 → 打印"所有阶段已完成",停下 161 ├─ 后端完成 & 前端完成 → 打印"所有阶段已完成",停下
165 162
@@ -194,23 +191,22 @@ erp-workflow-plugin/ @@ -194,23 +191,22 @@ erp-workflow-plugin/
194 │ 全部 FE approve: 191 │ 全部 FE approve:
195 │ test-gate(phase=frontend)(vitest + playwright,子会话跑) 192 │ test-gate(phase=frontend)(vitest + playwright,子会话跑)
196 │ → module-report(phase=frontend) 193 │ → module-report(phase=frontend)
197 - │ → mr-create(docs/08 § 三 整体 MR 194 + │ → milestone-tag(docs/08 § 三 整体里程碑
198 195
199 - └─ ⏸ 停下等人工 Approve + Merge  
200 - (合并后再跑 coding-start → "所有阶段已完成") 196 + └─ 自动回 coding-start → "所有阶段已完成"(无人工介入)
201 ``` 197 ```
202 198
203 | Skill | 做什么 | 谁触发它 | 199 | Skill | 做什么 | 谁触发它 |
204 |---|---|---| 200 |---|---|---|
205 -| `module-start` | **后端模块循环单一职责**(不感知前端阶段)。切 `module-<id>` 分支,扫 `docs/superpowers/reviews/*.md` 的 `verdict=approve` 计算已完成 REQ,推进第一个未完成 REQ;本模块全 approve → `test-gate`。**幂等可重入** | `coding-start` 派发(仅当后端有未 merged 模块时);`feature-review` approve 后回调 | 201 +| `module-start` | **后端模块循环单一职责**(不感知前端阶段)。切 `module-<id>` 分支,扫 `docs/superpowers/reviews/*.md` 的 `verdict=approve` 计算已完成 REQ,推进第一个未完成 REQ;本模块全 approve → `test-gate`。**幂等可重入** | `coding-start` 派发(仅当后端有未打里程碑模块时);`feature-review` approve 后回调 |
206 | `feature-brainstorm` | 功能循环步骤 1:交互 brainstorm → 生成 `docs/superpowers/specs/*.md` | `module-start` 推进 REQ 时调用 | 202 | `feature-brainstorm` | 功能循环步骤 1:交互 brainstorm → 生成 `docs/superpowers/specs/*.md` | `module-start` 推进 REQ 时调用 |
207 | `feature-plan` | 功能循环步骤 2:spec → 任务级 plan(文件路径 + API 签名 + 测试意图 + 完成判据,代码由 TDD 阶段产出),输出 `docs/superpowers/plans/*.md` | `feature-brainstorm` 链式调用 | 203 | `feature-plan` | 功能循环步骤 2:spec → 任务级 plan(文件路径 + API 签名 + 测试意图 + 完成判据,代码由 TDD 阶段产出),输出 `docs/superpowers/plans/*.md` | `feature-brainstorm` 链式调用 |
208 | `feature-tdd` | 功能循环步骤 3:红绿循环(写失败测试 → 实现 → 子会话验证通过 → commit 到 `module-<id>` 分支);路径硬护栏:`impl_file` 落 `frontend/` 前缀 → 硬停(UI 推迟到前端阶段) | `feature-plan` 链式调用 | 204 | `feature-tdd` | 功能循环步骤 3:红绿循环(写失败测试 → 实现 → 子会话验证通过 → commit 到 `module-<id>` 分支);路径硬护栏:`impl_file` 落 `frontend/` 前缀 → 硬停(UI 推迟到前端阶段) | `feature-plan` 链式调用 |
209 | `feature-verify` | 功能循环步骤 4:将全量测试派发到子会话执行一次,用模板渲染 evidence | `feature-tdd` 链式调用;`feature-review` 在 request-changes 修复后重新调用 | 205 | `feature-verify` | 功能循环步骤 4:将全量测试派发到子会话执行一次,用模板渲染 evidence | `feature-tdd` 链式调用;`feature-review` 在 request-changes 修复后重新调用 |
210 | `feature-review` | 功能循环步骤 5:AI 自审,写 `docs/superpowers/reviews/*.md`。approve → 回 `module-start`;request-changes → 逐项 Edit + fix commit → 回 `feature-verify` 重新执行(最多 5 轮,第 5 轮仍 request-changes 则停下) | `feature-verify` 链式调用 | 206 | `feature-review` | 功能循环步骤 5:AI 自审,写 `docs/superpowers/reviews/*.md`。approve → 回 `module-start`;request-changes → 逐项 Edit + fix commit → 回 `feature-verify` 重新执行(最多 5 轮,第 5 轮仍 request-changes 则停下) | `feature-verify` 链式调用 |
211 -| `test-gate` | MR 前硬闸门。按当前分支推 phase:`module-*` → 跑 `scripts/test.sh`(drop+create 空库、Flyway apply、测试);`frontend-phase` → 跑 vitest + playwright(命令取自 docs/04 § 零)。通过 → 写 `<phase_id>-test-gate.md` 并 commit 到当前分支;失败停下 | `module-start`(后端 REQ 全 approve 后)/ `frontend-start`(FE 全 approve 后) | 207 +| `test-gate` | 里程碑 tag 前硬闸门。按当前分支推 phase:`module-*` → 跑 `scripts/test.sh`(drop+create 空库、Flyway apply、测试);`frontend-phase` → 跑 vitest + playwright(命令取自 docs/04 § 零)。通过 → 写 `<phase_id>-test-gate.md` 并 commit 到当前分支;失败停下 | `module-start`(后端 REQ 全 approve 后)/ `frontend-start`(FE 全 approve 后) |
212 | `module-report` | 中断检查 → 生成 12 节完成报告 `docs/superpowers/module-reports/<date>-<phase_id>.md`(前端阶段 § ④/§ ⑥ 写 N/A)→ commit 到当前分支(后端:module-* 分支;前端:frontend-phase 分支) | `test-gate` 链式调用 | 208 | `module-report` | 中断检查 → 生成 12 节完成报告 `docs/superpowers/module-reports/<date>-<phase_id>.md`(前端阶段 § ④/§ ⑥ 写 N/A)→ commit 到当前分支(后端:module-* 分支;前端:frontend-phase 分支) | `test-gate` 链式调用 |
213 -| `mr-create` | 中断检查 → 验证当前分支 = `module-<id>` 或 `frontend-phase` 且 `git status --porcelain` worktree 干净 → `git push` 推代码与全部 evidence → 用 curl 调 GitLab REST API 创建 MR(完成报告嵌入 MR 描述)→ 追加 MR URL 到报告并 commit → 把 docs/08 § 二 该模块的 `MR: —`(后端) / § 三 `整体 MR: —`(前端) 回写为 `!<iid>` 并 commit → 再次 push;**停下等人工 Approve+Merge**。完成由 MR state 判定 | `module-report` 链式调用 | 209 +| `milestone-tag` | 验证当前分支 = `module-<id>` 或 `frontend-phase` 且 `git status --porcelain` worktree 干净 → 探测本地默认分支 → `git merge --no-ff` 本地集成进默认分支 → 把 docs/08 § 二 该模块的 `里程碑: —`(后端) / § 三 `整体里程碑: —`(前端) 回写为 `milestone/<id>` 并 commit → `git tag -a milestone/<id>` 打里程碑 → 追加 tag 名到报告并 commit → **自动回调 coding-start 推进下一阶段(无人工介入)**。完成由本地 `git tag -l` 判定 | `module-report` 链式调用 |
214 | `frontend-start` | 写前端阶段单一职责。步骤 1 自带 prototype/ 门禁(≥ 1 个 *.html,缺失则 AskUserQuestion)。步骤 2 准备 FE 清单(无审阅断点):§ 三 占位则 AI 自主推导写入;§ 三 已有则加载。后续切 `frontend-phase` 分支 + 计算未完成 FE + 推进第一个 FE 的 fe-feature 循环;全 approve → `test-gate(phase=frontend)` | `coding-start` 派发(仅当 `backend_done=true && frontend_done=false`);`fe-feature-review` approve 后回调 | 210 | `frontend-start` | 写前端阶段单一职责。步骤 1 自带 prototype/ 门禁(≥ 1 个 *.html,缺失则 AskUserQuestion)。步骤 2 准备 FE 清单(无审阅断点):§ 三 占位则 AI 自主推导写入;§ 三 已有则加载。后续切 `frontend-phase` 分支 + 计算未完成 FE + 推进第一个 FE 的 fe-feature 循环;全 approve → `test-gate(phase=frontend)` | `coding-start` 派发(仅当 `backend_done=true && frontend_done=false`);`fe-feature-review` approve 后回调 |
215 | `fe-feature-brainstorm` | 前端功能循环步骤 1:基于 FE 关联的 `associated_prototypes[]` + `associated_reqs[]` + docs/05 + docs/06 § 二 + docs/04 § 零前端 → spec | `frontend-start` 推进 FE 时调用,传 `{ fe_id, name, associated_reqs[], associated_prototypes[] }` | 211 | `fe-feature-brainstorm` | 前端功能循环步骤 1:基于 FE 关联的 `associated_prototypes[]` + `associated_reqs[]` + docs/05 + docs/06 § 二 + docs/04 § 零前端 → spec | `frontend-start` 推进 FE 时调用,传 `{ fe_id, name, associated_reqs[], associated_prototypes[] }` |
216 | `fe-feature-plan` | 前端功能循环步骤 2:spec → 任务级计划(组件/路由/hook/API client,`impl_file` 必须 `frontend/` 前缀) | `fe-feature-brainstorm` 链式调用 | 212 | `fe-feature-plan` | 前端功能循环步骤 2:spec → 任务级计划(组件/路由/hook/API client,`impl_file` 必须 `frontend/` 前缀) | `fe-feature-brainstorm` 链式调用 |
@@ -223,7 +219,7 @@ erp-workflow-plugin/ @@ -223,7 +219,7 @@ erp-workflow-plugin/
223 | Skill | 作用 | 流程中谁调用 | 219 | Skill | 作用 | 流程中谁调用 |
224 |---|---|---| 220 |---|---|---|
225 | `plan-start` | **A 阶段入口**。读取 docs/08 § 一 找第一个未勾 A 子项 → 派发对应 A skill;A 全部完成时提示运行 coding-start | **用户手动**运行 `/erp-workflow:plan-start` | 221 | `plan-start` | **A 阶段入口**。读取 docs/08 § 一 找第一个未勾 A 子项 → 派发对应 A skill;A 全部完成时提示运行 coding-start | **用户手动**运行 `/erp-workflow:plan-start` |
226 -| `coding-start` | **B 阶段入口 + 阶段分发器(只做分发)**。① 验证 Plan 已完成(docs/08 § 一 A0~A5 全勾选)② 后端完成性检查(§ 二 + GitLab state)③ 前端完成性检查(§ 三 整体 MR)④ 真值表派发:`backend=false` → `module-start`;`backend=true & frontend=false` → `frontend-start`;都 done → "全部完成"。前端阶段的 prototype/ 门禁由 `frontend-start` 自带,不在此处 | **用户手动**运行 `/erp-workflow:coding-start` | 222 +| `coding-start` | **B 阶段入口 + 阶段分发器(只做分发)**。① 验证 Plan 已完成(docs/08 § 一 A0~A5 全勾选)② 后端完成性检查(§ 二 + git tag)③ 前端完成性检查(§ 三 整体里程碑 + tag)④ 真值表派发:`backend=false` → `module-start`;`backend=true & frontend=false` → `frontend-start`;都 done → "全部完成"。前端阶段的 prototype/ 门禁由 `frontend-start` 自带,不在此处 | **用户手动**运行 `/erp-workflow:coding-start`;`milestone-tag` 每模块完成后自动回调 |
227 | `interrupt-check` | 检查 CLAUDE.md 的 3 项中断清单;触发则追加 Blocker 到计划文件并停下 | 功能循环各步骤和生成重要制品前自动调用 | 223 | `interrupt-check` | 检查 CLAUDE.md 的 3 项中断清单;触发则追加 Blocker 到计划文件并停下 | 功能循环各步骤和生成重要制品前自动调用 |
228 | `cross-module-log` | 给 `log-cross-module.sh` 追加的跨模块改动存根批量补「原因 / 影响评估」 | `module-report` § ⑦ 硬验收时一次性调用(CC 编辑中途不主动调);`module-start` 初始化日志文件时也会用其模板 | 224 | `cross-module-log` | 给 `log-cross-module.sh` 追加的跨模块改动存根批量补「原因 / 影响评估」 | `module-report` § ⑦ 硬验收时一次性调用(CC 编辑中途不主动调);`module-start` 初始化日志文件时也会用其模板 |
229 225
@@ -250,7 +246,7 @@ step 0 流程图被抽到独立 `.txt` 文件,SKILL.md 步骤 0 改为 `bash cat @@ -250,7 +246,7 @@ step 0 流程图被抽到独立 `.txt` 文件,SKILL.md 步骤 0 改为 `bash cat
250 246
251 **字节对齐保证**:每个文件 17 行,每行 visible width = 58 cell(内宽 56 + 2 个 `│` 边框)。改动需重新校准。 247 **字节对齐保证**:每个文件 17 行,每行 visible width = 58 cell(内宽 56 + 2 个 `│` 边框)。改动需重新校准。
252 248
253 -## Templates 清单(44 份) 249 +## Templates 清单(41 份)
254 250
255 | 所属 Skill | 模板文件 | 用途 | 251 | 所属 Skill | 模板文件 | 用途 |
256 |---|---|---| 252 |---|---|---|
@@ -266,7 +262,6 @@ step 0 流程图被抽到独立 `.txt` 文件,SKILL.md 步骤 0 改为 `bash cat @@ -266,7 +262,6 @@ step 0 流程图被抽到独立 `.txt` 文件,SKILL.md 步骤 0 改为 `bash cat
266 | skeleton-gen | `docs-09-structure-template.md` | docs/09 目录结构大纲 | 262 | skeleton-gen | `docs-09-structure-template.md` | docs/09 目录结构大纲 |
267 | skeleton-gen | `scripts-setup-test-db-template.sh` | 运行时 drop + create 空库脚本(0 槽位);schema apply 交给 Flyway | 263 | skeleton-gen | `scripts-setup-test-db-template.sh` | 运行时 drop + create 空库脚本(0 槽位);schema apply 交给 Flyway |
268 | skeleton-gen | `scripts-test-template.sh` | test.sh 骨架(4 个命令槽位:{{build_cmd}} / {{lint_cmd}} / {{test_cmd}} / {{e2e_cmd}},由 skeleton-gen 按技术栈推断填充) | 264 | skeleton-gen | `scripts-test-template.sh` | test.sh 骨架(4 个命令槽位:{{build_cmd}} / {{lint_cmd}} / {{test_cmd}} / {{e2e_cmd}},由 skeleton-gen 按技术栈推断填充) |
269 -| skeleton-gen | `githooks-pre-push-template.sh` | pre-push → 调 scripts/test.sh(0 槽位) |  
270 | skeleton-gen | `env-local-template` | 6 字段凭据模板(DB_* + JWT_SECRET) | 265 | skeleton-gen | `env-local-template` | 6 字段凭据模板(DB_* + JWT_SECRET) |
271 | skeleton-gen | `gitignore-append-template` | 插件推荐忽略项(`.env.local`、`.tmp/`、构建产物等) | 266 | skeleton-gen | `gitignore-append-template` | 插件推荐忽略项(`.env.local`、`.tmp/`、构建产物等) |
272 | db-design-gen | `docs-03-header-template.md` | docs/03 数据库设计头部 | 267 | db-design-gen | `docs-03-header-template.md` | docs/03 数据库设计头部 |
@@ -285,8 +280,6 @@ step 0 流程图被抽到独立 `.txt` 文件,SKILL.md 步骤 0 改为 `bash cat @@ -285,8 +280,6 @@ step 0 流程图被抽到独立 `.txt` 文件,SKILL.md 步骤 0 改为 `bash cat
285 | feature-review | `feature-review-template.md` | 自审报告结构 | 280 | feature-review | `feature-review-template.md` | 自审报告结构 |
286 | test-gate | `test-gate-result-template.md` | 闸门结果渲染 | 281 | test-gate | `test-gate-result-template.md` | 闸门结果渲染 |
287 | module-report | `module-report-template.md` | 12 节模块报告 | 282 | module-report | `module-report-template.md` | 12 节模块报告 |
288 -| mr-create | `mr-title-template.md` | MR 标题模板 |  
289 -| mr-create | `mr-description-template.md` | MR 描述模板(嵌入模块报告) |  
290 | interrupt-check | `interrupt-block-template.md` | Blocker 节追加模板 | 283 | interrupt-check | `interrupt-block-template.md` | Blocker 节追加模板 |
291 | cross-module-log | `cross-module-log-template.md` | cross-module 日志头(由 hook log-cross-module.sh 在首次跨模块改动时渲染创建;skill 自身不再读取) | 284 | cross-module-log | `cross-module-log-template.md` | cross-module 日志头(由 hook log-cross-module.sh 在首次跨模块改动时渲染创建;skill 自身不再读取) |
292 | cross-module-log | `cross-module-log-row-template.md` | 单条改动行模板 | 285 | cross-module-log | `cross-module-log-row-template.md` | 单条改动行模板 |
@@ -305,7 +298,7 @@ step 0 流程图被抽到独立 `.txt` 文件,SKILL.md 步骤 0 改为 `bash cat @@ -305,7 +298,7 @@ step 0 流程图被抽到独立 `.txt` 文件,SKILL.md 步骤 0 改为 `bash cat
305 - **MySQL 8.x** 实例已就绪(推荐本地 / `*.local` host;A4 `db-init` 的安全守护要求 host 在白名单且 schema 名含 `test`/`dev`/`local`,避免误删生产库) 298 - **MySQL 8.x** 实例已就绪(推荐本地 / `*.local` host;A4 `db-init` 的安全守护要求 host 在白名单且 schema 名含 `test`/`dev`/`local`,避免误删生产库)
306 - **`mysql` 命令行**:A4 `db-init` 验证连接 + 自动 `DROP+CREATE` schema 后 apply V1;`scripts/setup-test-db.sh` 在测试闸门前后 drop+create 空库 299 - **`mysql` 命令行**:A4 `db-init` 验证连接 + 自动 `DROP+CREATE` schema 后 apply V1;`scripts/setup-test-db.sh` 在测试闸门前后 drop+create 空库
307 - **Spring Boot + Flyway**(**必需**):pom.xml 声明 `flyway-core` + `flyway-mysql`;Spring 启动时自动 apply `sql/migrations/V*.sql`。本插件生成的 `setup-test-db.sh` 只清库,schema 必须由 Flyway 应用 300 - **Spring Boot + Flyway**(**必需**):pom.xml 声明 `flyway-core` + `flyway-mysql`;Spring 启动时自动 apply `sql/migrations/V*.sql`。本插件生成的 `setup-test-db.sh` 只清库,schema 必须由 Flyway 应用
308 -- **GitLab v3 API + Private Token**:`mr-create` 用 `curl` POST `/projects/:id/merge_requests` 建 MR;`coding-start` / `module-start` 用 `curl` GET `/projects/:id/merge_requests?iid=<iid>` 判定 state(v3 路径参数 `:merge_request_id` 要内部数字 id,所以统一用 iid 过滤列表)。HTTP 头用 `PRIVATE-TOKEN`;凭据(`GITLAB_API_URL=.../api/v3` / `GITLAB_TOKEN` / `GITLAB_PROJECT_ID`)放 `.env.local` 301 +- **本地 git 仓库**(纯本地,无需远程):A0 `project-init` 执行 `git init`;B 阶段每模块由 `milestone-tag` 本地 `git merge --no-ff` 进默认分支并 `git tag -a milestone/<id>`,完成信号由 `git tag -l` 判定。**不依赖任何远程仓库 / push / GitLab**
309 - **本地可运行 `mvn test` / `pnpm test`**:测试闸门 `scripts/test.sh` 由 `skeleton-gen` 生成 302 - **本地可运行 `mvn test` / `pnpm test`**:测试闸门 `scripts/test.sh` 由 `skeleton-gen` 生成
310 303
311 ## 设计原则 304 ## 设计原则
hooks/hooks.json
1 { 1 {
2 "hooks": { 2 "hooks": {
3 - "PreToolUse": [  
4 - {  
5 - "matcher": "Bash",  
6 - "hooks": [  
7 - { "type": "command", "command": "\"${CLAUDE_PLUGIN_ROOT}\"/hooks/scripts/deny-no-verify.sh" }  
8 - ]  
9 - }  
10 - ],  
11 "PostToolUse": [ 3 "PostToolUse": [
12 { 4 {
13 "matcher": "Edit|Write", 5 "matcher": "Edit|Write",
hooks/scripts/deny-no-verify.sh deleted
1 -#!/usr/bin/env bash  
2 -# PreToolUse hook: block any `git push --no-verify` — the local test.sh gate is the only hard gate.  
3 -  
4 -set -euo pipefail  
5 -  
6 -input="$(cat)"  
7 -tool_name="$(printf '%s' "$input" | jq -r '.tool_name // empty')"  
8 -[ "$tool_name" = "Bash" ] || exit 0  
9 -  
10 -cmd="$(printf '%s' "$input" | jq -r '.tool_input.command // empty')"  
11 -[ -n "$cmd" ] || exit 0  
12 -  
13 -if printf '%s' "$cmd" | grep -qE '\bgit[[:space:]]+push\b.*--no-verify\b'; then  
14 - echo "BLOCKED: --no-verify bypasses the local test.sh gate (唯一硬闸门). If test.sh is failing, fix the root cause; do not skip the gate. Use /test-gate to run the gate properly." >&2  
15 - exit 2  
16 -fi  
17 -  
18 -exit 0  
hooks/scripts/log-cross-module.sh
1 #!/usr/bin/env bash 1 #!/usr/bin/env bash
2 # PostToolUse hook: 检测 Edit/Write 是否触及"当前模块以外"的模块路径,若是则在当前模块的跨模块日志中留痕(软规则 S2)。 2 # PostToolUse hook: 检测 Edit/Write 是否触及"当前模块以外"的模块路径,若是则在当前模块的跨模块日志中留痕(软规则 S2)。
3 -# CC 在当前模块开发期间改动其他模块(无论目标模块是否已 merged)都会在此处留痕。 3 +# CC 在当前模块开发期间改动其他模块(无论目标模块是否已打里程碑)都会在此处留痕。
4 4
5 set -euo pipefail 5 set -euo pipefail
6 6
@@ -33,7 +33,7 @@ esac @@ -33,7 +33,7 @@ esac
33 # - module_0 <name> 33 # - module_0 <name>
34 # - 依赖: ... 34 # - 依赖: ...
35 # - 路径: backend/module/xxx/, frontend/pages/xxx/ 35 # - 路径: backend/module/xxx/, frontend/pages/xxx/
36 -# - MR: !N 或 — 36 +# - 里程碑: milestone/<id> 或 —
37 hit_module="" 37 hit_module=""
38 # 用 awk 逐模块解析:每碰到 `- module_` 记录 module_id($2),然后在其下找第一个 `- 路径:` 行 38 # 用 awk 逐模块解析:每碰到 `- module_` 记录 module_id($2),然后在其下找第一个 `- 路径:` 行
39 # current_module 已在上文计算,在外层循环被排除 → 只会命中"非当前模块"的路径 39 # current_module 已在上文计算,在外层循环被排除 → 只会命中"非当前模块"的路径
skills/coding/fe-feature-review/SKILL.md
@@ -20,7 +20,7 @@ allowed-tools: Read Write Edit Skill Agent Bash(git add *) Bash(git commit *) @@ -20,7 +20,7 @@ allowed-tools: Read Write Edit Skill Agent Bash(git add *) Bash(git commit *)
20 3. 按 `verdict` 分派: 20 3. 按 `verdict` 分派:
21 21
22 **approve** 22 **approve**
23 - - `Edit docs/08-模块任务管理.md § 三`,把本 FE 下 `- [ ] <fe_id> ...` 改为 `- [x] <fe_id> ...`(仅 FE 级可视化;前端阶段完成仍以 `整体 MR:` + GitLab API state 为准) 23 + - `Edit docs/08-模块任务管理.md § 三`,把本 FE 下 `- [ ] <fe_id> ...` 改为 `- [x] <fe_id> ...`(仅 FE 级可视化;前端阶段完成仍以 `整体里程碑:` 字段 + 本地 `git tag -l` 为准)
24 - 输出 `fe-feature-review: <fe_id> round <N> 通过`,调用 `Skill(frontend-start)` 推进下一 FE 或进入 test-gate(phase=frontend) 24 - 输出 `fe-feature-review: <fe_id> round <N> 通过`,调用 `Skill(frontend-start)` 推进下一 FE 或进入 test-gate(phase=frontend)
25 25
26 **request-changes(round < 5)** 26 **request-changes(round < 5)**
skills/coding/feature-review/SKILL.md
@@ -18,7 +18,7 @@ allowed-tools: Read Write Edit Skill Agent Bash(git add *) Bash(git commit *) @@ -18,7 +18,7 @@ allowed-tools: Read Write Edit Skill Agent Bash(git add *) Bash(git commit *)
18 3. 按 `verdict` 分派: 18 3. 按 `verdict` 分派:
19 19
20 **approve** 20 **approve**
21 - - `Edit docs/08-模块任务管理.md § 二`,把本模块下 `- [ ] <REQ-id> ...` 改为 `- [x] <REQ-id> ...`(仅功能级可视化;模块完成仍以 `MR:` + GitLab API state 为准,不依赖此勾选) 21 + - `Edit docs/08-模块任务管理.md § 二`,把本模块下 `- [ ] <REQ-id> ...` 改为 `- [x] <REQ-id> ...`(仅功能级可视化;模块完成仍以 `里程碑:` 字段 + 本地 `git tag -l` 为准,不依赖此勾选)
22 - 输出 `feature-review: <REQ> round <N> 通过`,调用 `Skill(module-start)` 22 - 输出 `feature-review: <REQ> round <N> 通过`,调用 `Skill(module-start)`
23 23
24 **request-changes(round < 5)** 24 **request-changes(round < 5)**
skills/coding/frontend-start/SKILL.md
@@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
2 name: frontend-start 2 name: frontend-start
3 description: 前端阶段循环入口。AI 自主推导 FE 业务功能清单写入 docs/08 § 三(已有则加载),定位未完成 FE 派发 fe-feature-brainstorm 或 test-gate(前端阶段)。幂等可重入。 3 description: 前端阶段循环入口。AI 自主推导 FE 业务功能清单写入 docs/08 § 三(已有则加载),定位未完成 FE 派发 fe-feature-brainstorm 或 test-gate(前端阶段)。幂等可重入。
4 user-invocable: false 4 user-invocable: false
5 -allowed-tools: Read Write Edit Skill Glob Grep AskUserQuestion Bash(git branch *) Bash(git checkout *) Bash(git rev-parse *) Bash(git pull *) Bash(git status *) Bash(git symbolic-ref *) Bash(curl *) Bash(jq *) Bash(find *) Bash(ls *) 5 +allowed-tools: Read Write Edit Skill Glob Grep AskUserQuestion Bash(git branch *) Bash(git checkout *) Bash(git rev-parse *) Bash(git status *) Bash(git symbolic-ref *) Bash(git tag *) Bash(find *) Bash(ls *)
6 --- 6 ---
7 7
8 **所有输出必须使用中文。** 8 **所有输出必须使用中文。**
@@ -29,19 +29,18 @@ allowed-tools: Read Write Edit Skill Glob Grep AskUserQuestion Bash(git branch * @@ -29,19 +29,18 @@ allowed-tools: Read Write Edit Skill Glob Grep AskUserQuestion Bash(git branch *
29 - [ ] FE-NN 功能名 | 关联 REQ:REQ-A, REQ-B | 关联原型:prototype/<file>.html 29 - [ ] FE-NN 功能名 | 关联 REQ:REQ-A, REQ-B | 关联原型:prototype/<file>.html
30 ``` 30 ```
31 31
32 - 保留 `- 整体 MR: —` 不动;写入后解析得 `fe_list[]`,继续步骤 3 32 + 保留 `- 整体里程碑: —` 不动;写入后解析得 `fe_list[]`,继续步骤 3
33 33
34 -### 步骤 3:检查前端 MR 状态 34 +### 步骤 3:检查前端里程碑状态
35 35
36 -读 § 三 `整体 MR:` 调 GitLab API 36 +读 § 三 `整体里程碑:` 字段并 `git tag -l 'milestone/frontend-phase'` 校验
37 37
38 -- `merged` → 打印"前端阶段已完成"并停(冗余保护,正常由 coding-start 拦掉)  
39 -- 其它(`—` / opened / closed)→ 进入步骤 4  
40 -- API 异常 → 硬停 + 诊断 38 +- 字段为 `milestone/frontend-phase` 且 tag 存在 → 打印"前端阶段已完成"并停(冗余保护,正常由 coding-start 拦掉)
  39 +- 否则(`—` 或 tag 不存在)→ 进入步骤 4
41 40
42 ### 步骤 4:切到 frontend-phase 分支 41 ### 步骤 4:切到 frontend-phase 分支
43 42
44 -目标分支 `frontend-phase`,分支管理逻辑同 module-start 步骤 3:已在 → 继续;存在 → checkout;不存在 → 切默认分支 fast-forward 后 `git checkout -b frontend-phase`。任何错误硬停 + 诊断,不自动 stash / 覆盖。 43 +目标分支 `frontend-phase`,分支管理逻辑同 module-start 步骤 3:已在 → 继续;存在 → checkout;不存在 → 切本地默认分支后 `git checkout -b frontend-phase`。任何错误硬停 + 诊断,不自动 stash / 覆盖。
45 44
46 ### 步骤 5:识别已完成的 FE 45 ### 步骤 5:识别已完成的 FE
47 46
@@ -59,7 +58,7 @@ allowed-tools: Read Write Edit Skill Glob Grep AskUserQuestion Bash(git branch * @@ -59,7 +58,7 @@ allowed-tools: Read Write Edit Skill Glob Grep AskUserQuestion Bash(git branch *
59 ## 参考 58 ## 参考
60 59
61 - `${CLAUDE_SKILL_DIR}/templates/frontend-start-banner-template.md` 60 - `${CLAUDE_SKILL_DIR}/templates/frontend-start-banner-template.md`
62 -- `docs/08-模块任务管理.md § 三`(前端阶段元数据:整体 MR + FE 清单) 61 +- `docs/08-模块任务管理.md § 三`(前端阶段元数据:整体里程碑 + FE 清单)
63 - `prototype/`(HTML mockup,FE 拆分粒度与文件数无关) 62 - `prototype/`(HTML mockup,FE 拆分粒度与文件数无关)
64 - `docs/superpowers/reviews/*-FE-*.md`(verdict=approve 即完成) 63 - `docs/superpowers/reviews/*-FE-*.md`(verdict=approve 即完成)
65 - 上游:`coding-start`(步骤 4 派发,仅当后端完成 + 前端未完成);`fe-feature-review` approve 后回调 64 - 上游:`coding-start`(步骤 4 派发,仅当后端完成 + 前端未完成);`fe-feature-review` approve 后回调
skills/coding/frontend-start/templates/frontend-start-banner-template.md
1 ## 前端阶段(frontend-phase) 1 ## 前端阶段(frontend-phase)
2 2
3 - 分支:frontend-phase 3 - 分支:frontend-phase
4 -- 整体 MR:{{overall_mr}} 4 +- 整体里程碑:{{overall_milestone}}
5 - FE 进度(`x` = 已完成 review approve;FE 是业务功能粒度,与 prototype/ HTML 文件数无关): 5 - FE 进度(`x` = 已完成 review approve;FE 是业务功能粒度,与 prototype/ HTML 文件数无关):
6 {{#each fes}} 6 {{#each fes}}
7 - [{{status}}] {{fe_id}} {{name}} | 关联 REQ:{{reqs}} | 关联原型:{{prototypes}} 7 - [{{status}}] {{fe_id}} {{name}} | 关联 REQ:{{reqs}} | 关联原型:{{prototypes}}
skills/coding/milestone-tag/SKILL.md 0 → 100644
  1 +---
  2 +name: milestone-tag
  3 +description: 完成报告生成后,把当前分支(module-* 后端 / frontend-phase 前端)本地合并进默认分支并打里程碑 tag(milestone/<id>),把 tag 名回写 docs/08(§ 二 模块行 / § 三 整体里程碑)+ 报告 § ⑫,然后自动回调 coding-start 推进下一阶段。全程无人工介入。
  4 +user-invocable: false
  5 +allowed-tools: Read Edit Skill Bash(git *)
  6 +---
  7 +
  8 +**所有输出必须使用中文。**
  9 +
  10 +# milestone-tag
  11 +
  12 +## 前置条件
  13 +
  14 +- `module-report` 已生成报告并 commit 到当前分支
  15 +- `test-gate` 绿色,test-gate.md 已 commit 到当前分支
  16 +- 当前分支 = `module-<module_id>` 或 `frontend-phase`(由 `module-start` 步骤 3 / `frontend-start` 步骤 4 切入)
  17 +
  18 +## 执行步骤
  19 +
  20 +### 步骤 1:验证当前分支并推断 phase
  21 +
  22 +`git branch --show-current`:
  23 +
  24 +- 匹配 `module-*` → `phase=backend`,`phase_id=` 去掉 `module-` 前缀,`tag=milestone/<phase_id>`
  25 +- 等于 `frontend-phase` → `phase=frontend`,`phase_id=frontend-phase`,`tag=milestone/frontend-phase`
  26 +- 其它 → 停下报错(不自动建分支——分支职责在上游 `module-start` / `frontend-start`)
  27 +
  28 +### 步骤 2:验证 worktree 干净
  29 +
  30 +`git status --porcelain` 输出非空 → 停下打印 dirty 文件清单:
  31 +
  32 +```
  33 +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  34 + [milestone-tag] ⚠️ worktree 不干净,无法集成 + 打里程碑
  35 +
  36 + <git status 输出>
  37 +
  38 + 集成前所有 evidence 必须已 commit。检查点:
  39 + - test-gate 步骤 3 是否已 commit test-gate.md?
  40 + - module-report 步骤 5 是否已 commit 报告 + cross-module log?
  41 +
  42 + 修复:git add <files> && git commit -m "...",然后重跑 /erp-workflow:coding-start。
  43 +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  44 +```
  45 +
  46 +### 步骤 3:探测本地默认分支
  47 +
  48 +无远程,用 `git rev-parse --verify` 依次探测本地 `main` / `master`,取第一个存在的作为 `default_branch`。两者都不存在 → 停下报错。
  49 +
  50 +### 步骤 4:本地集成(合并模块分支进默认分支)
  51 +
  52 +替代原来的"远程 push + 人工 MR merge"——本地完成集成:
  53 +
  54 +```bash
  55 +git checkout <default_branch>
  56 +git merge --no-ff <current_branch> -m "merge(<phase_id>): integrate <current_branch>"
  57 +```
  58 +
  59 +合并冲突 → 停下打印冲突文件清单,引导人工解决后重跑 `/erp-workflow:coding-start`(不自动 `--abort`、不强制覆盖)。
  60 +
  61 +### 步骤 5:回写 docs/08 里程碑字段并 commit
  62 +
  63 +在 `default_branch` 上 `Edit docs/08-模块任务管理.md`:
  64 +
  65 +- **phase=backend**:在 § 二 中找到当前模块的 ` - 里程碑: —` 改为 ` - 里程碑: milestone/<phase_id>`
  66 +- **phase=frontend**:在 § 三 中找到 `- 整体里程碑: —` 改为 `- 整体里程碑: milestone/frontend-phase`
  67 +
  68 +```bash
  69 +git add docs/08-模块任务管理.md
  70 +git commit -m "chore(<phase_id>): record milestone/<phase_id> in docs/08"
  71 +```
  72 +
  73 +### 步骤 6:在默认分支 HEAD 打 annotated 里程碑 tag
  74 +
  75 +```bash
  76 +git tag -a milestone/<phase_id> -m "milestone(<phase_id>): <phase> 阶段完成"
  77 +```
  78 +
  79 +tag 已存在(重跑场景)→ 跳过,不重复打。
  80 +
  81 +### 步骤 7:追加里程碑 tag 到完成报告 § ⑫ 并 commit
  82 +
  83 +`Edit docs/superpowers/module-reports/<date>-<phase_id>.md` 的 § ⑫,把 `{{milestone_tag}}` 替换为 `milestone/<phase_id>`(已替换则跳过)。
  84 +
  85 +```bash
  86 +git add docs/superpowers/module-reports/<date>-<phase_id>.md
  87 +git commit -m "docs(<phase_id>): record milestone/<phase_id> in completion report"
  88 +```
  89 +
  90 +### 步骤 8:自动回调 coding-start 推进下一阶段
  91 +
  92 +本阶段已集成 + 打 tag,**不停下等人工**。立即用 Skill 工具调用 `coding-start`:
  93 +
  94 +- coding-start 重新做后端 / 前端完成性检查(按 `里程碑:` 字段 + `git tag -l`),未完则推进下一模块 / 前端阶段,全部完成则打印"所有阶段已完成"。
  95 +
  96 +## 参考
  97 +
  98 +- 上游:`module-report`
  99 +- 下游:`coding-start`(自治回调,由其路由下一阶段)
skills/coding/module-report/SKILL.md
1 --- 1 ---
2 name: module-report 2 name: module-report
3 -description: 本地测试闸门通过后,生成标准化 12 节完成报告(后端模块 OR 前端阶段)并 commit 到当前分支供 MR 嵌入 3 +description: 本地测试闸门通过后,生成标准化 12 节完成报告(后端模块 OR 前端阶段)并 commit 到当前分支(供里程碑标记)
4 user-invocable: false 4 user-invocable: false
5 allowed-tools: Read Write Glob Grep Skill Bash(git diff *) Bash(git log *) Bash(git add *) Bash(git commit *) Bash(git branch *) 5 allowed-tools: Read Write Glob Grep Skill Bash(git diff *) Bash(git log *) Bash(git add *) Bash(git commit *) Bash(git branch *)
6 --- 6 ---
@@ -9,7 +9,7 @@ allowed-tools: Read Write Glob Grep Skill Bash(git diff *) Bash(git log *) Bash( @@ -9,7 +9,7 @@ allowed-tools: Read Write Glob Grep Skill Bash(git diff *) Bash(git log *) Bash(
9 9
10 # module-report 10 # module-report
11 11
12 -`test-gate` 绿色后渲染 12 节完成报告,commit 到当前分支供 MR 嵌入。**只读摘要,不读 diff 正文进上下文**。 12 +`test-gate` 绿色后渲染 12 节完成报告,commit 到当前分支供里程碑标记。**只读摘要,不读 diff 正文进上下文**。
13 13
14 按当前分支自动推断 `phase`: 14 按当前分支自动推断 `phase`:
15 15
@@ -59,12 +59,12 @@ allowed-tools: Read Write Glob Grep Skill Bash(git diff *) Bash(git log *) Bash( @@ -59,12 +59,12 @@ allowed-tools: Read Write Glob Grep Skill Bash(git diff *) Bash(git log *) Bash(
59 git add docs/superpowers/module-reports/<phase_id>-cross-module.md 59 git add docs/superpowers/module-reports/<phase_id>-cross-module.md
60 git commit -m "docs(<phase_id>): add completion report + cross-module log" 60 git commit -m "docs(<phase_id>): add completion report + cross-module log"
61 ``` 61 ```
62 - commit 是必需的——`mr-create` 的 worktree-clean 前置条件依赖此步。 62 + commit 是必需的——`milestone-tag` 的 worktree-clean 前置条件依赖此步。
63 63
64 -6. 调用 `Skill(mr-create)` 推送并创建 MR 64 +6. 调用 `Skill(milestone-tag)` 本地集成并打里程碑 tag
65 65
66 ## 参考 66 ## 参考
67 67
68 - `${CLAUDE_SKILL_DIR}/templates/module-report-template.md`(12 节,后端 + 前端共用) 68 - `${CLAUDE_SKILL_DIR}/templates/module-report-template.md`(12 节,后端 + 前端共用)
69 - 上游:`test-gate`(绿色时派发) 69 - 上游:`test-gate`(绿色时派发)
70 -- 下游:`mr-create`(phase 由当前分支推断) 70 +- 下游:`milestone-tag`(phase 由当前分支推断)
skills/coding/module-report/templates/module-report-template.md
@@ -64,5 +64,5 @@ git_range: {{git_range}} @@ -64,5 +64,5 @@ git_range: {{git_range}}
64 ## ⑪ 下一模块预览 64 ## ⑪ 下一模块预览
65 {{next_module}} 65 {{next_module}}
66 66
67 -## ⑫ MR 链接  
68 -{{mr_url}} 67 +## ⑫ 里程碑 tag
  68 +{{milestone_tag}}
skills/coding/module-start/SKILL.md
1 --- 1 ---
2 name: module-start 2 name: module-start
3 -description: 后端模块循环入口。定位当前未 merged 模块与未完成 REQ,派发 feature-brainstorm 或 test-gate;幂等可重入。阶段路由由 coding-start 负责,本 skill 不感知前端阶段。 3 +description: 后端模块循环入口。定位当前未完成(未打里程碑 tag)模块与未完成 REQ,派发 feature-brainstorm 或 test-gate;幂等可重入。阶段路由由 coding-start 负责,本 skill 不感知前端阶段。
4 user-invocable: false 4 user-invocable: false
5 -allowed-tools: Read Write Skill Glob Grep Bash(git branch *) Bash(git checkout *) Bash(git rev-parse *) Bash(git pull *) Bash(git status *) Bash(git symbolic-ref *) Bash(curl *) Bash(jq *) 5 +allowed-tools: Read Write Skill Glob Grep Bash(git branch *) Bash(git checkout *) Bash(git rev-parse *) Bash(git status *) Bash(git symbolic-ref *) Bash(git tag *)
6 --- 6 ---
7 7
8 **所有输出必须使用中文。** 8 **所有输出必须使用中文。**
@@ -11,29 +11,28 @@ allowed-tools: Read Write Skill Glob Grep Bash(git branch *) Bash(git checkout * @@ -11,29 +11,28 @@ allowed-tools: Read Write Skill Glob Grep Bash(git branch *) Bash(git checkout *
11 11
12 ## 职责说明 12 ## 职责说明
13 13
14 -本 skill 单一职责:推进**后端模块循环**。`coding-start` 已在派发前确认存在未 merged 后端模块;本 skill 不再做"后端是否全完"的判定,也不感知前端阶段。 14 +本 skill 单一职责:推进**后端模块循环**。`coding-start` 已在派发前确认存在未完成后端模块;本 skill 不再做"后端是否全完"的判定,也不感知前端阶段。
15 15
16 ## 执行步骤 16 ## 执行步骤
17 17
18 ### 步骤 1:定位当前模块与本模块 REQ 列表 18 ### 步骤 1:定位当前模块与本模块 REQ 列表
19 19
20 -按 `docs/02 § 二 开发顺序清单` 的 REQ 顺序扫描,找到第一个所属模块尚未 merged 的模块作为 `current_module`,并抽取本模块 REQ 序列。 20 +按 `docs/02 § 二 开发顺序清单` 的 REQ 顺序扫描,找到第一个所属模块尚未打里程碑 tag 的模块作为 `current_module`,并抽取本模块 REQ 序列。
21 21
22 -模块状态判定(`MR:` 字段 × GitLab API state 三种组合的语义和应对动作)参见 `CLAUDE.md § ✅ 阶段完成判定规则 § 状态语义`。 22 +模块状态判定(`里程碑:` 字段 + `git tag -l 'milestone/<module_id>'` 存在性)参见 `CLAUDE.md § ✅ 阶段完成判定规则 § 状态语义`。
23 23
24 找到 `current_module` 后,从 docs/02 § 二 的 REQ 列表里取出所有 `module_id == current_module` 的项,按原序得 `req_list[]`(A5 约束保证同模块 REQ 连续)。模块名、需求卡目录等其它字段由后续步骤按需从 `docs/08 § 二` 或 `docs/01-需求清单/` 取,不在本步骤预读。 24 找到 `current_module` 后,从 docs/02 § 二 的 REQ 列表里取出所有 `module_id == current_module` 的项,按原序得 `req_list[]`(A5 约束保证同模块 REQ 连续)。模块名、需求卡目录等其它字段由后续步骤按需从 `docs/08 § 二` 或 `docs/01-需求清单/` 取,不在本步骤预读。
25 25
26 约束: 26 约束:
27 27
28 -- GitLab 凭据从 `.env.local` 读取(`GITLAB_API_URL` / `GITLAB_TOKEN` / `GITLAB_PROJECT_ID`)  
29 -- API 异常(HTTP 非 2xx / 找不到 MR / state 非合法值)一律硬停,**禁止静默假设未 merged**,向用户打印诊断信息,引导核查上述凭据与 docs/08 的 iid 28 +- 模块完成 = `docs/08 § 二` 该模块 `里程碑:` 字段为 `milestone/<module_id>` 且 `git tag -l` 能查到该 tag;二者任一缺失即视为未完成
30 - 任何文件读取或解析失败 → 打印错误并停止 29 - 任何文件读取或解析失败 → 打印错误并停止
31 30
32 -### 步骤 2:找不到未 merged 后端模块的处理 31 +### 步骤 2:找不到未完成后端模块的处理
33 32
34 -如果步骤 1 没找到任何未 merged 的后端模块——理论上不应触达此分支(`coding-start` 步骤 3 已确认存在未 merged 模块才会派发到本 skill),属于异常调用: 33 +如果步骤 1 没找到任何未完成的后端模块——理论上不应触达此分支(`coding-start` 步骤 3 已确认存在未完成模块才会派发到本 skill),属于异常调用:
35 34
36 -- 打印诊断:"`module-start` 未发现未 merged 后端模块。请通过 `/erp-workflow:coding-start` 入口重新驱动——coding-start 会按 docs/08 § 二/§ 三 自动路由到正确阶段(后端 / 前端 / 全部完成)。" 35 +- 打印诊断:"`module-start` 未发现未完成后端模块。请通过 `/erp-workflow:coding-start` 入口重新驱动——coding-start 会按 docs/08 § 二/§ 三 自动路由到正确阶段(后端 / 前端 / 全部完成)。"
37 - 结束本 skill,不派发下游 36 - 结束本 skill,不派发下游
38 37
39 ### 步骤 3:确保处于模块分支 38 ### 步骤 3:确保处于模块分支
@@ -42,9 +41,9 @@ allowed-tools: Read Write Skill Glob Grep Bash(git branch *) Bash(git checkout * @@ -42,9 +41,9 @@ allowed-tools: Read Write Skill Glob Grep Bash(git branch *) Bash(git checkout *
42 41
43 - 已在该分支 → 继续步骤 4 42 - 已在该分支 → 继续步骤 4
44 - 该分支已存在但当前不在 → checkout 过去 43 - 该分支已存在但当前不在 → checkout 过去
45 -- 该分支不存在 → 先把工作树切到远程默认分支(main 或 master)并 fast-forward 同步,作为新分支的干净 base,再 `git checkout -b` 创建模块分支 44 +- 该分支不存在 → 先把工作树切到本地默认分支(main 或 master,已由 milestone-tag 的本地 merge 累积所有已完成模块),作为新分支的干净 base,再 `git checkout -b` 创建模块分支
46 45
47 -任何错误(定位不到默认分支 / 切换前工作树脏 / 不能 fast-forward / checkout 失败)一律停下并打印诊断信息,不自动 stash、不强制覆盖。 46 +任何错误(定位不到默认分支 / 切换前工作树脏 / checkout 失败)一律停下并打印诊断信息,不自动 stash、不强制覆盖。
48 47
49 ### 步骤 4:计算已完成 REQ 集合 `done_reqs[]` 48 ### 步骤 4:计算已完成 REQ 集合 `done_reqs[]`
50 49
@@ -64,10 +63,10 @@ allowed-tools: Read Write Skill Glob Grep Bash(git branch *) Bash(git checkout * @@ -64,10 +63,10 @@ allowed-tools: Read Write Skill Glob Grep Bash(git branch *) Bash(git checkout *
64 ## 参考 63 ## 参考
65 64
66 - `docs/02-开发计划.md § 二 开发顺序清单`(分发权威) 65 - `docs/02-开发计划.md § 二 开发顺序清单`(分发权威)
67 -- `docs/08-模块任务管理.md § 二`(后端模块元数据,含 `MR:` 字段;完成判定以 MR state 为准) 66 +- `docs/08-模块任务管理.md § 二`(后端模块元数据,含 `里程碑:` 字段;完成判定以 tag 存在为准)
68 - `docs/superpowers/reviews/*.md`(REQ 级进度事实——verdict=approve 即完成) 67 - `docs/superpowers/reviews/*.md`(REQ 级进度事实——verdict=approve 即完成)
69 - `${CLAUDE_SKILL_DIR}/templates/module-start-banner-template.md` 68 - `${CLAUDE_SKILL_DIR}/templates/module-start-banner-template.md`
70 - 下游: 69 - 下游:
71 - `feature-brainstorm`(每个未完成 REQ) 70 - `feature-brainstorm`(每个未完成 REQ)
72 - `test-gate`(本模块全部 REQ approve 后;phase=backend 由分支推断) 71 - `test-gate`(本模块全部 REQ approve 后;phase=backend 由分支推断)
73 -- 上游:`coding-start`(步骤 3 派发到此;后端模块全 merged 时不会派发到此) 72 +- 上游:`coding-start`(步骤 3 派发到此;后端模块全部打里程碑时不会派发到此)
skills/coding/mr-create/SKILL.md deleted
1 ----  
2 -name: mr-create  
3 -description: 完成报告生成后,把当前分支(module-* 后端 / frontend-phase 前端)推到远程并创建 GitLab MR,把 MR iid 回写 docs/08(§ 二 模块行 / § 三 整体 MR)+ URL 回写报告 § ⑫,停下等人工 Approve + Merge。  
4 -user-invocable: false  
5 -allowed-tools: Read Edit Bash(git *) Bash(bash *)  
6 ----  
7 -  
8 -**所有输出必须使用中文。**  
9 -  
10 -# mr-create  
11 -  
12 -## 前置条件  
13 -  
14 -- `module-report` 已生成报告并 commit 到当前分支  
15 -- `test-gate` 绿色,test-gate.md 已 commit 到当前分支  
16 -- 当前分支 = `module-<module_id>` 或 `frontend-phase`(由 `module-start` 步骤 3 / `frontend-start` 步骤 4 切入)  
17 -  
18 -## 执行步骤  
19 -  
20 -### 步骤 1:验证当前分支并推断 phase  
21 -  
22 -`git branch --show-current`:  
23 -  
24 -- 匹配 `module-*` → `phase=backend`,`phase_id=` 去掉 `module-` 前缀  
25 -- 等于 `frontend-phase` → `phase=frontend`,`phase_id=frontend-phase`  
26 -- 其它 → 停下报错(不自动建分支——分支职责在上游 `module-start` / `frontend-start`)  
27 -  
28 -### 步骤 2:验证 worktree 干净  
29 -  
30 -`git status --porcelain` 输出非空 → 停下打印 dirty 文件清单:  
31 -  
32 -```  
33 -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━  
34 - [mr-create] ⚠️ worktree 不干净,无法 push  
35 -  
36 - <git status 输出>  
37 -  
38 - push 前所有 evidence 必须已 commit。检查点:  
39 - - test-gate 步骤 3 是否已 commit test-gate.md?  
40 - - module-report 步骤 5 是否已 commit 报告 + cross-module log?  
41 -  
42 - 修复:git add <files> && git commit -m "...",然后重跑 /erp-workflow:coding-start。  
43 -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━  
44 -```  
45 -  
46 -### 步骤 3:初次 push  
47 -  
48 -`git push -u origin <current_branch>`——**禁用 `--no-verify`**。  
49 -  
50 -### 步骤 4:调脚本创建(或复用)MR  
51 -  
52 -```bash  
53 -bash "${CLAUDE_SKILL_DIR}/scripts/create-mr.sh" <phase_id> <current_branch> <YYYY-MM-DD>  
54 -```  
55 -  
56 -`<phase_id>` = 后端模块 id(如 `module_sys`)或前端常量 `frontend-phase`。脚本内部完成:加载 `.env.local` → 探测目标分支 → 取 `module_name`(后端从 docs/08 § 二,前端使用常量"前端阶段(整体)")→ test-gate.md 取结论 → 渲染 description → 查已有 opened MR → 否则创建新 MR。  
57 -  
58 -输出(stdout):单行 `<MR_IID> <MR_URL>`,由本步骤捕获供后续步骤使用。失败时脚本写诊断到 stderr 并 exit 1,本 skill 停下。  
59 -  
60 -### 步骤 5:回写 docs/08 MR 字段并 commit  
61 -  
62 -**先于步骤 6 执行**——若步骤 6 失败,重跑时步骤 4 脚本能识别已有 MR + docs/08 已含 IID,状态一致。  
63 -  
64 -`Edit docs/08-模块任务管理.md`:  
65 -  
66 -- **phase=backend**:在 § 二 中找到当前模块的 ` - MR: —` 改为 ` - MR: !<MR_IID>`  
67 -- **phase=frontend**:在 § 三 中找到 `- 整体 MR: —` 改为 `- 整体 MR: !<MR_IID>`  
68 -  
69 -```bash  
70 -git add docs/08-模块任务管理.md  
71 -git commit -m "chore(<phase_id>): record MR !<MR_IID> in docs/08"  
72 -```  
73 -  
74 -### 步骤 6:追加 MR URL 到完成报告 § ⑫ 并 commit  
75 -  
76 -`Edit docs/superpowers/module-reports/<date>-<phase_id>.md` 的 § ⑫,把 `{{mr_url}}` 替换为 `<MR_URL>`(已替换则追加一行)。  
77 -  
78 -```bash  
79 -git add docs/superpowers/module-reports/<date>-<phase_id>.md  
80 -git commit -m "docs(<phase_id>): record MR !<MR_IID> link in completion report"  
81 -```  
82 -  
83 -### 步骤 7:再次 push 同步新 commits  
84 -  
85 -步骤 5、6 产生了两个新 commit,必须再 push 让 MR 自动更新 commit 列表 + diff:  
86 -  
87 -`git push origin <current_branch>`  
88 -  
89 -### 步骤 8:打印 MR URL,停下等 Approve + Merge  
90 -  
91 -向会话打印 `<MR_URL>`,结束本 skill。  
92 -  
93 -- **phase=backend**:用户在 GitLab merge 后再运行 `/erp-workflow:coding-start`;coding-start 重新做后端完成性检查,未完则推进下一模块,全 merged 则路由到 `frontend-start`(frontend-start 自带 prototype/ 门禁)  
94 -- **phase=frontend**:用户在 GitLab merge 后再运行 `/erp-workflow:coding-start`,扫描到 § 三 整体 MR `state=merged` → 打印"所有阶段已完成"  
95 -  
96 -## 参考  
97 -  
98 -- `${CLAUDE_SKILL_DIR}/scripts/create-mr.sh`(步骤 4 主流程脚本,按 phase_id 自动选 backend / frontend 行为)  
99 -- `${CLAUDE_SKILL_DIR}/templates/mr-title-template.md`  
100 -- `${CLAUDE_SKILL_DIR}/templates/mr-description-template.md`  
101 -- 上游:`module-report`  
102 -- 下游闸门:用户手工 MR Approve + Merge  
skills/coding/mr-create/scripts/create-mr.sh deleted
1 -#!/usr/bin/env bash  
2 -# create-mr.sh — mr-create 主流程:渲染 description、查已有 MR / 创建新 MR  
3 -#  
4 -# 用法:  
5 -# bash create-mr.sh <phase_id> <current_branch> <date>  
6 -#  
7 -# <phase_id> = 后端模块 id(如 module_sys)或前端常量 "frontend-phase"  
8 -#  
9 -# 输出(stdout,单行,由调用方读取):  
10 -# <MR_IID> <MR_URL>  
11 -#  
12 -# 失败:诊断写 stderr,exit 1。  
13 -#  
14 -# 设计要点:  
15 -# - 报告整文只经 sed + awk 管道流入 description 与 GitLab API(curl --rawfile),  
16 -# 全程不进 LLM 上下文。  
17 -# - 幂等:同一 source_branch 已有 opened MR 时,复用其 iid/url,不再创建。  
18 -# - phase 自动:phase_id == "frontend-phase" 时跳过 docs/08 § 二 lookup,使用常量名。  
19 -  
20 -set -euo pipefail  
21 -  
22 -MODULE_ID="${1:?usage: create-mr.sh <phase_id> <current_branch> <date>}"  
23 -CURRENT_BRANCH="${2:?missing current_branch}"  
24 -DATE="${3:?missing date (YYYY-MM-DD)}"  
25 -  
26 -SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)  
27 -TPL_DIR="$SCRIPT_DIR/../templates"  
28 -DESC_TPL="$TPL_DIR/mr-description-template.md"  
29 -TITLE_TPL="$TPL_DIR/mr-title-template.md"  
30 -  
31 -REPORT="docs/superpowers/module-reports/${DATE}-${MODULE_ID}.md"  
32 -TEST_GATE="docs/superpowers/module-reports/${MODULE_ID}-test-gate.md"  
33 -  
34 -[ -f "$REPORT" ] || { echo "[create-mr] ⚠️ 完成报告不存在: $REPORT" >&2; exit 1; }  
35 -[ -f "$TEST_GATE" ] || { echo "[create-mr] ⚠️ test-gate evidence 不存在: $TEST_GATE" >&2; exit 1; }  
36 -  
37 -# 1. 加载凭据  
38 -[ -f .env.local ] || { echo "[create-mr] ⚠️ .env.local 不存在" >&2; exit 1; }  
39 -set -a; . ./.env.local; set +a  
40 -for v in GITLAB_API_URL GITLAB_TOKEN GITLAB_PROJECT_ID; do  
41 - eval "val=\${$v:-}"  
42 - [ -n "$val" ] || { echo "[create-mr] ⚠️ .env.local 缺少 $v" >&2; exit 1; }  
43 -done  
44 -  
45 -# 2. 探测目标分支(origin/HEAD → main → master)  
46 -TARGET_BRANCH=$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's|refs/remotes/origin/||' || true)  
47 -[ -n "$TARGET_BRANCH" ] || TARGET_BRANCH=$(git branch -r --format='%(refname:short)' | grep -E '^origin/(main|master)$' | head -1 | sed 's|^origin/||' || true)  
48 -[ -n "$TARGET_BRANCH" ] || { echo "[create-mr] ⚠️ 无法探测默认分支(origin/main 或 origin/master)" >&2; exit 1; }  
49 -  
50 -# 3. 取 module_name  
51 -if [ "$MODULE_ID" = "frontend-phase" ]; then  
52 - MODULE_NAME="前端阶段(整体)"  
53 -else  
54 - # 从 docs/08 § 二 提取后端模块 module_name  
55 - MODULE_NAME=$(awk -v mid="$MODULE_ID" '  
56 - $0 ~ "^- "mid" " { sub("^- "mid" ", ""); print; exit }  
57 - ' docs/08-模块任务管理.md)  
58 - [ -n "$MODULE_NAME" ] || { echo "[create-mr] ⚠️ docs/08 § 二 找不到模块 $MODULE_ID" >&2; exit 1; }  
59 -fi  
60 -  
61 -# 4. 从 test-gate evidence 提取 conclusion + subagent_id  
62 -TEST_SUBAGENT_ID=$(awk '/^- 子会话: / { sub("^- 子会话: ", ""); print; exit }' "$TEST_GATE")  
63 -TEST_GATE_CONCLUSION=$(awk '/^结论: / { sub("^结论: ", ""); print; exit }' "$TEST_GATE" | awk '{print $1}')  
64 -  
65 -# 5. 渲染 MR 标题(单行,可进 LLM 上下文)  
66 -TITLE=$(cat "$TITLE_TPL")  
67 -TITLE="${TITLE//\{\{module_id\}\}/$MODULE_ID}"  
68 -TITLE="${TITLE//\{\{module_name\}\}/$MODULE_NAME}"  
69 -  
70 -# 6. 渲染 description(整篇模块报告,全程不进 LLM 上下文)  
71 -mkdir -p .tmp  
72 -DESC_FILE=.tmp/mr-desc.md  
73 -  
74 -sed -e "s|{{test_gate_conclusion}}|$TEST_GATE_CONCLUSION|g" \  
75 - -e "s|{{test_subagent_id}}|$TEST_SUBAGENT_ID|g" \  
76 - -e "s|{{module_id}}|$MODULE_ID|g" \  
77 - -e "s|{{date}}|$DATE|g" \  
78 - "$DESC_TPL" > "$DESC_FILE"  
79 -  
80 -awk -v report="$REPORT" '  
81 - /\{\{module_report_contents\}\}/ { while ((getline line < report) > 0) print line; close(report); next }  
82 - { print }  
83 -' "$DESC_FILE" > .tmp/mr-desc.final  
84 -mv .tmp/mr-desc.final "$DESC_FILE"  
85 -  
86 -# 7. 幂等守门:查已有 opened MR  
87 -CURL_META=$(curl -sS -o .tmp/existing.json -w '%{http_code}|%{url_effective}' \  
88 - --header "PRIVATE-TOKEN: ${GITLAB_TOKEN}" \  
89 - "${GITLAB_API_URL}/projects/${GITLAB_PROJECT_ID}/merge_requests?source_branch=${CURRENT_BRANCH}&state=opened")  
90 -  
91 -HTTP_CODE=${CURL_META%%|*}  
92 -EFFECTIVE_URL=${CURL_META#*|}  
93 -  
94 -if [ "$HTTP_CODE" != "200" ]; then  
95 - echo "[create-mr] ⚠️ 查询已有 MR 失败 (HTTP $HTTP_CODE)" >&2  
96 - echo " effective URL: $EFFECTIVE_URL" >&2  
97 - FIRST=$(head -c 1 .tmp/existing.json 2>/dev/null || echo "")  
98 - case "$FIRST" in  
99 - '{'|'[')  
100 - echo " 响应(JSON):" >&2  
101 - jq -r '.message // .error // .' .tmp/existing.json 2>/dev/null | head -c 200 >&2  
102 - echo >&2  
103 - ;;  
104 - '<')  
105 - echo " 响应是 HTML(很可能反代/路由失配,把 API 请求送进了 web 处理链):" >&2  
106 - head -c 200 .tmp/existing.json >&2  
107 - echo >&2  
108 - echo " 常见原因:GITLAB_API_URL 错 / GITLAB_PROJECT_ID 不是数字 ID / 反代规范化路径" >&2  
109 - ;;  
110 - *)  
111 - echo " 响应非 JSON 非 HTML(前 200 bytes):" >&2  
112 - head -c 200 .tmp/existing.json >&2  
113 - echo >&2  
114 - ;;  
115 - esac  
116 - rm -f .tmp/existing.json "$DESC_FILE"  
117 - exit 1  
118 -fi  
119 -  
120 -EXISTING_IID=$(jq -r '.[0].iid // empty' .tmp/existing.json)  
121 -EXISTING_URL=$(jq -r '.[0].web_url // empty' .tmp/existing.json)  
122 -rm -f .tmp/existing.json  
123 -  
124 -if [ -n "$EXISTING_IID" ]; then  
125 - echo "[create-mr] 复用已有 opened MR: !$EXISTING_IID" >&2  
126 - rm -f "$DESC_FILE"  
127 - echo "$EXISTING_IID $EXISTING_URL"  
128 - exit 0  
129 -fi  
130 -  
131 -# 8. 创建新 MR(--rawfile desc 把 description 文件流入 jq → curl,不进 LLM 上下文)  
132 -CREATE_RESP=$(curl -sS -X POST \  
133 - --header "PRIVATE-TOKEN: ${GITLAB_TOKEN}" \  
134 - --header "Content-Type: application/json" \  
135 - --data "$(jq -n \  
136 - --arg src "$CURRENT_BRANCH" \  
137 - --arg tgt "$TARGET_BRANCH" \  
138 - --arg title "$TITLE" \  
139 - --rawfile desc "$DESC_FILE" \  
140 - '{source_branch: $src, target_branch: $tgt, title: $title, description: $desc, remove_source_branch: false}')" \  
141 - "${GITLAB_API_URL}/projects/${GITLAB_PROJECT_ID}/merge_requests")  
142 -  
143 -MR_IID=$(echo "$CREATE_RESP" | jq -r '.iid // empty')  
144 -MR_URL=$(echo "$CREATE_RESP" | jq -r '.web_url // empty')  
145 -  
146 -if [ -z "$MR_IID" ]; then  
147 - echo "[create-mr] ⚠️ MR 创建失败:" >&2  
148 - echo "$CREATE_RESP" | jq . >&2  
149 - rm -f "$DESC_FILE"  
150 - exit 1  
151 -fi  
152 -  
153 -rm -f "$DESC_FILE"  
154 -echo "$MR_IID $MR_URL"  
skills/coding/mr-create/templates/mr-description-template.md deleted
1 -## 完成报告  
2 -  
3 -见 `docs/superpowers/module-reports/{{date}}-{{module_id}}.md`(本 MR 仓库内完整贴入下方)。  
4 -  
5 ----  
6 -  
7 -{{module_report_contents}}  
8 -  
9 ----  
10 -  
11 -## 本地闸门证据  
12 -  
13 -- 测试: {{test_gate_conclusion}}(subagent: {{test_subagent_id}})  
14 -  
15 -## 审核入口  
16 -  
17 -- 本 MR = `{{module_id}}` 的唯一人工介入点(后端模块 / 前端阶段共用)  
18 -- Approve + Merge 后,下次用户运行 `/erp-workflow:coding-start` 时入口会自动扫描 GitLab API `state=merged`,探测默认分支后 `git pull --ff-only` 同步并推进下一模块(后端阶段)或宣告全部完成(前端阶段)  
skills/coding/mr-create/templates/mr-title-template.md deleted
1 -feat({{module_id}}): {{module_name}}  
skills/coding/test-gate/SKILL.md
1 --- 1 ---
2 name: test-gate 2 name: test-gate
3 -description: MR 创建前的硬闸门。后端阶段子会话跑 scripts/test.sh,前端阶段跑前端测试命令;绿则进入 module-report,红则停下并按失败类型引导用户。 3 +description: 打里程碑 tag 前的硬闸门。后端阶段子会话跑 scripts/test.sh,前端阶段跑前端测试命令;绿则进入 module-report,红则停下并按失败类型引导用户。
4 user-invocable: false 4 user-invocable: false
5 allowed-tools: Read Write Skill Agent Bash(git add *) Bash(git commit *) Bash(git branch *) 5 allowed-tools: Read Write Skill Agent Bash(git add *) Bash(git commit *) Bash(git branch *)
6 --- 6 ---
@@ -37,7 +37,7 @@ allowed-tools: Read Write Skill Agent Bash(git add *) Bash(git commit *) Bash(gi @@ -37,7 +37,7 @@ allowed-tools: Read Write Skill Agent Bash(git add *) Bash(git commit *) Bash(gi
37 } 37 }
38 ``` 38 ```
39 2. 按 `${CLAUDE_SKILL_DIR}/templates/test-gate-result-template.md` 渲染证据,写入 `docs/superpowers/module-reports/<phase_id>-test-gate.md`(后端:`<module_id>-test-gate.md`;前端:`frontend-phase-test-gate.md`)。 39 2. 按 `${CLAUDE_SKILL_DIR}/templates/test-gate-result-template.md` 渲染证据,写入 `docs/superpowers/module-reports/<phase_id>-test-gate.md`(后端:`<module_id>-test-gate.md`;前端:`frontend-phase-test-gate.md`)。
40 -3. Commit evidence 到当前分支(保证证据随 MR 合并进默认分支可审计): 40 +3. Commit evidence 到当前分支(保证证据随里程碑 merge 进默认分支可审计):
41 ```bash 41 ```bash
42 git add docs/superpowers/module-reports/<phase_id>-test-gate.md 42 git add docs/superpowers/module-reports/<phase_id>-test-gate.md
43 git commit -m "chore(<phase_id>): add local test-gate evidence" 43 git commit -m "chore(<phase_id>): add local test-gate evidence"
@@ -67,7 +67,7 @@ allowed-tools: Read Write Skill Agent Bash(git add *) Bash(git commit *) Bash(gi @@ -67,7 +67,7 @@ allowed-tools: Read Write Skill Agent Bash(git add *) Bash(git commit *) Bash(gi
67 ## 护栏 67 ## 护栏
68 68
69 - **绝不**在主会话直接执行 `./scripts/test.sh` / `pnpm test` / `pnpm e2e`,必须通过子会话 69 - **绝不**在主会话直接执行 `./scripts/test.sh` / `pnpm test` / `pnpm e2e`,必须通过子会话
70 -- **绝不**通过 `git push --no-verify` 绕过(hook `deny-no-verify.sh` 会硬拦) 70 +- 本闸门是里程碑 tag 前唯一的硬测试门:红色时**绝不**跳过直接进入 `module-report` / `milestone-tag`
71 71
72 ## 参考 72 ## 参考
73 73
skills/crosscut/coding-start/SKILL.md
@@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
2 name: coding-start 2 name: coding-start
3 description: B 阶段(Coding)入口与阶段分发器。验证 Plan 完成后做后端 + 前端的完成性检查,每段检查后立即派发:后端未完成 → module-start(写后端);后端已完成 + 前端未完成 → frontend-start(写前端);都完成 → 全部完成。本 skill 只做分发,不做 prototype/ 门禁。 3 description: B 阶段(Coding)入口与阶段分发器。验证 Plan 完成后做后端 + 前端的完成性检查,每段检查后立即派发:后端未完成 → module-start(写后端);后端已完成 + 前端未完成 → frontend-start(写前端);都完成 → 全部完成。本 skill 只做分发,不做 prototype/ 门禁。
4 user-invocable: true 4 user-invocable: true
5 -allowed-tools: Skill Read Glob Grep Bash(cat *) Bash(curl *) Bash(jq *) 5 +allowed-tools: Skill Read Glob Grep Bash(cat *) Bash(git tag *)
6 --- 6 ---
7 7
8 **所有输出必须使用中文。** 8 **所有输出必须使用中文。**
@@ -33,26 +33,25 @@ cat &quot;${CLAUDE_PLUGIN_ROOT}/skills/crosscut/coding-start/banners/flow-overview.tx @@ -33,26 +33,25 @@ cat &quot;${CLAUDE_PLUGIN_ROOT}/skills/crosscut/coding-start/banners/flow-overview.tx
33 33
34 ### 步骤 3:后端完成性检查 + 派发 34 ### 步骤 3:后端完成性检查 + 派发
35 35
36 -读 `docs/08 § 二`,对每个后端模块的 `MR:` 字段 36 +读 `docs/08 § 二`,对每个后端模块的 `里程碑:` 字段(并用 `git tag -l 'milestone/<module_id>'` 校验 tag 真实存在)
37 37
38 -- **任一模块 `MR: —` 或 state ∈ {`opened`, `closed`}** → 后端未完成,打印 `[coding-start] 后端未完成 → 派发 module-start(写后端)`,立即用 Skill 工具调用 module-start,本 skill 结束,不进入步骤 4。 38 +- **任一模块 `里程碑: —` 或对应 `milestone/<module_id>` tag 不存在** → 后端未完成,打印 `[coding-start] 后端未完成 → 派发 module-start(写后端)`,立即用 Skill 工具调用 module-start,本 skill 结束,不进入步骤 4。
39 39
40 -- **所有模块 `MR: !<iid>` 且 state == `merged`**(用API检查)→ 后端已完成,进入步骤 4。 40 +- **所有模块 `里程碑: milestone/<module_id>` 且 tag 存在** → 后端已完成,进入步骤 4。
41 41
42 ### 步骤 4:前端完成性检查 + 派发 42 ### 步骤 4:前端完成性检查 + 派发
43 43
44 -读 `docs/08 § 三 整体 MR:` 字段 44 +读 `docs/08 § 三 整体里程碑:` 字段(并用 `git tag -l 'milestone/frontend-phase'` 校验)
45 45
46 -- **`MR: !<iid>` 且 state == `merged`**(用API检查)→ 前端已完成,打印 `所有阶段已完成(后端模块 + 前端阶段均已 merged)`,结束本 skill。 46 +- **`整体里程碑: milestone/frontend-phase` 且 tag 存在** → 前端已完成,打印 `所有阶段已完成(后端模块 + 前端阶段里程碑均已标记)`,结束本 skill。
47 47
48 -- **`MR: —` 或 state ∈ {`opened`, `closed`}** → 前端未完成,打印 `[coding-start] 后端已完成、前端未完成 → 派发 frontend-start(写前端)`,立即用 Skill 工具调用 frontend-start,本 skill 结束。 48 +- **`整体里程碑: —` 或 tag 不存在** → 前端未完成,打印 `[coding-start] 后端已完成、前端未完成 → 派发 frontend-start(写前端)`,立即用 Skill 工具调用 frontend-start,本 skill 结束。
49 49
50 ## 参考 50 ## 参考
51 51
52 - `docs/08-模块任务管理.md § 一`(A0~A5 进度勾选,步骤 2 读取) 52 - `docs/08-模块任务管理.md § 一`(A0~A5 进度勾选,步骤 2 读取)
53 -- `docs/08-模块任务管理.md § 二`(后端模块元数据 + MR 字段,步骤 3 读取)  
54 -- `docs/08-模块任务管理.md § 三`(前端阶段整体 MR,步骤 4 读取)  
55 -- `.env.local`(GitLab API 凭据,步骤 3 / 4 读取) 53 +- `docs/08-模块任务管理.md § 二`(后端模块元数据 + 里程碑字段,步骤 3 读取)
  54 +- `docs/08-模块任务管理.md § 三`(前端阶段整体里程碑,步骤 4 读取)
56 - 下游: 55 - 下游:
57 - `module-start`(写后端:步骤 3 派发) 56 - `module-start`(写后端:步骤 3 派发)
58 - `frontend-start`(写前端:步骤 4 派发) 57 - `frontend-start`(写前端:步骤 4 派发)
skills/crosscut/coding-start/banners/flow-overview.txt
@@ -3,10 +3,10 @@ @@ -3,10 +3,10 @@
3 │ │ 3 │ │
4 │ coding-start (只做分发) │ 4 │ coding-start (只做分发) │
5 │ ① Plan 完成校验(docs/08 § 一 A0~A5) │ 5 │ ① Plan 完成校验(docs/08 § 一 A0~A5) │
6 -│ ② 后端完成性检查(§ 二 + GitLab state) 6 +│ ② 后端完成性检查(§ 二 + git tag)
7 │ ├ 未完成 → 立即派发 module-start,结束 │ 7 │ ├ 未完成 → 立即派发 module-start,结束 │
8 │ └ 已完成 → 继续 ③ │ 8 │ └ 已完成 → 继续 ③ │
9 -│ ③ 前端完成性检查(§ 三 整体 MR + state) 9 +│ ③ 前端完成性检查(§ 三 整体里程碑 + tag)
10 │ ├ 已完成 → 打印"全部完成",结束 │ 10 │ ├ 已完成 → 打印"全部完成",结束 │
11 │ └ 未完成 → 派发 frontend-start,结束 │ 11 │ └ 未完成 → 派发 frontend-start,结束 │
12 │ │ 12 │ │
@@ -38,9 +38,9 @@ @@ -38,9 +38,9 @@
38 │ ↓ 本模块所有 REQ approve │ 38 │ ↓ 本模块所有 REQ approve │
39 │ test-gate(phase=backend) │ 39 │ test-gate(phase=backend) │
40 │ ↓ │ 40 │ ↓ │
41 -│ module-report → mr-create │  
42 -│ ↓ 停下,等人工 Approve + Merge │  
43 -│ ↺ 用户重跑 coding-start → coding-start 再分发 │ 41 +│ module-report → milestone-tag │
  42 +│ ↓ 本地 merge 进默认分支 + 打 milestone tag │
  43 +│ ↺ 自动回 coding-start → 再分发(无人工) │
44 │ │ 44 │ │
45 │ ┌─ 前端功能循环(每 FE-NN)─────┐ │ 45 │ ┌─ 前端功能循环(每 FE-NN)─────┐ │
46 │ │ fe-feature-brainstorm │ │ 46 │ │ fe-feature-brainstorm │ │
@@ -59,8 +59,8 @@ @@ -59,8 +59,8 @@
59 │ ↓ 全部 FE approve │ 59 │ ↓ 全部 FE approve │
60 │ test-gate(phase=frontend) │ 60 │ test-gate(phase=frontend) │
61 │ ↓ │ 61 │ ↓ │
62 -│ module-report → mr-create │  
63 -│ (分支 frontend-phase,docs/08 § 三 整体 MR) │  
64 -│ ↓ 停下,等人工 Approve + Merge │  
65 -│ ↺ 用户重跑 coding-start → 全部完成 │ 62 +│ module-report → milestone-tag │
  63 +│ (分支 frontend-phase,docs/08 § 三 整体里程碑)│
  64 +│ ↓ 本地 merge + 打 milestone/frontend-phase │
  65 +│ ↺ 自动回 coding-start → 全部完成 │
66 └────────────────────────────────────────────────────────┘ 66 └────────────────────────────────────────────────────────┘
skills/crosscut/cross-module-log/templates/cross-module-log-template.md
1 # 跨模块改动日志 — {{module_name}} 1 # 跨模块改动日志 — {{module_name}}
2 2
3 -软规则 S2:本模块开发期间对**非当前模块**代码的改动(无论目标模块是否已 MR merged)记录在此;模块完成报告必须单列「跨模块改动」节完整贴入。漏留痕或未评估影响 → 升级为中断。 3 +软规则 S2:本模块开发期间对**非当前模块**代码的改动(无论目标模块是否已打里程碑)记录在此;模块完成报告必须单列「跨模块改动」节完整贴入。漏留痕或未评估影响 → 升级为中断。
4 4
5 **本日志由 CC 自主维护**——hook `log-cross-module.sh` 自动落存根(含 `TBD(CC 补)` 占位),CC 调 `cross-module-log` skill 自主推断补「原因 / 影响评估」两列。**不需要人工填写**。 5 **本日志由 CC 自主维护**——hook `log-cross-module.sh` 自动落存根(含 `TBD(CC 补)` 占位),CC 调 `cross-module-log` skill 自主推断补「原因 / 影响评估」两列。**不需要人工填写**。
6 6
skills/crosscut/plan-start/SKILL.md
@@ -51,14 +51,14 @@ cat &quot;${CLAUDE_PLUGIN_ROOT}/skills/crosscut/plan-start/banners/flow-overview.txt&quot; @@ -51,14 +51,14 @@ cat &quot;${CLAUDE_PLUGIN_ROOT}/skills/crosscut/plan-start/banners/flow-overview.txt&quot;
51 ⚠️ 进入 B 阶段前必须完成: 51 ⚠️ 进入 B 阶段前必须完成:
52 1. 人工通读 docs/* + CLAUDE.md + sql/migrations/V1 + 各 scripts/* 52 1. 人工通读 docs/* + CLAUDE.md + sql/migrations/V1 + 各 scripts/*
53 53
54 - 2. 把全部 Plan 产物 commit 54 + 2. 把全部 Plan 产物 commit 到本地默认分支(main / master)
55 git add -A && git commit -m "chore: plan phase A0~A5 done" 55 git add -A && git commit -m "chore: plan phase A0~A5 done"
56 56
57 - 3. 推到远程:  
58 - git remote add origin <gitlab-url> # 若尚未添加  
59 - git -c core.hooksPath=/dev/null push -u origin master 57 + 3. B 阶段全程纯本地(无需远程仓库 / push / MR):
  58 + 每个模块由 milestone-tag 本地 merge 进默认分支并打 milestone/<id> tag。
  59 + 确认当前已在本地默认分支(main / master)上即可。
60 60
61 - 4. main(或 master)就绪后,再运行 /erp-workflow:coding-start 61 + 4. 运行 /erp-workflow:coding-start 进入 B 阶段
62 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 62 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
63 ``` 63 ```
64 64
skills/plan/downstream-gen/SKILL.md
@@ -122,30 +122,10 @@ cp &quot;${CLAUDE_SKILL_DIR}/templates/docs-10-header-template.md&quot; docs/10-验收检 @@ -122,30 +122,10 @@ cp &quot;${CLAUDE_SKILL_DIR}/templates/docs-10-header-template.md&quot; docs/10-验收检
122 ⚠️ 进入 B 阶段前必须完成: 122 ⚠️ 进入 B 阶段前必须完成:
123 1. 审核 docs/01~10 + CLAUDE.md + sql/migrations/V1 + 各 scripts/* 123 1. 审核 docs/01~10 + CLAUDE.md + sql/migrations/V1 + 各 scripts/*
124 124
125 - 2. 把全部 Plan 产物 commit 125 + 2. 把全部 Plan 产物 commit 到本地默认分支(main / master)
126 git add -A && git commit -m "chore: plan phase done" 126 git add -A && git commit -m "chore: plan phase done"
127 127
128 - 3. 推到远程,按仓库状态二选一:  
129 -  
130 - 情况 A — 远程仓库是全新的(尚无 main / master):  
131 - git remote add origin <gitlab-url> # 若尚未添加  
132 - git -c core.hooksPath=/dev/null push -u origin master  
133 -  
134 - 情况 B — 远程已有 main 需要走 MR 审核:  
135 - git checkout -b plan-init  
136 - git push -u origin plan-init  
137 - # 在 GitLab 打开 plan-init → main 的 MR,审核并合并  
138 -  
139 - 4. 补齐 `.env.local` 三个 GITLAB_* 字段  
140 -  
141 - - `GITLAB_TOKEN`:去 GitLab Profile → Account → Private token 生成后粘贴  
142 - - `GITLAB_PROJECT_ID`,`GITLAB_API_URL`:按平台运行(脚本只依赖 git)  
143 - macOS / Linux:  
144 - bash <plugin-skill-dir>/scripts/derive-gitlab.sh  
145 - Windows (PowerShell 5.1+,系统自带,无需额外安装):  
146 - powershell -NoProfile -ExecutionPolicy Bypass -File <plugin-skill-dir>/scripts/derive-gitlab.ps1  
147 -  
148 - 5. remote git 就绪后,再运行 /erp-workflow:coding-start 128 + 3. 运行 /erp-workflow:coding-start 进入 B 阶段
149 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 129 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
150 ``` 130 ```
151 131
@@ -157,4 +137,3 @@ cp &quot;${CLAUDE_SKILL_DIR}/templates/docs-10-header-template.md&quot; docs/10-验收检 @@ -157,4 +137,3 @@ cp &quot;${CLAUDE_SKILL_DIR}/templates/docs-10-header-template.md&quot; docs/10-验收检
157 - `${CLAUDE_SKILL_DIR}/templates/docs-06-module-pagelist-template.md`(追加到 docs/06 § 三) 137 - `${CLAUDE_SKILL_DIR}/templates/docs-06-module-pagelist-template.md`(追加到 docs/06 § 三)
158 - `${CLAUDE_SKILL_DIR}/templates/docs-08-module-row-template.md`(模块 bullet 行模板) 138 - `${CLAUDE_SKILL_DIR}/templates/docs-08-module-row-template.md`(模块 bullet 行模板)
159 - `${CLAUDE_SKILL_DIR}/templates/docs-10-header-template.md` 139 - `${CLAUDE_SKILL_DIR}/templates/docs-10-header-template.md`
160 -- `${CLAUDE_SKILL_DIR}/scripts/derive-gitlab.sh` / `derive-gitlab.ps1`(**用户可选辅助**:在 add origin 之后手动跑一次,自动派生 GITLAB_PROJECT_ID / GITLAB_API_URL 写入 .env.local;`.sh` 给 macOS/Linux,`.ps1` 给 Windows,两份严格等价 — 改动必须同步双方)  
skills/plan/downstream-gen/scripts/derive-gitlab.ps1 deleted
1 -#!/usr/bin/env pwsh  
2 -# derive-gitlab.ps1 — Windows 对应版(PowerShell 5.1+ 原生可跑,无外部依赖)  
3 -# 与同目录 derive-gitlab.sh 严格等价 — 改动任一份必须同步对方。  
4 -#  
5 -# 用法: powershell -NoProfile -ExecutionPolicy Bypass -File derive-gitlab.ps1 [.env.local 路径]  
6 -#  
7 -# 派生字段、退出码、回填策略 见 derive-gitlab.sh 头部注释。  
8 -  
9 -[CmdletBinding()]  
10 -param([string]$EnvFile = '.env.local')  
11 -  
12 -# 让 Chinese 输出在 cmd / PowerShell 控制台正常显示  
13 -try { [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 } catch {}  
14 -  
15 -if (-not (Test-Path -LiteralPath $EnvFile -PathType Leaf)) {  
16 - [Console]::Error.WriteLine("derive-gitlab.ps1: env file not found: $EnvFile")  
17 - exit 2  
18 -}  
19 -  
20 -# ---- 取 origin URL ----  
21 -$url = ''  
22 -try {  
23 - $raw = & git remote get-url origin 2>$null  
24 - if ($LASTEXITCODE -eq 0 -and $raw) { $url = ($raw -join '').Trim() }  
25 -} catch { $url = '' }  
26 -  
27 -if ([string]::IsNullOrEmpty($url)) {  
28 - [Console]::Error.WriteLine("derive-gitlab.ps1: 未配置 origin 远程,GITLAB_* 留给用户手填")  
29 - exit 0  
30 -}  
31 -  
32 -# ---- 仅支持 http(s) ----  
33 -$scheme = $null  
34 -if ($url.StartsWith('https://')) { $scheme = 'https' }  
35 -elseif ($url.StartsWith('http://')) { $scheme = 'http' }  
36 -else {  
37 - [Console]::Error.WriteLine("derive-gitlab.ps1: origin 不是 http(s) URL ($url),跳过派生")  
38 - exit 0  
39 -}  
40 -  
41 -$rest = $url.Substring("${scheme}://".Length)  
42 -$slashIdx = $rest.IndexOf('/')  
43 -if ($slashIdx -lt 0) {  
44 - [Console]::Error.WriteLine("derive-gitlab.ps1: origin URL 缺少路径段 ($url),跳过派生")  
45 - exit 0  
46 -}  
47 -$gitlabHost = $rest.Substring(0, $slashIdx)  
48 -$pathRaw = $rest.Substring($slashIdx + 1)  
49 -if ($pathRaw.EndsWith('.git')) { $pathRaw = $pathRaw.Substring(0, $pathRaw.Length - 4) }  
50 -$repoName = Split-Path -Leaf $pathRaw  
51 -  
52 -$apiUrl = "${scheme}://${gitlabHost}/api/v3"  
53 -  
54 -# ---- 读 .env.local 全文,按原行尾切分 ----  
55 -$rawBytes = [System.IO.File]::ReadAllBytes($EnvFile)  
56 -$hasBom = ($rawBytes.Length -ge 3 -and $rawBytes[0] -eq 0xEF -and $rawBytes[1] -eq 0xBB -and $rawBytes[2] -eq 0xBF)  
57 -$rawText = if ($hasBom) {  
58 - [System.Text.Encoding]::UTF8.GetString($rawBytes, 3, $rawBytes.Length - 3)  
59 -} else {  
60 - [System.Text.Encoding]::UTF8.GetString($rawBytes)  
61 -}  
62 -$eol = if ($rawText -match "`r`n") { "`r`n" } else { "`n" }  
63 -$hadTrailingNewline = $rawText.EndsWith("`n")  
64 -$lines = [System.Collections.Generic.List[string]]::new()  
65 -foreach ($l in ($rawText -split "`r?`n")) { $lines.Add($l) | Out-Null }  
66 -if ($hadTrailingNewline -and $lines.Count -gt 0 -and $lines[$lines.Count - 1] -eq '') {  
67 - $lines.RemoveAt($lines.Count - 1)  
68 -}  
69 -  
70 -function Get-FieldStripped {  
71 - param([string]$Key)  
72 - for ($i = 0; $i -lt $script:lines.Count; $i++) {  
73 - $ln = $script:lines[$i]  
74 - if ($ln.StartsWith("$Key=")) {  
75 - $val = $ln.Substring($Key.Length + 1)  
76 - # 剥外层单/双引号  
77 - if ($val.Length -ge 2) {  
78 - $f = $val[0]; $l = $val[$val.Length - 1]  
79 - if (($f -eq "'" -and $l -eq "'") -or ($f -eq '"' -and $l -eq '"')) {  
80 - $val = $val.Substring(1, $val.Length - 2)  
81 - }  
82 - }  
83 - return @{ Found = $true; Index = $i; Stripped = $val }  
84 - }  
85 - }  
86 - return @{ Found = $false }  
87 -}  
88 -  
89 -function Update-Field {  
90 - param([string]$Key, [string]$NewVal)  
91 - $info = Get-FieldStripped -Key $Key  
92 - if (-not $info.Found) {  
93 - [Console]::Error.WriteLine(" $Key = (.env.local 中无此行,跳过)")  
94 - return  
95 - }  
96 - $stripped = $info.Stripped  
97 - if ([string]::IsNullOrEmpty($stripped) -or $stripped -eq 'TBD(A5 自动补)') {  
98 - $script:lines[$info.Index] = "$Key=$NewVal"  
99 - $script:modified = $true  
100 - Write-Host " $Key = $NewVal [已派生填入]"  
101 - } elseif ($stripped -eq $NewVal) {  
102 - Write-Host " $Key = $NewVal [已是派生值,无需更新]"  
103 - } else {  
104 - Write-Host " $Key = $stripped [保留用户手填,未覆盖派生值 $NewVal]"  
105 - }  
106 -}  
107 -  
108 -function Report-Token {  
109 - $info = Get-FieldStripped -Key 'GITLAB_TOKEN'  
110 - if (-not $info.Found) {  
111 - [Console]::Error.WriteLine(" GITLAB_TOKEN = (.env.local 中无此行,跳过)")  
112 - return  
113 - }  
114 - $stripped = $info.Stripped  
115 - if ([string]::IsNullOrEmpty($stripped) -or $stripped.StartsWith('【人工填写:') -or $stripped.StartsWith('TBD')) {  
116 - Write-Host " GITLAB_TOKEN = $stripped [待人工填写:GitLab Profile → Account → Private token]"  
117 - } else {  
118 - $masked = if ($stripped.Length -le 8) {  
119 - ('*' * $stripped.Length)  
120 - } else {  
121 - $stripped.Substring(0, 4) + ('*' * ($stripped.Length - 8)) + $stripped.Substring($stripped.Length - 4)  
122 - }  
123 - Write-Host " GITLAB_TOKEN = $masked [已填入,长度 $($stripped.Length)]"  
124 - }  
125 -}  
126 -  
127 -$script:modified = $false  
128 -  
129 -Write-Host "derive-gitlab.ps1: 从 origin ($url) 派生 GitLab 凭据:"  
130 -Update-Field -Key 'GITLAB_API_URL' -NewVal $apiUrl  
131 -  
132 -# ---- GITLAB_PROJECT_ID:经 GitLab API 解析数字 ID ----  
133 -$tokenInfo = Get-FieldStripped -Key 'GITLAB_TOKEN'  
134 -$tokenVal = if ($tokenInfo.Found) { $tokenInfo.Stripped } else { '' }  
135 -  
136 -$tokenUsable = $true  
137 -if ([string]::IsNullOrEmpty($tokenVal) -or $tokenVal.StartsWith('【人工填写:') -or $tokenVal.StartsWith('TBD')) {  
138 - Write-Host " GITLAB_PROJECT_ID = TBD [token 未填,跳过 API 解析;填完 token 后重跑此脚本]"  
139 - $tokenUsable = $false  
140 -}  
141 -  
142 -if ($tokenUsable) {  
143 - # PS 5.1 默认 TLS1.0/1.1,自建 GitLab 通常需要 TLS1.2  
144 - try { [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 } catch {}  
145 - $headers = @{ 'PRIVATE-TOKEN' = $tokenVal }  
146 -  
147 - $userOk = $false  
148 - try {  
149 - $userResp = Invoke-WebRequest -Uri "$apiUrl/user" -Headers $headers -UseBasicParsing -ErrorAction Stop  
150 - if ([int]$userResp.StatusCode -eq 200) { $userOk = $true }  
151 - else { Write-Host " GITLAB_PROJECT_ID = TBD [token 验证失败 HTTP $([int]$userResp.StatusCode),留 TBD 待人工确认]" }  
152 - } catch {  
153 - $code = 0  
154 - if ($_.Exception.Response) { try { $code = [int]$_.Exception.Response.StatusCode } catch {} }  
155 - if ($code -eq 0) { $code = '000' }  
156 - Write-Host " GITLAB_PROJECT_ID = TBD [token 验证失败 HTTP $code,留 TBD 待人工确认]"  
157 - }  
158 -  
159 - if ($userOk) {  
160 - try {  
161 - $searchUri = "$apiUrl/projects?search=$([uri]::EscapeDataString($repoName))&simple=true&per_page=50"  
162 - $projects = Invoke-RestMethod -Uri $searchUri -Headers $headers -UseBasicParsing -ErrorAction Stop  
163 - $match = $projects | Where-Object { $_.path_with_namespace -eq $pathRaw } | Select-Object -First 1  
164 - if ($match) {  
165 - Update-Field -Key 'GITLAB_PROJECT_ID' -NewVal "$($match.id)"  
166 - } else {  
167 - Write-Host " GITLAB_PROJECT_ID = TBD [API 未匹配 path_with_namespace=$pathRaw,请到 GitLab 项目设置页查数字 ID 后填入]"  
168 - }  
169 - } catch {  
170 - Write-Host " GITLAB_PROJECT_ID = TBD [API 调用失败:$($_.Exception.Message)]"  
171 - }  
172 - }  
173 -}  
174 -  
175 -Report-Token  
176 -  
177 -# ---- 回写 .env.local(保持 EOL / BOM 状态)----  
178 -if ($script:modified) {  
179 - $newText = [string]::Join($eol, $lines.ToArray())  
180 - if ($hadTrailingNewline) { $newText += $eol }  
181 - $encoding = New-Object System.Text.UTF8Encoding($hasBom)  
182 - [System.IO.File]::WriteAllText($EnvFile, $newText, $encoding)  
183 -}  
skills/plan/downstream-gen/scripts/derive-gitlab.sh deleted
1 -#!/usr/bin/env bash  
2 -# derive-gitlab.sh — 从 git origin 远程派生 GitLab 凭据并回填 .env.local  
3 -# macOS / Linux 用此版本;Windows 用同目录 derive-gitlab.ps1。  
4 -# 两份脚本严格等价 — 改动任一份必须同步对方。  
5 -#  
6 -# 用法: bash derive-gitlab.sh [.env.local 路径,默认 .env.local]  
7 -#  
8 -# 派生字段:  
9 -# GITLAB_API_URL = <scheme>://<host>/api/v3  
10 -# GITLAB_PROJECT_ID = 通过 GitLab API(GET /projects?search=...)解析得到的项目数字 ID  
11 -# 要求 GITLAB_TOKEN 已填且有效;token 缺失 / 验证失败 / 未匹配时留 TBD  
12 -#  
13 -# 仅当字段值为 TBD(A5 自动补) 或空时回填;用户手填值不动。  
14 -# 仅支持 http(s) origin URL;其他协议(ssh / git@)跳过。  
15 -# GITLAB_TOKEN 不派生,留给用户手填。  
16 -#  
17 -# 退出码:  
18 -# 0 = 派生完成或主动跳过(origin 不存在 / 协议不支持)  
19 -# 2 = .env.local 路径错  
20 -  
21 -set -uo pipefail  
22 -  
23 -ENV_FILE=${1:-.env.local}  
24 -[ -f "$ENV_FILE" ] || { echo "derive-gitlab.sh: env file not found: $ENV_FILE" >&2; exit 2; }  
25 -  
26 -URL=$(git remote get-url origin 2>/dev/null || true)  
27 -if [ -z "$URL" ]; then  
28 - echo "derive-gitlab.sh: 未配置 origin 远程,GITLAB_* 留给用户手填" >&2  
29 - exit 0  
30 -fi  
31 -  
32 -case "$URL" in  
33 - https://*) SCHEME=https ;;  
34 - http://*) SCHEME=http ;;  
35 - *)  
36 - echo "derive-gitlab.sh: origin 不是 http(s) URL ($URL),跳过派生" >&2  
37 - exit 0  
38 - ;;  
39 -esac  
40 -  
41 -REST=${URL#${SCHEME}://}  
42 -HOST=${REST%%/*}  
43 -PATH_RAW=${REST#*/}  
44 -PATH_RAW=${PATH_RAW%.git}  
45 -REPO_NAME=$(basename "$PATH_RAW")  
46 -  
47 -API_URL="${SCHEME}://${HOST}/api/v3"  
48 -  
49 -update_field() {  
50 - local key=$1 newval=$2  
51 - local line  
52 - line=$(grep -E "^${key}=" "$ENV_FILE" | head -1)  
53 - if [ -z "$line" ]; then  
54 - echo " ${key} = (.env.local 中无此行,跳过)" >&2  
55 - return  
56 - fi  
57 - local current=${line#${key}=}  
58 - # 剥外层单/双引号再比较,模板里 TBD(A5 自动补) 因含空格/括号必须加引号才能被 source  
59 - local stripped=$current  
60 - case "$stripped" in  
61 - \'*\') stripped=${stripped#\'}; stripped=${stripped%\'} ;;  
62 - \"*\") stripped=${stripped#\"}; stripped=${stripped%\"} ;;  
63 - esac  
64 - if [ -z "$stripped" ] || [ "$stripped" = "TBD(A5 自动补)" ]; then  
65 - sed -i.bak -E "s|^${key}=.*$|${key}=${newval}|" "$ENV_FILE" && rm -f "${ENV_FILE}.bak"  
66 - echo " ${key} = ${newval} [已派生填入]"  
67 - elif [ "$stripped" = "$newval" ]; then  
68 - echo " ${key} = ${newval} [已是派生值,无需更新]"  
69 - else  
70 - echo " ${key} = ${stripped} [保留用户手填,未覆盖派生值 ${newval}]"  
71 - fi  
72 -}  
73 -  
74 -report_token() {  
75 - local key=GITLAB_TOKEN  
76 - local line  
77 - line=$(grep -E "^${key}=" "$ENV_FILE" | head -1)  
78 - if [ -z "$line" ]; then  
79 - echo " ${key} = (.env.local 中无此行,跳过)" >&2  
80 - return  
81 - fi  
82 - local current=${line#${key}=}  
83 - local stripped=$current  
84 - case "$stripped" in  
85 - \'*\') stripped=${stripped#\'}; stripped=${stripped%\'} ;;  
86 - \"*\") stripped=${stripped#\"}; stripped=${stripped%\"} ;;  
87 - esac  
88 - case "$stripped" in  
89 - ""|"【人工填写:"*|"TBD"*)  
90 - echo " ${key} = ${stripped} [待人工填写:GitLab Profile → Account → Private token]"  
91 - ;;  
92 - *)  
93 - local masked  
94 - if [ ${#stripped} -le 8 ]; then  
95 - masked=$(printf '%*s' ${#stripped} '' | tr ' ' '*')  
96 - else  
97 - masked="${stripped:0:4}$(printf '%*s' $((${#stripped}-8)) '' | tr ' ' '*')${stripped: -4}"  
98 - fi  
99 - echo " ${key} = ${masked} [已填入,长度 ${#stripped}]"  
100 - ;;  
101 - esac  
102 -}  
103 -  
104 -echo "derive-gitlab.sh: 从 origin ($URL) 派生 GitLab 凭据:"  
105 -update_field GITLAB_API_URL "$API_URL"  
106 -  
107 -# GITLAB_PROJECT_ID:通过 GitLab API 解析数字 ID(要求 token 已填且有效)  
108 -TOKEN_LINE=$(grep -E '^GITLAB_TOKEN=' "$ENV_FILE" | head -1)  
109 -TOKEN_VAL=${TOKEN_LINE#GITLAB_TOKEN=}  
110 -case "$TOKEN_VAL" in  
111 - \'*\') TOKEN_VAL=${TOKEN_VAL#\'}; TOKEN_VAL=${TOKEN_VAL%\'} ;;  
112 - \"*\") TOKEN_VAL=${TOKEN_VAL#\"}; TOKEN_VAL=${TOKEN_VAL%\"} ;;  
113 -esac  
114 -  
115 -case "$TOKEN_VAL" in  
116 - ""|"【人工填写:"*|"TBD"*)  
117 - echo " GITLAB_PROJECT_ID = TBD [token 未填,跳过 API 解析;填完 token 后重跑此脚本]"  
118 - ;;  
119 - *)  
120 - USER_HTTP=$(curl -sS -o /dev/null -w '%{http_code}' --header "PRIVATE-TOKEN: $TOKEN_VAL" "$API_URL/user" 2>/dev/null || echo "000")  
121 - if [ "$USER_HTTP" != "200" ]; then  
122 - echo " GITLAB_PROJECT_ID = TBD [token 验证失败 HTTP $USER_HTTP,留 TBD 待人工确认]"  
123 - else  
124 - SEARCH_RESP=$(curl -sS --header "PRIVATE-TOKEN: $TOKEN_VAL" \  
125 - "$API_URL/projects?search=$REPO_NAME&simple=true&per_page=50" 2>/dev/null || echo "[]")  
126 - NUMERIC_ID=$(echo "$SEARCH_RESP" | jq -r --arg p "$PATH_RAW" \  
127 - '.[] | select(.path_with_namespace == $p) | .id' 2>/dev/null | head -1)  
128 - if [ -n "$NUMERIC_ID" ]; then  
129 - update_field GITLAB_PROJECT_ID "$NUMERIC_ID"  
130 - else  
131 - echo " GITLAB_PROJECT_ID = TBD [API 未匹配 path_with_namespace=$PATH_RAW,请到 GitLab 项目设置页查数字 ID 后填入]"  
132 - fi  
133 - fi  
134 - ;;  
135 -esac  
136 -  
137 -report_token  
skills/plan/downstream-gen/templates/docs-02-template.md
@@ -10,7 +10,7 @@ @@ -10,7 +10,7 @@
10 10
11 ## 二、开发顺序清单(CC 分发权威) 11 ## 二、开发顺序清单(CC 分发权威)
12 12
13 -> 本清单由 A5 `downstream-gen` 一次性生成。**每行是一个 REQ**,不是模块。CC 按表格行序从上到下扫描,对每个 REQ 所属模块查 `docs/08 § 二` 的 `MR:` 字段 + GitLab API `state`:`merged` 跳过,其他(`—` / opened / closed / 查不到)选为当前模块;`module-start` 会把该模块的所有 REQ 一次做完。 13 +> 本清单由 A5 `downstream-gen` 一次性生成。**每行是一个 REQ**,不是模块。CC 按表格行序从上到下扫描,对每个 REQ 所属模块查 `docs/08 § 二` 的 `里程碑:` 字段 + 本地 `git tag -l 'milestone/<id>'`:tag 存在则跳过,否则(`—` / tag 不存在)选为当前模块;`module-start` 会把该模块的所有 REQ 一次做完。
14 > 14 >
15 > **约束**:同一模块的所有 REQ 必须**连续排列**。允许打破依赖拓扑(如环依赖、业务必须先做),但必须在「备注」列写明原因。 15 > **约束**:同一模块的所有 REQ 必须**连续排列**。允许打破依赖拓扑(如环依赖、业务必须先做),但必须在「备注」列写明原因。
16 16
@@ -20,7 +20,7 @@ @@ -20,7 +20,7 @@
20 | {{index}} | **{{req_id}}** | {{module_id}} | {{rationale}} | {{note}} | 20 | {{index}} | **{{req_id}}** | {{module_id}} | {{rationale}} | {{note}} |
21 {{/each}} 21 {{/each}}
22 22
23 -> **后端模块全部 merged 后**:用户重跑 `/erp-workflow:coding-start` → coding-start 检测到 `backend_done=true && frontend_done=false` → 派发 `frontend-start`。`frontend-start` 步骤 1 自带 prototype/ 门禁(≥ 1 个 `*.html` mockup,缺失则 AskUserQuestion 提示用户补齐)。前端阶段以业务功能(不是 HTML 文件数)为粒度拆分 FE,每个 FE 跑一次 feature 循环(fe-feature-*),最后整个阶段合 1 个 MR(分支 `frontend-phase`,记录在 `docs/08 § 三 整体 MR`)。 23 +> **后端模块全部打里程碑后**:milestone-tag 自动回调 `coding-start` → coding-start 检测到 `backend_done=true && frontend_done=false` → 派发 `frontend-start`。`frontend-start` 步骤 1 自带 prototype/ 门禁(≥ 1 个 `*.html` mockup,缺失则 AskUserQuestion 提示用户补齐)。前端阶段以业务功能(不是 HTML 文件数)为粒度拆分 FE,每个 FE 跑一次 feature 循环(fe-feature-*),最后整个阶段打 1 个里程碑 tag(分支 `frontend-phase`,记录在 `docs/08 § 三 整体里程碑`)。
24 24
25 ## 三、关键说明 25 ## 三、关键说明
26 {{notes}} 26 {{notes}}
skills/plan/downstream-gen/templates/docs-08-module-row-template.md
1 - {{module_id}} {{module_name}} 1 - {{module_id}} {{module_name}}
2 - 依赖: {{depends_on}} 2 - 依赖: {{depends_on}}
3 - 路径: {{path_scopes}} 3 - 路径: {{path_scopes}}
4 - - MR: — 4 + - 里程碑: —
5 - 功能: 5 - 功能:
6 {{req_checklist}} 6 {{req_checklist}}
skills/plan/project-init/templates/CLAUDE-template.md
@@ -21,8 +21,8 @@ B 阶段分两段,**全部固化到 skills**。入口:`/erp-workflow:coding- @@ -21,8 +21,8 @@ B 阶段分两段,**全部固化到 skills**。入口:`/erp-workflow:coding-
21 21
22 `coding-start` 每次入口做两段完成性检查后真值表派发: 22 `coding-start` 每次入口做两段完成性检查后真值表派发:
23 23
24 -- 后端完成性检查 → `backend_done`(扫 docs/08 § 二 + GitLab state)  
25 -- 前端完成性检查 → `frontend_done`(扫 docs/08 § 三 整体 MR + state) 24 +- 后端完成性检查 → `backend_done`(扫 docs/08 § 二 里程碑字段 + `git tag -l`)
  25 +- 前端完成性检查 → `frontend_done`(扫 docs/08 § 三 整体里程碑 + `git tag -l`)
26 26
27 | `backend_done` | `frontend_done` | 派发 | 27 | `backend_done` | `frontend_done` | 派发 |
28 |---|---|---| 28 |---|---|---|
@@ -32,33 +32,33 @@ B 阶段分两段,**全部固化到 skills**。入口:`/erp-workflow:coding- @@ -32,33 +32,33 @@ B 阶段分两段,**全部固化到 skills**。入口:`/erp-workflow:coding-
32 32
33 前端阶段前置(prototype/ 门禁)由 `frontend-start` 自带,不在 coding-start。`module-start` 与 `frontend-start` **互不感知对方**。 33 前端阶段前置(prototype/ 门禁)由 `frontend-start` 自带,不在 coding-start。`module-start` 与 `frontend-start` **互不感知对方**。
34 34
35 -### 后端阶段(每模块一个 MR 35 +### 后端阶段(每模块一个里程碑 tag
36 36
37 -- **模块循环(外)**:`module-start` → `test-gate(phase=backend)` → `module-report` → `mr-create` → 人工 Approve MR → 用户重跑 coding-start → coding-start 再次路由 37 +- **模块循环(外)**:`module-start` → `test-gate(phase=backend)` → `module-report` → `milestone-tag`(本地 merge 进默认分支 + 打 `milestone/<id>` tag)→ 自动回调 coding-start 路由下一阶段(无人工介入)
38 - **功能循环(内,每 REQ-XXX-NNN 一遍)**:`feature-brainstorm` → `feature-plan` → `feature-tdd` → `feature-verify` → `feature-review` 38 - **功能循环(内,每 REQ-XXX-NNN 一遍)**:`feature-brainstorm` → `feature-plan` → `feature-tdd` → `feature-verify` → `feature-review`
39 - 后端阶段任务严格落在 `backend/` 路径下;docs/01 REQ 卡片的 UI 描述在此阶段忽略,UI 推迟到前端阶段。 39 - 后端阶段任务严格落在 `backend/` 路径下;docs/01 REQ 卡片的 UI 描述在此阶段忽略,UI 推迟到前端阶段。
40 40
41 -### 前端阶段(整体一个 MR,所有后端模块 merged 后启动) 41 +### 前端阶段(整体一个里程碑 tag,所有后端模块打里程碑后启动)
42 42
43 -- **FE 清单(AI 自主推导,无审阅断点)**:`frontend-start` 进入时扫 prototype + docs/01 + docs/05 → AI 自主推导 FE 业务功能清单写入 `docs/08 § 三`(已有则加载)。**FE 是业务功能粒度,与 prototype HTML 文件数无关**——一个 HTML 可拆多个 FE,多个 HTML 也可合成一个 FE。FE 清单的合理性由 fe-feature-review / mr-create 在整体 MR 提交时一并校核(人工只在 MR Approve+Merge 处介入)。  
44 -- **FE 循环(外)**:`frontend-start` → fe-feature 循环 → `test-gate(phase=frontend)` → `module-report(phase=frontend)` → `mr-create`(分支 `frontend-phase`,docs/08 § 三 整体 MR)。 43 +- **FE 清单(AI 自主推导,无审阅断点)**:`frontend-start` 进入时扫 prototype + docs/01 + docs/05 → AI 自主推导 FE 业务功能清单写入 `docs/08 § 三`(已有则加载)。**FE 是业务功能粒度,与 prototype HTML 文件数无关**——一个 HTML 可拆多个 FE,多个 HTML 也可合成一个 FE。FE 清单的合理性由 fe-feature-review / milestone-tag 在整体里程碑标记时一并校核(全程无人工介入)。
  44 +- **FE 循环(外)**:`frontend-start` → fe-feature 循环 → `test-gate(phase=frontend)` → `module-report(phase=frontend)` → `milestone-tag`(分支 `frontend-phase`,docs/08 § 三 整体里程碑)。
45 - **FE 功能循环(内,每个 FE-NN 一遍)**:`fe-feature-brainstorm` → `fe-feature-plan` → `fe-feature-tdd` → `fe-feature-verify` → `fe-feature-review`(专用 `fe-code-reviewer` agent,硬编码 7 维 review checklist) 45 - **FE 功能循环(内,每个 FE-NN 一遍)**:`fe-feature-brainstorm` → `fe-feature-plan` → `fe-feature-tdd` → `fe-feature-verify` → `fe-feature-review`(专用 `fe-code-reviewer` agent,硬编码 7 维 review checklist)
46 - 前端阶段任务严格落在 `frontend/` 路径下;布局以 `prototype/` 为权威。 46 - 前端阶段任务严格落在 `frontend/` 路径下;布局以 `prototype/` 为权威。
47 47
48 -### MR 前测试闸门 48 +### 里程碑前测试闸门
49 49
50 - `test-gate`:后端阶段子会话跑 `scripts/test.sh`(含本模块新增 + 已合并模块回归);前端阶段子会话跑 vitest + playwright。 50 - `test-gate`:后端阶段子会话跑 `scripts/test.sh`(含本模块新增 + 已合并模块回归);前端阶段子会话跑 vitest + playwright。
51 -- `.githooks/pre-push` 兜底;`git push --no-verify` 被 `deny-no-verify.sh` 硬拦 51 +- `test-gate` 是打里程碑 tag 前唯一的硬测试门;红色不得跳过进入 `module-report` / `milestone-tag`
52 52
53 --- 53 ---
54 54
55 ## ✅ 阶段完成判定规则 55 ## ✅ 阶段完成判定规则
56 56
57 `docs/08-模块任务管理.md` 分两段: 57 `docs/08-模块任务管理.md` 分两段:
58 -- `§ 二`:后端模块元数据表(每个模块一行 bullet,记录依赖 / 路径 / MR iid / 功能子项)  
59 -- `§ 三`:前端阶段元数据(整体 MR + FE 子项清单,由 `frontend-start` 在所有后端模块 merged 后填入) 58 +- `§ 二`:后端模块元数据表(每个模块一行 bullet,记录依赖 / 路径 / 里程碑 tag / 功能子项)
  59 +- `§ 三`:前端阶段元数据(整体里程碑 + FE 子项清单,由 `frontend-start` 在所有后端模块打里程碑后填入)
60 60
61 -**阶段完成判定**统一以 `MR:` 字段(§ 二 各模块) / `整体 MR:` 字段(§ 三)+ `GitLab API state=merged` 判定;子项勾选只作可视化进度,不参与完成判定。 61 +**阶段完成判定**统一以 `里程碑:` 字段(§ 二 各模块) / `整体里程碑:` 字段(§ 三)+ 本地 `git tag -l 'milestone/<id>'` 判定;子项勾选只作可视化进度,不参与完成判定。
62 62
63 ### 后端模块格式 63 ### 后端模块格式
64 64
@@ -68,37 +68,36 @@ B 阶段分两段,**全部固化到 skills**。入口:`/erp-workflow:coding- @@ -68,37 +68,36 @@ B 阶段分两段,**全部固化到 skills**。入口:`/erp-workflow:coding-
68 - module_0 系统管理 68 - module_0 系统管理
69 - 依赖: — 69 - 依赖: —
70 - 路径: backend/module/sys/ 70 - 路径: backend/module/sys/
71 - - MR: — 71 + - 里程碑: —
72 - 功能: 72 - 功能:
73 - [ ] REQ-SYS-001 用户登录 73 - [ ] REQ-SYS-001 用户登录
74 - [ ] REQ-SYS-002 用户注册 74 - [ ] REQ-SYS-002 用户注册
75 ``` 75 ```
76 76
77 -- `MR:` 字段由 `mr-create` 在创建 MR 时从 `—` 改为 `!<iid>`。 77 +- `里程碑:` 字段由 `milestone-tag` 在打里程碑 tag 时从 `—` 改为 `milestone/<module_id>`。
78 - 每个 `REQ-*` 子项由 `feature-review` 在 `verdict=approve` 时自动勾选为 `[x]`。 78 - 每个 `REQ-*` 子项由 `feature-review` 在 `verdict=approve` 时自动勾选为 `[x]`。
79 - 路径限定为后端目录(如 `backend/module/sys/`);前端代码不在此阶段产生。 79 - 路径限定为后端目录(如 `backend/module/sys/`);前端代码不在此阶段产生。
80 80
81 ### 前端阶段格式(§ 三) 81 ### 前端阶段格式(§ 三)
82 82
83 ```markdown 83 ```markdown
84 -- 整体 MR: — 84 +- 整体里程碑: —
85 - 功能: 85 - 功能:
86 - [ ] FE-01 用户登录与注册 | 关联 REQ:REQ-SYS-001, REQ-SYS-002 | 关联原型:prototype/auth.html 86 - [ ] FE-01 用户登录与注册 | 关联 REQ:REQ-SYS-001, REQ-SYS-002 | 关联原型:prototype/auth.html
87 - [ ] FE-02 仪表盘总览 | 关联 REQ:REQ-DASH-001 | 关联原型:prototype/dashboard.html 87 - [ ] FE-02 仪表盘总览 | 关联 REQ:REQ-DASH-001 | 关联原型:prototype/dashboard.html
88 ``` 88 ```
89 89
90 -- `整体 MR:` 字段由 `mr-create` 在创建前端 MR 时从 `—` 改为 `!<iid>`。  
91 -- "功能:" 列表由 `frontend-start` 进入时由 AI 自主推导写入(无人工审阅断点)。FE 是业务功能粒度,与 prototype HTML 文件数无关;合理性由 fe-feature-review / 整体 MR 时统一校核。 90 +- `整体里程碑:` 字段由 `milestone-tag` 在打前端里程碑 tag 时从 `—` 改为 `milestone/frontend-phase`。
  91 +- "功能:" 列表由 `frontend-start` 进入时由 AI 自主推导写入(无人工审阅断点)。FE 是业务功能粒度,与 prototype HTML 文件数无关;合理性由 fe-feature-review / 整体里程碑标记时统一校核。
92 - 每个 `FE-NN` 子项由 `fe-feature-review` 在 `verdict=approve` 时自动勾选为 `[x]`。 92 - 每个 `FE-NN` 子项由 `fe-feature-review` 在 `verdict=approve` 时自动勾选为 `[x]`。
93 - 进入前端阶段前 `frontend-start` 步骤 1 自带 prototype/ 门禁,强制检查项目根 `prototype/` 至少含 1 个 `*.html` mockup。 93 - 进入前端阶段前 `frontend-start` 步骤 1 自带 prototype/ 门禁,强制检查项目根 `prototype/` 至少含 1 个 `*.html` mockup。
94 94
95 ### 状态语义(后端模块 + 前端阶段共用) 95 ### 状态语义(后端模块 + 前端阶段共用)
96 96
97 -| `MR:` 字段 | `GitLab API state` | 含义 | 你(Claude Code)的行为 | 97 +| `里程碑:` 字段 | `git tag -l` | 含义 | 你(Claude Code)的行为 |
98 |---|---|---|---| 98 |---|---|---|---|
99 -| `—` | — | 该阶段未开始(未创建 MR) | ✅ 开始该阶段开发 |  
100 -| `!<iid>` | `opened` / `closed` | 阶段开发中 / 打回 | ✅ 继续推进该阶段 |  
101 -| `!<iid>` | `merged` | 阶段**已完成** | 🟢 后端:进入下一未完成模块;后端全完 → 前端阶段;前端 merged → 全部完成 | 99 +| `—` | tag 不存在 | 该阶段未开始 / 进行中(未打里程碑) | ✅ 开始 / 继续该阶段开发 |
  100 +| `milestone/<id>` | tag 存在 | 阶段**已完成** | 🟢 后端:进入下一未完成模块;后端全完 → 前端阶段;前端已打里程碑 → 全部完成 |
102 101
103 ### 模块完成报告 102 ### 模块完成报告
104 103
@@ -133,7 +132,7 @@ B 阶段分两段,**全部固化到 skills**。入口:`/erp-workflow:coding- @@ -133,7 +132,7 @@ B 阶段分两段,**全部固化到 skills**。入口:`/erp-workflow:coding-
133 ### 你禁止做的 🚫 132 ### 你禁止做的 🚫
134 133
135 1. **主会话直接 `mysql -e` 跑业务 DDL**(只读查询 / 临时本地调试除外)——业务 schema 必须走 `sql/migrations/V_n__*.sql`,详见下方 Schema 演化规约 134 1. **主会话直接 `mysql -e` 跑业务 DDL**(只读查询 / 临时本地调试除外)——业务 schema 必须走 `sql/migrations/V_n__*.sql`,详见下方 Schema 演化规约
136 -2. **手动 Edit `docs/08 § 二/§ 三` 的 `MR:` / `整体 MR:` 字段**,必须要由 `mr-create` 自动回写 135 +2. **手动 Edit `docs/08 § 二/§ 三` 的 `里程碑:` / `整体里程碑:` 字段**,必须要由 `milestone-tag` 自动回写
137 136
138 ### Schema 演化规约(Flyway migration) 137 ### Schema 演化规约(Flyway migration)
139 138
@@ -167,7 +166,7 @@ B 阶段分两段,**全部固化到 skills**。入口:`/erp-workflow:coding- @@ -167,7 +166,7 @@ B 阶段分两段,**全部固化到 skills**。入口:`/erp-workflow:coding-
167 | `docs` | **文档改动**——只动 Markdown / 代码注释,不动实现 | 166 | `docs` | **文档改动**——只动 Markdown / 代码注释,不动实现 |
168 | `style` | **格式调整**——空白 / 缩进 / import 顺序,逻辑 0 变化 | 167 | `style` | **格式调整**——空白 / 缩进 / import 顺序,逻辑 0 变化 |
169 | `test` | **只动测试代码**——补用例 / 修 fixture,不碰实现 | 168 | `test` | **只动测试代码**——补用例 / 修 fixture,不碰实现 |
170 -| `chore` | **流程维护**——构建 / 依赖 / 工具 / 证据档案 / MR 元数据等非业务动作 | 169 +| `chore` | **流程维护**——构建 / 依赖 / 工具 / 证据档案 / 里程碑元数据等非业务动作 |
171 170
172 --- 171 ---
173 172
skills/plan/project-init/templates/docs-08-initial-template.md
@@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
2 2
3 > 全流程进度跟踪。CC 每完成一项产出就勾选一项。 3 > 全流程进度跟踪。CC 每完成一项产出就勾选一项。
4 > - **§ 一 Plan(A0~A5)**:`plan-start` 找第一个未勾 A 子项分发到对应 skill 4 > - **§ 一 Plan(A0~A5)**:`plan-start` 找第一个未勾 A 子项分发到对应 skill
5 -> - **§ 二 Coding(模块)**:分发以 `docs/02-开发计划.md § 二 开发顺序清单` 为准;`coding-start` 按 docs/02 顺序扫描,对每个 REQ 所属模块查询本 § 二的 `MR:` 字段 + GitLab API `state`,找第一个非 merged 模块分发。本 § 二 行序无语义,仅作模块元数据表 5 +> - **§ 二 Coding(模块)**:分发以 `docs/02-开发计划.md § 二 开发顺序清单` 为准;`coding-start` 按 docs/02 顺序扫描,对每个 REQ 所属模块查询本 § 二的 `里程碑:` 字段 + 本地 `git tag -l 'milestone/<id>'`,找第一个未打里程碑模块分发。本 § 二 行序无语义,仅作模块元数据表
6 6
7 ## 一、Plan 阶段(一次性) 7 ## 一、Plan 阶段(一次性)
8 8
@@ -19,7 +19,7 @@ @@ -19,7 +19,7 @@
19 19
20 - [ ] A2 骨架生成 — skeleton-gen 20 - [ ] A2 骨架生成 — skeleton-gen
21 - [ ] 架构文档已生成(docs/04 § 一+、docs/06、docs/07、docs/09) 21 - [ ] 架构文档已生成(docs/04 § 一+、docs/06、docs/07、docs/09)
22 - - [ ] 工具脚本已生成(scripts/*.sh、.githooks/pre-push、.env.local) 22 + - [ ] 工具脚本已生成(scripts/*.sh、.env.local)
23 - [ ] .gitignore 已配置 23 - [ ] .gitignore 已配置
24 24
25 - [ ] A3 DB 设计 + REQ 回填 — db-design-gen 25 - [ ] A3 DB 设计 + REQ 回填 — db-design-gen
@@ -43,13 +43,13 @@ @@ -43,13 +43,13 @@
43 43
44 ## 二、Coding 阶段(后端模块循环) 44 ## 二、Coding 阶段(后端模块循环)
45 45
46 -(A5 填入后,每行一个后端模块。每个模块的 `MR:` 字段在 `—` 和 `!<iid>` 之间变化,完成由 GitLab API `state=merged` 判定。`coding-start` 每次按 docs/02 REQ 序扫每模块的 MR state 决定派发。后端模块全部 merged 后自动进入 § 三 前端阶段。) 46 +(A5 填入后,每行一个后端模块。每个模块的 `里程碑:` 字段在 `—` 和 `milestone/<id>` 之间变化,完成由本地 `git tag -l` 判定。`coding-start` 每次按 docs/02 REQ 序扫每模块的里程碑 tag 决定派发。后端模块全部打里程碑后自动进入 § 三 前端阶段。)
47 47
48 <!-- 模块格式示例(由 A5 downstream-gen 追加;功能子项由 feature-review 在 approve 时勾选): 48 <!-- 模块格式示例(由 A5 downstream-gen 追加;功能子项由 feature-review 在 approve 时勾选):
49 - module_0 系统管理 49 - module_0 系统管理
50 - 依赖: — 50 - 依赖: —
51 - 路径: backend/module/sys/ 51 - 路径: backend/module/sys/
52 - - MR: — 52 + - 里程碑: —
53 - 功能: 53 - 功能:
54 - [ ] REQ-SYS-001 用户登录 54 - [ ] REQ-SYS-001 用户登录
55 - [ ] REQ-SYS-002 用户注册 55 - [ ] REQ-SYS-002 用户注册
@@ -57,9 +57,9 @@ @@ -57,9 +57,9 @@
57 57
58 ## 三、Coding 阶段(前端整体) 58 ## 三、Coding 阶段(前端整体)
59 59
60 -(`frontend-start` 进入时扫 prototype/ + docs/01 + docs/05 → AI 自主推导 FE 业务功能清单写到下方"功能:"项(无人工审阅断点;合理性由整体 MR 时统一校核)。已有清单则直接加载。整个前端阶段 1 个 MR,分支 `frontend-phase`。) 60 +(`frontend-start` 进入时扫 prototype/ + docs/01 + docs/05 → AI 自主推导 FE 业务功能清单写到下方"功能:"项(无人工审阅断点;合理性由整体里程碑标记时统一校核)。已有清单则直接加载。整个前端阶段 1 个里程碑 tag,分支 `frontend-phase`。)
61 61
62 -- 整体 MR: — 62 +- 整体里程碑: —
63 - 功能: 63 - 功能:
64 <!-- AI 进入时按以下行格式写入(每行 1 个 FE,可关联多个 REQ / 多份原型): 64 <!-- AI 进入时按以下行格式写入(每行 1 个 FE,可关联多个 REQ / 多份原型):
65 - [ ] FE-NN 功能名 | 关联 REQ:REQ-A, REQ-B | 关联原型:prototype/<file>.html, prototype/<other>.html 65 - [ ] FE-NN 功能名 | 关联 REQ:REQ-A, REQ-B | 关联原型:prototype/<file>.html, prototype/<other>.html
skills/plan/skeleton-gen/SKILL.md
@@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
2 name: skeleton-gen 2 name: skeleton-gen
3 description: A2 骨架生成——基于 docs/04 § 零 技术栈 + docs/01-需求清单/index.md 模块索引,生成项目专属的架构文档(docs/04 § 一+、docs/06、docs/07、docs/09)和工具脚本。固定工具文件走 cp,架构文档由 LLM 按大纲生成。 3 description: A2 骨架生成——基于 docs/04 § 零 技术栈 + docs/01-需求清单/index.md 模块索引,生成项目专属的架构文档(docs/04 § 一+、docs/06、docs/07、docs/09)和工具脚本。固定工具文件走 cp,架构文档由 LLM 按大纲生成。
4 user-invocable: false 4 user-invocable: false
5 -allowed-tools: Read Write Edit Skill Grep Glob AskUserQuestion Bash(mkdir *) Bash(cp *) Bash(touch *) Bash(chmod *) Bash(git config *) Bash(cat *) Bash(bash *) 5 +allowed-tools: Read Write Edit Skill Grep Glob AskUserQuestion Bash(mkdir *) Bash(cp *) Bash(touch *) Bash(chmod *) Bash(cat *) Bash(bash *)
6 --- 6 ---
7 7
8 **所有输出必须使用中文。** 8 **所有输出必须使用中文。**
@@ -61,10 +61,9 @@ docs/04 已由 scope-lock 写入 § 零。本步骤追加 § 一 ~ 三。 @@ -61,10 +61,9 @@ docs/04 已由 scope-lock 写入 § 零。本步骤追加 § 一 ~ 三。
61 #### C.1 复制 61 #### C.1 复制
62 62
63 ```bash 63 ```bash
64 -mkdir -p scripts .githooks sql/migrations src/styles 64 +mkdir -p scripts sql/migrations src/styles
65 touch sql/migrations/.gitkeep 65 touch sql/migrations/.gitkeep
66 cp "${CLAUDE_SKILL_DIR}/templates/env-local-template" .env.local 66 cp "${CLAUDE_SKILL_DIR}/templates/env-local-template" .env.local
67 -cp "${CLAUDE_SKILL_DIR}/templates/githooks-pre-push-template.sh" .githooks/pre-push  
68 cp "${CLAUDE_SKILL_DIR}/templates/scripts-setup-test-db-template.sh" scripts/setup-test-db.sh 67 cp "${CLAUDE_SKILL_DIR}/templates/scripts-setup-test-db-template.sh" scripts/setup-test-db.sh
69 cp "${CLAUDE_SKILL_DIR}/templates/styles-tokens-template.css" src/styles/tokens.css 68 cp "${CLAUDE_SKILL_DIR}/templates/styles-tokens-template.css" src/styles/tokens.css
70 ``` 69 ```
@@ -85,15 +84,14 @@ cp &quot;${CLAUDE_SKILL_DIR}/templates/styles-tokens-template.css&quot; src/styles/tokens. @@ -85,15 +84,14 @@ cp &quot;${CLAUDE_SKILL_DIR}/templates/styles-tokens-template.css&quot; src/styles/tokens.
85 > 84 >
86 > 表结构异常(列名变更 / 无中文前缀)时停下,用 `AskUserQuestion` 让用户显式确认每 stack 命令。 85 > 表结构异常(列名变更 / 无中文前缀)时停下,用 `AskUserQuestion` 让用户显式确认每 stack 命令。
87 86
88 -#### C.3 赋权 + 配置 git hooks 87 +#### C.3 赋权
89 88
90 ```bash 89 ```bash
91 -chmod +x scripts/*.sh .githooks/pre-push  
92 -git config core.hooksPath .githooks 90 +chmod +x scripts/*.sh
93 ``` 91 ```
94 92
95 完成后,用 `Edit` 在 `docs/08-模块任务管理.md` 中勾选: 93 完成后,用 `Edit` 在 `docs/08-模块任务管理.md` 中勾选:
96 -- ` - [ ] 工具脚本已生成(scripts/*.sh、.githooks/pre-push、.env.local)` 94 +- ` - [ ] 工具脚本已生成(scripts/*.sh、.env.local)`
97 - ` - [ ] 样式 token 骨架已生成(src/styles/tokens.css)` 95 - ` - [ ] 样式 token 骨架已生成(src/styles/tokens.css)`
98 96
99 ### D. 追加 .gitignore 忽略项 97 ### D. 追加 .gitignore 忽略项
@@ -113,7 +111,7 @@ bash &quot;${CLAUDE_SKILL_DIR}/scripts/merge-gitignore.sh&quot; &quot;${CLAUDE_SKILL_DIR}/templ @@ -113,7 +111,7 @@ bash &quot;${CLAUDE_SKILL_DIR}/scripts/merge-gitignore.sh&quot; &quot;${CLAUDE_SKILL_DIR}/templ
113 111
114 用 `Grep` 在以下 8 个路径扫 `【人工填写:`,记录命中(文件 / 行号 / 说明): 112 用 `Grep` 在以下 8 个路径扫 `【人工填写:`,记录命中(文件 / 行号 / 说明):
115 - `docs/04-技术规范.md` / `docs/06-UI交互规范.md` / `docs/07-环境配置.md` / `docs/09-项目目录结构.md` 113 - `docs/04-技术规范.md` / `docs/06-UI交互规范.md` / `docs/07-环境配置.md` / `docs/09-项目目录结构.md`
116 -- `scripts/*.sh` / `.githooks/pre-push` / `.gitignore` 114 +- `scripts/*.sh` / `.gitignore`
117 - `.env.local` 115 - `.env.local`
118 116
119 分两组: 117 分两组:
@@ -139,7 +137,7 @@ bash &quot;${CLAUDE_SKILL_DIR}/scripts/merge-gitignore.sh&quot; &quot;${CLAUDE_SKILL_DIR}/templ @@ -139,7 +137,7 @@ bash &quot;${CLAUDE_SKILL_DIR}/scripts/merge-gitignore.sh&quot; &quot;${CLAUDE_SKILL_DIR}/templ
139 137
140 每次弹 QA 前重扫;有残留则打印残留位置清单(文件:行号 — 说明)+ 再弹 QA。 138 每次弹 QA 前重扫;有残留则打印残留位置清单(文件:行号 — 说明)+ 再弹 QA。
141 139
142 -QA 横幅涵盖:产出文件清单(docs/04 / 06 / 07 / 09 + scripts/*.sh + .githooks/pre-push + .env.local + .gitignore)、占位状态(N=0 或待填清单)、「继续」/「有疑问先沟通」两选项。 140 +QA 横幅涵盖:产出文件清单(docs/04 / 06 / 07 / 09 + scripts/*.sh + .env.local + .gitignore)、占位状态(N=0 或待填清单)、「继续」/「有疑问先沟通」两选项。
143 141
144 通过后(N=0 且用户选「继续」),用 `Edit` 在 `docs/08-模块任务管理.md` 中勾选: 142 通过后(N=0 且用户选「继续」),用 `Edit` 在 `docs/08-模块任务管理.md` 中勾选:
145 - `- [ ] A2 骨架生成 — skeleton-gen` 143 - `- [ ] A2 骨架生成 — skeleton-gen`
@@ -158,7 +156,6 @@ QA 横幅涵盖:产出文件清单(docs/04 / 06 / 07 / 09 + scripts/*.sh + . @@ -158,7 +156,6 @@ QA 横幅涵盖:产出文件清单(docs/04 / 06 / 07 / 09 + scripts/*.sh + .
158 - `${CLAUDE_SKILL_DIR}/templates/docs-09-structure-template.md`(大纲) 156 - `${CLAUDE_SKILL_DIR}/templates/docs-09-structure-template.md`(大纲)
159 - `${CLAUDE_SKILL_DIR}/templates/scripts-test-template.sh`(推断命令填充 7 槽:backend/frontend × build/lint/test + e2e;缺席 stack 填 `:`) 157 - `${CLAUDE_SKILL_DIR}/templates/scripts-test-template.sh`(推断命令填充 7 槽:backend/frontend × build/lint/test + e2e;缺席 stack 填 `:`)
160 - `${CLAUDE_SKILL_DIR}/templates/scripts-setup-test-db-template.sh`(0 槽位) 158 - `${CLAUDE_SKILL_DIR}/templates/scripts-setup-test-db-template.sh`(0 槽位)
161 -- `${CLAUDE_SKILL_DIR}/templates/githooks-pre-push-template.sh`(0 槽位)  
162 - `${CLAUDE_SKILL_DIR}/templates/env-local-template`(0 槽位) 159 - `${CLAUDE_SKILL_DIR}/templates/env-local-template`(0 槽位)
163 - `${CLAUDE_SKILL_DIR}/templates/gitignore-append-template`(0 槽位) 160 - `${CLAUDE_SKILL_DIR}/templates/gitignore-append-template`(0 槽位)
164 - `${CLAUDE_SKILL_DIR}/templates/styles-tokens-template.css`(0 槽位,样式 token 骨架) 161 - `${CLAUDE_SKILL_DIR}/templates/styles-tokens-template.css`(0 槽位,样式 token 骨架)
skills/plan/skeleton-gen/templates/docs-04-skeleton-template.md
@@ -6,22 +6,26 @@ skeleton-gen 读取 docs/04 § 零(技术栈表)和 docs/01-需求清单/ind @@ -6,22 +6,26 @@ skeleton-gen 读取 docs/04 § 零(技术栈表)和 docs/01-需求清单/ind
6 6
7 ## 一、后端规范 7 ## 一、后端规范
8 8
9 -### 1.1 分层结构 9 +### 1.1 规则
  10 +<!-- 后端通用约定:保留下方占位符不要代填,由人工在 skeleton-gen § E 填写;每条一个 bullet,按需复制本行新增更多。 -->
  11 +- 【人工填写:一条后端通用约定,按需复制本行新增更多;无则填「无」】
  12 +
  13 +### 1.2 分层结构
10 <!-- 按 § 零 的后端框架定层次:controller/service/mapper 等;每层职责一句话。 --> 14 <!-- 按 § 零 的后端框架定层次:controller/service/mapper 等;每层职责一句话。 -->
11 15
12 -### 1.2 命名约定 16 +### 1.3 命名约定
13 <!-- 包名(根包用【人工填写:根包名】占位)/ 类名 / 方法名 / 常量的大小写规则,含 2 个示例。 --> 17 <!-- 包名(根包用【人工填写:根包名】占位)/ 类名 / 方法名 / 常量的大小写规则,含 2 个示例。 -->
14 18
15 -### 1.3 统一响应格式 19 +### 1.4 统一响应格式
16 <!-- 成功/失败的 JSON 结构,错误码段位划分。 --> 20 <!-- 成功/失败的 JSON 结构,错误码段位划分。 -->
17 21
18 -### 1.4 异常处理 22 +### 1.5 异常处理
19 <!-- 全局异常处理器的使用方式;哪些异常要 catch,哪些禁止;**接口响应禁止回显后端异常堆栈**(返用户友好错误码 + 文案)。 --> 23 <!-- 全局异常处理器的使用方式;哪些异常要 catch,哪些禁止;**接口响应禁止回显后端异常堆栈**(返用户友好错误码 + 文案)。 -->
20 24
21 -### 1.5 事务 25 +### 1.6 事务
22 <!-- 事务边界(通常 service 层);跨服务调用的禁止/替代方案。 --> 26 <!-- 事务边界(通常 service 层);跨服务调用的禁止/替代方案。 -->
23 27
24 -### 1.6 认证 28 +### 1.7 认证
25 <!-- 基于 § 零 认证方案推导:token 生命周期、刷新机制、密钥管理。 --> 29 <!-- 基于 § 零 认证方案推导:token 生命周期、刷新机制、密钥管理。 -->
26 30
27 ## 二、前端规范 31 ## 二、前端规范
@@ -62,4 +66,4 @@ skeleton-gen 读取 docs/04 § 零(技术栈表)和 docs/01-需求清单/ind @@ -62,4 +66,4 @@ skeleton-gen 读取 docs/04 § 零(技术栈表)和 docs/01-需求清单/ind
62 66
63 ### 3.5 配置与安全 67 ### 3.5 配置与安全
64 <!-- 配置:DB 连接 / 端口 / 密钥 / 第三方 URL 等一律放 `application.yml` + `.env.local`,代码里**禁止硬编码**。 68 <!-- 配置:DB 连接 / 端口 / 密钥 / 第三方 URL 等一律放 `application.yml` + `.env.local`,代码里**禁止硬编码**。
65 - 前端安全:`localStorage` 不存敏感信息(token / 身份 / 个人数据),推荐 HttpOnly Cookie 或 内存 + 刷新 token 模式;接口响应禁止回显后端异常堆栈(与 § 1.4 一致)。 --> 69 + 前端安全:`localStorage` 不存敏感信息(token / 身份 / 个人数据),推荐 HttpOnly Cookie 或 内存 + 刷新 token 模式;接口响应禁止回显后端异常堆栈(与 § 1.5 一致)。 -->
skills/plan/skeleton-gen/templates/docs-07-env-template.md
@@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
3 skeleton-gen 基于 docs/04 § 零 技术栈表推导各节内容: 3 skeleton-gen 基于 docs/04 § 零 技术栈表推导各节内容:
4 § 一 依赖清单 → 从技术栈的每一行技术推导运行时和构建依赖 4 § 一 依赖清单 → 从技术栈的每一行技术推导运行时和构建依赖
5 § 二 端口约定 → 从后端/前端/数据库/缓存/反向代理 各取默认端口 5 § 二 端口约定 → 从后端/前端/数据库/缓存/反向代理 各取默认端口
6 - § 四 常用命令 → 基于构建工具、包管理器、MR 工具给出开发者最常用命令 6 + § 四 常用命令 → 基于构建工具、包管理器给出开发者最常用命令
7 --> 7 -->
8 8
9 # 07-环境配置 9 # 07-环境配置
@@ -23,4 +23,4 @@ skeleton-gen 基于 docs/04 § 零 技术栈表推导各节内容: @@ -23,4 +23,4 @@ skeleton-gen 基于 docs/04 § 零 技术栈表推导各节内容:
23 23
24 ## 四、常用命令 24 ## 四、常用命令
25 25
26 -<!-- 表格:| 命令 | 说明 |;包含 启动后端 / 启动前端 / 打包 / 运行测试 / 重置测试数据 / 创建 MR。 --> 26 +<!-- 表格:| 命令 | 说明 |;包含 启动后端 / 启动前端 / 打包 / 运行测试 / 重置测试数据。 -->
skills/plan/skeleton-gen/templates/docs-09-structure-template.md
@@ -13,7 +13,7 @@ skeleton-gen 基于 docs/04 § 零 技术栈推导目录树: @@ -13,7 +13,7 @@ skeleton-gen 基于 docs/04 § 零 技术栈推导目录树:
13 13
14 ## 一、仓库顶层 14 ## 一、仓库顶层
15 15
16 -<!-- 用代码块画出顶层目录树,含 CLAUDE.md / README.md / .env.local / .githooks / scripts / docs / sql / backend / frontend 等。 --> 16 +<!-- 用代码块画出顶层目录树,含 CLAUDE.md / README.md / .env.local / scripts / docs / sql / backend / frontend 等。 -->
17 17
18 ## 二、后端目录 18 ## 二、后端目录
19 19
skills/plan/skeleton-gen/templates/env-local-template
@@ -23,15 +23,3 @@ JWT_SECRET=【人工填写:JWT 签名密钥,256+ bit 随机串】 @@ -23,15 +23,3 @@ JWT_SECRET=【人工填写:JWT 签名密钥,256+ bit 随机串】
23 # 仅用于你完全可控的测试库;生产/共享库/多人共享的 staging 库**千万别列**。 23 # 仅用于你完全可控的测试库;生产/共享库/多人共享的 staging 库**千万别列**。
24 # (防护 2 还会检查 schema 名须含 test/_dev/_local/_ci,独立兜底。) 24 # (防护 2 还会检查 schema 名须含 test/_dev/_local/_ci,独立兜底。)
25 TEST_DB_ALLOWED_HOSTS= 25 TEST_DB_ALLOWED_HOSTS=
26 -  
27 -# GitLab REST API 接入(mr-create / coding-start / module-start 用 curl 调用,无需 glab CLI):  
28 -# - GITLAB_API_URL:GitLab API base。本项目服务器用 v3。A5 `downstream-gen` 从 `git remote get-url origin`  
29 -# 自动派生为 `<scheme>://<host>/api/v3`;如派生的 scheme 错(例如远程是 ssh 但实际 web 走 https),手动改掉即可  
30 -# - GITLAB_TOKEN:GitLab v3 的 **Private Token**(用户 Profile → Account → Private token 生成;HTTP 调用仍用  
31 -# `PRIVATE-TOKEN` 头。v3 token 是全权限、无细粒度 scope)。**无法派生,必须人工填**  
32 -# - GITLAB_PROJECT_ID:项目数字 ID(GitLab 项目设置 → General → 顶部 Project ID 字段,纯整数)。  
33 -# A5 `downstream-gen` 在 GITLAB_TOKEN 已填的前提下会调 API 自动解析数字 ID 写入;  
34 -# token 未填 / API 解析失败时留 TBD,请人工到设置页查到后填入  
35 -GITLAB_API_URL='TBD(A5 自动补)'  
36 -GITLAB_TOKEN=【人工填写:GitLab Private Token(Profile → Account → Private token)】  
37 -GITLAB_PROJECT_ID='TBD(A5 自动补)'  
skills/plan/skeleton-gen/templates/githooks-pre-push-template.sh deleted
1 -#!/usr/bin/env bash  
2 -# .githooks/pre-push — run scripts/test.sh before every push.  
3 -# No --no-verify: the claude-code hook deny-no-verify.sh also blocks it.  
4 -  
5 -set -euo pipefail  
6 -  
7 -cd "$(git rev-parse --show-toplevel)"  
8 -  
9 -./scripts/test.sh  
skills/plan/skeleton-gen/templates/scripts-test-template.sh
1 #!/usr/bin/env bash 1 #!/usr/bin/env bash
2 # scripts/test.sh —— 合并到默认分支(main / master)前的测试闸门。 2 # scripts/test.sh —— 合并到默认分支(main / master)前的测试闸门。
3 # 顺序:detect → setup-db → build → lint → unit+integration → e2e → reset-db 3 # 顺序:detect → setup-db → build → lint → unit+integration → e2e → reset-db
4 -# 由 .githooks/pre-push 和 test-gate skill(通过子会话)调用。 4 +# 由 test-gate skill(通过子会话)调用。
5 5
6 set -euo pipefail 6 set -euo pipefail
7 7