Commit 2f5b758dfe8c5874e9e43d911be538a5101d8668
1 parent
25afa9f0
README: sync with config consolidation, DB guard removal, REQ-card model, A1 aut…
…o-chain, docs/06+A6 removal
Showing
1 changed file
with
23 additions
and
32 deletions
README.md
| ... | ... | @@ -7,7 +7,7 @@ Claude Code 插件:ERP / 后端管理系统全流程开发框架。 |
| 7 | 7 | ## 这个插件做什么 |
| 8 | 8 | |
| 9 | 9 | ``` |
| 10 | -📋 阶段 A:规划(一次性,交互式;入口 /erp-workflow:plan-start 派发 A0~A6 共 7 个 skill) | |
| 10 | +📋 阶段 A:规划(一次性,交互式;入口 /erp-workflow:plan-start 派发 A0~A5 共 6 个 skill) | |
| 11 | 11 | |
| 12 | 12 | A0 project-init → A1 scope-lock(结构化 REQ 卡片 + secrets/commands 锁) |
| 13 | 13 | ↓ |
| ... | ... | @@ -19,10 +19,8 @@ Claude Code 插件:ERP / 后端管理系统全流程开发框架。 |
| 19 | 19 | ↓ |
| 20 | 20 | A4 db-init(docs/03 → V1 migration → 自动 apply 到本地 MySQL) |
| 21 | 21 | ↓ |
| 22 | - A5 downstream-gen(docs/02 / docs/05 / docs/06 § 三 / docs/10) | |
| 22 | + A5 downstream-gen(docs/02 / docs/05 / docs/10 / docs/08 § 三 FE 清单;prototype/ 门禁) | |
| 23 | 23 | ↓ ⛔ docs/05 + docs/02 评审闸(必须确认) |
| 24 | - A6 frontend-scope-lock(项目级 UI 约定 / design tokens / 组件库;prototype/ 门禁) | |
| 25 | - ↓ | |
| 26 | 24 | ⛔ Plan 终结硬闸(全部前移闸门通过才放行) |
| 27 | 25 | ↓ |
| 28 | 26 | 用户显式 /erp-workflow:coding-start |
| ... | ... | @@ -63,11 +61,10 @@ Claude Code 插件:ERP / 后端管理系统全流程开发框架。 |
| 63 | 61 | ``` |
| 64 | 62 | /erp-workflow:plan-start |
| 65 | 63 | ``` |
| 66 | - Plan 阶段**三段式**执行,中间有两个人工审阅断点: | |
| 64 | + Plan 阶段**两段式**执行,中间有一个人工审阅断点(docs/03 数据库 schema): | |
| 67 | 65 | |
| 68 | - - **第一段(首次运行)**:执行 **A0 → A1**(创建骨架 / 锁技术栈 / 填需求 / 生成 REQ 卡片骨架)后**停下**,等你审阅并补全 `docs/01-需求清单/<module>/REQ-*.md`(CC 已起草 req_id / title / goal / rules / constraints / acceptance;输入 / 输出 各含一句简述 + N 张示例字段表,模板原样复制由你按业务编辑;依赖表 / 依赖接口保留 `TBD(A3/A5 自动补)` 由后续 skill 回填——Plan 阶段第一个人工关口:业务范围) | |
| 69 | - - **第二段(REQ 审阅完重新运行)**:继续 **A2 → A3**(生成骨架 / 从 REQ 正向设计 `docs/03-数据库设计文档.md` 并回填 REQ 依赖表)后再次**停下**,等你审阅 docs/03 的表 / 字段 / 索引 / 外键(第二个人工关口:数据库 schema —— A4 会基于它翻译 DDL 并 apply 到 MySQL,所以这关口与 REQ 审阅同等重要) | |
| 70 | - - **第三段(docs/03 审阅完重新运行)**:执行 **A4 → A5 → A6**(解析 docs/03 → 生成 V1 migration → 自动 `DROP+CREATE` 本地 schema 并 apply → 生成下游文档 → **docs/05 + docs/02 评审闸** → A6 `frontend-scope-lock` 锁定项目级前端约定 / design tokens / 组件库 + prototype/ 门禁),通过 **Plan 终结硬闸** 后再次**停下** | |
| 66 | + - **第一段(首次运行)**:执行 **A0 → A1 → A2 → A3**(创建骨架 / 锁技术栈 / 填需求 / 生成 REQ 卡片 / 生成项目骨架 / 从 REQ 正向设计 `docs/03-数据库设计文档.md` 并回填 REQ 依赖表)后**停下**,等你审阅 docs/03 的表 / 字段 / 索引 / 外键(人工关口:数据库 schema —— A4 会基于它翻译 DDL 并 apply 到 MySQL)。A1 的 REQ 卡片由 CC 据 index.md 填 6 个占位、字段表按模板原样复制,**不再单独停下审阅** | |
| 67 | + - **第二段(docs/03 审阅完重新运行)**:执行 **A4 → A5**(解析 docs/03 → 生成 V1 migration → 自动 `DROP+CREATE` 本地 schema 并 apply → 生成下游文档 → **docs/05 + docs/02 评审闸** → prototype/ 门禁 + 推导 FE 清单写 docs/08 § 三),通过 **Plan 终结硬闸** 后再次**停下**(前端布局/交互以 `prototype/` 为权威,不另设 UI 规范文档) | |
| 71 | 68 | |
| 72 | 69 | Plan 完成后不会自动进入编码,需手动 /erp-workflow:coding-start。 |
| 73 | 70 | |
| ... | ... | @@ -90,22 +87,21 @@ erp-workflow-plugin/ |
| 90 | 87 | │ └── coding.mjs # 阶段 B:整个编码阶段编排为单个静默 Workflow |
| 91 | 88 | ├── lib/ # 跨平台 Node 助手(ESM,node:test 单测) |
| 92 | 89 | │ ├── merge-gitignore.mjs # .gitignore 逐行判重合并(替代 merge-gitignore.sh) |
| 93 | -│ ├── render.mjs # 字面量安全模板渲染(替代 render.sh) | |
| 94 | 90 | │ ├── validate-ddl.mjs # docs/03 ↔ DDL 5 维校验(替代 validate.sh) |
| 95 | -│ ├── apply-ddl.mjs # 安全 env 解析 + mysql apply(替代内联 mysql bash) | |
| 91 | +│ ├── yaml-config.mjs # config-vars.yaml 极简 YAML 读取(2 层 map + 标量) | |
| 92 | +│ ├── apply-ddl.mjs # 解析 config-vars.yaml database: 段 + mysql2 apply | |
| 96 | 93 | │ └── *.test.mjs # 各助手的 node:test 单测 |
| 97 | 94 | ├── agents/ |
| 98 | 95 | │ └── code-reviewer.md # 统一 reviewer(coding.mjs review stage 调用,phase 选维度集) |
| 99 | 96 | └── skills/ # 按阶段分组(slug 不变,由 SKILL.md frontmatter name 决定) |
| 100 | - ├── plan/ # 阶段 A:8 个 skill(入口 + A0~A6) | |
| 97 | + ├── plan/ # 阶段 A:7 个 skill(入口 + A0~A5) | |
| 101 | 98 | │ ├── plan-start/ # A 阶段入口 + Plan 终结硬闸 |
| 102 | 99 | │ ├── project-init/ # A0 |
| 103 | 100 | │ ├── scope-lock/ # A1 |
| 104 | 101 | │ ├── skeleton-gen/ # A2 |
| 105 | 102 | │ ├── db-design-gen/ # A3 |
| 106 | 103 | │ ├── db-init/ # A4 |
| 107 | - │ ├── downstream-gen/ # A5 | |
| 108 | - │ └── frontend-scope-lock/ # A6 | |
| 104 | + │ └── downstream-gen/ # A5(含前端 FE 清单推导,原 A6 已并入) | |
| 109 | 105 | └── coding/ # 阶段 B:1 个 skill(瘦入口) |
| 110 | 106 | └── coding-start/ # 启动 workflows/coding.mjs |
| 111 | 107 | ``` |
| ... | ... | @@ -116,20 +112,19 @@ erp-workflow-plugin/ |
| 116 | 112 | |
| 117 | 113 | | Skill | 作用 | 谁调用 | |
| 118 | 114 | |---|---|---| |
| 119 | -| `plan-start` | **A 阶段入口 + Plan 终结硬闸**。读 docs/08 § 一 找第一个未勾 A 子项 → 派发对应 A skill(含 A6 → `frontend-scope-lock`);A 全部完成时校验 5 项前移闸门(REQ 真实数据、`.env.local` secrets 全锁 + `config-vars.yaml` 配置字段全锁、docs/04 § 零 命令齐、docs/05+02 已评审、A6 前端 scope 已锁),全过才提示运行 `/erp-workflow:coding-start`,否则指出缺口不放行 | **用户手动** `/erp-workflow:plan-start` | | |
| 115 | +| `plan-start` | **A 阶段入口 + Plan 终结硬闸**。读 docs/08 § 一 找第一个未勾 A 子项 → 派发对应 A skill;A 全部完成时校验 4 项前移闸门(REQ 真实数据、`config-vars.yaml` 全部配置(含 DB 凭据 / 密钥)全锁、docs/04 § 零 命令齐、docs/05+02 已评审),全过才提示运行 `/erp-workflow:coding-start`,否则指出缺口不放行 | **用户手动** `/erp-workflow:plan-start` | | |
| 120 | 116 | | `coding-start` | **B 阶段瘦入口**(`allowed-tools: Read Glob Workflow Bash(git ...) Bash(pwd)`)。校验 Plan 终结闸(docs/08 § 一 全勾、git 在默认分支、工作树干净)→ 读 docs/08 § 二/§ 三 + `git tag -l 'milestone/*'` 概述阶段进度(Workflow Router 再用 `req-done/*` 判定功能级 resume)→ 调用 `Workflow({scriptPath:"${CLAUDE_PLUGIN_ROOT}/workflows/coding.mjs", args:{projectRoot}})` 启动整个编码阶段 → 告知"已在后台启动" | **用户手动** `/erp-workflow:coding-start` | |
| 121 | 117 | |
| 122 | -### Plan 阶段 A skill(A0~A6,共 7 个) | |
| 118 | +### Plan 阶段 A skill(A0~A5,共 6 个) | |
| 123 | 119 | |
| 124 | 120 | | # | Skill | 作用 | 流程中谁调用 | |
| 125 | 121 | |---|---|---|---| |
| 126 | 122 | | A0 | `project-init` | • **依赖检查**:检测 git / mysql / node 是否在 PATH,缺失则按 OS(darwin/win32/linux)打印安装指引并 halt(**不自动 brew/apt 安装**)<br>• 空目录初始化:用 Read/Write/Glob 工具拷模板创建 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 卡片(每字段一行:字段名/类型/必填/校验/业务规则/示例值,示例值必须替换为真实约束)<br>• **A1 终结校验**:REQ 字段非空且非占位、`config-vars.yaml` 配置字段(包名 / 端口 / 初始账号等)+ `secrets_ref` 键名(引用 `.env.local`)已锁、各 stack 的 build/lint/unit/e2e 命令写入 docs/04 § 零;缺失则在此(Plan 期)用 `AskUserQuestion` 问清<br>• 用 `node ${CLAUDE_PLUGIN_ROOT}/lib/render.mjs` 渲染模板<br>• **停下**等人工审阅,审阅完毕用 `/plan-start` 续进 A2 | A0 | | |
| 128 | -| A2 | `skeleton-gen` | • 生成架构文档:docs/04 § 一+ / docs/06 / docs/07 / docs/09<br>• 生成跨平台工具脚本:`scripts/*.mjs`、.env.local(**无 chmod**)<br>• 创建 `sql/migrations/` 空目录(Flyway 准备)<br>• 用 `node ${CLAUDE_PLUGIN_ROOT}/lib/merge-gitignore.mjs` 合并 .gitignore(逐行判重) | `plan-start` | | |
| 123 | +| A1 | `scope-lock` | • 引导填项目概述 / 技术栈 / 需求索引<br>• 按 `docs/01-需求清单/<module>/{_module.md, REQ-*.md}` 子目录结构生成 REQ 卡片(CC 据 index.md 填 `{{req_id/title/goal/rules/constraints/acceptance}}` 6 个占位,模板其余内容含输入/输出示例字段表原样复制)<br>• **A1 终结校验**:REQ 6 个占位均填真实数据、无 `{{` 残留、`config-vars.yaml` **全部配置**(包名 / 端口 / 初始账号 + DB 凭据 / 密钥占位)已锁、各 stack 的 build/lint/unit/e2e 命令写入 docs/04 § 零;缺失则在此(Plan 期)用 `AskUserQuestion` 问清(敏感凭据由用户自填,不进会话)<br>• 据模板直接 `Write` 生成 `_module.md` / `REQ-*.md`<br>• 终结校验通过后**自动**调用 `Skill(skeleton-gen)` 进入 A2(不停下) | A0 | | |
| 124 | +| A2 | `skeleton-gen` | • 生成架构文档:docs/04 § 一+ / docs/07 / docs/09<br>• 生成跨平台工具脚本:`scripts/*.mjs`(**无 chmod**;凭据 / 配置统一在 A1 产出的 config-vars.yaml)<br>• 创建 `sql/migrations/` 空目录(Flyway 准备)<br>• 用 `node ${CLAUDE_PLUGIN_ROOT}/lib/merge-gitignore.mjs` 合并 .gitignore(逐行判重) | `plan-start` | | |
| 129 | 125 | | A3 | `db-design-gen` | • A3 起始用 `AskUserQuestion` 确认 ERP 约定(主键策略 / 租户列 / 列前缀规则,默认值可覆盖),结果写 docs/04 + CLAUDE.md<br>• 从 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>• `node ${CLAUDE_PLUGIN_ROOT}/lib/validate-ddl.mjs` 校验 DDL ↔ docs/03(5 维:表/列名/列类型/索引/FK),fail-closed<br>• `node ${CLAUDE_PLUGIN_ROOT}/lib/apply-ddl.mjs .env.local V1.sql`(安全 env 解析 + mysql2 apply,**无 shell-source**) | A3 | | |
| 131 | -| A5 | `downstream-gen` | • 一次性生成 docs/02 / docs/05 / docs/06 § 三 / docs/10<br>• 回填 REQ 卡片依赖接口(`TBD(A5 自动补)` → 实际 endpoint)<br>• 追加模块清单到 docs/08 § 二<br>• **docs/05 + docs/02 评审闸**:用 `AskUserQuestion` 让用户确认 API 端点/字段无误 + 构建顺序可接受,未确认不勾 A5<br>• 最终占位符 + 结构残留扫描 | A4 | | |
| 132 | -| A6 | `frontend-scope-lock` | • `user-invocable:false`,由 plan-start 在 A5 后派发<br>• **prototype/ 门禁**:项目根 `prototype/*.html` 缺失则 `AskUserQuestion` 要求补齐(Plan 期可问)<br>• 从 prototype + docs/01 + docs/05/06 提炼项目级 UI 约定 / design tokens / 组件库选型,逐一 `AskUserQuestion` 确认<br>• 写入 docs/06(UI 交互规范)+ docs/04(前端栈) | `plan-start` | | |
| 126 | +| A4 | `db-init` | • LLM 解析 docs/03 → `sql/migrations/V1__initial_schema.sql`(DDL only)<br>• `node ${CLAUDE_PLUGIN_ROOT}/lib/validate-ddl.mjs` 校验 DDL ↔ docs/03(5 维:表/列名/列类型/索引/FK),fail-closed<br>• `node ${CLAUDE_PLUGIN_ROOT}/lib/apply-ddl.mjs config-vars.yaml V1.sql`(解析 config-vars.yaml database: 段 + mysql2 apply,**无 shell-source**) | A3 | | |
| 127 | +| A5 | `downstream-gen` | • 一次性生成 docs/02 / docs/05 / docs/10<br>• 回填 REQ 卡片依赖接口(`TBD(A5 自动补)` → 实际 endpoint)<br>• 追加模块清单到 docs/08 § 二<br>• **docs/05 + docs/02 评审闸**:用 `AskUserQuestion` 让用户确认 API 端点/字段无误 + 构建顺序可接受,未确认不勾 A5<br>• **prototype/ 门禁 + 推导 FE 清单写 docs/08 § 三**(原 A6 已并入;无 prototype 则问「无前端」→ § 三 留空)<br>• 最终占位符 + 结构残留扫描 | A4 | | |
| 133 | 128 | |
| 134 | 129 | ### Coding 阶段(1 个 Workflow,非 skill) |
| 135 | 130 | |
| ... | ... | @@ -148,34 +143,30 @@ erp-workflow-plugin/ |
| 148 | 143 | | project-init | `CLAUDE-template.md` | 项目根的 CLAUDE.md(4 条通用准则 + ERP 专属约定) | |
| 149 | 144 | | project-init | `docs-01-index-template.md` | 需求清单索引骨架,等用户填模块表 | |
| 150 | 145 | | project-init | `docs-04-stack-template.md` | docs/04 § 零 默认技术栈总览(零槽位,拷即可) | |
| 151 | -| project-init | `docs-08-initial-template.md` | 工作流进度文件骨架(Plan A0~A6 checkbox) | | |
| 152 | -| scope-lock | `req-card-template.md` | 单张 REQ-XXX-NNN 卡片骨架(结构化字段表:字段名/类型/必填/校验/业务规则/示例值,示例值须替换为真实约束) | | |
| 146 | +| project-init | `docs-08-initial-template.md` | 工作流进度文件骨架(Plan A0~A5 checkbox) | | |
| 147 | +| scope-lock | `req-card-template.md` | 单张 REQ-XXX-NNN 卡片模板(`{{req_id/title/goal/rules/constraints/acceptance}}` 占位 + 输入/输出示例字段表;A1 原样复制,只填这 6 个占位) | | |
| 153 | 148 | | scope-lock | `_module-template.md` | 模块子目录的 `_module.md` 模块头(模块代码-名 / 简述 / 依赖模块 TBD / 涉及表 TBD) | |
| 154 | -| scope-lock | `config-vars-template.yaml` | 仓库根 `config-vars.yaml` 骨架(跨栈中立):非敏感项目级配置(包名/端口/前端包名/初始账号)+ `secrets_ref` 键名引用 `.env.local`;A1 E.2 锁定 | | |
| 149 | +| scope-lock | `config-vars-template.yaml` | 仓库根 `config-vars.yaml` 骨架(跨栈中立):项目**全部配置**——非敏感(包名/端口/前端包名/初始账号)+ 敏感凭据(database / admin_init.password / secrets);A1 E.2 锁定,随项目提交 | | |
| 155 | 150 | | skeleton-gen | `docs-04-skeleton-template.md` | docs/04 § 一+ 编码规范大纲(HTML 注释引导 LLM) | |
| 156 | -| skeleton-gen | `docs-06-static-template.md` | docs/06 § 一~二 大纲(通用交互 + Design Tokens;布局以 prototype/ 为权威) | | |
| 157 | -| skeleton-gen | `docs-07-env-template.md` | docs/07 环境配置大纲(只记规则/约定,不记具体值;配置值指向 config-vars.yaml + .env.local) | | |
| 151 | +| skeleton-gen | `docs-07-env-template.md` | docs/07 环境配置大纲(只记规则/约定,不记具体值;配置值统一指向 config-vars.yaml) | | |
| 158 | 152 | | skeleton-gen | `docs-09-structure-template.md` | docs/09 目录结构大纲 | |
| 159 | -| skeleton-gen | `scripts-setup-test-db-template.mjs` | 跨平台 drop + create 空库脚本(安全 env 解析,无 shell-source);schema apply 交给 Flyway | | |
| 153 | +| skeleton-gen | `scripts-setup-test-db-template.mjs` | 跨平台 drop + create 空库脚本(内联极简 YAML 读 config-vars.yaml database: 段,无 shell-source);schema apply 交给 Flyway | | |
| 160 | 154 | | skeleton-gen | `scripts-test-template.mjs` | test.mjs 骨架(命令槽位按后端/前端/build/lint/test/e2e 分开,`spawnSync(shell:true)` 跨平台执行) | |
| 161 | -| skeleton-gen | `env-local-template` | 凭据模板(DB_* + JWT_SECRET);A2 据 config-vars.yaml `secrets_ref` 追加项目专属 secret 键 | | |
| 162 | -| skeleton-gen | `gitignore-append-template` | 插件推荐忽略项(`.env.local`、`.tmp/`、构建产物等) | | |
| 155 | +| skeleton-gen | `gitignore-append-template` | 插件推荐忽略项(`.tmp/`、构建产物等;config-vars.yaml 随项目提交,不忽略) | | |
| 163 | 156 | | skeleton-gen | `styles-tokens-template.css` | 前端 design tokens CSS 变量骨架 | |
| 164 | 157 | | db-design-gen | `docs-03-header-template.md` | docs/03 数据库设计头部 | |
| 165 | 158 | | db-design-gen | `docs-03-table-template.md` | docs/03 单表小节模板 | |
| 166 | 159 | | downstream-gen | `docs-02-template.md` | docs/02 开发计划 | |
| 167 | 160 | | downstream-gen | `docs-05-header-template.md` | docs/05 API 契约头部 | |
| 168 | 161 | | downstream-gen | `docs-05-endpoint-template.md` | docs/05 单接口小节 | |
| 169 | -| downstream-gen | `docs-06-module-pagelist-template.md` | docs/06 § 三 单模块页面清单 | | |
| 170 | 162 | | downstream-gen | `docs-08-module-row-template.md` | docs/08 § 二 单模块 bullet 行 | |
| 171 | 163 | | downstream-gen | `docs-10-header-template.md` | docs/10 验收清单(项目级 SOP,零槽位 + 引用指针) | |
| 172 | -| frontend-scope-lock | `fe-scope-template.md` | A6 前端 scope:UI 约定 / design tokens / 组件库 / 每个 FE-NN 设计决策表 | | |
| 173 | 164 | |
| 174 | 165 | ## 前置依赖 |
| 175 | 166 | |
| 176 | 167 | - **Node.js ≥ 18**:`lib/*.mjs` 助手 + 生成进目标项目的 `scripts/*.mjs` 为 Node ESM;`workflows/coding.mjs` 是 Claude Workflow 运行时脚本(由 `Workflow` 工具执行,不作为普通 `node` CLI 入口)。A0 `project-init` 检测 git / mysql / node 在 PATH,缺失则按 OS 打印安装指引并 halt(不自动安装) |
| 177 | -- **MySQL 8.x** 实例已就绪(推荐本地 / `*.local` host;A4 `db-init` 的安全守护要求 host 在白名单且 schema 名含 `test` 或以 `_dev` / `_local` / `_ci` 结尾,避免误删生产库) | |
| 178 | -- **`mysql2`(目标项目侧)**:A4 `db-init` 经 `lib/apply-ddl.mjs` 用 mysql2 连接 + 安全 env 解析 apply V1;`apply-ddl.mjs` 与生成的 `scripts/setup-test-db.mjs` 都会校验 host 白名单 + schema 名测试库特征,生成的 `scripts/setup-test-db.mjs` 在测试闸门前后 drop+create 空库 | |
| 168 | +- **MySQL 8.x** 实例已就绪(host / 库名 / 凭据取自 `config-vars.yaml` 的 `database:` 段,由你填写并完全信任——`setup-test-db.mjs` 会按该值无条件 DROP+CREATE,请确保 schema 指向测试库而非生产库) | |
| 169 | +- **`mysql2`(目标项目侧)**:A4 `db-init` 经 `lib/apply-ddl.mjs` 用 mysql2 连接 + 解析 config-vars.yaml `database:` 段 apply V1;生成的 `scripts/setup-test-db.mjs` 在测试闸门前后 drop+create 空库 | |
| 179 | 170 | - **Spring Boot + Flyway**(**必需**):pom.xml 声明 `flyway-core` + `flyway-mysql`;Spring 启动时自动 apply `sql/migrations/V*.sql`。本插件生成的 `setup-test-db.mjs` 只清库,schema 必须由 Flyway 应用 |
| 180 | 171 | - **本地 git 仓库**(纯本地,无需远程):A0 `project-init` 执行 `git init`;B 阶段每模块由 `coding.mjs` 的 milestone stage 本地 `git merge --no-ff` 进默认分支并 `git tag -a milestone/<id>`,完成信号由 `git tag -l` 判定。**不依赖任何远程仓库 / push / GitLab** |
| 181 | 172 | - **本地可运行 `mvn test` / `pnpm test`**:测试命令由 A1 写入 docs/04 § 零,生成的 `scripts/test.mjs` 由 `skeleton-gen` 产出,`coding.mjs` 的 testGate stage 调用 | ... | ... |