From 4706a8d99679b299d7827109ea3ac090f6669d5f Mon Sep 17 00:00:00 2001 From: zichun Date: Fri, 24 Apr 2026 18:06:14 +0800 Subject: [PATCH] refactor(plugin): 标准化 skill 命名 + 精简 A 阶段流程 + 统一术语 --- README.md | 261 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------------------------------------------------------------------------------------------------------- hooks/scripts/deny-no-verify.sh | 2 +- hooks/scripts/log-cross-module.sh | 4 ++-- skills/coding/erp-feature-brainstorm/SKILL.md | 39 --------------------------------------- skills/coding/erp-feature-brainstorm/templates/feature-spec-template.md | 31 ------------------------------- skills/coding/erp-feature-plan/SKILL.md | 34 ---------------------------------- skills/coding/erp-feature-plan/templates/feature-plan-template.md | 28 ---------------------------- skills/coding/erp-feature-review/SKILL.md | 41 ----------------------------------------- skills/coding/erp-feature-review/templates/feature-review-template.md | 24 ------------------------ skills/coding/erp-feature-tdd/SKILL.md | 45 --------------------------------------------- skills/coding/erp-feature-tdd/templates/commit-message-template.md | 1 - skills/coding/erp-feature-verify/SKILL.md | 40 ---------------------------------------- skills/coding/erp-feature-verify/templates/feature-verify-evidence-template.md | 16 ---------------- skills/coding/erp-local-test-gate/SKILL.md | 79 ------------------------------------------------------------------------------- skills/coding/erp-local-test-gate/templates/test-gate-result-template.md | 16 ---------------- skills/coding/erp-module-report/SKILL.md | 54 ------------------------------------------------------ skills/coding/erp-module-report/templates/module-report-template.md | 67 ------------------------------------------------------------------- skills/coding/erp-module-start/SKILL.md | 85 ------------------------------------------------------------------------------------- skills/coding/erp-module-start/templates/cross-module-log-template.md | 8 -------- skills/coding/erp-module-start/templates/module-start-banner-template.md | 11 ----------- skills/coding/erp-mr-create/SKILL.md | 183 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- skills/coding/erp-mr-create/templates/mr-description-template.md | 18 ------------------ skills/coding/erp-mr-create/templates/mr-title-template.md | 1 - skills/coding/feature-brainstorm/SKILL.md | 39 +++++++++++++++++++++++++++++++++++++++ skills/coding/feature-brainstorm/templates/feature-spec-template.md | 31 +++++++++++++++++++++++++++++++ skills/coding/feature-plan/SKILL.md | 34 ++++++++++++++++++++++++++++++++++ skills/coding/feature-plan/templates/feature-plan-template.md | 28 ++++++++++++++++++++++++++++ skills/coding/feature-review/SKILL.md | 41 +++++++++++++++++++++++++++++++++++++++++ skills/coding/feature-review/templates/feature-review-template.md | 24 ++++++++++++++++++++++++ skills/coding/feature-tdd/SKILL.md | 47 +++++++++++++++++++++++++++++++++++++++++++++++ skills/coding/feature-tdd/templates/commit-message-template.md | 1 + skills/coding/feature-verify/SKILL.md | 40 ++++++++++++++++++++++++++++++++++++++++ skills/coding/feature-verify/templates/feature-verify-evidence-template.md | 16 ++++++++++++++++ skills/coding/module-report/SKILL.md | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ skills/coding/module-report/templates/module-report-template.md | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ skills/coding/module-start/SKILL.md | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ skills/coding/module-start/templates/cross-module-log-template.md | 8 ++++++++ skills/coding/module-start/templates/module-start-banner-template.md | 11 +++++++++++ skills/coding/mr-create/SKILL.md | 183 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ skills/coding/mr-create/templates/mr-description-template.md | 18 ++++++++++++++++++ skills/coding/mr-create/templates/mr-title-template.md | 1 + skills/coding/test-gate/SKILL.md | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ skills/coding/test-gate/templates/test-gate-result-template.md | 16 ++++++++++++++++ skills/crosscut/coding-start/SKILL.md | 168 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ skills/crosscut/cross-module-log/SKILL.md | 37 +++++++++++++++++++++++++++++++++++++ skills/crosscut/cross-module-log/templates/cross-module-log-row-template.md | 1 + skills/crosscut/cross-module-log/templates/cross-module-log-template.md | 8 ++++++++ skills/crosscut/erp-coding-start/SKILL.md | 166 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- skills/crosscut/erp-cross-module-log/SKILL.md | 37 ------------------------------------- skills/crosscut/erp-cross-module-log/templates/cross-module-log-row-template.md | 1 - skills/crosscut/erp-cross-module-log/templates/cross-module-log-template.md | 8 -------- skills/crosscut/erp-plan-start/SKILL.md | 103 ------------------------------------------------------------------------------------------------------- skills/crosscut/erp-red-flag-check/SKILL.md | 49 ------------------------------------------------- skills/crosscut/erp-red-flag-check/templates/red-flag-block-template.md | 8 -------- skills/crosscut/interrupt-check/SKILL.md | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ skills/crosscut/interrupt-check/templates/interrupt-block-template.md | 8 ++++++++ skills/crosscut/plan-start/SKILL.md | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ skills/internal/superpower-writing-plans/SKILL.md | 6 +++--- skills/plan/db-design-gen/SKILL.md | 128 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ skills/plan/db-design-gen/templates/docs-03-header-template.md | 14 ++++++++++++++ skills/plan/db-design-gen/templates/docs-03-table-template.md | 22 ++++++++++++++++++++++ skills/plan/db-init/SKILL.md | 207 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ skills/plan/db-init/templates/migration-v1-header-template.sql | 8 ++++++++ skills/plan/downstream-gen/SKILL.md | 235 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ skills/plan/downstream-gen/templates/docs-02-template.md | 24 ++++++++++++++++++++++++ skills/plan/downstream-gen/templates/docs-05-endpoint-template.md | 24 ++++++++++++++++++++++++ skills/plan/downstream-gen/templates/docs-05-header-template.md | 30 ++++++++++++++++++++++++++++++ skills/plan/downstream-gen/templates/docs-06-module-pagelist-template.md | 9 +++++++++ skills/plan/downstream-gen/templates/docs-08-module-row-template.md | 6 ++++++ skills/plan/downstream-gen/templates/docs-10-header-template.md | 14 ++++++++++++++ skills/plan/downstream-gen/templates/docs-10-module-template.md | 18 ++++++++++++++++++ skills/plan/erp-db-design-gen/SKILL.md | 110 -------------------------------------------------------------------------------------------------------------- skills/plan/erp-db-design-gen/templates/docs-03-header-template.md | 14 -------------- skills/plan/erp-db-design-gen/templates/docs-03-table-template.md | 22 ---------------------- skills/plan/erp-db-init/SKILL.md | 163 ------------------------------------------------------------------------------------------------------------------------------------------------------------------- skills/plan/erp-db-init/templates/migration-v1-header-template.sql | 8 -------- skills/plan/erp-db-init/templates/seed-data-sql-template.sql | 10 ---------- skills/plan/erp-downstream-gen/SKILL.md | 228 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ skills/plan/erp-downstream-gen/templates/docs-02-template.md | 24 ------------------------ skills/plan/erp-downstream-gen/templates/docs-05-endpoint-template.md | 24 ------------------------ skills/plan/erp-downstream-gen/templates/docs-05-header-template.md | 30 ------------------------------ skills/plan/erp-downstream-gen/templates/docs-06-module-pagelist-template.md | 9 --------- skills/plan/erp-downstream-gen/templates/docs-08-module-row-template.md | 4 ---- skills/plan/erp-downstream-gen/templates/docs-10-header-template.md | 14 -------------- skills/plan/erp-downstream-gen/templates/docs-10-module-template.md | 18 ------------------ skills/plan/erp-project-init/SKILL.md | 94 ---------------------------------------------------------------------------------------------- skills/plan/erp-project-init/templates/CLAUDE-template.md | 347 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- skills/plan/erp-project-init/templates/docs-01-readme-template.md | 16 ---------------- skills/plan/erp-project-init/templates/docs-08-initial-template.md | 51 --------------------------------------------------- skills/plan/erp-scope-lock/SKILL.md | 234 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ skills/plan/erp-scope-lock/templates/docs-01-module-template.md | 11 ----------- skills/plan/erp-scope-lock/templates/req-card-template.md | 10 ---------- skills/plan/erp-skeleton-gen/SKILL.md | 304 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- skills/plan/erp-skeleton-gen/scripts/merge-gitignore.sh | 39 --------------------------------------- skills/plan/erp-skeleton-gen/templates/docs-04-skeleton-template.md | 50 -------------------------------------------------- skills/plan/erp-skeleton-gen/templates/docs-06-static-template.md | 47 ----------------------------------------------- skills/plan/erp-skeleton-gen/templates/docs-07-env-template.md | 26 -------------------------- skills/plan/erp-skeleton-gen/templates/docs-09-structure-template.md | 45 --------------------------------------------- skills/plan/erp-skeleton-gen/templates/env-local-template | 36 ------------------------------------ skills/plan/erp-skeleton-gen/templates/githooks-pre-push-template.sh | 9 --------- skills/plan/erp-skeleton-gen/templates/gitignore-append-template | 32 -------------------------------- skills/plan/erp-skeleton-gen/templates/scripts-setup-test-db-template.sh | 65 ----------------------------------------------------------------- skills/plan/project-init/SKILL.md | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ skills/plan/project-init/templates/CLAUDE-template.md | 218 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ skills/plan/project-init/templates/docs-01-index-template.md | 16 ++++++++++++++++ skills/plan/project-init/templates/docs-04-stack-template.md | 32 ++++++++++++++++++++++++++++++++ skills/plan/project-init/templates/docs-08-initial-template.md | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ skills/plan/scope-lock/SKILL.md | 157 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ skills/plan/scope-lock/templates/docs-01-module-template.md | 11 +++++++++++ skills/plan/scope-lock/templates/req-card-template.md | 29 +++++++++++++++++++++++++++++ skills/plan/skeleton-gen/SKILL.md | 166 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ skills/plan/skeleton-gen/scripts/merge-gitignore.sh | 39 +++++++++++++++++++++++++++++++++++++++ skills/plan/skeleton-gen/templates/docs-04-skeleton-template.md | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ skills/plan/skeleton-gen/templates/docs-06-static-template.md | 47 +++++++++++++++++++++++++++++++++++++++++++++++ skills/plan/skeleton-gen/templates/docs-07-env-template.md | 26 ++++++++++++++++++++++++++ skills/plan/skeleton-gen/templates/docs-09-structure-template.md | 45 +++++++++++++++++++++++++++++++++++++++++++++ skills/plan/skeleton-gen/templates/env-local-template | 36 ++++++++++++++++++++++++++++++++++++ skills/plan/skeleton-gen/templates/githooks-pre-push-template.sh | 9 +++++++++ skills/plan/skeleton-gen/templates/gitignore-append-template | 32 ++++++++++++++++++++++++++++++++ skills/plan/skeleton-gen/templates/scripts-setup-test-db-template.sh | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ skills/plan/skeleton-gen/templates/scripts-test-template.sh | 29 +++++++++++++++++++++++++++++ 121 files changed, 3229 insertions(+), 3418 deletions(-) delete mode 100644 skills/coding/erp-feature-brainstorm/SKILL.md delete mode 100644 skills/coding/erp-feature-brainstorm/templates/feature-spec-template.md delete mode 100644 skills/coding/erp-feature-plan/SKILL.md delete mode 100644 skills/coding/erp-feature-plan/templates/feature-plan-template.md delete mode 100644 skills/coding/erp-feature-review/SKILL.md delete mode 100644 skills/coding/erp-feature-review/templates/feature-review-template.md delete mode 100644 skills/coding/erp-feature-tdd/SKILL.md delete mode 100644 skills/coding/erp-feature-tdd/templates/commit-message-template.md delete mode 100644 skills/coding/erp-feature-verify/SKILL.md delete mode 100644 skills/coding/erp-feature-verify/templates/feature-verify-evidence-template.md delete mode 100644 skills/coding/erp-local-test-gate/SKILL.md delete mode 100644 skills/coding/erp-local-test-gate/templates/test-gate-result-template.md delete mode 100644 skills/coding/erp-module-report/SKILL.md delete mode 100644 skills/coding/erp-module-report/templates/module-report-template.md delete mode 100644 skills/coding/erp-module-start/SKILL.md delete mode 100644 skills/coding/erp-module-start/templates/cross-module-log-template.md delete mode 100644 skills/coding/erp-module-start/templates/module-start-banner-template.md delete mode 100644 skills/coding/erp-mr-create/SKILL.md delete mode 100644 skills/coding/erp-mr-create/templates/mr-description-template.md delete mode 100644 skills/coding/erp-mr-create/templates/mr-title-template.md create mode 100644 skills/coding/feature-brainstorm/SKILL.md create mode 100644 skills/coding/feature-brainstorm/templates/feature-spec-template.md create mode 100644 skills/coding/feature-plan/SKILL.md create mode 100644 skills/coding/feature-plan/templates/feature-plan-template.md create mode 100644 skills/coding/feature-review/SKILL.md create mode 100644 skills/coding/feature-review/templates/feature-review-template.md create mode 100644 skills/coding/feature-tdd/SKILL.md create mode 100644 skills/coding/feature-tdd/templates/commit-message-template.md create mode 100644 skills/coding/feature-verify/SKILL.md create mode 100644 skills/coding/feature-verify/templates/feature-verify-evidence-template.md create mode 100644 skills/coding/module-report/SKILL.md create mode 100644 skills/coding/module-report/templates/module-report-template.md create mode 100644 skills/coding/module-start/SKILL.md create mode 100644 skills/coding/module-start/templates/cross-module-log-template.md create mode 100644 skills/coding/module-start/templates/module-start-banner-template.md create mode 100644 skills/coding/mr-create/SKILL.md create mode 100644 skills/coding/mr-create/templates/mr-description-template.md create mode 100644 skills/coding/mr-create/templates/mr-title-template.md create mode 100644 skills/coding/test-gate/SKILL.md create mode 100644 skills/coding/test-gate/templates/test-gate-result-template.md create mode 100644 skills/crosscut/coding-start/SKILL.md create mode 100644 skills/crosscut/cross-module-log/SKILL.md create mode 100644 skills/crosscut/cross-module-log/templates/cross-module-log-row-template.md create mode 100644 skills/crosscut/cross-module-log/templates/cross-module-log-template.md delete mode 100644 skills/crosscut/erp-coding-start/SKILL.md delete mode 100644 skills/crosscut/erp-cross-module-log/SKILL.md delete mode 100644 skills/crosscut/erp-cross-module-log/templates/cross-module-log-row-template.md delete mode 100644 skills/crosscut/erp-cross-module-log/templates/cross-module-log-template.md delete mode 100644 skills/crosscut/erp-plan-start/SKILL.md delete mode 100644 skills/crosscut/erp-red-flag-check/SKILL.md delete mode 100644 skills/crosscut/erp-red-flag-check/templates/red-flag-block-template.md create mode 100644 skills/crosscut/interrupt-check/SKILL.md create mode 100644 skills/crosscut/interrupt-check/templates/interrupt-block-template.md create mode 100644 skills/crosscut/plan-start/SKILL.md create mode 100644 skills/plan/db-design-gen/SKILL.md create mode 100644 skills/plan/db-design-gen/templates/docs-03-header-template.md create mode 100644 skills/plan/db-design-gen/templates/docs-03-table-template.md create mode 100644 skills/plan/db-init/SKILL.md create mode 100644 skills/plan/db-init/templates/migration-v1-header-template.sql create mode 100644 skills/plan/downstream-gen/SKILL.md create mode 100644 skills/plan/downstream-gen/templates/docs-02-template.md create mode 100644 skills/plan/downstream-gen/templates/docs-05-endpoint-template.md create mode 100644 skills/plan/downstream-gen/templates/docs-05-header-template.md create mode 100644 skills/plan/downstream-gen/templates/docs-06-module-pagelist-template.md create mode 100644 skills/plan/downstream-gen/templates/docs-08-module-row-template.md create mode 100644 skills/plan/downstream-gen/templates/docs-10-header-template.md create mode 100644 skills/plan/downstream-gen/templates/docs-10-module-template.md delete mode 100644 skills/plan/erp-db-design-gen/SKILL.md delete mode 100644 skills/plan/erp-db-design-gen/templates/docs-03-header-template.md delete mode 100644 skills/plan/erp-db-design-gen/templates/docs-03-table-template.md delete mode 100644 skills/plan/erp-db-init/SKILL.md delete mode 100644 skills/plan/erp-db-init/templates/migration-v1-header-template.sql delete mode 100644 skills/plan/erp-db-init/templates/seed-data-sql-template.sql delete mode 100644 skills/plan/erp-downstream-gen/SKILL.md delete mode 100644 skills/plan/erp-downstream-gen/templates/docs-02-template.md delete mode 100644 skills/plan/erp-downstream-gen/templates/docs-05-endpoint-template.md delete mode 100644 skills/plan/erp-downstream-gen/templates/docs-05-header-template.md delete mode 100644 skills/plan/erp-downstream-gen/templates/docs-06-module-pagelist-template.md delete mode 100644 skills/plan/erp-downstream-gen/templates/docs-08-module-row-template.md delete mode 100644 skills/plan/erp-downstream-gen/templates/docs-10-header-template.md delete mode 100644 skills/plan/erp-downstream-gen/templates/docs-10-module-template.md delete mode 100644 skills/plan/erp-project-init/SKILL.md delete mode 100644 skills/plan/erp-project-init/templates/CLAUDE-template.md delete mode 100644 skills/plan/erp-project-init/templates/docs-01-readme-template.md delete mode 100644 skills/plan/erp-project-init/templates/docs-08-initial-template.md delete mode 100644 skills/plan/erp-scope-lock/SKILL.md delete mode 100644 skills/plan/erp-scope-lock/templates/docs-01-module-template.md delete mode 100644 skills/plan/erp-scope-lock/templates/req-card-template.md delete mode 100644 skills/plan/erp-skeleton-gen/SKILL.md delete mode 100755 skills/plan/erp-skeleton-gen/scripts/merge-gitignore.sh delete mode 100644 skills/plan/erp-skeleton-gen/templates/docs-04-skeleton-template.md delete mode 100644 skills/plan/erp-skeleton-gen/templates/docs-06-static-template.md delete mode 100644 skills/plan/erp-skeleton-gen/templates/docs-07-env-template.md delete mode 100644 skills/plan/erp-skeleton-gen/templates/docs-09-structure-template.md delete mode 100644 skills/plan/erp-skeleton-gen/templates/env-local-template delete mode 100644 skills/plan/erp-skeleton-gen/templates/githooks-pre-push-template.sh delete mode 100644 skills/plan/erp-skeleton-gen/templates/gitignore-append-template delete mode 100644 skills/plan/erp-skeleton-gen/templates/scripts-setup-test-db-template.sh create mode 100644 skills/plan/project-init/SKILL.md create mode 100644 skills/plan/project-init/templates/CLAUDE-template.md create mode 100644 skills/plan/project-init/templates/docs-01-index-template.md create mode 100644 skills/plan/project-init/templates/docs-04-stack-template.md create mode 100644 skills/plan/project-init/templates/docs-08-initial-template.md create mode 100644 skills/plan/scope-lock/SKILL.md create mode 100644 skills/plan/scope-lock/templates/docs-01-module-template.md create mode 100644 skills/plan/scope-lock/templates/req-card-template.md create mode 100644 skills/plan/skeleton-gen/SKILL.md create mode 100755 skills/plan/skeleton-gen/scripts/merge-gitignore.sh create mode 100644 skills/plan/skeleton-gen/templates/docs-04-skeleton-template.md create mode 100644 skills/plan/skeleton-gen/templates/docs-06-static-template.md create mode 100644 skills/plan/skeleton-gen/templates/docs-07-env-template.md create mode 100644 skills/plan/skeleton-gen/templates/docs-09-structure-template.md create mode 100644 skills/plan/skeleton-gen/templates/env-local-template create mode 100644 skills/plan/skeleton-gen/templates/githooks-pre-push-template.sh create mode 100644 skills/plan/skeleton-gen/templates/gitignore-append-template create mode 100644 skills/plan/skeleton-gen/templates/scripts-setup-test-db-template.sh create mode 100644 skills/plan/skeleton-gen/templates/scripts-test-template.sh diff --git a/README.md b/README.md index 109cfda..a30ed62 100644 --- a/README.md +++ b/README.md @@ -2,43 +2,34 @@ Claude Code 插件:ERP / 后端管理系统全流程开发框架。 -把"从零到 N 个模块上线"的整个流程固化成 **19 个 skill + 2 个 hook + 38 份模板**,让 CC 在 schema 演化用 Flyway migration、需求可追溯、人工审核可控的前提下推进编码。 +把"从零到 N 个模块上线"的整个流程固化成 **21 个 skill + 1 个 agent + 2 个 hook + 37 份模板**,让 CC 在 schema 演化用 Flyway migration、需求可追溯、人工审核可控的前提下推进编码。 ## 这个插件做什么 ``` -📋 阶段 A:规划(一次性,入口 /erp-workflow:erp-plan-start) - 初始化项目 → 锁范围(REQ 卡片生成) - ↓ - ⏸ 审阅 REQ 卡片 → 重新运行 /erp-plan-start 继续 - ↓ - 生成骨架 → 初始化 DB(V1 migration + seed)→ 生成 DB 设计 → 生成下游文档 - ↓ - 用户显式 /erp-workflow:erp-coding-start - -🔁 阶段 B:编码(按模块循环,入口 /erp-workflow:erp-coding-start) +📋 阶段 A:规划(一次性,入口 /erp-workflow:plan-start) + + A0 初始化项目 → A1 锁范围(生成 REQ 卡片) + ↓ + ⏸ 审阅 REQ → 重新运行 /plan-start + ↓ + A2 生成骨架 → A3 生成 DB 设计(REQ → docs/03 + 回填依赖表) + ↓ + ⏸ 审阅 docs/03 → 重新运行 /plan-start + ↓ + A4 初始化 DB(docs/03 → V1 migration → 自动 apply 到本地 MySQL) + ↓ + A5 生成下游文档(docs/02 / docs/05 / docs/06 § 五 / docs/10) + ↓ + 用户显式 /erp-workflow:coding-start + +🔁 阶段 B:编码(按模块循环,入口 /erp-workflow:coding-start) 功能循环:Brainstorm → Plan → TDD → Verify → Review 模块循环:本地测试闸门 → 写模块报告 → 创建 GitLab MR → ⏸ 用户 Approve+Merge → 下次 coding-start 自动扫描 MR 状态为 merged → 下一模块 -⚙️ 后台守门:占位符未填 / 红旗触发 / 跨模块改动未记录 +⚙️ 后台守门:占位符未填 / 中断触发 / 跨模块改动未记录 ``` -## 安装 - -### 方式 1:本地测试(开发期) - -```bash -claude --plugin-dir /path/to/erp-workflow-plugin -``` - -### 方式 2:从 marketplace 安装(发布后) - -``` -/plugin install erp-workflow@ -``` - -详见官方文档 [Discover and install plugins](https://code.claude.com/docs/en/discover-plugins)。 - ## 首次使用 1. **进入空项目目录并启动 Claude Code**: @@ -49,25 +40,30 @@ claude --plugin-dir /path/to/erp-workflow-plugin 2. **Plan 阶段入口**(一次性规划): ``` - /erp-workflow:erp-plan-start + /erp-workflow:plan-start ``` - Plan 阶段**两段式**执行,中间有一个 REQ 审阅断点: + Plan 阶段**三段式**执行,中间有两个人工审阅断点: + + - **第一段(首次运行)**:执行 **A0 → A1**(创建骨架 / 锁技术栈 / 填需求 / 生成 REQ 卡片)后**停下**,等你审阅 `docs/01-需求清单/*.md` 里的 REQ 卡片(Plan 阶段第一个人工关口:业务范围) + - **第二段(REQ 审阅完重新运行)**:继续 **A2 → A3**(生成骨架 / 从 REQ 正向设计 `docs/03-数据库设计文档.md` 并回填 REQ 依赖表)后再次**停下**,等你审阅 docs/03 的表 / 字段 / 索引 / 外键(第二个人工关口:数据库 schema —— A4 会基于它翻译 DDL 并 apply 到 MySQL,所以这关口与 REQ 审阅同等重要) + - **第三段(docs/03 审阅完重新运行)**:执行 **A4 → A5**(解析 docs/03 → 生成 V1 migration → 自动 `DROP+CREATE` 本地 schema 并 apply → 生成下游文档),Plan 完成后再次**停下** - - **第一段(首次运行)**:执行 **A0 → A1**(创建骨架 / 锁技术栈 / 填需求 / 生成 REQ 卡片)后**停下**,等你审阅 `docs/01-需求清单/*.md` 里的 REQ 卡片(这是 Plan 阶段最关键的人工关口) - - **第二段(审阅完重新运行同一命令)**:继续 **A2 → A5**(生成骨架 / 初始化 DB / 生成设计 / 生成下游文档),Plan 完成后再次**停下** + 每次运行都会自动接上次停下的地方继续;中途可以随时关闭 CC,下次运行同样的命令即可恢复。Plan 完成后**不会自动进入编码**,需要你手动运行 `/erp-workflow:coding-start`。 - 每次运行都会自动接上次停下的地方继续;中途可以随时关闭 CC,下次运行同样的命令即可恢复。Plan 完成后**不会自动进入编码**,需要你手动运行 `/erp-workflow:erp-coding-start`。 + > 两个审阅断点的勾选位置都在 `docs/08-模块任务管理.md § 一`:A1 审阅完后系统已自动勾选 A1 全部子项;A3 审阅完后需要手动勾选「用户已审阅 docs/03 表结构」+ A3 父项 `[ ]` → `[x]`,下次 `/plan-start` 才会派发到 A4。 3. **Coding 阶段入口**(模块循环): ``` - /erp-workflow:erp-coding-start + /erp-workflow:coding-start ``` Plan 全部完成后由你显式触发。**按 `docs/02 § 二` REQ 开发顺序清单**扫描,决定当前模块: - 对每个 REQ 所属模块查询 `docs/08` 的 `MR:` 字段 + GitLab API `state`: - - `state == merged` → 模块已完成,跳过 - - `MR: —` / opened / closed / 查不到 → 该模块是当前模块 + 对每个 REQ 所属模块查询 `docs/08` 的 `MR:` 字段,必要时调 GitLab API 取 `state`: + - `MR: —` → 该模块是当前模块(未建过 MR) + - `MR: !` 且 API `state == merged` → 模块已完成,跳过 + - `MR: !` 且 API `state ∈ {opened, closed}` → 该模块是当前模块 + - `MR: !` 但 API HTTP 非 200 / 查不到 / state 非法 → **停下报错**让用户排查 token / API URL / project ID / iid(绝不静默假设未 merged) - 之后 `git checkout main` + `git pull --ff-only` 同步远程 main(保证下次 module 分支切出时 base 新鲜),再派发到 `erp-module-start`。 + 之后**自动探测远程默认分支** → `git checkout <默认分支>` + `git pull --ff-only` 同步远程 → 派发到 `module-start`。 **`docs/08 § 二` 每模块占一行 bullet**,完成信号由 MR merged state 判定;即使用户提前触发 coding-start,未 merged 的模块仍会被选中,不会跳过。 @@ -78,150 +74,165 @@ claude --plugin-dir /path/to/erp-workflow-plugin ``` erp-workflow-plugin/ ├── .claude-plugin/ -│ └── plugin.json # 插件清单,声明 skills 三个子目录 -├── README.md # 本文档 +│ └── plugin.json # 插件清单,声明 skills 四个子目录 +├── README.md # 本文档 ├── hooks/ -│ ├── hooks.json # hook 注册表(2 个 hook) -│ └── scripts/*.sh # 2 个 hook 脚本 +│ ├── hooks.json # hook 注册表(2 个 hook) +│ └── scripts/*.sh # 2 个 hook 脚本 +├── agents/ +│ └── superpower-code-reviewer.md # code-reviewer agent(feature-review 调用) └── skills/ - ├── plan/ # 阶段 A:6 个一次性规划 skill - ├── coding/ # 阶段 B:9 个模块/功能循环 skill - └── crosscut/ # 横切:2 个入口 + 1 红旗 + 1 留痕 skill + ├── plan/ # 阶段 A:6 个一次性规划 skill + ├── coding/ # 阶段 B:9 个模块/功能循环 skill + ├── crosscut/ # 横切:2 个入口 + 1 中断守门 + 1 留痕 skill + └── internal/ # superpowers 本地 fork:2 个无门 brainstorming / writing-plans ``` -插件加载时按 `plugin.json` 的 `skills: ["./skills/plan", "./skills/coding", "./skills/crosscut"]` 扫描。skill 名称不含子目录前缀(如 `/erp-workflow:erp-scope-lock`)。 - ## Hook 清单(2 个,全部在 hooks/hooks.json 注册) | Hook | 脚本 | 事件 | 触发条件 | 作用 | |---|---|---|---|---| | 拒绝 no-verify | `deny-no-verify.sh` | PreToolUse / Bash | CC 尝试 `git push --no-verify` | 硬拦截,强制 `.githooks/pre-push` 生效 | -| 跨模块改动留痕 | `log-cross-module.sh` | PostToolUse / Edit \| Write | 当前处于 `module-*` 分支 且 编辑目标路径落在 `docs/08 § 二` 中**非当前模块**的 path 范围内(无论目标模块 MR 是否已 merged) | 把改动追加为 `TBD(CC 补)` 存根到 `-cross-module.md`;通过 `additionalContext` 软提示 CC 调 `erp-cross-module-log` skill **自主推断**补「原因 / 影响评估」两列。即时性由 CC 自己决定;**最迟在 `erp-module-report` § ⑦ 硬闸门处**(TBD 未清空会阻断模块完成报告),保证模块完成前所有 TBD 必被 CC 填实 | - -**流程使用情况**:2 个 hook 全部在 hooks.json 注册、被 CC 自动触发。 +| 跨模块改动留痕 | `log-cross-module.sh` | PostToolUse / Edit \| Write | 当前处于 `module-*` 分支 且 编辑目标路径落在 `docs/08 § 二` 中**非当前模块**的 path 范围内(无论目标模块 MR 是否已 merged) | 把改动追加为 `TBD(CC 补)` 存根到 `-cross-module.md`;通过 `additionalContext` 软提示 CC 调 `cross-module-log` skill **自主推断**补「原因 / 影响评估」两列。即时性由 CC 自己决定;**最迟在 `module-report` § ⑦ 硬闸门处**(TBD 未清空会阻断模块完成报告),保证模块完成前所有 TBD 必被 CC 填实 | -## Skill 清单(19 个) +## Skill 清单(21 个) ### Plan 阶段(6 个,`skills/plan/`) | # | Skill | 作用 | 流程中谁调用 | |---|---|---|---| -| A0 | `erp-project-init` | • 依赖检查(`mysql` / `mysqldump` 在 PATH,缺失则尝试自动安装)
• 空目录初始化:`cp` 模板创建 CLAUDE.md / docs/01/README.md / docs/08
• `git init` | `erp-plan-start` | -| A1 | `erp-scope-lock` | • 引导填项目概述 / 技术栈 / 需求索引
• 生成 REQ 卡片(`schema_refs=TBD(A4 自动补)`、`api_refs=TBD(A5 自动补)`)
• **停下**等人工审阅 REQ 卡片,审阅完毕用 `/erp-plan-start` 恢复续进 A2 | A0 | -| A2 | `erp-skeleton-gen` | • 生成架构文档:docs/04 § 一+ / docs/06 / docs/07 / docs/09
• 生成工具脚本:scripts/*.sh、.githooks/pre-push、.env.local
• 创建 `sql/migrations/` 空目录(Flyway 准备)
• 合并 .gitignore(逐行判重) | `erp-plan-start` | -| A3 | `erp-db-init` | • 验证 MySQL 连接
• 导出 schema 为 `sql/migrations/V1__initial_schema.sql`(DDL only)
• 导出数据为 `sql/seed-data.sql`(INSERT only) | A2 | -| A4 | `erp-db-design-gen` | • 生成 `docs/03-数据库设计文档.md`
• 回填 REQ 卡片依赖表(`TBD(A4 自动补)` → 实际表名)
• schema 一致性检查 | A3 | -| A5 | `erp-downstream-gen` | • 一次性生成 docs/02 / docs/05 / docs/06 § 五 / docs/10
• 回填 REQ 卡片依赖接口(`TBD(A5 自动补)` → 实际 endpoint)
• 追加模块清单到 docs/08 § 二
• 最终占位符扫描(TBD 自动补 + `【人工填写:】` QA 循环)
• 打印 Plan 完成横幅并**停下**(不自动进 B) | A4 | +| A0 | `project-init` | • 依赖检查(`mysql` 在 PATH,缺失则尝试自动安装)
• 空目录初始化:`cp` 模板创建 CLAUDE.md / docs/01/index.md / docs/08
• `git init` | `plan-start` | +| A1 | `scope-lock` | • 引导填项目概述 / 技术栈 / 需求索引
• 生成 REQ 卡片(`schema_refs=TBD(A3 自动补)`、`api_refs=TBD(A5 自动补)`)
• **停下**等人工审阅 REQ 卡片,审阅完毕用 `/plan-start` 恢复续进 A2 | A0 | +| A2 | `skeleton-gen` | • 生成架构文档:docs/04 § 一+ / docs/06 / docs/07 / docs/09
• 生成工具脚本:scripts/*.sh、.githooks/pre-push、.env.local
• 创建 `sql/migrations/` 空目录(Flyway 准备)
• 合并 .gitignore(逐行判重) | `plan-start` | +| A3 | `db-design-gen` | • 从 docs/01 REQ 卡片正向设计 `docs/03-数据库设计文档.md`(schema SSoT)
• 回填 REQ 卡片依赖表(`TBD(A3 自动补)` → 实际表名)
• **停下**等人工审阅 docs/03,审阅完毕用 `/plan-start` 恢复续进 A4 | A2 | +| A4 | `db-init` | • LLM 解析 docs/03 → `sql/migrations/V1__initial_schema.sql`(DDL only)
• **5 维度全量校验** DDL ↔ docs/03(表名 / 列名+列序 / 类型+nullable+默认值 / 索引名 / FK 名),fail-closed
• 验证 MySQL 连接
• 调 `scripts/setup-test-db.sh` 复用三层防护(与 B 阶段 test.sh 共用)→ DROP+CREATE 空库
• apply V1 + `SHOW TABLES` 行数自检 | A3 | +| A5 | `downstream-gen` | • 一次性生成 docs/02 / docs/05 / docs/06 § 五 / docs/10
• 回填 REQ 卡片依赖接口(`TBD(A5 自动补)` → 实际 endpoint)
• 追加模块清单到 docs/08 § 二
• 最终占位符扫描(TBD 自动补 + `【人工填写:】` QA 循环)
• 打印 Plan 完成横幅并**停下**(不自动进 B) | A4 | ### Coding 阶段(9 个,`skills/coding/`) -**触发与顺序**(`erp-coding-start` 是唯一由用户手动触发的入口,下面所有 skill 都由 skill 链自动调用): +**触发与顺序**(`coding-start` 是唯一由用户手动触发的入口,下面所有 skill 都由 skill 链自动调用): ``` -/erp-workflow:erp-coding-start ← 用户每次手动触发 +/erp-workflow:coding-start ← 用户每次手动触发 │ │ 扫描 docs/02 REQ 序 + docs/08 MR 字段 + GitLab API state 判定当前模块: │ - 所有模块都 merged → 打印"所有模块已完成" │ - 找到第一个非 merged 模块 → 派发 - │ 派发前 git checkout main + git pull --ff-only(同步远程 base) + │ 派发前自动探测远程默认分支(main / master),git checkout + git pull --ff-only 同步远程 base │ - └─→ erp-module-start(幂等可重入,切 module- 分支) + └─→ module-start(幂等可重入,切 module- 分支) │ │ 对每个未完成 REQ,按序串链: - │ erp-feature-brainstorm → -plan → -tdd → -verify → -review + │ feature-brainstorm → -plan → -tdd → -verify → -review │ - │ review approve → 回 erp-module-start(推进下一 REQ) - │ review request-changes (<5) → fix commit → 回 erp-feature-verify 重新执行 + │ review approve → 回 module-start(推进下一 REQ) + │ review request-changes (<5) → fix commit → 回 feature-verify 重新执行 │ review request-changes (=5) → 停下(升级给人) │ │ 模块全部 REQ approve → - │ erp-local-test-gate(commit test-gate.md) - │ → erp-module-report(commit 模块报告 + cross-module log) - │ → erp-mr-create(worktree clean 校验 → push 代码+evidence → 创建 MR + │ test-gate(commit test-gate.md) + │ → module-report(commit 模块报告 + cross-module log) + │ → mr-create(worktree clean 校验 → push 代码+evidence → 创建 MR │ → 追 MR URL 到报告 + commit → 写 MR iid 到 docs/08 + commit │ → 再 push) │ └─ ⏸ 停下等人工 Approve + Merge (人工合并后再次运行 coding-start,扫描到 state=merged 自动跳过 - → pull main → 推进下一模块) + → pull 默认分支 → 推进下一模块) ``` | Skill | 做什么 | 谁触发它 | |---|---|---| -| `erp-module-start` | 定位当前模块(docs/02 REQ 序)+ 切换或创建 `module-` 分支 + 扫描 `docs/superpowers/reviews/*.md` 的 `verdict=approve` 计算已完成 REQ + 推进第一个未完成 REQ 的功能循环。全部完成 → `erp-local-test-gate`。**幂等可重入**(中途断开后重新运行会自动跳过已 approve 的 REQ) | `erp-coding-start` 派发;`erp-feature-review` approve 后回调 | -| `erp-feature-brainstorm` | 功能循环步骤 1:交互 brainstorm → 生成 `docs/superpowers/specs/*.md` | `erp-module-start` 推进 REQ 时调用 | -| `erp-feature-plan` | 功能循环步骤 2:spec → 任务级 plan(含文件路径 + 完整代码),输出 `docs/superpowers/plans/*.md` | `erp-feature-brainstorm` 链式调用 | -| `erp-feature-tdd` | 功能循环步骤 3:红绿循环(写失败测试 → 实现 → 子会话验证通过 → commit 到 `module-` 分支) | `erp-feature-plan` 链式调用 | -| `erp-feature-verify` | 功能循环步骤 4:将全量测试派发到子会话执行一次,用模板渲染 evidence | `erp-feature-tdd` 链式调用;`erp-feature-review` 在 request-changes 修复后重新调用 | -| `erp-feature-review` | 功能循环步骤 5:AI 自审,写 `docs/superpowers/reviews/*.md`。approve → 回 `erp-module-start`;request-changes → 逐项 Edit + fix commit → 回 `erp-feature-verify` 重新执行(最多 5 轮,第 5 轮仍 request-changes 则停下) | `erp-feature-verify` 链式调用 | -| `erp-local-test-gate` | MR 前硬闸门:子会话执行 `scripts/test.sh`(脚本内部 drop+create 空库、Flyway apply `sql/migrations/V*.sql`、再执行测试);通过 → 写 `-test-gate.md` 并 `git add + commit`(evidence 提交到 module 分支);失败停下 | `erp-module-start` 在本模块所有 REQ approve 后调用 | -| `erp-module-report` | 红旗检查 → 生成 12 节模块完成报告 `docs/superpowers/module-reports/-.md` → `git add + commit`(报告 + cross-module log 提交到 module 分支,erp-mr-create 的 worktree clean 前置条件依赖此步) | `erp-local-test-gate` 链式调用 | -| `erp-mr-create` | 红旗检查 → 验证当前分支 = `module-` 且 `git status --porcelain` worktree 干净 → `git push` 推代码与全部 evidence → 用 curl 调 GitLab REST API 创建 MR(模块报告嵌入 MR 描述)→ 追加 MR URL 到报告并 commit → 把 docs/08 该模块的 `MR: —` 回写为 `MR: !` 并 commit → 再次 push;**停下等人工 Approve+Merge**。完成由 MR state 判定 | `erp-module-report` 链式调用 | +| `module-start` | 定位当前模块(docs/02 REQ 序)+ 切换或创建 `module-` 分支 + 扫描 `docs/superpowers/reviews/*.md` 的 `verdict=approve` 计算已完成 REQ + 推进第一个未完成 REQ 的功能循环。全部完成 → `test-gate`。**幂等可重入**(中途断开后重新运行会自动跳过已 approve 的 REQ) | `coding-start` 派发;`feature-review` approve 后回调 | +| `feature-brainstorm` | 功能循环步骤 1:交互 brainstorm → 生成 `docs/superpowers/specs/*.md` | `module-start` 推进 REQ 时调用 | +| `feature-plan` | 功能循环步骤 2:spec → 任务级 plan(文件路径 + API 签名 + 测试意图 + 完成判据,代码由 TDD 阶段产出),输出 `docs/superpowers/plans/*.md` | `feature-brainstorm` 链式调用 | +| `feature-tdd` | 功能循环步骤 3:红绿循环(写失败测试 → 实现 → 子会话验证通过 → commit 到 `module-` 分支) | `feature-plan` 链式调用 | +| `feature-verify` | 功能循环步骤 4:将全量测试派发到子会话执行一次,用模板渲染 evidence | `feature-tdd` 链式调用;`feature-review` 在 request-changes 修复后重新调用 | +| `feature-review` | 功能循环步骤 5:AI 自审,写 `docs/superpowers/reviews/*.md`。approve → 回 `module-start`;request-changes → 逐项 Edit + fix commit → 回 `feature-verify` 重新执行(最多 5 轮,第 5 轮仍 request-changes 则停下) | `feature-verify` 链式调用 | +| `test-gate` | MR 前硬闸门:子会话执行 `scripts/test.sh`(脚本内部 drop+create 空库、Flyway apply `sql/migrations/V*.sql`、再执行测试);通过 → 写 `-test-gate.md` 并 `git add + commit`(evidence 提交到 module 分支);失败停下 | `module-start` 在本模块所有 REQ approve 后调用 | +| `module-report` | 中断检查 → 生成 12 节模块完成报告 `docs/superpowers/module-reports/-.md` → `git add + commit`(报告 + cross-module log 提交到 module 分支,mr-create 的 worktree clean 前置条件依赖此步) | `test-gate` 链式调用 | +| `mr-create` | 中断检查 → 验证当前分支 = `module-` 且 `git status --porcelain` worktree 干净 → `git push` 推代码与全部 evidence → 用 curl 调 GitLab REST API 创建 MR(模块报告嵌入 MR 描述)→ 追加 MR URL 到报告并 commit → 把 docs/08 该模块的 `MR: —` 回写为 `MR: !` 并 commit → 再次 push;**停下等人工 Approve+Merge**。完成由 MR state 判定 | `module-report` 链式调用 | ### Crosscut(4 个,`skills/crosscut/`) | Skill | 作用 | 流程中谁调用 | |---|---|---| -| `erp-plan-start` | **A 阶段入口**。读取 docs/08 § 一 找第一个未勾 A 子项 → 派发对应 A skill;A 全部完成时提示运行 coding-start | **用户手动**运行 `/erp-workflow:erp-plan-start` | -| `erp-coding-start` | **B 阶段入口**。先验证 Plan 已完成;**按 `docs/02 § 二` REQ 序扫描**,对每个 REQ 所属模块查询 `MR:` 字段 + GitLab API `state`:`merged` 跳过;`—`/opened/closed/查不到 选为当前模块。派发前 `git checkout main + git pull --ff-only` 同步远程 base,然后调用 `erp-module-start` | **用户手动**运行 `/erp-workflow:erp-coding-start` | -| `erp-red-flag-check` | 检查 CLAUDE.md 的 3 项红旗清单;命中则追加 Blocker 到计划文件并停下 | 功能循环各步骤和生成重要制品前自动调用 | -| `erp-cross-module-log` | 给 `log-cross-module.sh` 追加的跨模块改动存根补「原因 / 影响评估」 | 用户看到 hook 提示后调用;`erp-module-start` 初始化日志文件时也会用其模板 | +| `plan-start` | **A 阶段入口**。读取 docs/08 § 一 找第一个未勾 A 子项 → 派发对应 A skill;A 全部完成时提示运行 coding-start | **用户手动**运行 `/erp-workflow:plan-start` | +| `coding-start` | **B 阶段入口**。先验证 Plan 已完成;**按 `docs/02 § 二` REQ 序扫描**,对每个 REQ 所属模块查询 `MR:` 字段 + GitLab API `state`:`merged` 跳过;`—`/opened/closed 选为当前模块;查不到则停下报错。派发前自动探测远程默认分支(main / master),`git checkout + git pull --ff-only` 同步远程 base,然后调用 `module-start` | **用户手动**运行 `/erp-workflow:coding-start` | +| `interrupt-check` | 检查 CLAUDE.md 的 3 项中断清单;触发则追加 Blocker 到计划文件并停下 | 功能循环各步骤和生成重要制品前自动调用 | +| `cross-module-log` | 给 `log-cross-module.sh` 追加的跨模块改动存根批量补「原因 / 影响评估」 | `module-report` § ⑦ 硬验收时一次性调用(CC 编辑中途不主动调);`module-start` 初始化日志文件时也会用其模板 | + +### Internal / Superpowers Fork(2 个,`skills/internal/`) + +`superpowers:brainstorming` / `superpowers:writing-plans` 原版内含 `` 与"等用户 approve 设计 / review spec / Which approach?"等用户等待点,与本插件"除真正卡死外不停"目标冲突。fork 进来剥掉门控后作为 `feature-brainstorm` / `feature-plan` 的内部实现用。 + +| Skill | 源(superpowers 版本) | 剥掉了什么 | +|---|---|---| +| `superpower-brainstorming` | `superpowers:brainstorming` 5.0.7 | `` 整块、Anti-Pattern 段、Checklist 里 Visual Companion / approve-design / review-spec 三项、User Review Gate、Visual Companion 整节、终点 `invoke writing-plans` | +| `superpower-writing-plans` | `superpowers:writing-plans` 5.0.7 | Execution Handoff 整节("Which approach?" 问询)、"Complete code in every step" 硬要求(改为"API 签名 + 测试意图"粒度,完整代码留给 TDD) | + +## Agent 清单(1 个) + +| Agent | 源 | 用途 | 谁调用 | +|---|---|---|---| +| `superpower-code-reviewer` | `superpowers:code-reviewer` 5.0.7 agent,仅改 name | 对 REQ diff 做 AI 自审,产出 `must_fix[]` / `nice_to_have[]` / `gaps` | `feature-review` 步骤 1:`Agent(subagent_type=superpower-code-reviewer)` | -## Templates 清单(38 份) +## Templates 清单(37 份) | 所属 Skill | 模板文件 | 用途 | |---|---|---| -| erp-project-init | `CLAUDE-template.md` | 项目根的 CLAUDE.md(4 条通用准则 + ERP 专属约定) | -| erp-project-init | `docs-01-readme-template.md` | 需求清单索引骨架,等用户填模块表 | -| erp-project-init | `docs-08-initial-template.md` | 工作流进度文件骨架(Plan A0~A5 checkbox) | -| erp-scope-lock | `req-card-template.md` | 单张 REQ-XXX-NNN 卡片字段结构 | -| erp-scope-lock | `docs-01-module-template.md` | 单模块 `-.md` 外壳 | -| erp-skeleton-gen | `docs-04-skeleton-template.md` | docs/04 § 一+ 编码规范大纲(HTML 注释引导 LLM) | -| erp-skeleton-gen | `docs-06-static-template.md` | docs/06 § 一~四 UI 模式大纲 | -| erp-skeleton-gen | `docs-07-env-template.md` | docs/07 环境配置大纲 | -| erp-skeleton-gen | `docs-09-structure-template.md` | docs/09 目录结构大纲 | -| erp-skeleton-gen | `scripts-setup-test-db-template.sh` | 运行时 drop + create 空库脚本(0 槽位);schema apply 交给 Flyway | -| erp-skeleton-gen | `githooks-pre-push-template.sh` | pre-push → 调 scripts/test.sh(0 槽位) | -| erp-skeleton-gen | `env-local-template` | 6 字段凭据模板(DB_* + JWT_SECRET) | -| erp-skeleton-gen | `gitignore-append-template` | 插件推荐忽略项(`.env.local`、`.tmp/`、构建产物等) | -| erp-db-init | `migration-v1-header-template.sql` | V1 initial migration 文件头部注释 | -| erp-db-init | `seed-data-sql-template.sql` | seed-data.sql 文件头部注释 | -| erp-db-design-gen | `docs-03-header-template.md` | docs/03 数据库设计头部 | -| erp-db-design-gen | `docs-03-table-template.md` | docs/03 单表小节模板 | -| erp-downstream-gen | `docs-02-template.md` | docs/02 开发计划 | -| erp-downstream-gen | `docs-05-header-template.md` | docs/05 API 契约头部 | -| erp-downstream-gen | `docs-05-endpoint-template.md` | docs/05 单接口小节 | -| erp-downstream-gen | `docs-06-module-pagelist-template.md` | docs/06 § 五 单模块页面清单 | -| erp-downstream-gen | `docs-08-module-row-template.md` | docs/08 § 二 单模块 bullet 行 | -| erp-downstream-gen | `docs-10-header-template.md` | docs/10 验收清单头部 | -| erp-downstream-gen | `docs-10-module-template.md` | docs/10 单模块验收项 | -| erp-module-start | `module-start-banner-template.md` | 模块启动横幅 | -| erp-module-start | `cross-module-log-template.md` | cross-module 日志头(副本) | -| erp-feature-brainstorm | `feature-spec-template.md` | 功能 spec 结构 | -| erp-feature-plan | `feature-plan-template.md` | 功能 plan 结构 | -| erp-feature-tdd | `commit-message-template.md` | TDD 每步 commit 信息 | -| erp-feature-verify | `feature-verify-evidence-template.md` | 验证证据渲染模板 | -| erp-feature-review | `feature-review-template.md` | 自审报告结构 | -| erp-local-test-gate | `test-gate-result-template.md` | 闸门结果渲染 | -| erp-module-report | `module-report-template.md` | 12 节模块报告 | -| erp-mr-create | `mr-title-template.md` | MR 标题模板 | -| erp-mr-create | `mr-description-template.md` | MR 描述模板(嵌入模块报告) | -| erp-red-flag-check | `red-flag-block-template.md` | Blocker 节追加模板 | -| erp-cross-module-log | `cross-module-log-template.md` | cross-module 日志头(主本) | -| erp-cross-module-log | `cross-module-log-row-template.md` | 单条改动行模板 | +| project-init | `CLAUDE-template.md` | 项目根的 CLAUDE.md(4 条通用准则 + ERP 专属约定) | +| project-init | `docs-01-index-template.md` | 需求清单索引骨架,等用户填模块表 | +| project-init | `docs-08-initial-template.md` | 工作流进度文件骨架(Plan A0~A5 checkbox) | +| project-init | `docs-04-stack-template.md` | docs/04 § 零 默认技术栈总览(零槽位,cp 即可) | +| scope-lock | `req-card-template.md` | 单张 REQ-XXX-NNN 卡片字段结构 | +| scope-lock | `docs-01-module-template.md` | 单模块 `-.md` 外壳 | +| skeleton-gen | `docs-04-skeleton-template.md` | docs/04 § 一+ 编码规范大纲(HTML 注释引导 LLM) | +| skeleton-gen | `docs-06-static-template.md` | docs/06 § 一~四 UI 模式大纲 | +| skeleton-gen | `docs-07-env-template.md` | docs/07 环境配置大纲 | +| skeleton-gen | `docs-09-structure-template.md` | docs/09 目录结构大纲 | +| skeleton-gen | `scripts-setup-test-db-template.sh` | 运行时 drop + create 空库脚本(0 槽位);schema apply 交给 Flyway | +| skeleton-gen | `scripts-test-template.sh` | test.sh 骨架(4 个命令槽位:{{build_cmd}} / {{lint_cmd}} / {{test_cmd}} / {{e2e_cmd}},由 skeleton-gen 按技术栈推断填充) | +| skeleton-gen | `githooks-pre-push-template.sh` | pre-push → 调 scripts/test.sh(0 槽位) | +| skeleton-gen | `env-local-template` | 6 字段凭据模板(DB_* + JWT_SECRET) | +| skeleton-gen | `gitignore-append-template` | 插件推荐忽略项(`.env.local`、`.tmp/`、构建产物等) | +| db-init | `migration-v1-header-template.sql` | V1 initial migration 文件头部注释 | +| db-design-gen | `docs-03-header-template.md` | docs/03 数据库设计头部 | +| db-design-gen | `docs-03-table-template.md` | docs/03 单表小节模板 | +| downstream-gen | `docs-02-template.md` | docs/02 开发计划 | +| downstream-gen | `docs-05-header-template.md` | docs/05 API 契约头部 | +| downstream-gen | `docs-05-endpoint-template.md` | docs/05 单接口小节 | +| downstream-gen | `docs-06-module-pagelist-template.md` | docs/06 § 五 单模块页面清单 | +| downstream-gen | `docs-08-module-row-template.md` | docs/08 § 二 单模块 bullet 行 | +| downstream-gen | `docs-10-header-template.md` | docs/10 验收清单头部 | +| downstream-gen | `docs-10-module-template.md` | docs/10 单模块验收项 | +| module-start | `module-start-banner-template.md` | 模块启动横幅 | +| module-start | `cross-module-log-template.md` | cross-module 日志头(副本) | +| feature-brainstorm | `feature-spec-template.md` | 功能 spec 结构 | +| feature-plan | `feature-plan-template.md` | 功能 plan 结构 | +| feature-tdd | `commit-message-template.md` | TDD 每步 commit 信息 | +| feature-verify | `feature-verify-evidence-template.md` | 验证证据渲染模板 | +| feature-review | `feature-review-template.md` | 自审报告结构 | +| test-gate | `test-gate-result-template.md` | 闸门结果渲染 | +| module-report | `module-report-template.md` | 12 节模块报告 | +| mr-create | `mr-title-template.md` | MR 标题模板 | +| mr-create | `mr-description-template.md` | MR 描述模板(嵌入模块报告) | +| interrupt-check | `interrupt-block-template.md` | Blocker 节追加模板 | +| cross-module-log | `cross-module-log-template.md` | cross-module 日志头(主本) | +| cross-module-log | `cross-module-log-row-template.md` | 单条改动行模板 | **流程使用情况**:所有模板都被对应 skill 的 `SKILL.md` 引用,没有孤儿模板。 ## 前置依赖 -- **MySQL 8.x** 实例已就绪(CC 不执行 DDL;schema 由人工初始化) -- **`mysql` / `mysqldump` 命令行**:`erp-db-init` (A3) 验证连接 + 导出 V1 initial migration + 导出 seed-data.sql;`scripts/setup-test-db.sh` 在测试闸门前后 drop+create 空库 +- **MySQL 8.x** 实例已就绪(推荐本地 / `*.local` host;A4 `db-init` 的安全守护要求 host 在白名单且 schema 名含 `test`/`dev`/`local`,避免误删生产库) +- **`mysql` 命令行**:A4 `db-init` 验证连接 + 自动 `DROP+CREATE` schema 后 apply V1;`scripts/setup-test-db.sh` 在测试闸门前后 drop+create 空库 - **Spring Boot + Flyway**(**必需**):pom.xml 声明 `flyway-core` + `flyway-mysql`;Spring 启动时自动 apply `sql/migrations/V*.sql`。本插件生成的 `setup-test-db.sh` 只清库,schema 必须由 Flyway 应用 -- **GitLab v3 API + Private Token**:`erp-mr-create` 用 `curl` POST `/projects/:id/merge_requests` 建 MR;`erp-coding-start` / `erp-module-start` 用 `curl` GET `/projects/:id/merge_requests?iid=` 判定 state(v3 路径参数 `:merge_request_id` 要内部数字 id,所以统一用 iid 过滤列表)。HTTP 头用 `PRIVATE-TOKEN`;凭据(`GITLAB_API_URL=.../api/v3` / `GITLAB_TOKEN` / `GITLAB_PROJECT_ID`)放 `.env.local` -- **本地可运行 `mvn test` / `pnpm test`**:测试闸门 `scripts/test.sh` 由 `erp-skeleton-gen` 生成 +- **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=` 判定 state(v3 路径参数 `:merge_request_id` 要内部数字 id,所以统一用 iid 过滤列表)。HTTP 头用 `PRIVATE-TOKEN`;凭据(`GITLAB_API_URL=.../api/v3` / `GITLAB_TOKEN` / `GITLAB_PROJECT_ID`)放 `.env.local` +- **本地可运行 `mvn test` / `pnpm test`**:测试闸门 `scripts/test.sh` 由 `skeleton-gen` 生成 ## 设计原则 -参见 `erp-project-init/templates/CLAUDE-template.md` 末尾的「🧭 通用工作准则」4 条:① Think Before Coding ② Simplicity First ③ Surgical Changes ④ Goal-Driven Execution。 +参见 `project-init/templates/CLAUDE-template.md` 末尾的「🧭 通用工作准则」4 条:① Think Before Coding ② Simplicity First ③ Surgical Changes ④ Goal-Driven Execution。 最关键的 1 条:"**所有测试与验证派发到全新子会话执行,主会话只接收结构化结论**"——避免主会话被测试输出污染,并让测试结果作为独立证据存档。 diff --git a/hooks/scripts/deny-no-verify.sh b/hooks/scripts/deny-no-verify.sh index 786736d..9fdf716 100755 --- a/hooks/scripts/deny-no-verify.sh +++ b/hooks/scripts/deny-no-verify.sh @@ -11,7 +11,7 @@ cmd="$(printf '%s' "$input" | jq -r '.tool_input.command // empty')" [ -n "$cmd" ] || exit 0 if printf '%s' "$cmd" | grep -qE '\bgit[[:space:]]+push\b.*--no-verify\b'; then - 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 /erp-local-test-gate to run the gate properly." >&2 + 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 exit 2 fi diff --git a/hooks/scripts/log-cross-module.sh b/hooks/scripts/log-cross-module.sh index 24bd34f..b48fcbe 100755 --- a/hooks/scripts/log-cross-module.sh +++ b/hooks/scripts/log-cross-module.sh @@ -19,7 +19,7 @@ docs08="$project_dir/docs/08-模块任务管理.md" case "$file_path" in *"/docs/08-模块任务管理.md") exit 0 ;; esac # 当前模块 = 当前 git 分支名去掉 `module-` 前缀。 -# erp-module-start 步骤 3 保证模块循环期间处于 module- 分支; +# module-start 步骤 3 保证模块循环期间处于 module- 分支; # 非 module-* 分支(如 main、feature/*、docs/*)不在模块循环内,不触发 S2 留痕。 current_branch="$(cd "$project_dir" 2>/dev/null && git branch --show-current 2>/dev/null || echo '')" case "$current_branch" in @@ -78,4 +78,4 @@ rel_path="${file_path#$project_dir/}" echo "| ${ts} | ${hit_module} | ${rel_path} | ${tool_name} | TBD(CC 补) | TBD(CC 补) |" >> "$log_file" jq -n --arg m "$hit_module" --arg f "$log_file" --arg p "$rel_path" \ - '{hookSpecificOutput:{hookEventName:"PostToolUse",additionalContext:("跨模块改动检测:\($p) 属于模块 [\($m)](非当前模块)。存根已写入 \($f),含 TBD(CC 补) 占位。请由 CC 调用 erp-cross-module-log skill 自主推断并补填原因与影响评估(软规则 S2,CC 自主维护,非人工填写)。")}}' + '{hookSpecificOutput:{hookEventName:"PostToolUse",additionalContext:("跨模块改动检测:\($p) 属于模块 [\($m)](非当前模块)。存根已写入 \($f),含 TBD(CC 补) 占位。**不需要现在处理**——所有 TBD 由 module-report § ⑦ 一次性调用 cross-module-log skill 批量补齐(软规则 S2)。")}}' diff --git a/skills/coding/erp-feature-brainstorm/SKILL.md b/skills/coding/erp-feature-brainstorm/SKILL.md deleted file mode 100644 index 9948d49..0000000 --- a/skills/coding/erp-feature-brainstorm/SKILL.md +++ /dev/null @@ -1,39 +0,0 @@ ---- -name: erp-feature-brainstorm -description: 功能循环第 1 步。针对单个 REQ-XXX-NNN 进行交互式头脑风暴,产出功能规格文件到 docs/superpowers/specs/。 -user-invocable: false -allowed-tools: Read Write Skill Bash(mysql *) ---- - -**所有输出必须使用中文。** - -# erp-feature-brainstorm - -## 说明 - -针对一个 REQ-XXX-NNN,委托本插件的 `superpower-brainstorming`(superpowers:brainstorming 的本地 fork,已剥掉 approval gates)进行头脑风暴,再把输出填入标准规格模板,产出单页功能规格。 - -## 执行步骤 - -1. **红旗检查**:调用 `erp-red-flag-check`。如果命中 → 停止。 -2. 确定输入: - - 当前 REQ-XXX-NNN(从对话中获取,或 `docs/08` 当前模块下一个未完成的 REQ)。 - - REQ 卡片:`docs/01-需求清单/.md` 中对应的 REQ-XXX-NNN 节。 - - 相关数据表(从 `docs/03` 或实时 mysql 命令行查询)。 -3. 委托本插件 `superpower-brainstorming`,以 REQ 卡片 + schema 引用作为上下文;把步骤 4 推导出的落盘路径作为 caller-provided path 传入。 -4. 推导路径:`docs/superpowers/specs/$(date +%F)-.md`。如已存在,征求用户确认后覆盖。 -5. 用 `Read` 读取 `${CLAUDE_SKILL_DIR}/templates/feature-spec-template.md`,从头脑风暴输出填充槽位: - - `goal`、`input`、`output`、`rules`、`constraints`、`schema_refs`、`api_refs`、`acceptance` -6. 将填充后的规格写入推导路径。 -7. **验证**:模板中每个顶级节必须非空;**spec 全文不得包含 `【人工填写:...】` 或 `TBD`**。如出现:先在 `.env.local` / `docs/07-环境配置.md` / `CLAUDE.md` / 现有代码中查找真值并写入(同时注明来源),查不到则用 `AskUserQuestion` 向用户询问;拒绝把"待人工填写"的标记写入 B 阶段 spec(该标记仅供 A 阶段用户审阅文档用)。 -8. 输出 `feature-brainstorm: `。 - -## 衔接 - -立即调用 `Skill(erp-feature-plan)` 进入下一步。 - -## 参考 - -- `${CLAUDE_SKILL_DIR}/templates/feature-spec-template.md` -- 委托:`superpower-brainstorming`(本插件 `skills/internal/superpower-brainstorming/`,superpowers:brainstorming 的无门 fork) -- 守门:`erp-red-flag-check` diff --git a/skills/coding/erp-feature-brainstorm/templates/feature-spec-template.md b/skills/coding/erp-feature-brainstorm/templates/feature-spec-template.md deleted file mode 100644 index 09715ab..0000000 --- a/skills/coding/erp-feature-brainstorm/templates/feature-spec-template.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -req_id: {{req_id}} -date: {{date}} -module: {{module}} ---- - -# Spec: {{req_id}} — {{title}} - -## 目标 -{{goal}} - -## 输入 / 触发 -{{input}} - -## 输出 / 结果 -{{output}} - -## 业务规则 -{{rules}} - -## 边界与约束 -{{constraints}} - -## 依赖的 schema 表 / 字段 -{{schema_refs}} - -## 依赖的接口 -{{api_refs}} - -## 验收标准 -{{acceptance}} diff --git a/skills/coding/erp-feature-plan/SKILL.md b/skills/coding/erp-feature-plan/SKILL.md deleted file mode 100644 index c96c153..0000000 --- a/skills/coding/erp-feature-plan/SKILL.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -name: erp-feature-plan -description: 功能循环第 2 步。将规格转化为任务级计划(每任务 2-5 分钟,含文件路径和完整代码),输出到 docs/superpowers/plans/。 -user-invocable: false -allowed-tools: Read Write Grep Skill ---- - -**所有输出必须使用中文。** - -# erp-feature-plan - -## 执行步骤 - -1. **红旗检查**:调用 `erp-red-flag-check`。 -2. 确定输入: - - 当前 REQ-XXX-NNN 及其规格文件 `docs/superpowers/specs/YYYY-MM-DD-.md`(规格不存在则报错)。 - - 相关代码指针(已有的待修改文件,通过 Grep 发现)。 - - `docs/04-技术规范.md` 和 `docs/09-项目目录结构.md`(编码规范 + 目录规范)。 -3. 委托本插件 `superpower-writing-plans`(superpowers:writing-plans 的本地 fork,已剥掉"Which approach?"执行交接门),以规格 + 代码指针 + 规范作为上下文;把步骤 4 推导出的落盘路径作为 caller-provided path 传入。 -4. 推导路径:`docs/superpowers/plans/$(date +%F)-.md`。 -5. 用 `Read` 读取 `${CLAUDE_SKILL_DIR}/templates/feature-plan-template.md`,填充 `files[]`、`tasks[]`、`commits[]`。 -6. 强制要求:每个任务有失败测试标识、实现路径和完成标准;**plan 全文不得包含 `【人工填写:...】` 或 `TBD`**——该标记仅限 A 阶段用户审阅文档,B 阶段 plan 必须写具体值(先在 `.env.local` / `docs/07` / `CLAUDE.md` / 现有代码查找并注明来源;查不到就 `AskUserQuestion` 向用户问)。 -7. 写入计划文件。 -8. 输出 `feature-plan: `。 - -## 衔接 - -立即调用 `Skill(erp-feature-tdd)` 进入下一步。 - -## 参考 - -- `${CLAUDE_SKILL_DIR}/templates/feature-plan-template.md` -- 委托:`superpower-writing-plans`(本插件 `skills/internal/superpower-writing-plans/`,superpowers:writing-plans 的无门 fork) -- 守门:`erp-red-flag-check` diff --git a/skills/coding/erp-feature-plan/templates/feature-plan-template.md b/skills/coding/erp-feature-plan/templates/feature-plan-template.md deleted file mode 100644 index 00d36f6..0000000 --- a/skills/coding/erp-feature-plan/templates/feature-plan-template.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -req_id: {{req_id}} -date: {{date}} -spec_ref: docs/superpowers/specs/{{date}}-{{req_id}}.md ---- - -# Plan: {{req_id}} - -## Schema 改动 -{{schema_change_decision}} - -## 文件变更清单 -{{#each files}} -- `{{path}}` — {{action}}({{rationale}}) -{{/each}} - -## 任务步骤 -{{#each tasks}} -### Task {{index}}: {{title}} -- 失败测试: `{{test_file}}::{{test_name}}` — {{test_intent}} -- 实现路径: `{{impl_file}}` -- 完成判据: {{done_when}} -{{/each}} - -## 提交计划 -{{#each commits}} -- `{{message}}`(覆盖 Task {{task_index}}) -{{/each}} diff --git a/skills/coding/erp-feature-review/SKILL.md b/skills/coding/erp-feature-review/SKILL.md deleted file mode 100644 index e84be23..0000000 --- a/skills/coding/erp-feature-review/SKILL.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -name: erp-feature-review -description: 功能循环第 5 步。AI 自审,输出审阅报告到 docs/superpowers/reviews/。approve 回调 erp-module-start;request-changes 则编辑代码并 fix commit,重新执行 verify。自修复循环上限 5 轮。 -user-invocable: false -allowed-tools: Read Write Edit Skill Agent Bash(git add *) Bash(git commit *) ---- - -**所有输出必须使用中文。** - -# erp-feature-review - -## 执行步骤 - -1. 通过 `Agent(subagent_type=superpower-code-reviewer)` 调用本插件 code-reviewer agent(superpowers:code-reviewer 的本地 fork),以该 REQ 的 diff(`git diff ..HEAD`)和规格作为输入。 -2. 推导路径:`docs/superpowers/reviews/$(date +%F)-.md`。 -3. 用 `Read` 读取 `${CLAUDE_SKILL_DIR}/templates/feature-review-template.md`,填充 `round`、`verdict`、`must_fix[]`、`nice_to_have[]`、`gaps`。verdict 必须是 `approve` 或 `request-changes`。 -4. 写入报告。 - -5. 分发: - - **`verdict = approve`** → 输出 `feature-review: round 通过`,然后调用 `Skill(erp-module-start)` 回模块主循环(module-start 会自动把本 REQ 识别为 done 并推进下一个 REQ)。 - - **`verdict = request-changes`** → 执行"自修复子流程": - - 逐项处理 `must_fix[]`:对每个条目用 `Edit` 修改其指向的代码文件。 - - 所有 Must-fix 修复后,拼 commit 消息(格式与 `erp-feature-tdd` 一致,单行):`fix(): 修复 review round must-fix `。 - - `Bash`: `git add <修改的代码文件>` + `git commit -m "<上一步拼出的消息>"`。 - - 调用 `Skill(erp-feature-verify)` 重新执行验证;verify 通过后会再次链到本 skill,作为 round `` 重审。 - -6. 上限:**5 轮**。第 5 轮仍为 `request-changes` → 停止并打印摘要(升级给用户手工介入),不再自动修复,不回调 module-start。 - -## 衔接 - -- `approve` → `Skill(erp-module-start)` 回主循环。 -- `request-changes`(round < 5)→ `Skill(erp-feature-verify)` 重新执行。 -- `request-changes`(round == 5)→ 停止。 - -## 参考 - -- `${CLAUDE_SKILL_DIR}/templates/feature-review-template.md` -- Fix commit 格式与 `erp-feature-tdd` 的 `commit-message-template.md` 对齐(`fix(): `) -- 委托:`superpower-code-reviewer`(本插件 `agents/superpower-code-reviewer.md`,superpowers:code-reviewer 的本地 fork) -- 上游:`erp-feature-verify` -- 下游:`erp-module-start`(approve)或 `erp-feature-verify`(request-changes) diff --git a/skills/coding/erp-feature-review/templates/feature-review-template.md b/skills/coding/erp-feature-review/templates/feature-review-template.md deleted file mode 100644 index 27fa018..0000000 --- a/skills/coding/erp-feature-review/templates/feature-review-template.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -req_id: {{req_id}} -date: {{date}} -round: {{round}} -reviewer: superpower-code-reviewer ---- - -# Review: {{req_id}} — round {{round}} - -## 结论 -{{verdict}} (approve / request-changes) - -## Must-fix -{{#each must_fix}} -- [{{severity}}] {{file}}:{{line}} — {{issue}}(建议:{{suggestion}}) -{{/each}} - -## Nice-to-have -{{#each nice_to_have}} -- {{file}}:{{line}} — {{suggestion}} -{{/each}} - -## 反例 / 测试覆盖缺口 -{{gaps}} diff --git a/skills/coding/erp-feature-tdd/SKILL.md b/skills/coding/erp-feature-tdd/SKILL.md deleted file mode 100644 index 9a74487..0000000 --- a/skills/coding/erp-feature-tdd/SKILL.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -name: erp-feature-tdd -description: 功能循环第 3 步。逐任务执行计划:写失败测试 → 实现代码 → 测试通过 → 提交。所有测试运行均派发到子会话执行。 -user-invocable: false -allowed-tools: Read Write Edit Agent Skill Bash(git add *) Bash(git commit *) ---- - -**所有输出必须使用中文。** - -# erp-feature-tdd - -## 执行步骤 - -1. **红旗检查**:调用 `erp-red-flag-check`。 -2. 加载计划文件 `docs/superpowers/plans/YYYY-MM-DD-.md`。 -3. **Schema 改动优先(如果计划声明了需要)**:若 plan 标注 "本 REQ 需要 schema 改动",**第一个任务必须是写 migration 文件**: - - `ls sql/migrations/V*.sql` 得最大版本号 n_max,新文件版本号 = n_max + 1 - - 文件名格式 `V__.sql`,例 `V5__add_user_email.sql` - - `Write` 该文件(只含 DDL:`ALTER TABLE ... ADD COLUMN ...` / `CREATE TABLE ...` 等),commit - - 之后的代码任务(entity / DAO / service / 测试)在此之后做;测试运行时 Spring Boot 启动会由 Flyway 自动 apply 这个新 migration(`scripts/setup-test-db.sh` 只负责清空库) -4. 按顺序处理每个(代码类)任务: - a. 在 `test_file::test_name` 处编写失败测试。 - b. **派发子会话**(通过 `Agent`,general-purpose)运行测试并确认失败;子会话只返回 `{command, exit_code, failing_assertion}`。主会话**不直接**运行测试。 - c. 在 `impl_file` 处实现最小代码使测试通过。 - d. **再次派发子会话**运行测试并确认通过。 - e. 持续失败(同一测试 >10 次修复尝试)→ 调用 `erp-red-flag-check`(红旗 #1)。 - f. 暂存变更并使用 `${CLAUDE_SKILL_DIR}/templates/commit-message-template.md` 提交;`scope` 匹配任务的模块,`subject` ≤50 字符,`req_id` 必填。 -5. 所有任务完成后 → 交接给 `erp-feature-verify`。 - -## 护栏 - -- **绝不**在主会话直接运行 `mvn test` / `pnpm test` / `scripts/test.sh`,必须通过子会话。 -- 每次提交必须包含 REQ-XXX-NNN 标签。 -- 不要将不相关的变更合并到一次提交中。 -- **禁止**在主会话直接 `mysql -e "ALTER ..."` 执行业务 DDL;所有业务 schema 变更必须走 `sql/migrations/V_n__.sql` 文件(只读查询 / 临时调试探索除外)。 - -## 衔接 - -立即调用 `Skill(erp-feature-verify)` 进入下一步。 - -## 参考 - -- `${CLAUDE_SKILL_DIR}/templates/commit-message-template.md` -- 原则参考:`superpowers:test-driven-development`(本插件未镜像;仅作为 TDD 原则手册参考,不做运行时 invoke — 本 skill 已把"子会话跑测试 + REQ tag commit"流程直接写死) -- 守门:`erp-red-flag-check` diff --git a/skills/coding/erp-feature-tdd/templates/commit-message-template.md b/skills/coding/erp-feature-tdd/templates/commit-message-template.md deleted file mode 100644 index ecf5222..0000000 --- a/skills/coding/erp-feature-tdd/templates/commit-message-template.md +++ /dev/null @@ -1 +0,0 @@ -{{type}}({{scope}}): {{subject}} {{req_id}} diff --git a/skills/coding/erp-feature-verify/SKILL.md b/skills/coding/erp-feature-verify/SKILL.md deleted file mode 100644 index aea6773..0000000 --- a/skills/coding/erp-feature-verify/SKILL.md +++ /dev/null @@ -1,40 +0,0 @@ ---- -name: erp-feature-verify -description: 功能循环第 4 步。将本功能的测试派发到子会话执行,用模板渲染验证证据。无证据不得声称完成。 -user-invocable: false -allowed-tools: Skill Read Write Agent ---- - -**所有输出必须使用中文。** - -# erp-feature-verify - -## 执行步骤 - -1. 从计划文件或项目标准命令中确定功能的测试目标(Maven profile / pnpm script / pytest path)。 -2. **派发子会话**(通过 `Agent`,general-purpose),prompt 类似: - - ``` - 任务:运行功能测试目标并报告结果。不要修改任何代码。步骤: - 1. 执行:(例如 mvn -pl user-module test -Dtest=REQ*) - 2. 仅返回结构化 JSON:{"command":"","exit_code":,"passed":,"failed":,"failed_list":["", ...],"stdout_excerpt":"<最后 30 行或最相关的失败摘录>"} - 不要输出任何描述性文字。 - ``` - -3. 解析 JSON;用 `Read` 读取 `${CLAUDE_SKILL_DIR}/templates/feature-verify-evidence-template.md`,填充槽位(包括 `subagent_id` 和 `conclusion`)。 -4. 如果 `exit_code != 0` 或 `failed > 0` → 打印填充后的证据到会话并**停止**,不进入审阅。 -5. 通过 → 打印证据,交接给 `erp-feature-review`。 - -## 护栏 - -- 不要将原始测试 stdout 粘贴到主会话(超过 30 行的 `stdout_excerpt`)。 -- 证据必须从模板渲染,不能自由编写。 - -## 衔接 - -立即调用 `Skill(erp-feature-review)` 进入下一步。 - -## 参考 - -- `${CLAUDE_SKILL_DIR}/templates/feature-verify-evidence-template.md` -- 原则参考:`superpowers:verification-before-completion`(本插件未镜像;仅作为"证据先于断言"原则参考,不做运行时 invoke — 本 skill 已把子会话派发 + 模板渲染证据流程直接写死) diff --git a/skills/coding/erp-feature-verify/templates/feature-verify-evidence-template.md b/skills/coding/erp-feature-verify/templates/feature-verify-evidence-template.md deleted file mode 100644 index efaa70b..0000000 --- a/skills/coding/erp-feature-verify/templates/feature-verify-evidence-template.md +++ /dev/null @@ -1,16 +0,0 @@ -## Verify evidence — {{req_id}} - -- 命令: `{{command}}` -- 子会话: {{subagent_id}} -- 退出码: {{exit_code}} -- 通过用例数: {{passed}} -- 失败用例数: {{failed}} -- 失败列表: {{failed_list}} - -关键 stdout 片段 (≤30 行): - -``` -{{stdout_excerpt}} -``` - -结论: {{conclusion}} (pass / fail) diff --git a/skills/coding/erp-local-test-gate/SKILL.md b/skills/coding/erp-local-test-gate/SKILL.md deleted file mode 100644 index a044ebe..0000000 --- a/skills/coding/erp-local-test-gate/SKILL.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -name: erp-local-test-gate -description: MR 创建前的唯一硬闸门。子会话执行 scripts/test.sh(setup-test-db.sh 清库后,Spring Boot 启动时 Flyway 自动 apply 当前 sql/migrations/V*.sql),任一失败则停止。 -user-invocable: false -allowed-tools: Read Write Skill Agent Bash(git add *) Bash(git commit *) ---- - -**所有输出必须使用中文。** - -# erp-local-test-gate - -## 执行步骤 - -1. **派发子会话**(`Agent`,general-purpose)运行 `./scripts/test.sh`: - - ``` - 任务:运行项目本地测试闸门。不要修改任何代码或数据。步骤: - 1. cd 到仓库根目录。 - 2. 执行:./scripts/test.sh - 3. 仅返回 JSON:{"command":"./scripts/test.sh","exit_code":,"passed":,"failed":,"stdout_excerpt":"<最后 30 行,包含 FAIL 摘要>"} - 不要输出任何描述性文字。 - ``` - -2. 用 `Read` 读取 `${CLAUDE_SKILL_DIR}/templates/test-gate-result-template.md`,用结果填充槽位。 - -3. 写入 `docs/superpowers/module-reports/-test-gate.md`。 - -3b. **commit evidence 到 module 分支**(确保 test-gate.md 随 MR 合并进默认分支,审计可追溯): - - ```bash - git add docs/superpowers/module-reports/-test-gate.md - git commit -m "chore(): add local test-gate evidence" - ``` - -4. 如果 `exit_code = 0` → 交接给 `erp-module-report`(输出 `local-test-gate: 通过`)。 - -5. 否则打印以下横幅并**停下**(不自动重试、不自动修复——失败分类需人工判断): - - ``` - ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - [erp-local-test-gate] ⚠️ 未通过 - - 失败清单: <失败测试清单(来自子会话 JSON)> - stdout 摘录: <最后 30 行 / FAIL 摘要> - 详细证据: docs/superpowers/module-reports/-test-gate.md - - 请根据失败类型选择下一步: - - ① 测试脆弱(flakey,偶发) - → 重新运行 /erp-workflow:erp-coding-start - (module-start 幂等:reviews 已全 approve 会跳过功能循环,直接重新执行本闸门) - - ② 真有回归(某个 REQ 破坏了其他 REQ/已合并模块) - → 定位到具体 REQ,删除其 review 记录: - rm docs/superpowers/reviews/*-.md - → 重新运行 /erp-workflow:erp-coding-start - (module-start 把该 REQ 视为未完成,重走 brainstorm→...→review 循环修复) - - ③ 环境/依赖问题(DB 连不上、外部 API 失败、证书失效) - → 命中红旗 #3(外部接口不可达) - → 调用 Skill(erp-red-flag-check) 追加 Blocker 到本模块任一 plan 文件 - → 修复环境后重新运行 /erp-workflow:erp-coding-start - ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ``` - - 然后**停止**,不调用下游 skill(module-report / mr-create)。 - -## 护栏 - -- **绝不**在主会话直接执行 `./scripts/test.sh`。 -- **绝不**通过 `git push --no-verify` 绕过(hook `deny-no-verify.sh` 会拦截)。 - -## 衔接 - -立即调用 `Skill(erp-module-report)` 生成模块报告。 - -## 参考 - -- `${CLAUDE_SKILL_DIR}/templates/test-gate-result-template.md` diff --git a/skills/coding/erp-local-test-gate/templates/test-gate-result-template.md b/skills/coding/erp-local-test-gate/templates/test-gate-result-template.md deleted file mode 100644 index 1382801..0000000 --- a/skills/coding/erp-local-test-gate/templates/test-gate-result-template.md +++ /dev/null @@ -1,16 +0,0 @@ -## Local test gate — {{module_id}} - -执行时间: {{timestamp}} - -### scripts/test.sh (subagent) -- 子会话: {{subagent_id}} -- 命令: {{command}} -- 退出码: {{exit_code}} -- 通过: {{passed}} / 失败: {{failed}} -- 关键 stdout (≤30 行): - -``` -{{stdout_excerpt}} -``` - -结论: {{conclusion}} (green / red) diff --git a/skills/coding/erp-module-report/SKILL.md b/skills/coding/erp-module-report/SKILL.md deleted file mode 100644 index 6e125aa..0000000 --- a/skills/coding/erp-module-report/SKILL.md +++ /dev/null @@ -1,54 +0,0 @@ ---- -name: erp-module-report -description: 本地测试闸门通过后,生成标准化 12 节模块完成报告,嵌入本模块新增的 migration 清单和跨模块改动日志。 -user-invocable: false -allowed-tools: Read Write Glob Grep Skill Bash(git diff *) Bash(git log *) Bash(git add *) Bash(git commit *) ---- - -**所有输出必须使用中文。** - -# erp-module-report - -## 执行步骤 - -0. **红旗检查**:调用 `Skill(erp-red-flag-check)` → 命中则停止(与 `erp-red-flag-check` SKILL 描述"生成模块级制品前"对齐)。 - -1. 验证上游:`erp-local-test-gate` 返回了绿色。否则停止。 -2. 收集输入(优先 shell 摘要,避免把 diff 正文读进上下文): - - **文件变更 § ③** — 只用摘要,**不**读 diff 正文: - - `git diff --stat ..HEAD` → 每文件增减行数 - - `git diff --name-status ..HEAD` → A/M/D 状态 - - `git log --oneline ..HEAD` → commit 列表 - - `docs/superpowers/specs|plans|reviews/-<本模块的 REQ>.md` → § ②、§ ⑨(正常 Read,一般不大) - - **§ ⑥ 本模块新增 migration**:用 `git diff --name-only --diff-filter=A ..HEAD -- 'sql/migrations/V*.sql'` 列出本模块提交的新 migration 文件;每个文件 Read 第一行(V_n 描述)作为说明 - - `docs/superpowers/module-reports/-cross-module.md` → § ⑦ - - `docs/superpowers/module-reports/-test-gate.md` → § ⑤ - - § ④(读写的表):**用 `grep -rlE "(SELECT|INSERT|UPDATE|DELETE).*FROM|INTO"` 定位涉及 SQL 的文件,再按需读取片段**。不要全量读取 docs/03。 -3. 用 `Read` 读取 `${CLAUDE_SKILL_DIR}/templates/module-report-template.md`,填充全部 12 节。 -4. **硬性验证**: - - § ⑦:如果 cross-module 有任何行含 `TBD(CC 补)` → **停止**,调用 `Skill(erp-cross-module-log)` 让 CC **自主推断**补齐,补完再回本步骤重验。 - - § ⑦:如果非空但某行缺少影响评估(被填成空/敷衍)→ 同样调 `erp-cross-module-log` 重补。 - - § ⑧ 必须列举所有偏离规格之处;如果没有,明确写"无偏离"。 -5. 写入 `docs/superpowers/module-reports/$(date +%F)-.md`。 - -5b. **commit 模块报告 + cross-module 日志到 module 分支**(确保审计证据随 MR 合并进默认分支;erp-mr-create 的 worktree clean 前置条件依赖此步): - - ```bash - git add docs/superpowers/module-reports/$(date +%F)-.md - # cross-module log 若存在且有改动(erp-cross-module-log 补齐过 TBD)也一并提交 - [ -f "docs/superpowers/module-reports/-cross-module.md" ] && \ - git add docs/superpowers/module-reports/-cross-module.md - git commit -m "docs(): add module completion report + cross-module log" - ``` - -6. 交接给 `erp-mr-create`。 - -## 衔接 - -立即调用 `Skill(erp-mr-create)` 推送并创建 MR。 - -## 参考 - -- `${CLAUDE_SKILL_DIR}/templates/module-report-template.md`(12 节) -- 上游:`erp-local-test-gate` -- 下游:`erp-mr-create` diff --git a/skills/coding/erp-module-report/templates/module-report-template.md b/skills/coding/erp-module-report/templates/module-report-template.md deleted file mode 100644 index 30c8281..0000000 --- a/skills/coding/erp-module-report/templates/module-report-template.md +++ /dev/null @@ -1,67 +0,0 @@ ---- -module_id: {{module_id}} -date: {{date}} -git_range: {{git_range}} ---- - -# 模块完成报告 — {{module_id}} {{module_name}} - -## ① 模块信息 -- 模块 ID: {{module_id}} -- 模块名: {{module_name}} -- 开发区间: {{git_range}} - -## ② REQ 完成清单 -{{#each reqs}} -- [{{status}}] {{req_id}} — {{title}} - - spec: docs/superpowers/specs/{{date}}-{{req_id}}.md - - plan: docs/superpowers/plans/{{date}}-{{req_id}}.md - - review: docs/superpowers/reviews/{{date}}-{{req_id}}.md -{{/each}} - -## ③ 文件变更表 -| 文件 | 操作 | 说明 | -|---|---|---| -{{#each file_changes}} -| {{path}} | {{action}} | {{note}} | -{{/each}} - -## ④ 数据库使用表 -- 读: {{tables_read}} -- 写: {{tables_written}} - -## ⑤ 测试结果 -- `scripts/test.sh` 最终:{{test_conclusion}} -- 通过: {{passed}} / 失败: {{failed}} / 跳过: {{skipped}} -- 覆盖率: {{coverage}} - -## ⑥ 本模块新增 Migration - -{{#each migrations}} -- `sql/migrations/{{filename}}` — {{desc}} -{{/each}} - -(若本模块无 schema 改动,写 "—") - -## ⑦ 跨模块改动清单(软规则 S2) - -{{cross_module_contents}} - -## ⑧ 偏离 spec 清单 -{{#each deviations}} -- {{req_id}}: {{deviation}} (原因: {{reason}}) -{{/each}} - -## ⑨ AI reviewer 报告汇总 -{{#each reviews}} -- {{req_id}}: round {{round}} — {{verdict}}(link: docs/superpowers/reviews/{{date}}-{{req_id}}.md) -{{/each}} - -## ⑩ 已知问题 -{{known_issues}} - -## ⑪ 下一模块预览 -{{next_module}} - -## ⑫ MR 链接 -{{mr_url}} diff --git a/skills/coding/erp-module-start/SKILL.md b/skills/coding/erp-module-start/SKILL.md deleted file mode 100644 index adf0330..0000000 --- a/skills/coding/erp-module-start/SKILL.md +++ /dev/null @@ -1,85 +0,0 @@ ---- -name: erp-module-start -description: 启动/恢复模块循环。按 docs/02 § 二 REQ 清单定位当前模块及其 REQ 序列,确保处于模块分支,扫描 docs/superpowers/reviews/ 计算已完成 REQ,驱动第一个未完成 REQ 的功能循环;全部完成则调用 erp-local-test-gate。幂等可重入。 -user-invocable: false -allowed-tools: Read Write Skill Glob Grep Bash(git branch *) Bash(git checkout *) Bash(git rev-parse *) Bash(curl *) Bash(jq *) Bash(mkdir -p .tmp) Bash(rm -f .tmp/*) ---- - -**所有输出必须使用中文。** - -# erp-module-start - -## 执行步骤 - -### 步骤 1:按 `docs/02 § 二` REQ 序 + MR state 定位当前模块 + 本模块 REQ 列表 - -与 `erp-coding-start` 步骤 3 同构(完成判定以 `MR:` 字段 + GitLab API `state` 为准;curl 调用,凭据读 `.env.local` 的 `GITLAB_API_URL` / `GITLAB_TOKEN` / `GITLAB_PROJECT_ID`): - -- 用 `Read` 读取 `docs/02-开发计划.md`,用 `Grep`(pattern `^\|\s*[0-9]+\s*\|\s*\*\*(REQ-[A-Z0-9]+-[0-9]+)\*\*\s*\|\s*(module_\w+)`)抽取 § 二 表格数据行,按行号升序得 `req_order[]`。 -- 若 `req_order` 为空 → 打印"⚠️ docs/02 § 二 REQ 开发顺序清单为空或无法解析,请检查"并停止。 -- 初始化 `module_merged[module_id → bool]` 空缓存。按序遍历 `req_order[]`: - - `module_merged[module_id]` 已缓存为 `true` → 跳过本 REQ。 - - `module_merged[module_id]` 已缓存为 `false` → `current_module = module_id`,结束遍历。 - - 未缓存 → 读取 docs/08 § 二 该模块条目的 ` - MR:` 字段: - - `MR: —` → `module_merged[module_id] = false`,`current_module = module_id`,结束遍历。 - - `MR: !` → 先 `Bash`: `set -a; . ./.env.local; set +a`,然后**分步校验 HTTP + 返回条数 + state 枚举**(语义与 `erp-coding-start` 步骤 3 严格一致): - ```bash - mkdir -p .tmp - HTTP_CODE=$(curl -sS -o .tmp/mr.json -w '%{http_code}' \ - --header "PRIVATE-TOKEN: ${GITLAB_TOKEN}" \ - "${GITLAB_API_URL}/projects/${GITLAB_PROJECT_ID}/merge_requests?iid=") - ``` - 硬停条件(任一命中 → 打印与 `erp-coding-start` 同款诊断横幅后**停下**,不进入下游 skill): - 1. `HTTP_CODE != 200` - 2. `HTTP_CODE == 200` 但 `jq 'length' .tmp/mr.json != 1` - 3. state 不在 `{merged, opened, closed}` 里 - - 通过后按 state 分派: - - `merged` → 缓存 `true`,跳过本 REQ - - `opened` / `closed` → 缓存 `false`,`current_module = module_id`,结束遍历 -- **抽取本模块 REQ 序列 `req_list[]`**:从 `req_order[]` 取出所有 `module_id == current_module` 的项,按原序组成(同模块 REQ 必须连续,见 A5 约束)。 -- 用 `Read` 读取 docs/08 § 二 该模块行 + 后续缩进行,提取 `module_name` / `depends_on`(REQ 列表以 docs/02 为准,不再读取 docs/08)。 - -### 步骤 2:所有模块已完成短路 - -如果 `req_order[]` 全部遍历完 `current_module` 仍未赋值(即所有模块都 merged)→ 打印"所有模块已完成"摘要并停止。 - -### 步骤 3:确保处于模块分支 - -- `target_branch = module-`(例 `module-module_sys`)。 -- 用 `Bash` 执行 `git branch --show-current` 得 `current_branch`。 -- `current_branch == target_branch` → 继续步骤 4。 -- 否则用 `Bash` 执行 `git rev-parse --verify 2>/dev/null`: - - 存在 → `git checkout ` - - 不存在 → `git checkout -b ` -- 若当前工作区有未提交改动且 checkout 失败 → 打印错误并停止(请用户手工处理 dirty state)。 - -### 步骤 4:初始化跨模块日志(幂等) - -`docs/superpowers/module-reports/-cross-module.md` — 不存在则从 `${CLAUDE_SKILL_DIR}/templates/cross-module-log-template.md` 创建。 - -### 步骤 5:计算已完成 REQ 集合 `done_reqs[]`(幂等断点恢复关键) - -- 对 `req_list[]` 每个 `req_id`,用 `Glob` 查 `docs/superpowers/reviews/*-.md`。 -- 命中后用 `Grep`(pattern `^verdict:\s*approve`,`-i` 不敏感)检查首部 verdict。 -- 两者都命中 → 加入 `done_reqs[]`。 - -### 步骤 6:渲染并打印模块横幅 - -`Read ${CLAUDE_SKILL_DIR}/templates/module-start-banner-template.md`,填充槽位;`reqs[]` 每项的 `status` 字段根据 `done_reqs[]` 填 `x`(已完成)或空格(未完成)。 - -### 步骤 7:推进主循环 - -- 从 `req_list[]` 取第一个不在 `done_reqs[]` 中的 REQ 作为 `next_req`。 -- **没有 `next_req`**(全部完成)→ 调用 `Skill(erp-local-test-gate)` 进入模块闸门。 -- **有 `next_req`** → 调用 `Skill(erp-feature-brainstorm)` 启动该 REQ 的功能循环。功能循环链(brainstorm → plan → tdd → verify → review)完成后,`erp-feature-review` 在 `verdict=approve` 分支会回调 `Skill(erp-module-start)` —— 再次进入本 skill 时,步骤 5 会把刚通过的 REQ 加入 `done_reqs[]`,步骤 7 自动取下一 REQ,形成可重入推进。 -- 任何中断(红旗 / 测试持续失败 / review 5 轮仍 request-changes)→ 停止本模块,不要静默跳下一 REQ。 - -## 参考 - -- `docs/02-开发计划.md § 二 开发顺序清单`(分发权威) -- `docs/08-模块任务管理.md § 二`(模块元数据,含 `MR:` 字段;完成判定以 MR state 为准) -- `docs/superpowers/reviews/*.md`(REQ 级进度事实——verdict=approve 即完成) -- `${CLAUDE_SKILL_DIR}/templates/module-start-banner-template.md` -- `${CLAUDE_SKILL_DIR}/templates/cross-module-log-template.md` -- 下游:`erp-feature-*`、`erp-local-test-gate` diff --git a/skills/coding/erp-module-start/templates/cross-module-log-template.md b/skills/coding/erp-module-start/templates/cross-module-log-template.md deleted file mode 100644 index 3a653ed..0000000 --- a/skills/coding/erp-module-start/templates/cross-module-log-template.md +++ /dev/null @@ -1,8 +0,0 @@ -# 跨模块改动日志 — {{module_name}} - -软规则 S2:本模块开发期间对**非当前模块**代码的改动(无论目标模块是否已 MR merged)记录在此;模块完成报告必须单列「跨模块改动」节完整贴入。漏留痕或未评估影响 → 升级为红旗。 - -**本日志由 CC 自主维护**——hook `log-cross-module.sh` 自动落存根(含 `TBD(CC 补)` 占位),CC 调 `erp-cross-module-log` skill 自主推断补「原因 / 影响评估」两列。**不需要人工填写**。 - -| 时间戳 | 目标模块 | 文件 | 改动摘要 | 原因 | 影响评估 | -|---|---|---|---|---|---| diff --git a/skills/coding/erp-module-start/templates/module-start-banner-template.md b/skills/coding/erp-module-start/templates/module-start-banner-template.md deleted file mode 100644 index 81ae4e2..0000000 --- a/skills/coding/erp-module-start/templates/module-start-banner-template.md +++ /dev/null @@ -1,11 +0,0 @@ -## Module start — {{module_id}} ({{module_name}}) - -- 模块依赖: {{depends_on}} -- 对应需求文件: docs/01-需求清单/{{req_file}} -- 分支: module-{{module_id}} -- 功能清单(`x` = 已完成 review approve): -{{#each reqs}} - - [{{status}}] {{req_id}} — {{title}} -{{/each}} - -开始/恢复功能循环(Layer 3),本次处理清单中第一个未完成 REQ。命中红旗 → 停;所有 REQ 完成 → 进入模块闸门。 diff --git a/skills/coding/erp-mr-create/SKILL.md b/skills/coding/erp-mr-create/SKILL.md deleted file mode 100644 index e580354..0000000 --- a/skills/coding/erp-mr-create/SKILL.md +++ /dev/null @@ -1,183 +0,0 @@ ---- -name: erp-mr-create -description: 模块报告完成后,验证当前分支为 module- 且 worktree 干净,push 推代码和所有 evidence,创建 GitLab MR(报告嵌入描述),把 MR URL 追加到模块报告 § ⑫ 并 commit,把 MR iid 回写到 docs/08 该模块 `MR:` 字段并 commit,再次 push 同步。完成信号由 MR merged state 判定。停下等待人工审核。 -user-invocable: false -allowed-tools: Read Write Edit Skill Bash(git *) Bash(curl *) Bash(jq *) Bash(sed *) Bash(awk *) Bash(cat *) Bash(echo *) Bash(mkdir -p .tmp) Bash(mv .tmp/*) Bash(rm -f .tmp/*) ---- - -**所有输出必须使用中文。** - -# erp-mr-create - -## 前置条件 - -- `erp-module-report` 已生成报告文件并 commit 到 module 分支。 -- `erp-local-test-gate` 返回了绿色,test-gate.md 已 commit 到 module 分支。 -- 当前分支 = `module-`(由 `erp-module-start` 步骤 3 负责切入)。 - -## 执行步骤 - -### 步骤 0:红旗检查 - -调用 `Skill(erp-red-flag-check)` → 命中则停止。 - -### 步骤 1:验证当前分支 - -- `Bash`: `git branch --show-current` → `current_branch`。 -- `current_branch` 必须匹配 `module-*`;否则打印错误并**停止**(不自动创建分支——分支职责在 `erp-module-start` 步骤 3)。 -- 从 `current_branch` 取 `module_id = current_branch` 去掉 `"module-"` 前缀。 - -### 步骤 2:验证 worktree 干净(防止 evidence 文件漏 commit) - -- `Bash`: `git status --porcelain` -- 输出非空 → 打印 dirty 文件清单并**停止**: - ``` - ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - [erp-mr-create] ⚠️ worktree 不干净,无法 push - - 以下文件有未提交改动: - - - push 前所有 evidence 必须已 commit 到 module 分支。检查点: - - erp-local-test-gate 步骤 3b 是否已 commit test-gate.md? - - erp-module-report 步骤 5b 是否已 commit 模块报告 + cross-module log? - - 本 skill 前没人跑过额外的 Edit/Write? - - 修复方式:`git add && git commit -m "..."`,然后重新运行 /erp-workflow:erp-coding-start。 - ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ``` - -### 步骤 3:push 推送全部已 commit 内容 - -`git push -u origin ` — **不要**使用 `--no-verify`(hook `deny-no-verify.sh` 会拦截)。 - -此 push 包含:代码 commit(erp-feature-tdd 产出)+ 模块 review fix commit(erp-feature-review 产出)+ test-gate evidence commit(erp-local-test-gate 产出)+ 模块完成报告 commit(erp-module-report 产出)。 - -### 步骤 4:读取 MR 标题模板 - -用 `Read` 读取 `${CLAUDE_SKILL_DIR}/templates/mr-title-template.md`,填充 `module_id`、`module_name`,得到 MR 标题字符串(一行,较短,进上下文 OK)。 - -### 步骤 5:生成 MR 描述文件(纯 shell,不读模块报告内容进上下文) - -```bash -mkdir -p .tmp -DESC_FILE=.tmp/mr-desc.md -REPORT="docs/superpowers/module-reports/-.md" - -# 先用 sed 替换 description 模板的简单槽位 -sed -e "s|{{test_gate_conclusion}}|<值>|g" \ - -e "s|{{test_subagent_id}}|<值>|g" \ - -e "s|{{module_id}}|<值>|g" \ - -e "s|{{date}}|<值>|g" \ - "${CLAUDE_SKILL_DIR}/templates/mr-description-template.md" > "$DESC_FILE" - -# 把模块报告完整内容直接管道注入,替换 {{module_report_contents}} 所在行 -awk -v report="$REPORT" ' - /\{\{module_report_contents\}\}/ { while ((getline line < report) > 0) print line; close(report); next } - { print } -' "$DESC_FILE" > .tmp/mr-desc.final -mv .tmp/mr-desc.final "$DESC_FILE" -``` - -关键:**模块报告内容只经 awk 管道流过**,从不进入 LLM 上下文。 - -### 步骤 5.3:加载 GitLab 凭据并探测目标分支 - -```bash -# 加载 .env.local 中的 GITLAB_API_URL / GITLAB_TOKEN / GITLAB_PROJECT_ID -set -a; . ./.env.local; set +a -for v in GITLAB_API_URL GITLAB_TOKEN GITLAB_PROJECT_ID; do - eval "val=\${$v:-}"; [ -n "$val" ] || { echo "[erp-mr-create] ⚠️ .env.local 缺少 $v"; exit 1; } -done - -# 探测默认分支作为 target_branch(与 erp-coding-start 同策略) -TARGET_BRANCH=$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's|refs/remotes/origin/||') -[ -n "$TARGET_BRANCH" ] || TARGET_BRANCH=$(git branch -r --format='%(refname:short)' | grep -E '^origin/(main|master)$' | head -1 | sed 's|^origin/||') -[ -n "$TARGET_BRANCH" ] || { echo "[erp-mr-create] ⚠️ 无法探测默认分支(origin/main 或 origin/master)"; exit 1; } -``` - -### 步骤 5.5:幂等守门——检查 source branch 是否已有 opened MR - -防止部分失败后重试创建重复 MR;查询失败不吞,硬停避免误创第二个 MR: - -```bash -mkdir -p .tmp -HTTP_CODE=$(curl -sS -o .tmp/existing.json -w '%{http_code}' \ - --header "PRIVATE-TOKEN: ${GITLAB_TOKEN}" \ - "${GITLAB_API_URL}/projects/${GITLAB_PROJECT_ID}/merge_requests?source_branch=${current_branch}&state=opened") -if [ "$HTTP_CODE" != "200" ]; then - echo "[erp-mr-create] ⚠️ 查询已有 opened MR 失败 (HTTP $HTTP_CODE)" >&2 - jq -r '.message // .error // .' .tmp/existing.json | head -c 200 >&2; echo >&2 - echo " 请核对 .env.local 的 GITLAB_API_URL / GITLAB_TOKEN / GITLAB_PROJECT_ID 后重跑" >&2 - rm -f .tmp/existing.json - exit 1 -fi -EXISTING_IID=$(jq -r '.[0].iid // empty' .tmp/existing.json) -EXISTING_URL=$(jq -r '.[0].web_url // empty' .tmp/existing.json) -rm -f .tmp/existing.json -``` - -- `EXISTING_IID` 非空 → 打印 `[erp-mr-create] 检测到已有 opened MR: !${EXISTING_IID}`,**跳过步骤 6**,直接用 `EXISTING_IID` / `EXISTING_URL` 进入步骤 7。 -- `EXISTING_IID` 为空 → 正常走步骤 6 创建新 MR。 - -### 步骤 6:创建 MR(仅当 5.5 未命中时) - -```bash -TITLE="<步骤 4 得到的标题>" - -CREATE_RESP=$(curl -sS -X POST \ - --header "PRIVATE-TOKEN: ${GITLAB_TOKEN}" \ - --header "Content-Type: application/json" \ - --data "$(jq -n \ - --arg src "$current_branch" \ - --arg tgt "$TARGET_BRANCH" \ - --arg title "$TITLE" \ - --rawfile desc "$DESC_FILE" \ - '{source_branch: $src, target_branch: $tgt, title: $title, description: $desc, remove_source_branch: false}')" \ - "${GITLAB_API_URL}/projects/${GITLAB_PROJECT_ID}/merge_requests") - -MR_IID=$(echo "$CREATE_RESP" | jq -r '.iid // empty') -MR_URL=$(echo "$CREATE_RESP" | jq -r '.web_url // empty') -[ -n "$MR_IID" ] || { echo "[erp-mr-create] ⚠️ MR 创建失败,API 响应:"; echo "$CREATE_RESP" | jq . >&2; exit 1; } -rm -f "$DESC_FILE" -``` - -对应 5.5 命中时复用 `EXISTING_IID` / `EXISTING_URL` 作为 `MR_IID` / `MR_URL`。 - -### 步骤 7:回写 docs/08 的 MR 字段并 commit(durable state 先持久化) - -> 先写 docs/08 再追模块报告——这样如果步骤 8 失败,重跑时 5.5 能直接识别已有 MR 且 docs/08 已含 IID,避免状态不一致。 - -- `Edit docs/08-模块任务管理.md`:把当前模块条目的 ` - MR: —` 改为 ` - MR: !`(只改一行)。docs/08 § 二 中 `MR:` 是唯一动态字段。 -- `Bash`: `git add docs/08-模块任务管理.md && git commit -m "chore(): record MR ! in docs/08"`。 - -### 步骤 8:追加 MR URL 到模块报告 § ⑫ 并 commit - -- `Edit docs/superpowers/module-reports/-.md` 的 § ⑫:把 `{{mr_url}}` 占位替换为 ``(若已替换过,追加一行)。 -- `Bash`: `git add docs/superpowers/module-reports/-.md && git commit -m "docs(): record MR ! link in module report"`。 - -### 步骤 9:再次 push - -步骤 3 的 push 之后,步骤 7、8 又产生了两个新 commit(docs/08 MR iid + 模块报告 MR link)。必须再次 push 让 MR 自动更新 commit 列表 + diff: - -`Bash`: `git push origin ` - -### 步骤 10:向会话打印 MR URL - -### 步骤 11:停止 — 等待人工 Approve + Merge - -用户合并后再次运行 `/erp-workflow:erp-coding-start`,入口会自动检测 MR merged → 探测默认分支(`main` 或 `master`)→ `git checkout <默认分支>` + `git pull --ff-only origin <默认分支>` 同步远程 → 派发下一模块。 - -## 设计要点 - -- **默认分支(main 或 master)是 protected branch**,只能通过 MR 修改。MR diff 覆盖代码、模块报告、test-gate evidence、cross-module log,以及 docs/08 的 `MR: !` 字段。 -- **完成信号以 MR state 为准**:docs/08 § 二 中仅 `MR:` 字段在 `—` / `!` 之间变化,避免提前合并未完成模块的顺序错误。 -- **worktree 干净前置**(步骤 2):保证 test-gate.md、module-report.md、cross-module log.md 都已进 repo,审计证据完整;防止下次 coding-start 切回默认分支时遇到 dirty state。 - -## 参考 - -- `${CLAUDE_SKILL_DIR}/templates/mr-title-template.md` -- `${CLAUDE_SKILL_DIR}/templates/mr-description-template.md` -- 上游:`erp-module-report` -- 守门:`erp-red-flag-check` -- 下游闸门:用户手工 MR Approve + Merge diff --git a/skills/coding/erp-mr-create/templates/mr-description-template.md b/skills/coding/erp-mr-create/templates/mr-description-template.md deleted file mode 100644 index c5db7e5..0000000 --- a/skills/coding/erp-mr-create/templates/mr-description-template.md +++ /dev/null @@ -1,18 +0,0 @@ -## 模块完成报告 - -见 `docs/superpowers/module-reports/{{date}}-{{module_id}}.md`(本 MR 仓库内完整贴入下方)。 - ---- - -{{module_report_contents}} - ---- - -## 本地闸门证据 - -- test.sh: {{test_gate_conclusion}}(subagent: {{test_subagent_id}}) - -## 审核入口 - -- 本 MR = 模块 `{{module_id}}` 的唯一人工介入点 -- Approve + Merge 后,下次用户运行 `/erp-workflow:erp-coding-start` 时入口会自动扫描到 GitLab API `state=merged`,探测默认分支后 `git pull --ff-only` 同步并推进下一模块 diff --git a/skills/coding/erp-mr-create/templates/mr-title-template.md b/skills/coding/erp-mr-create/templates/mr-title-template.md deleted file mode 100644 index 2cf9c1a..0000000 --- a/skills/coding/erp-mr-create/templates/mr-title-template.md +++ /dev/null @@ -1 +0,0 @@ -feat({{module_id}}): {{module_name}} diff --git a/skills/coding/feature-brainstorm/SKILL.md b/skills/coding/feature-brainstorm/SKILL.md new file mode 100644 index 0000000..0c68dc8 --- /dev/null +++ b/skills/coding/feature-brainstorm/SKILL.md @@ -0,0 +1,39 @@ +--- +name: feature-brainstorm +description: 功能循环第 1 步。针对单个 REQ-XXX-NNN 进行交互式头脑风暴,产出功能规格文件到 docs/superpowers/specs/。 +user-invocable: false +allowed-tools: Read Write Skill Bash(mysql *) +--- + +**所有输出必须使用中文。** + +# feature-brainstorm + +## 说明 + +针对一个 REQ-XXX-NNN,委托本插件的 `superpower-brainstorming`(superpowers:brainstorming 的本地 fork,已剥掉 approval gates)进行头脑风暴,再把输出填入标准规格模板,产出单页功能规格。 + +## 执行步骤 + +1. **中断检查**:调用 `interrupt-check`。如果触发 → 停止。 +2. 确定输入: + - 当前 REQ-XXX-NNN(从对话中获取,或 `docs/08` 当前模块下一个未完成的 REQ)。 + - REQ 卡片:`docs/01-需求清单/.md` 中对应的 REQ-XXX-NNN 节。 + - 相关数据表(从 `docs/03` 或实时 mysql 命令行查询)。 +3. 委托本插件 `superpower-brainstorming`,以 REQ 卡片 + schema 引用作为上下文;把步骤 4 推导出的落盘路径作为 caller-provided path 传入。 +4. 推导路径:`docs/superpowers/specs/$(date +%F)-.md`。如已存在,征求用户确认后覆盖。 +5. 用 `Read` 读取 `${CLAUDE_SKILL_DIR}/templates/feature-spec-template.md`,从头脑风暴输出填充槽位: + - `goal`、`input`、`output`、`rules`、`constraints`、`schema_refs`、`api_refs`、`acceptance` +6. 将填充后的规格写入推导路径。 +7. **验证**:模板中每个顶级节必须非空;**spec 全文不得包含 `【人工填写:...】` 或 `TBD`**。如出现:先在 `.env.local` / `docs/07-环境配置.md` / `CLAUDE.md` / 现有代码中查找真值并写入(同时注明来源),查不到则用 `AskUserQuestion` 向用户询问;拒绝把"待人工填写"的标记写入 B 阶段 spec(该标记仅供 A 阶段用户审阅文档用)。 +8. 输出 `feature-brainstorm: `。 + +## 衔接 + +立即调用 `Skill(feature-plan)` 进入下一步。 + +## 参考 + +- `${CLAUDE_SKILL_DIR}/templates/feature-spec-template.md` +- 委托:`superpower-brainstorming`(本插件 `skills/internal/superpower-brainstorming/`,superpowers:brainstorming 的无门 fork) +- 守门:`interrupt-check` diff --git a/skills/coding/feature-brainstorm/templates/feature-spec-template.md b/skills/coding/feature-brainstorm/templates/feature-spec-template.md new file mode 100644 index 0000000..09715ab --- /dev/null +++ b/skills/coding/feature-brainstorm/templates/feature-spec-template.md @@ -0,0 +1,31 @@ +--- +req_id: {{req_id}} +date: {{date}} +module: {{module}} +--- + +# Spec: {{req_id}} — {{title}} + +## 目标 +{{goal}} + +## 输入 / 触发 +{{input}} + +## 输出 / 结果 +{{output}} + +## 业务规则 +{{rules}} + +## 边界与约束 +{{constraints}} + +## 依赖的 schema 表 / 字段 +{{schema_refs}} + +## 依赖的接口 +{{api_refs}} + +## 验收标准 +{{acceptance}} diff --git a/skills/coding/feature-plan/SKILL.md b/skills/coding/feature-plan/SKILL.md new file mode 100644 index 0000000..84a8d99 --- /dev/null +++ b/skills/coding/feature-plan/SKILL.md @@ -0,0 +1,34 @@ +--- +name: feature-plan +description: 功能循环第 2 步。将规格转化为任务级计划(每任务 2-5 分钟,含文件路径和完整代码),输出到 docs/superpowers/plans/。 +user-invocable: false +allowed-tools: Read Write Grep Skill +--- + +**所有输出必须使用中文。** + +# feature-plan + +## 执行步骤 + +1. **中断检查**:调用 `interrupt-check`。 +2. 确定输入: + - 当前 REQ-XXX-NNN 及其规格文件 `docs/superpowers/specs/YYYY-MM-DD-.md`(规格不存在则报错)。 + - 相关代码指针(已有的待修改文件,通过 Grep 发现)。 + - `docs/04-技术规范.md` 和 `docs/09-项目目录结构.md`(编码规范 + 目录规范)。 +3. 委托本插件 `superpower-writing-plans`(superpowers:writing-plans 的本地 fork,已剥掉"Which approach?"执行交接门),以规格 + 代码指针 + 规范作为上下文;把步骤 4 推导出的落盘路径作为 caller-provided path 传入。 +4. 推导路径:`docs/superpowers/plans/$(date +%F)-.md`。 +5. 用 `Read` 读取 `${CLAUDE_SKILL_DIR}/templates/feature-plan-template.md`,填充 `files[]`、`tasks[]`、`commits[]`。 +6. 强制要求:每个任务有失败测试标识、实现路径和完成标准;**plan 全文不得包含 `【人工填写:...】` 或 `TBD`**——该标记仅限 A 阶段用户审阅文档,B 阶段 plan 必须写具体值(先在 `.env.local` / `docs/07` / `CLAUDE.md` / 现有代码查找并注明来源;查不到就 `AskUserQuestion` 向用户问)。 +7. 写入计划文件。 +8. 输出 `feature-plan: `。 + +## 衔接 + +立即调用 `Skill(feature-tdd)` 进入下一步。 + +## 参考 + +- `${CLAUDE_SKILL_DIR}/templates/feature-plan-template.md` +- 委托:`superpower-writing-plans`(本插件 `skills/internal/superpower-writing-plans/`,superpowers:writing-plans 的无门 fork) +- 守门:`interrupt-check` diff --git a/skills/coding/feature-plan/templates/feature-plan-template.md b/skills/coding/feature-plan/templates/feature-plan-template.md new file mode 100644 index 0000000..00d36f6 --- /dev/null +++ b/skills/coding/feature-plan/templates/feature-plan-template.md @@ -0,0 +1,28 @@ +--- +req_id: {{req_id}} +date: {{date}} +spec_ref: docs/superpowers/specs/{{date}}-{{req_id}}.md +--- + +# Plan: {{req_id}} + +## Schema 改动 +{{schema_change_decision}} + +## 文件变更清单 +{{#each files}} +- `{{path}}` — {{action}}({{rationale}}) +{{/each}} + +## 任务步骤 +{{#each tasks}} +### Task {{index}}: {{title}} +- 失败测试: `{{test_file}}::{{test_name}}` — {{test_intent}} +- 实现路径: `{{impl_file}}` +- 完成判据: {{done_when}} +{{/each}} + +## 提交计划 +{{#each commits}} +- `{{message}}`(覆盖 Task {{task_index}}) +{{/each}} diff --git a/skills/coding/feature-review/SKILL.md b/skills/coding/feature-review/SKILL.md new file mode 100644 index 0000000..1621fb8 --- /dev/null +++ b/skills/coding/feature-review/SKILL.md @@ -0,0 +1,41 @@ +--- +name: feature-review +description: 功能循环第 5 步。AI 自审,输出审阅报告到 docs/superpowers/reviews/。approve 回调 module-start;request-changes 则编辑代码并 fix commit,重新执行 verify。自修复循环上限 5 轮。 +user-invocable: false +allowed-tools: Read Write Edit Skill Agent Bash(git add *) Bash(git commit *) +--- + +**所有输出必须使用中文。** + +# feature-review + +## 执行步骤 + +1. 通过 `Agent(subagent_type=superpower-code-reviewer)` 调用本插件 code-reviewer agent(superpowers:code-reviewer 的本地 fork),以该 REQ 的 diff(`git diff ..HEAD`)和规格作为输入。 +2. 推导路径:`docs/superpowers/reviews/$(date +%F)-.md`。 +3. 用 `Read` 读取 `${CLAUDE_SKILL_DIR}/templates/feature-review-template.md`,填充 `round`、`verdict`、`must_fix[]`、`nice_to_have[]`、`gaps`。verdict 必须是 `approve` 或 `request-changes`。 +4. 写入报告。 + +5. 分发: + - **`verdict = approve`** → 用 `Edit` 在 `docs/08-模块任务管理.md § 二` 本模块 bullet 下找到 ` - [ ] ...` 行勾选为 ` - [x] ...`(功能级进度可视化;模块完成仍由 `MR:` + GitLab API state 判定,不依赖本勾选)。然后输出 `feature-review: round 通过`,调用 `Skill(module-start)` 回模块主循环(module-start 会自动把本 REQ 识别为 done 并推进下一个 REQ)。 + - **`verdict = request-changes`** → 执行"自修复子流程": + - 逐项处理 `must_fix[]`:对每个条目用 `Edit` 修改其指向的代码文件。 + - 所有 Must-fix 修复后,拼 commit 消息(格式与 `feature-tdd` 一致,单行):`fix(): 修复 review round must-fix `。 + - `Bash`: `git add <修改的代码文件>` + `git commit -m "<上一步拼出的消息>"`。 + - 调用 `Skill(feature-verify)` 重新执行验证;verify 通过后会再次链到本 skill,作为 round `` 重审。 + +6. 上限:**5 轮**。第 5 轮仍为 `request-changes` → 停止并打印摘要(升级给用户手工介入),不再自动修复,不回调 module-start。 + +## 衔接 + +- `approve` → `Skill(module-start)` 回主循环。 +- `request-changes`(round < 5)→ `Skill(feature-verify)` 重新执行。 +- `request-changes`(round == 5)→ 停止。 + +## 参考 + +- `${CLAUDE_SKILL_DIR}/templates/feature-review-template.md` +- Fix commit 格式与 `feature-tdd` 的 `commit-message-template.md` 对齐(`fix(): `) +- 委托:`superpower-code-reviewer`(本插件 `agents/superpower-code-reviewer.md`,superpowers:code-reviewer 的本地 fork) +- 上游:`feature-verify` +- 下游:`module-start`(approve)或 `feature-verify`(request-changes) diff --git a/skills/coding/feature-review/templates/feature-review-template.md b/skills/coding/feature-review/templates/feature-review-template.md new file mode 100644 index 0000000..27fa018 --- /dev/null +++ b/skills/coding/feature-review/templates/feature-review-template.md @@ -0,0 +1,24 @@ +--- +req_id: {{req_id}} +date: {{date}} +round: {{round}} +reviewer: superpower-code-reviewer +--- + +# Review: {{req_id}} — round {{round}} + +## 结论 +{{verdict}} (approve / request-changes) + +## Must-fix +{{#each must_fix}} +- [{{severity}}] {{file}}:{{line}} — {{issue}}(建议:{{suggestion}}) +{{/each}} + +## Nice-to-have +{{#each nice_to_have}} +- {{file}}:{{line}} — {{suggestion}} +{{/each}} + +## 反例 / 测试覆盖缺口 +{{gaps}} diff --git a/skills/coding/feature-tdd/SKILL.md b/skills/coding/feature-tdd/SKILL.md new file mode 100644 index 0000000..5920010 --- /dev/null +++ b/skills/coding/feature-tdd/SKILL.md @@ -0,0 +1,47 @@ +--- +name: feature-tdd +description: 功能循环第 3 步。逐任务执行计划:写失败测试 → 实现代码 → 测试通过 → 提交。所有测试运行均派发到子会话执行。 +user-invocable: false +allowed-tools: Read Write Edit Agent Skill Bash(git add *) Bash(git commit *) +--- + +**所有输出必须使用中文。** + +# feature-tdd + +## 执行步骤 + +1. **中断检查**:调用 `interrupt-check`。 +2. 加载计划文件 `docs/superpowers/plans/YYYY-MM-DD-.md`。 +3. **Schema 改动优先(如果计划声明了需要)**:若 plan 标注 "本 REQ 需要 schema 改动",**第一个任务必须是写 migration 文件 + 同步更新 docs/03**: + - `ls sql/migrations/V*.sql` 得最大版本号 n_max,新文件版本号 = n_max + 1 + - 文件名格式 `V__.sql`,例 `V5__add_user_email.sql` + - `Write` 该文件(只含 DDL:`ALTER TABLE ... ADD COLUMN ...` / `CREATE TABLE ...` 等) + - **同步把新 CREATE/ALTER 反向更新到 `docs/03-数据库设计文档.md` 对应表小节**(字段表格 / 索引 / 外键 / 业务注记),保持 docs/03 仍是 schema SSoT;新增表则按 `docs-03-table-template.md` 格式追加一节 + - 把 migration + docs/03 改动**一起 commit**(避免 SSoT 与 migration 分裂) + - 之后的代码任务(entity / DAO / service / 测试)在此之后做;测试运行时 Spring Boot 启动会由 Flyway 自动 apply 这个新 migration(`scripts/setup-test-db.sh` 只负责清空库) +4. 按顺序处理每个(代码类)任务: + a. 在 `test_file::test_name` 处编写失败测试。 + b. **派发子会话**(通过 `Agent`,general-purpose)运行测试并确认失败;子会话只返回 `{command, exit_code, failing_assertion}`。主会话**不直接**运行测试。 + c. 在 `impl_file` 处实现最小代码使测试通过。 + d. **再次派发子会话**运行测试并确认通过。 + e. 持续失败(同一测试 >10 次修复尝试)→ 调用 `interrupt-check`(中断 #1)。 + f. 暂存变更并使用 `${CLAUDE_SKILL_DIR}/templates/commit-message-template.md` 提交;`scope` 匹配任务的模块,`subject` ≤50 字符,`req_id` 必填。 +5. 所有任务完成后 → 交接给 `feature-verify`。 + +## 护栏 + +- **绝不**在主会话直接运行 `mvn test` / `pnpm test` / `scripts/test.sh`,必须通过子会话。 +- 每次提交必须包含 REQ-XXX-NNN 标签。 +- 不要将不相关的变更合并到一次提交中。 +- **禁止**在主会话直接 `mysql -e "ALTER ..."` 执行业务 DDL;所有业务 schema 变更必须走 `sql/migrations/V_n__.sql` 文件(只读查询 / 临时调试探索除外)。 + +## 衔接 + +立即调用 `Skill(feature-verify)` 进入下一步。 + +## 参考 + +- `${CLAUDE_SKILL_DIR}/templates/commit-message-template.md` +- 原则参考:`superpowers:test-driven-development`(本插件未镜像;仅作为 TDD 原则手册参考,不做运行时 invoke — 本 skill 已把"子会话跑测试 + REQ tag commit"流程直接写死) +- 守门:`interrupt-check` diff --git a/skills/coding/feature-tdd/templates/commit-message-template.md b/skills/coding/feature-tdd/templates/commit-message-template.md new file mode 100644 index 0000000..ecf5222 --- /dev/null +++ b/skills/coding/feature-tdd/templates/commit-message-template.md @@ -0,0 +1 @@ +{{type}}({{scope}}): {{subject}} {{req_id}} diff --git a/skills/coding/feature-verify/SKILL.md b/skills/coding/feature-verify/SKILL.md new file mode 100644 index 0000000..33ae76e --- /dev/null +++ b/skills/coding/feature-verify/SKILL.md @@ -0,0 +1,40 @@ +--- +name: feature-verify +description: 功能循环第 4 步。将本功能的测试派发到子会话执行,用模板渲染验证证据。无证据不得声称完成。 +user-invocable: false +allowed-tools: Skill Read Agent +--- + +**所有输出必须使用中文。** + +# feature-verify + +## 执行步骤 + +1. 从计划文件或项目标准命令中确定功能的测试目标(Maven profile / pnpm script / pytest path)。 +2. **派发子会话**(通过 `Agent`,general-purpose),prompt 类似: + + ``` + 任务:运行功能测试目标并报告结果。不要修改任何代码。步骤: + 1. 执行:(例如 mvn -pl user-module test -Dtest=REQ*) + 2. 仅返回结构化 JSON:{"command":"","exit_code":,"passed":,"failed":,"failed_list":["", ...],"stdout_excerpt":"<最后 30 行或最相关的失败摘录>"} + 不要输出任何描述性文字。 + ``` + +3. 解析 JSON;用 `Read` 读取 `${CLAUDE_SKILL_DIR}/templates/feature-verify-evidence-template.md`,填充槽位(包括 `subagent_id` 和 `conclusion`)。 +4. 如果 `exit_code != 0` 或 `failed > 0` → 打印填充后的证据到会话并**停止**,不进入审阅。 +5. 通过 → 打印证据,交接给 `feature-review`。 + +## 护栏 + +- 不要将原始测试 stdout 粘贴到主会话(超过 30 行的 `stdout_excerpt`)。 +- 证据必须从模板渲染,不能自由编写。 + +## 衔接 + +立即调用 `Skill(feature-review)` 进入下一步。 + +## 参考 + +- `${CLAUDE_SKILL_DIR}/templates/feature-verify-evidence-template.md` +- 原则参考:`superpowers:verification-before-completion`(本插件未镜像;仅作为"证据先于断言"原则参考,不做运行时 invoke — 本 skill 已把子会话派发 + 模板渲染证据流程直接写死) diff --git a/skills/coding/feature-verify/templates/feature-verify-evidence-template.md b/skills/coding/feature-verify/templates/feature-verify-evidence-template.md new file mode 100644 index 0000000..efaa70b --- /dev/null +++ b/skills/coding/feature-verify/templates/feature-verify-evidence-template.md @@ -0,0 +1,16 @@ +## Verify evidence — {{req_id}} + +- 命令: `{{command}}` +- 子会话: {{subagent_id}} +- 退出码: {{exit_code}} +- 通过用例数: {{passed}} +- 失败用例数: {{failed}} +- 失败列表: {{failed_list}} + +关键 stdout 片段 (≤30 行): + +``` +{{stdout_excerpt}} +``` + +结论: {{conclusion}} (pass / fail) diff --git a/skills/coding/module-report/SKILL.md b/skills/coding/module-report/SKILL.md new file mode 100644 index 0000000..89b42a1 --- /dev/null +++ b/skills/coding/module-report/SKILL.md @@ -0,0 +1,54 @@ +--- +name: module-report +description: 本地测试闸门通过后,生成标准化 12 节模块完成报告,嵌入本模块新增的 migration 清单和跨模块改动日志。 +user-invocable: false +allowed-tools: Read Write Glob Grep Skill Bash(git diff *) Bash(git log *) Bash(git add *) Bash(git commit *) +--- + +**所有输出必须使用中文。** + +# module-report + +## 执行步骤 + +0. **中断检查**:调用 `Skill(interrupt-check)` → 触发则停止(与 `interrupt-check` SKILL 描述"生成模块级制品前"对齐)。 + +1. 验证上游:`test-gate` 返回了绿色。否则停止。 +2. 收集输入(优先 shell 摘要,避免把 diff 正文读进上下文): + - **文件变更 § ③** — 只用摘要,**不**读 diff 正文: + - `git diff --stat ..HEAD` → 每文件增减行数 + - `git diff --name-status ..HEAD` → A/M/D 状态 + - `git log --oneline ..HEAD` → commit 列表 + - `docs/superpowers/specs|plans|reviews/-<本模块的 REQ>.md` → § ②、§ ⑨(正常 Read,一般不大) + - **§ ⑥ 本模块新增 migration**:用 `git diff --name-only --diff-filter=A ..HEAD -- 'sql/migrations/V*.sql'` 列出本模块提交的新 migration 文件;每个文件 Read 第一行(V_n 描述)作为说明 + - `docs/superpowers/module-reports/-cross-module.md` → § ⑦ + - `docs/superpowers/module-reports/-test-gate.md` → § ⑤ + - § ④(读写的表):**用 `grep -rlE "(SELECT|INSERT|UPDATE|DELETE).*FROM|INTO"` 定位涉及 SQL 的文件,再按需读取片段**。不要全量读取 docs/03。 +3. 用 `Read` 读取 `${CLAUDE_SKILL_DIR}/templates/module-report-template.md`,填充全部 12 节。 +4. **硬性验证 + 批量补齐跨模块 TBD**: + - § ⑦:这是整模块周期里**唯一补齐 `TBD(CC 补)` 的时机**(编辑中途 CC 不应主动调 `cross-module-log`)。如果 cross-module 有任何行含 `TBD(CC 补)` → 调用 `Skill(cross-module-log)` 一次性批量补齐所有 TBD,补完再回本步骤重验。 + - § ⑦:如果非空但某行缺少影响评估(被填成空/敷衍)→ 同样调 `cross-module-log` 重补。 + - § ⑧ 必须列举所有偏离规格之处;如果没有,明确写"无偏离"。 +5. 写入 `docs/superpowers/module-reports/$(date +%F)-.md`。 + +5b. **commit 模块报告 + cross-module 日志到 module 分支**(确保审计证据随 MR 合并进默认分支;mr-create 的 worktree clean 前置条件依赖此步): + + ```bash + git add docs/superpowers/module-reports/$(date +%F)-.md + # cross-module log 若存在且有改动(cross-module-log 补齐过 TBD)也一并提交 + [ -f "docs/superpowers/module-reports/-cross-module.md" ] && \ + git add docs/superpowers/module-reports/-cross-module.md + git commit -m "docs(): add module completion report + cross-module log" + ``` + +6. 交接给 `mr-create`。 + +## 衔接 + +立即调用 `Skill(mr-create)` 推送并创建 MR。 + +## 参考 + +- `${CLAUDE_SKILL_DIR}/templates/module-report-template.md`(12 节) +- 上游:`test-gate` +- 下游:`mr-create` diff --git a/skills/coding/module-report/templates/module-report-template.md b/skills/coding/module-report/templates/module-report-template.md new file mode 100644 index 0000000..30c8281 --- /dev/null +++ b/skills/coding/module-report/templates/module-report-template.md @@ -0,0 +1,67 @@ +--- +module_id: {{module_id}} +date: {{date}} +git_range: {{git_range}} +--- + +# 模块完成报告 — {{module_id}} {{module_name}} + +## ① 模块信息 +- 模块 ID: {{module_id}} +- 模块名: {{module_name}} +- 开发区间: {{git_range}} + +## ② REQ 完成清单 +{{#each reqs}} +- [{{status}}] {{req_id}} — {{title}} + - spec: docs/superpowers/specs/{{date}}-{{req_id}}.md + - plan: docs/superpowers/plans/{{date}}-{{req_id}}.md + - review: docs/superpowers/reviews/{{date}}-{{req_id}}.md +{{/each}} + +## ③ 文件变更表 +| 文件 | 操作 | 说明 | +|---|---|---| +{{#each file_changes}} +| {{path}} | {{action}} | {{note}} | +{{/each}} + +## ④ 数据库使用表 +- 读: {{tables_read}} +- 写: {{tables_written}} + +## ⑤ 测试结果 +- `scripts/test.sh` 最终:{{test_conclusion}} +- 通过: {{passed}} / 失败: {{failed}} / 跳过: {{skipped}} +- 覆盖率: {{coverage}} + +## ⑥ 本模块新增 Migration + +{{#each migrations}} +- `sql/migrations/{{filename}}` — {{desc}} +{{/each}} + +(若本模块无 schema 改动,写 "—") + +## ⑦ 跨模块改动清单(软规则 S2) + +{{cross_module_contents}} + +## ⑧ 偏离 spec 清单 +{{#each deviations}} +- {{req_id}}: {{deviation}} (原因: {{reason}}) +{{/each}} + +## ⑨ AI reviewer 报告汇总 +{{#each reviews}} +- {{req_id}}: round {{round}} — {{verdict}}(link: docs/superpowers/reviews/{{date}}-{{req_id}}.md) +{{/each}} + +## ⑩ 已知问题 +{{known_issues}} + +## ⑪ 下一模块预览 +{{next_module}} + +## ⑫ MR 链接 +{{mr_url}} diff --git a/skills/coding/module-start/SKILL.md b/skills/coding/module-start/SKILL.md new file mode 100644 index 0000000..70124d8 --- /dev/null +++ b/skills/coding/module-start/SKILL.md @@ -0,0 +1,87 @@ +--- +name: module-start +description: 启动/恢复模块循环。按 docs/02 § 二 REQ 清单定位当前模块及其 REQ 序列,确保处于模块分支,扫描 docs/superpowers/reviews/ 计算已完成 REQ,驱动第一个未完成 REQ 的功能循环;全部完成则调用 test-gate。幂等可重入。 +user-invocable: false +allowed-tools: Read Write Skill Glob Grep Bash(git branch *) Bash(git checkout *) Bash(git rev-parse *) Bash(curl *) Bash(jq *) Bash(mkdir -p .tmp) Bash(rm -f .tmp/*) +--- + +**所有输出必须使用中文。** + +# module-start + +## 执行步骤 + +### 步骤 1:按 `docs/02 § 二` REQ 序 + MR state 定位当前模块 + 本模块 REQ 列表 + +> `MR:` 字段 × GitLab API state 的三组合判定规则见 `CLAUDE.md § ✅ 模块完成判定规则 § 模块状态语义`。 + +与 `coding-start` 步骤 3 同构(完成判定以 `MR:` 字段 + GitLab API `state` 为准;curl 调用,凭据读 `.env.local` 的 `GITLAB_API_URL` / `GITLAB_TOKEN` / `GITLAB_PROJECT_ID`): + +- 用 `Read` 读取 `docs/02-开发计划.md`,用 `Grep`(pattern `^\|\s*[0-9]+\s*\|\s*\*\*(REQ-[A-Z0-9]+-[0-9]+)\*\*\s*\|\s*(module_\w+)`)抽取 § 二 表格数据行,按行号升序得 `req_order[]`。 +- 若 `req_order` 为空 → 打印"⚠️ docs/02 § 二 REQ 开发顺序清单为空或无法解析,请检查"并停止。 +- 初始化 `module_merged[module_id → bool]` 空缓存。按序遍历 `req_order[]`: + - `module_merged[module_id]` 已缓存为 `true` → 跳过本 REQ。 + - `module_merged[module_id]` 已缓存为 `false` → `current_module = module_id`,结束遍历。 + - 未缓存 → 读取 docs/08 § 二 该模块条目的 ` - MR:` 字段: + - `MR: —` → `module_merged[module_id] = false`,`current_module = module_id`,结束遍历。 + - `MR: !` → 先 `Bash`: `set -a; . ./.env.local; set +a`,然后**分步校验 HTTP + 返回条数 + state 枚举**(语义与 `coding-start` 步骤 3 严格一致): + ```bash + mkdir -p .tmp + HTTP_CODE=$(curl -sS -o .tmp/mr.json -w '%{http_code}' \ + --header "PRIVATE-TOKEN: ${GITLAB_TOKEN}" \ + "${GITLAB_API_URL}/projects/${GITLAB_PROJECT_ID}/merge_requests?iid=") + ``` + 硬停条件(任一触发 → 打印与 `coding-start` 同款诊断横幅后**停下**,不进入下游 skill): + 1. `HTTP_CODE != 200` + 2. `HTTP_CODE == 200` 但 `jq 'length' .tmp/mr.json != 1` + 3. state 不在 `{merged, opened, closed}` 里 + + 通过后按 state 分派: + - `merged` → 缓存 `true`,跳过本 REQ + - `opened` / `closed` → 缓存 `false`,`current_module = module_id`,结束遍历 +- **抽取本模块 REQ 序列 `req_list[]`**:从 `req_order[]` 取出所有 `module_id == current_module` 的项,按原序组成(同模块 REQ 必须连续,见 A5 约束)。 +- 用 `Read` 读取 docs/08 § 二 该模块行 + 后续缩进行,提取 `module_name` / `depends_on`(REQ 列表以 docs/02 为准,不再读取 docs/08)。 + +### 步骤 2:所有模块已完成短路 + +如果 `req_order[]` 全部遍历完 `current_module` 仍未赋值(即所有模块都 merged)→ 打印"所有模块已完成"摘要并停止。 + +### 步骤 3:确保处于模块分支 + +- `target_branch = module-`(例 `module-module_sys`)。 +- 用 `Bash` 执行 `git branch --show-current` 得 `current_branch`。 +- `current_branch == target_branch` → 继续步骤 4。 +- 否则用 `Bash` 执行 `git rev-parse --verify 2>/dev/null`: + - 存在 → `git checkout ` + - 不存在 → `git checkout -b ` +- 若当前工作区有未提交改动且 checkout 失败 → 打印错误并停止(请用户手工处理 dirty state)。 + +### 步骤 4:初始化跨模块日志(幂等) + +`docs/superpowers/module-reports/-cross-module.md` — 不存在则从 `${CLAUDE_SKILL_DIR}/templates/cross-module-log-template.md` 创建。 + +### 步骤 5:计算已完成 REQ 集合 `done_reqs[]`(幂等断点恢复关键) + +- 对 `req_list[]` 每个 `req_id`,用 `Glob` 查 `docs/superpowers/reviews/*-.md`。 +- 命中后用 `Grep`(pattern `^verdict:\s*approve`,`-i` 不敏感)检查首部 verdict。 +- 两者都命中 → 加入 `done_reqs[]`。 + +### 步骤 6:渲染并打印模块横幅 + +`Read ${CLAUDE_SKILL_DIR}/templates/module-start-banner-template.md`,填充槽位;`reqs[]` 每项的 `status` 字段根据 `done_reqs[]` 填 `x`(已完成)或空格(未完成)。 + +### 步骤 7:推进主循环 + +- 从 `req_list[]` 取第一个不在 `done_reqs[]` 中的 REQ 作为 `next_req`。 +- **没有 `next_req`**(全部完成)→ 调用 `Skill(test-gate)` 进入模块闸门。 +- **有 `next_req`** → 调用 `Skill(feature-brainstorm)` 启动该 REQ 的功能循环。功能循环链(brainstorm → plan → tdd → verify → review)完成后,`feature-review` 在 `verdict=approve` 分支会回调 `Skill(module-start)` —— 再次进入本 skill 时,步骤 5 会把刚通过的 REQ 加入 `done_reqs[]`,步骤 7 自动取下一 REQ,形成可重入推进。 +- 任何停止条件触发(中断触发 / 测试持续失败 / review 5 轮仍 request-changes)→ 停止本模块,不要静默跳下一 REQ。 + +## 参考 + +- `docs/02-开发计划.md § 二 开发顺序清单`(分发权威) +- `docs/08-模块任务管理.md § 二`(模块元数据,含 `MR:` 字段;完成判定以 MR state 为准) +- `docs/superpowers/reviews/*.md`(REQ 级进度事实——verdict=approve 即完成) +- `${CLAUDE_SKILL_DIR}/templates/module-start-banner-template.md` +- `${CLAUDE_SKILL_DIR}/templates/cross-module-log-template.md` +- 下游:`feature-*`、`test-gate` diff --git a/skills/coding/module-start/templates/cross-module-log-template.md b/skills/coding/module-start/templates/cross-module-log-template.md new file mode 100644 index 0000000..e9338fb --- /dev/null +++ b/skills/coding/module-start/templates/cross-module-log-template.md @@ -0,0 +1,8 @@ +# 跨模块改动日志 — {{module_name}} + +软规则 S2:本模块开发期间对**非当前模块**代码的改动(无论目标模块是否已 MR merged)记录在此;模块完成报告必须单列「跨模块改动」节完整贴入。漏留痕或未评估影响 → 升级为中断。 + +**本日志由 CC 自主维护**——hook `log-cross-module.sh` 自动落存根(含 `TBD(CC 补)` 占位),CC 调 `cross-module-log` skill 自主推断补「原因 / 影响评估」两列。**不需要人工填写**。 + +| 时间戳 | 目标模块 | 文件 | 改动摘要 | 原因 | 影响评估 | +|---|---|---|---|---|---| diff --git a/skills/coding/module-start/templates/module-start-banner-template.md b/skills/coding/module-start/templates/module-start-banner-template.md new file mode 100644 index 0000000..77c9723 --- /dev/null +++ b/skills/coding/module-start/templates/module-start-banner-template.md @@ -0,0 +1,11 @@ +## Module start — {{module_id}} ({{module_name}}) + +- 模块依赖: {{depends_on}} +- 对应需求文件: docs/01-需求清单/{{req_file}} +- 分支: module-{{module_id}} +- 功能清单(`x` = 已完成 review approve): +{{#each reqs}} + - [{{status}}] {{req_id}} — {{title}} +{{/each}} + +开始/恢复功能循环(Layer 3),本次处理清单中第一个未完成 REQ。触发中断 → 停;所有 REQ 完成 → 进入模块闸门。 diff --git a/skills/coding/mr-create/SKILL.md b/skills/coding/mr-create/SKILL.md new file mode 100644 index 0000000..7f1b614 --- /dev/null +++ b/skills/coding/mr-create/SKILL.md @@ -0,0 +1,183 @@ +--- +name: mr-create +description: 模块报告完成后,验证当前分支为 module- 且 worktree 干净,push 推代码和所有 evidence,创建 GitLab MR(报告嵌入描述),把 MR URL 追加到模块报告 § ⑫ 并 commit,把 MR iid 回写到 docs/08 该模块 `MR:` 字段并 commit,再次 push 同步。完成信号由 MR merged state 判定。停下等待人工审核。 +user-invocable: false +allowed-tools: Read Write Edit Skill Bash(git *) Bash(curl *) Bash(jq *) Bash(sed *) Bash(awk *) Bash(cat *) Bash(echo *) Bash(mkdir -p .tmp) Bash(mv .tmp/*) Bash(rm -f .tmp/*) +--- + +**所有输出必须使用中文。** + +# mr-create + +## 前置条件 + +- `module-report` 已生成报告文件并 commit 到 module 分支。 +- `test-gate` 返回了绿色,test-gate.md 已 commit 到 module 分支。 +- 当前分支 = `module-`(由 `module-start` 步骤 3 负责切入)。 + +## 执行步骤 + +### 步骤 0:中断检查 + +调用 `Skill(interrupt-check)` → 触发则停止。 + +### 步骤 1:验证当前分支 + +- `Bash`: `git branch --show-current` → `current_branch`。 +- `current_branch` 必须匹配 `module-*`;否则打印错误并**停止**(不自动创建分支——分支职责在 `module-start` 步骤 3)。 +- 从 `current_branch` 取 `module_id = current_branch` 去掉 `"module-"` 前缀。 + +### 步骤 2:验证 worktree 干净(防止 evidence 文件漏 commit) + +- `Bash`: `git status --porcelain` +- 输出非空 → 打印 dirty 文件清单并**停止**: + ``` + ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + [mr-create] ⚠️ worktree 不干净,无法 push + + 以下文件有未提交改动: + + + push 前所有 evidence 必须已 commit 到 module 分支。检查点: + - test-gate 步骤 3b 是否已 commit test-gate.md? + - module-report 步骤 5b 是否已 commit 模块报告 + cross-module log? + - 本 skill 前没人跑过额外的 Edit/Write? + + 修复方式:`git add && git commit -m "..."`,然后重新运行 /erp-workflow:coding-start。 + ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + ``` + +### 步骤 3:push 推送全部已 commit 内容 + +`git push -u origin ` — **不要**使用 `--no-verify`(hook `deny-no-verify.sh` 会拦截)。 + +此 push 包含:代码 commit(feature-tdd 产出)+ 模块 review fix commit(feature-review 产出)+ test-gate evidence commit(test-gate 产出)+ 模块完成报告 commit(module-report 产出)。 + +### 步骤 4:读取 MR 标题模板 + +用 `Read` 读取 `${CLAUDE_SKILL_DIR}/templates/mr-title-template.md`,填充 `module_id`、`module_name`,得到 MR 标题字符串(一行,较短,进上下文 OK)。 + +### 步骤 5:生成 MR 描述文件(纯 shell,不读模块报告内容进上下文) + +```bash +mkdir -p .tmp +DESC_FILE=.tmp/mr-desc.md +REPORT="docs/superpowers/module-reports/-.md" + +# 先用 sed 替换 description 模板的简单槽位 +sed -e "s|{{test_gate_conclusion}}|<值>|g" \ + -e "s|{{test_subagent_id}}|<值>|g" \ + -e "s|{{module_id}}|<值>|g" \ + -e "s|{{date}}|<值>|g" \ + "${CLAUDE_SKILL_DIR}/templates/mr-description-template.md" > "$DESC_FILE" + +# 把模块报告完整内容直接管道注入,替换 {{module_report_contents}} 所在行 +awk -v report="$REPORT" ' + /\{\{module_report_contents\}\}/ { while ((getline line < report) > 0) print line; close(report); next } + { print } +' "$DESC_FILE" > .tmp/mr-desc.final +mv .tmp/mr-desc.final "$DESC_FILE" +``` + +关键:**模块报告内容只经 awk 管道流过**,从不进入 LLM 上下文。 + +### 步骤 5.3:加载 GitLab 凭据并探测目标分支 + +```bash +# 加载 .env.local 中的 GITLAB_API_URL / GITLAB_TOKEN / GITLAB_PROJECT_ID +set -a; . ./.env.local; set +a +for v in GITLAB_API_URL GITLAB_TOKEN GITLAB_PROJECT_ID; do + eval "val=\${$v:-}"; [ -n "$val" ] || { echo "[mr-create] ⚠️ .env.local 缺少 $v"; exit 1; } +done + +# 探测默认分支作为 target_branch(与 coding-start 同策略) +TARGET_BRANCH=$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's|refs/remotes/origin/||') +[ -n "$TARGET_BRANCH" ] || TARGET_BRANCH=$(git branch -r --format='%(refname:short)' | grep -E '^origin/(main|master)$' | head -1 | sed 's|^origin/||') +[ -n "$TARGET_BRANCH" ] || { echo "[mr-create] ⚠️ 无法探测默认分支(origin/main 或 origin/master)"; exit 1; } +``` + +### 步骤 5.5:幂等守门——检查 source branch 是否已有 opened MR + +防止部分失败后重试创建重复 MR;查询失败不吞,硬停避免误创第二个 MR: + +```bash +mkdir -p .tmp +HTTP_CODE=$(curl -sS -o .tmp/existing.json -w '%{http_code}' \ + --header "PRIVATE-TOKEN: ${GITLAB_TOKEN}" \ + "${GITLAB_API_URL}/projects/${GITLAB_PROJECT_ID}/merge_requests?source_branch=${current_branch}&state=opened") +if [ "$HTTP_CODE" != "200" ]; then + echo "[mr-create] ⚠️ 查询已有 opened MR 失败 (HTTP $HTTP_CODE)" >&2 + jq -r '.message // .error // .' .tmp/existing.json | head -c 200 >&2; echo >&2 + echo " 请核对 .env.local 的 GITLAB_API_URL / GITLAB_TOKEN / GITLAB_PROJECT_ID 后重跑" >&2 + rm -f .tmp/existing.json + exit 1 +fi +EXISTING_IID=$(jq -r '.[0].iid // empty' .tmp/existing.json) +EXISTING_URL=$(jq -r '.[0].web_url // empty' .tmp/existing.json) +rm -f .tmp/existing.json +``` + +- `EXISTING_IID` 非空 → 打印 `[mr-create] 检测到已有 opened MR: !${EXISTING_IID}`,**跳过步骤 6**,直接用 `EXISTING_IID` / `EXISTING_URL` 进入步骤 7。 +- `EXISTING_IID` 为空 → 正常走步骤 6 创建新 MR。 + +### 步骤 6:创建 MR(仅当 5.5 未命中时) + +```bash +TITLE="<步骤 4 得到的标题>" + +CREATE_RESP=$(curl -sS -X POST \ + --header "PRIVATE-TOKEN: ${GITLAB_TOKEN}" \ + --header "Content-Type: application/json" \ + --data "$(jq -n \ + --arg src "$current_branch" \ + --arg tgt "$TARGET_BRANCH" \ + --arg title "$TITLE" \ + --rawfile desc "$DESC_FILE" \ + '{source_branch: $src, target_branch: $tgt, title: $title, description: $desc, remove_source_branch: false}')" \ + "${GITLAB_API_URL}/projects/${GITLAB_PROJECT_ID}/merge_requests") + +MR_IID=$(echo "$CREATE_RESP" | jq -r '.iid // empty') +MR_URL=$(echo "$CREATE_RESP" | jq -r '.web_url // empty') +[ -n "$MR_IID" ] || { echo "[mr-create] ⚠️ MR 创建失败,API 响应:"; echo "$CREATE_RESP" | jq . >&2; exit 1; } +rm -f "$DESC_FILE" +``` + +对应 5.5 命中时复用 `EXISTING_IID` / `EXISTING_URL` 作为 `MR_IID` / `MR_URL`。 + +### 步骤 7:回写 docs/08 的 MR 字段并 commit(durable state 先持久化) + +> 先写 docs/08 再追模块报告——这样如果步骤 8 失败,重跑时 5.5 能直接识别已有 MR 且 docs/08 已含 IID,避免状态不一致。 + +- `Edit docs/08-模块任务管理.md`:把当前模块条目的 ` - MR: —` 改为 ` - MR: !`(只改一行)。docs/08 § 二 中 `MR:` 是唯一动态字段。 +- `Bash`: `git add docs/08-模块任务管理.md && git commit -m "chore(): record MR ! in docs/08"`。 + +### 步骤 8:追加 MR URL 到模块报告 § ⑫ 并 commit + +- `Edit docs/superpowers/module-reports/-.md` 的 § ⑫:把 `{{mr_url}}` 占位替换为 ``(若已替换过,追加一行)。 +- `Bash`: `git add docs/superpowers/module-reports/-.md && git commit -m "docs(): record MR ! link in module report"`。 + +### 步骤 9:再次 push + +步骤 3 的 push 之后,步骤 7、8 又产生了两个新 commit(docs/08 MR iid + 模块报告 MR link)。必须再次 push 让 MR 自动更新 commit 列表 + diff: + +`Bash`: `git push origin ` + +### 步骤 10:向会话打印 MR URL + +### 步骤 11:停止 — 等待人工 Approve + Merge + +用户合并后再次运行 `/erp-workflow:coding-start`,入口会自动检测 MR merged → 探测默认分支(`main` 或 `master`)→ `git checkout <默认分支>` + `git pull --ff-only origin <默认分支>` 同步远程 → 派发下一模块。 + +## 设计要点 + +- **默认分支(main 或 master)是 protected branch**,只能通过 MR 修改。MR diff 覆盖代码、模块报告、test-gate evidence、cross-module log,以及 docs/08 的 `MR: !` 字段。 +- **完成信号以 MR state 为准**:docs/08 § 二 中仅 `MR:` 字段在 `—` / `!` 之间变化,避免提前合并未完成模块的顺序错误。 +- **worktree 干净前置**(步骤 2):保证 test-gate.md、module-report.md、cross-module log.md 都已进 repo,审计证据完整;防止下次 coding-start 切回默认分支时遇到 dirty state。 + +## 参考 + +- `${CLAUDE_SKILL_DIR}/templates/mr-title-template.md` +- `${CLAUDE_SKILL_DIR}/templates/mr-description-template.md` +- 上游:`module-report` +- 守门:`interrupt-check` +- 下游闸门:用户手工 MR Approve + Merge diff --git a/skills/coding/mr-create/templates/mr-description-template.md b/skills/coding/mr-create/templates/mr-description-template.md new file mode 100644 index 0000000..6850f62 --- /dev/null +++ b/skills/coding/mr-create/templates/mr-description-template.md @@ -0,0 +1,18 @@ +## 模块完成报告 + +见 `docs/superpowers/module-reports/{{date}}-{{module_id}}.md`(本 MR 仓库内完整贴入下方)。 + +--- + +{{module_report_contents}} + +--- + +## 本地闸门证据 + +- test.sh: {{test_gate_conclusion}}(subagent: {{test_subagent_id}}) + +## 审核入口 + +- 本 MR = 模块 `{{module_id}}` 的唯一人工介入点 +- Approve + Merge 后,下次用户运行 `/erp-workflow:coding-start` 时入口会自动扫描到 GitLab API `state=merged`,探测默认分支后 `git pull --ff-only` 同步并推进下一模块 diff --git a/skills/coding/mr-create/templates/mr-title-template.md b/skills/coding/mr-create/templates/mr-title-template.md new file mode 100644 index 0000000..2cf9c1a --- /dev/null +++ b/skills/coding/mr-create/templates/mr-title-template.md @@ -0,0 +1 @@ +feat({{module_id}}): {{module_name}} diff --git a/skills/coding/test-gate/SKILL.md b/skills/coding/test-gate/SKILL.md new file mode 100644 index 0000000..b921419 --- /dev/null +++ b/skills/coding/test-gate/SKILL.md @@ -0,0 +1,79 @@ +--- +name: test-gate +description: MR 创建前的唯一硬闸门。子会话执行 scripts/test.sh(setup-test-db.sh 清库后,Spring Boot 启动时 Flyway 自动 apply 当前 sql/migrations/V*.sql),任一失败则停止。 +user-invocable: false +allowed-tools: Read Write Skill Agent Bash(git add *) Bash(git commit *) +--- + +**所有输出必须使用中文。** + +# test-gate + +## 执行步骤 + +1. **派发子会话**(`Agent`,general-purpose)运行 `./scripts/test.sh`: + + ``` + 任务:运行项目本地测试闸门。不要修改任何代码或数据。步骤: + 1. cd 到仓库根目录。 + 2. 执行:./scripts/test.sh + 3. 仅返回 JSON:{"command":"./scripts/test.sh","exit_code":,"passed":,"failed":,"stdout_excerpt":"<最后 30 行,包含 FAIL 摘要>"} + 不要输出任何描述性文字。 + ``` + +2. 用 `Read` 读取 `${CLAUDE_SKILL_DIR}/templates/test-gate-result-template.md`,用结果填充槽位。 + +3. 写入 `docs/superpowers/module-reports/-test-gate.md`。 + +3b. **commit evidence 到 module 分支**(确保 test-gate.md 随 MR 合并进默认分支,审计可追溯): + + ```bash + git add docs/superpowers/module-reports/-test-gate.md + git commit -m "chore(): add local test-gate evidence" + ``` + +4. 如果 `exit_code = 0` → 交接给 `module-report`(输出 `test-gate: 通过`)。 + +5. 否则打印以下横幅并**停下**(不自动重试、不自动修复——失败分类需人工判断): + + ``` + ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + [test-gate] ⚠️ 未通过 + + 失败清单: <失败测试清单(来自子会话 JSON)> + stdout 摘录: <最后 30 行 / FAIL 摘要> + 详细证据: docs/superpowers/module-reports/-test-gate.md + + 请根据失败类型选择下一步: + + ① 测试脆弱(flakey,偶发) + → 重新运行 /erp-workflow:coding-start + (module-start 幂等:reviews 已全 approve 会跳过功能循环,直接重新执行本闸门) + + ② 真有回归(某个 REQ 破坏了其他 REQ/已合并模块) + → 定位到具体 REQ,删除其 review 记录: + rm docs/superpowers/reviews/*-.md + → 重新运行 /erp-workflow:coding-start + (module-start 把该 REQ 视为未完成,重走 brainstorm→...→review 循环修复) + + ③ 环境/依赖问题(DB 连不上、外部 API 失败、证书失效) + → 触发中断 #3(外部接口不可达) + → 调用 Skill(interrupt-check) 追加 Blocker 到本模块任一 plan 文件 + → 修复环境后重新运行 /erp-workflow:coding-start + ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + ``` + + 然后**停止**,不调用下游 skill(module-report / mr-create)。 + +## 护栏 + +- **绝不**在主会话直接执行 `./scripts/test.sh`。 +- **绝不**通过 `git push --no-verify` 绕过(hook `deny-no-verify.sh` 会拦截)。 + +## 衔接 + +立即调用 `Skill(module-report)` 生成模块报告。 + +## 参考 + +- `${CLAUDE_SKILL_DIR}/templates/test-gate-result-template.md` diff --git a/skills/coding/test-gate/templates/test-gate-result-template.md b/skills/coding/test-gate/templates/test-gate-result-template.md new file mode 100644 index 0000000..1382801 --- /dev/null +++ b/skills/coding/test-gate/templates/test-gate-result-template.md @@ -0,0 +1,16 @@ +## Local test gate — {{module_id}} + +执行时间: {{timestamp}} + +### scripts/test.sh (subagent) +- 子会话: {{subagent_id}} +- 命令: {{command}} +- 退出码: {{exit_code}} +- 通过: {{passed}} / 失败: {{failed}} +- 关键 stdout (≤30 行): + +``` +{{stdout_excerpt}} +``` + +结论: {{conclusion}} (green / red) diff --git a/skills/crosscut/coding-start/SKILL.md b/skills/crosscut/coding-start/SKILL.md new file mode 100644 index 0000000..3aa8cb1 --- /dev/null +++ b/skills/crosscut/coding-start/SKILL.md @@ -0,0 +1,168 @@ +--- +name: coding-start +description: B 阶段(Coding)入口。先验证 Plan 已完成;按 docs/02 § 二 REQ 开发顺序清单扫描,对每个 REQ 所属模块用 docs/08 的 `MR:` 字段 + GitLab API state 判定是否完成——merged 跳过,`—` 或 opened/closed 选为当前模块并派发到 module-start。派发前自动探测默认分支(main / master)并 git checkout + pull --ff-only 保持 base 最新。 +user-invocable: true +allowed-tools: Skill Read Glob Grep Bash(curl *) Bash(jq *) Bash(git branch *) Bash(git checkout *) Bash(git pull *) Bash(git status *) Bash(git symbolic-ref *) Bash(sed *) Bash(mkdir -p .tmp) Bash(rm -f .tmp/*) +--- + +**所有输出必须使用中文。** + +B 阶段(Coding)的入口分发器。职责:**验证 Plan 已完成 → 按 docs/02 § 二 REQ 序 + MR state 定位当前模块 → 切回默认分支并同步远程 → 派发 module-start**。不直接生成任何文件。开发顺序以 `docs/02 § 二` 为准;完成判定以 `docs/08 条目的 MR: 字段 + GitLab API state` 为准(curl 调用,凭据读 `.env.local` 的 `GITLAB_API_URL` / `GITLAB_TOKEN` / `GITLAB_PROJECT_ID`)。默认分支(`main` 或 `master`)在步骤 4 自动探测,不硬编码。 + +## 执行步骤 + +### 步骤 1:确认 docs/08 存在 + +用 `Glob` 检查 `docs/08-模块任务管理.md`。 +- 不存在 → 打印"⚠️ 项目尚未初始化,请先运行 `/erp-workflow:plan-start`"并停下。 + +### 步骤 2:Plan 完成性检查 + +用 `Grep` 在 `docs/08-模块任务管理.md` 搜索 `^- \[ \] A[0-5]`(pattern 可以直接匹配父项未勾的情况;也可以用更宽的 `^[[:space:]]*- \[ \].*A[0-5]` 覆盖子项)。 + +- **命中任一 A 未勾** → 打印: + ``` + ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + [coding-start] ⚠️ Plan 尚未完成 + + docs/08 § 一 还有未勾选项,请先运行: + /erp-workflow:plan-start + + 继续 Plan 阶段直到 A5 下游文档生成完成,再回来运行 coding-start。 + ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + ``` + **停下**。 + +- 无命中 → Plan 已完成,进入步骤 3。 + +### 步骤 3:按 docs/02 REQ 序 + MR state 找当前模块 + +> `MR:` 字段 × GitLab API state 的三组合判定规则见 `CLAUDE.md § ✅ 模块完成判定规则 § 模块状态语义`。 + +1. 用 `Read` 读取 `docs/02-开发计划.md` 的 § 二;用 `Grep`(pattern `^\|\s*[0-9]+\s*\|\s*\*\*(REQ-[A-Z0-9]+-[0-9]+)\*\*\s*\|\s*(module_\w+)`,`-n`)抽取所有表格数据行,按行号升序得 `req_order[]`,每项含 `req_id` + `module_id`。 +2. 若 `req_order` 为空 → 打印错误并**停下**(与原逻辑相同,略)。 +3. **初始化模块完成缓存 `module_merged[module_id → bool]`**(空)。 +4. 按序遍历 `req_order[]`: + - 若 `module_merged[module_id]` 已有缓存: + - `true` → 跳过本 REQ,继续下一个 + - `false` → `current_module = module_id`,结束遍历,进入步骤 4 + - 未缓存 → 读取 docs/08 § 二 该模块条目的 ` - MR:` 字段: + - `MR: —` → `module_merged[module_id] = false`;`current_module = module_id`,结束遍历 + - `MR: !` → 先 `Bash`: `set -a; . ./.env.local; set +a` 加载凭据,然后**分步校验 HTTP 状态 + 返回条数 + state 枚举**(v3 API 用 iid 过滤列表): + ```bash + mkdir -p .tmp + HTTP_CODE=$(curl -sS -o .tmp/mr.json -w '%{http_code}' \ + --header "PRIVATE-TOKEN: ${GITLAB_TOKEN}" \ + "${GITLAB_API_URL}/projects/${GITLAB_PROJECT_ID}/merge_requests?iid=") + ``` + **硬停条件**(触发任一则打印诊断横幅并**停下**,不派发;任何"查不到就假设未 merged"的静默处理都禁止): + 1. `HTTP_CODE != 200`:API 不可达 / token 错 / URL 错 + 2. `HTTP_CODE == 200` 但 `jq 'length' .tmp/mr.json != 1`:docs/08 记了 `!` 但远程查不到对应 MR(数据不一致) + 3. `state = jq -r '.[0].state' .tmp/mr.json` 不在 `{merged, opened, closed}` 三个合法值里 + + 诊断横幅模板: + ``` + ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + [coding-start] ⚠️ 无法确定 MR !(模块 )的状态 + + 原因: | 查不到 MR | state=<异常值>> + API : ${GITLAB_API_URL}/projects/${GITLAB_PROJECT_ID} + body: + + 请按下列顺序核查: + 1. .env.local 的 GITLAB_TOKEN 是否有效(在 GitLab Profile → Private token 页检查) + 2. GITLAB_API_URL 前缀 / v3 路径 / host 是否匹配你的 GitLab 部署 + 3. GITLAB_PROJECT_ID 是否是该项目的 URL-encoded 路径或数字 ID + 4. docs/08 记的 iid 是否存在于 GitLab 项目的 MR 列表 + + 修正后重跑 /erp-workflow:coding-start。 + ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + ``` + 清理:`rm -f .tmp/mr.json`。 + + 校验通过后按 state 分派: + - `merged` → `module_merged[module_id] = true`,跳过本 REQ + - `opened` / `closed` → `module_merged[module_id] = false`;`current_module = module_id`,结束遍历 +5. 全遍历完仍无命中(所有模块都 merged) → 打印: + ``` + ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + [coding-start] ✅ 所有模块已完成 + + docs/02 § 二 清单中每个 REQ 所属模块的 MR 都已 merged。项目结束。 + ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + ``` + 并**停下**。 +6. 命中后:记录 `current_module` 的 `MR:` 字段值(`—` / `!-opened` / `!-closed` / `!-查不到`,用于步骤 5 横幅展示)。 + +### 步骤 4:探测默认分支 + 切回并同步远程(准备 module-start 切新分支的干净 base) + +4.0 **探测默认分支**: + +```bash +DEFAULT_BRANCH=$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's|refs/remotes/origin/||') +if [ -z "$DEFAULT_BRANCH" ]; then + # HEAD 未设置,回退:在 main / master 里取第一个实际存在的远程分支 + DEFAULT_BRANCH=$(git branch -r --format='%(refname:short)' | grep -E '^origin/(main|master)$' | head -1 | sed 's|^origin/||') +fi +``` + +- `DEFAULT_BRANCH` 为空 → 打印错误并**停下**(既无 `origin/main` 也无 `origin/master`,说明远程未就绪,提示用户先完成 Plan 的首次 push 或 `git remote set-head origin -a` 设置 HEAD)。 + +4.1 **切回 + 同步**: + +- `Bash`: `git branch --show-current` → `current_branch`。 +- 若 `current_branch != $DEFAULT_BRANCH`: + - `Bash`: `git status --porcelain`;非空 → 打印: + ``` + ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + [coding-start] ⚠️ 当前分支 有未提交改动,无法切换到 + + + + 请手工处理后重新运行 /erp-workflow:coding-start。 + ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + ``` + 并**停下**。 + - `Bash`: `git checkout "$DEFAULT_BRANCH"`。 +- `Bash`: `git pull --ff-only origin "$DEFAULT_BRANCH"`。 + - 失败(非 fast-forward / 网络 / 冲突)→ 打印错误横幅: + ``` + ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + [coding-start] ⚠️ 同步 失败 + + 本地 无法 fast-forward 到 remote。请手工处理: + git status + git log ..origin/ # 远程领先的 commit + git log origin/.. # 本地未推的 commit + 修复后重新运行 /erp-workflow:coding-start。 + ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + ``` + 并**停下**。 + +### 步骤 5:打印横幅并分发 + +``` +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + [coding-start] + 阶段:B 编码 + 当前模块: + MR 状态:<未建 | opened | closed | 查不到> + 下一步:invoke module-start +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +``` + +然后立即用 `Skill` 工具调用 `module-start`。 + +> 分发前先调用 `interrupt-check`;触发中断则停在此不分发。 + +## 设计要点 + +- **完成判定直接读取 `MR:` 字段 + GitLab API state**(curl,`PRIVATE-TOKEN` 头):MR 未 merge 前 docs/08 没有任何"已完成"标记;用户提前触发 coding-start 时,步骤 3 扫描到 MR opened 仍会选中当前模块,module-start 会 `git checkout module-` 回到原分支继续,不会跳到下一模块。 +- **每次派发前都 pull 默认分支**:代码同步的同时,也保证 module-start 切出新分支时 base 新鲜。默认分支由步骤 4.0 探测(main 或 master),不硬编码。 + +## 参考 + +- `docs/02-开发计划.md § 二 开发顺序清单`(分发追踪) +- `docs/08-模块任务管理.md § 二`(模块元数据,含 `MR:` 字段) +- `CLAUDE.md`(项目指令) +- `plan-start`(姊妹入口,A 阶段) diff --git a/skills/crosscut/cross-module-log/SKILL.md b/skills/crosscut/cross-module-log/SKILL.md new file mode 100644 index 0000000..862813e --- /dev/null +++ b/skills/crosscut/cross-module-log/SKILL.md @@ -0,0 +1,37 @@ +--- +name: cross-module-log +description: 为 log-cross-module.sh hook 自动追加到跨模块改动日志中的条目批量补填「原因」和「影响评估」。**仅由 module-report § ⑦ 硬验收时调用**,CC 编辑中途不主动调用(节省 LLM 调用次数)。 +user-invocable: false +allowed-tools: Read Write Edit Bash(git branch *) +--- + +**所有输出必须使用中文。** + +# cross-module-log + +## 说明 + +软规则 S2 执行:对**非当前模块**文件的每次编辑(无论目标模块是否已 MR merged)必须记录原因 + 影响评估。 + +**本日志由 hook + skill 协作维护**——hook 自动落存根(4 列机械数据),CC 不主动处理 TBD;由 `module-report` § ⑦ 硬验收阶段统一调用本 skill,一次性推断补齐「原因 / 影响评估」两列。**不需要人工填写**,人工只在最终看 MR 描述时复核。 + +## 执行步骤 + +1. 确定当前模块(从当前 git 分支名推导:`git branch --show-current` → `module-` → 取 `module_id`。`module-start` 步骤 3 保证本 skill 执行时一定处于 `module-*` 分支)。 +2. 打开 `docs/superpowers/module-reports/-cross-module.md`(不存在则从 `${CLAUDE_SKILL_DIR}/templates/cross-module-log-template.md` 初始化)。 +3. 找到「原因」或「影响评估」列中含 `TBD(CC 补)` 的行。 +4. 对每个 TBD 行,CC **自主推断**填写以下两列(基于当前 session 的改动上下文 + REQ 卡片 + 目标模块的代码): + - **原因**:为什么要修改目标模块的代码?当前模块的哪个需求迫使这样做? + - **影响评估**:目标模块的哪些 API / 行为 / 调用方可能受影响?其现有测试是否仍然有效?是否需要新测试?(1-3 句话) +5. 编辑该行;保持时间戳 / 目标模块 / 文件 / 改动摘要列不变。 +6. 输出确认:`cross-module-log: 更新了 N 行`。 + +## 下游 + +填充后的日志会被 `module-report` 原文嵌入到 `module-report-template.md` § ⑦。 + +## 参考 + +- `${CLAUDE_SKILL_DIR}/templates/cross-module-log-template.md` +- `${CLAUDE_SKILL_DIR}/templates/cross-module-log-row-template.md` +- `CLAUDE.md` § 🟡 软规则 S2 diff --git a/skills/crosscut/cross-module-log/templates/cross-module-log-row-template.md b/skills/crosscut/cross-module-log/templates/cross-module-log-row-template.md new file mode 100644 index 0000000..883cdcd --- /dev/null +++ b/skills/crosscut/cross-module-log/templates/cross-module-log-row-template.md @@ -0,0 +1 @@ +| {{timestamp}} | {{target_module}} | {{file_path}} | {{change_summary}} | {{reason}} | {{impact}} | diff --git a/skills/crosscut/cross-module-log/templates/cross-module-log-template.md b/skills/crosscut/cross-module-log/templates/cross-module-log-template.md new file mode 100644 index 0000000..e9338fb --- /dev/null +++ b/skills/crosscut/cross-module-log/templates/cross-module-log-template.md @@ -0,0 +1,8 @@ +# 跨模块改动日志 — {{module_name}} + +软规则 S2:本模块开发期间对**非当前模块**代码的改动(无论目标模块是否已 MR merged)记录在此;模块完成报告必须单列「跨模块改动」节完整贴入。漏留痕或未评估影响 → 升级为中断。 + +**本日志由 CC 自主维护**——hook `log-cross-module.sh` 自动落存根(含 `TBD(CC 补)` 占位),CC 调 `cross-module-log` skill 自主推断补「原因 / 影响评估」两列。**不需要人工填写**。 + +| 时间戳 | 目标模块 | 文件 | 改动摘要 | 原因 | 影响评估 | +|---|---|---|---|---|---| diff --git a/skills/crosscut/erp-coding-start/SKILL.md b/skills/crosscut/erp-coding-start/SKILL.md deleted file mode 100644 index 95d2b1a..0000000 --- a/skills/crosscut/erp-coding-start/SKILL.md +++ /dev/null @@ -1,166 +0,0 @@ ---- -name: erp-coding-start -description: B 阶段(Coding)入口。先验证 Plan 已完成;按 docs/02 § 二 REQ 开发顺序清单扫描,对每个 REQ 所属模块用 docs/08 的 `MR:` 字段 + GitLab API state 判定是否完成——merged 跳过,`—` 或 opened/closed 选为当前模块并派发到 erp-module-start。派发前自动探测默认分支(main / master)并 git checkout + pull --ff-only 保持 base 最新。 -user-invocable: true -allowed-tools: Skill Read Glob Grep Bash(curl *) Bash(jq *) Bash(git branch *) Bash(git checkout *) Bash(git pull *) Bash(git status *) Bash(git symbolic-ref *) Bash(sed *) Bash(mkdir -p .tmp) Bash(rm -f .tmp/*) ---- - -**所有输出必须使用中文。** - -B 阶段(Coding)的入口分发器。职责:**验证 Plan 已完成 → 按 docs/02 § 二 REQ 序 + MR state 定位当前模块 → 切回默认分支并同步远程 → 派发 erp-module-start**。不直接生成任何文件。开发顺序以 `docs/02 § 二` 为准;完成判定以 `docs/08 条目的 MR: 字段 + GitLab API state` 为准(curl 调用,凭据读 `.env.local` 的 `GITLAB_API_URL` / `GITLAB_TOKEN` / `GITLAB_PROJECT_ID`)。默认分支(`main` 或 `master`)在步骤 4 自动探测,不硬编码。 - -## 执行步骤 - -### 步骤 1:确认 docs/08 存在 - -用 `Glob` 检查 `docs/08-模块任务管理.md`。 -- 不存在 → 打印"⚠️ 项目尚未初始化,请先运行 `/erp-workflow:erp-plan-start`"并停下。 - -### 步骤 2:Plan 完成性检查 - -用 `Grep` 在 `docs/08-模块任务管理.md` 搜索 `^- \[ \] A[0-5]`(pattern 可以直接匹配父项未勾的情况;也可以用更宽的 `^[[:space:]]*- \[ \].*A[0-5]` 覆盖子项)。 - -- **命中任一 A 未勾** → 打印: - ``` - ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - [erp-coding-start] ⚠️ Plan 尚未完成 - - docs/08 § 一 还有未勾选项,请先运行: - /erp-workflow:erp-plan-start - - 继续 Plan 阶段直到 A5 下游文档生成完成,再回来运行 coding-start。 - ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ``` - **停下**。 - -- 无命中 → Plan 已完成,进入步骤 3。 - -### 步骤 3:按 docs/02 REQ 序 + MR state 找当前模块 - -1. 用 `Read` 读取 `docs/02-开发计划.md` 的 § 二;用 `Grep`(pattern `^\|\s*[0-9]+\s*\|\s*\*\*(REQ-[A-Z0-9]+-[0-9]+)\*\*\s*\|\s*(module_\w+)`,`-n`)抽取所有表格数据行,按行号升序得 `req_order[]`,每项含 `req_id` + `module_id`。 -2. 若 `req_order` 为空 → 打印错误并**停下**(与原逻辑相同,略)。 -3. **初始化模块完成缓存 `module_merged[module_id → bool]`**(空)。 -4. 按序遍历 `req_order[]`: - - 若 `module_merged[module_id]` 已有缓存: - - `true` → 跳过本 REQ,继续下一个 - - `false` → `current_module = module_id`,结束遍历,进入步骤 4 - - 未缓存 → 读取 docs/08 § 二 该模块条目的 ` - MR:` 字段: - - `MR: —` → `module_merged[module_id] = false`;`current_module = module_id`,结束遍历 - - `MR: !` → 先 `Bash`: `set -a; . ./.env.local; set +a` 加载凭据,然后**分步校验 HTTP 状态 + 返回条数 + state 枚举**(v3 API 用 iid 过滤列表): - ```bash - mkdir -p .tmp - HTTP_CODE=$(curl -sS -o .tmp/mr.json -w '%{http_code}' \ - --header "PRIVATE-TOKEN: ${GITLAB_TOKEN}" \ - "${GITLAB_API_URL}/projects/${GITLAB_PROJECT_ID}/merge_requests?iid=") - ``` - **硬停条件**(命中任一则打印诊断横幅并**停下**,不派发;任何"查不到就假设未 merged"的静默处理都禁止): - 1. `HTTP_CODE != 200`:API 不可达 / token 错 / URL 错 - 2. `HTTP_CODE == 200` 但 `jq 'length' .tmp/mr.json != 1`:docs/08 记了 `!` 但远程查不到对应 MR(数据不一致) - 3. `state = jq -r '.[0].state' .tmp/mr.json` 不在 `{merged, opened, closed}` 三个合法值里 - - 诊断横幅模板: - ``` - ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - [erp-coding-start] ⚠️ 无法确定 MR !(模块 )的状态 - - 原因: | 查不到 MR | state=<异常值>> - API : ${GITLAB_API_URL}/projects/${GITLAB_PROJECT_ID} - body: - - 请按下列顺序核查: - 1. .env.local 的 GITLAB_TOKEN 是否有效(在 GitLab Profile → Private token 页检查) - 2. GITLAB_API_URL 前缀 / v3 路径 / host 是否匹配你的 GitLab 部署 - 3. GITLAB_PROJECT_ID 是否是该项目的 URL-encoded 路径或数字 ID - 4. docs/08 记的 iid 是否存在于 GitLab 项目的 MR 列表 - - 修正后重跑 /erp-workflow:erp-coding-start。 - ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ``` - 清理:`rm -f .tmp/mr.json`。 - - 校验通过后按 state 分派: - - `merged` → `module_merged[module_id] = true`,跳过本 REQ - - `opened` / `closed` → `module_merged[module_id] = false`;`current_module = module_id`,结束遍历 -5. 全遍历完仍无命中(所有模块都 merged) → 打印: - ``` - ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - [erp-coding-start] ✅ 所有模块已完成 - - docs/02 § 二 清单中每个 REQ 所属模块的 MR 都已 merged。项目结束。 - ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ``` - 并**停下**。 -6. 命中后:记录 `current_module` 的 `MR:` 字段值(`—` / `!-opened` / `!-closed` / `!-查不到`,用于步骤 5 横幅展示)。 - -### 步骤 4:探测默认分支 + 切回并同步远程(准备 module-start 切新分支的干净 base) - -4.0 **探测默认分支**: - -```bash -DEFAULT_BRANCH=$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's|refs/remotes/origin/||') -if [ -z "$DEFAULT_BRANCH" ]; then - # HEAD 未设置,回退:在 main / master 里取第一个实际存在的远程分支 - DEFAULT_BRANCH=$(git branch -r --format='%(refname:short)' | grep -E '^origin/(main|master)$' | head -1 | sed 's|^origin/||') -fi -``` - -- `DEFAULT_BRANCH` 为空 → 打印错误并**停下**(既无 `origin/main` 也无 `origin/master`,说明远程未就绪,提示用户先完成 Plan 的首次 push 或 `git remote set-head origin -a` 设置 HEAD)。 - -4.1 **切回 + 同步**: - -- `Bash`: `git branch --show-current` → `current_branch`。 -- 若 `current_branch != $DEFAULT_BRANCH`: - - `Bash`: `git status --porcelain`;非空 → 打印: - ``` - ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - [erp-coding-start] ⚠️ 当前分支 有未提交改动,无法切换到 - - - - 请手工处理后重新运行 /erp-workflow:erp-coding-start。 - ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ``` - 并**停下**。 - - `Bash`: `git checkout "$DEFAULT_BRANCH"`。 -- `Bash`: `git pull --ff-only origin "$DEFAULT_BRANCH"`。 - - 失败(非 fast-forward / 网络 / 冲突)→ 打印错误横幅: - ``` - ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - [erp-coding-start] ⚠️ 同步 失败 - - 本地 无法 fast-forward 到 remote。请手工处理: - git status - git log ..origin/ # 远程领先的 commit - git log origin/.. # 本地未推的 commit - 修复后重新运行 /erp-workflow:erp-coding-start。 - ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ``` - 并**停下**。 - -### 步骤 5:打印横幅并分发 - -``` -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - [erp-coding-start] - 阶段:B 编码 - 当前模块: - MR 状态:<未建 | opened | closed | 查不到> - 下一步:invoke erp-module-start -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -``` - -然后立即用 `Skill` 工具调用 `erp-module-start`。 - -> 分发前先调用 `erp-red-flag-check`;命中红旗则停在此不分发。 - -## 设计要点 - -- **完成判定直接读取 `MR:` 字段 + GitLab API state**(curl,`PRIVATE-TOKEN` 头):MR 未 merge 前 docs/08 没有任何"已完成"标记;用户提前触发 coding-start 时,步骤 3 扫描到 MR opened 仍会选中当前模块,module-start 会 `git checkout module-` 回到原分支继续,不会跳到下一模块。 -- **每次派发前都 pull 默认分支**:代码同步的同时,也保证 module-start 切出新分支时 base 新鲜。默认分支由步骤 4.0 探测(main 或 master),不硬编码。 - -## 参考 - -- `docs/02-开发计划.md § 二 开发顺序清单`(分发权威) -- `docs/08-模块任务管理.md § 二`(模块元数据,含 `MR:` 字段) -- `CLAUDE.md`(项目指令) -- `erp-plan-start`(姊妹入口,A 阶段) diff --git a/skills/crosscut/erp-cross-module-log/SKILL.md b/skills/crosscut/erp-cross-module-log/SKILL.md deleted file mode 100644 index c9e7d04..0000000 --- a/skills/crosscut/erp-cross-module-log/SKILL.md +++ /dev/null @@ -1,37 +0,0 @@ ---- -name: erp-cross-module-log -description: 为 log-cross-module.sh hook 自动追加到跨模块改动日志中的条目补填「原因」和「影响评估」。覆盖对"非当前模块"文件的编辑(无论目标模块是否已 MR merged)。 -user-invocable: false -allowed-tools: Read Write Edit Bash(git branch *) ---- - -**所有输出必须使用中文。** - -# erp-cross-module-log - -## 说明 - -软规则 S2 执行:对**非当前模块**文件的每次编辑(无论目标模块是否已 MR merged)必须记录原因 + 影响评估。 - -**本日志由 CC 自主维护**——hook 自动落存根、CC 自主推断补齐两列,**不需要人工填写**。人工只在最终看 MR 描述时复核。 - -## 执行步骤 - -1. 确定当前模块(从当前 git 分支名推导:`git branch --show-current` → `module-` → 取 `module_id`。`erp-module-start` 步骤 3 保证本 skill 执行时一定处于 `module-*` 分支)。 -2. 打开 `docs/superpowers/module-reports/-cross-module.md`(不存在则从 `${CLAUDE_SKILL_DIR}/templates/cross-module-log-template.md` 初始化)。 -3. 找到「原因」或「影响评估」列中含 `TBD(CC 补)` 的行。 -4. 对每个 TBD 行,CC **自主推断**填写以下两列(基于当前 session 的改动上下文 + REQ 卡片 + 目标模块的代码): - - **原因**:为什么要修改目标模块的代码?当前模块的哪个需求迫使这样做? - - **影响评估**:目标模块的哪些 API / 行为 / 调用方可能受影响?其现有测试是否仍然有效?是否需要新测试?(1-3 句话) -5. 编辑该行;保持时间戳 / 目标模块 / 文件 / 改动摘要列不变。 -6. 输出确认:`cross-module-log: 更新了 N 行`。 - -## 下游 - -填充后的日志会被 `erp-module-report` 原文嵌入到 `module-report-template.md` § ⑦。 - -## 参考 - -- `${CLAUDE_SKILL_DIR}/templates/cross-module-log-template.md` -- `${CLAUDE_SKILL_DIR}/templates/cross-module-log-row-template.md` -- `CLAUDE.md` § 🟡 软规则 S2 diff --git a/skills/crosscut/erp-cross-module-log/templates/cross-module-log-row-template.md b/skills/crosscut/erp-cross-module-log/templates/cross-module-log-row-template.md deleted file mode 100644 index 883cdcd..0000000 --- a/skills/crosscut/erp-cross-module-log/templates/cross-module-log-row-template.md +++ /dev/null @@ -1 +0,0 @@ -| {{timestamp}} | {{target_module}} | {{file_path}} | {{change_summary}} | {{reason}} | {{impact}} | diff --git a/skills/crosscut/erp-cross-module-log/templates/cross-module-log-template.md b/skills/crosscut/erp-cross-module-log/templates/cross-module-log-template.md deleted file mode 100644 index 3a653ed..0000000 --- a/skills/crosscut/erp-cross-module-log/templates/cross-module-log-template.md +++ /dev/null @@ -1,8 +0,0 @@ -# 跨模块改动日志 — {{module_name}} - -软规则 S2:本模块开发期间对**非当前模块**代码的改动(无论目标模块是否已 MR merged)记录在此;模块完成报告必须单列「跨模块改动」节完整贴入。漏留痕或未评估影响 → 升级为红旗。 - -**本日志由 CC 自主维护**——hook `log-cross-module.sh` 自动落存根(含 `TBD(CC 补)` 占位),CC 调 `erp-cross-module-log` skill 自主推断补「原因 / 影响评估」两列。**不需要人工填写**。 - -| 时间戳 | 目标模块 | 文件 | 改动摘要 | 原因 | 影响评估 | -|---|---|---|---|---|---| diff --git a/skills/crosscut/erp-plan-start/SKILL.md b/skills/crosscut/erp-plan-start/SKILL.md deleted file mode 100644 index a8977e7..0000000 --- a/skills/crosscut/erp-plan-start/SKILL.md +++ /dev/null @@ -1,103 +0,0 @@ ---- -name: erp-plan-start -description: A 阶段(Plan)入口与分发器。根据 docs/08 § 一 的 checkbox 状态派发到 A0~A5 对应 skill(§ 二是 B 阶段模块元数据,本 skill 不读)。Plan 全部完成(A5 已勾)时打印提示让用户运行 /erp-workflow:erp-coding-start 进入 B 阶段。 -user-invocable: true -allowed-tools: Skill Read Glob Grep ---- - -**所有输出必须使用中文。** 用户是中文用户,所有对话、横幅、提示、报告一律用中文。 - -你是 ERP 项目**规划阶段的编排器**。你**只派发 A 阶段(A0~A5)的 skill**;docs/08 § 一 全部勾选后即停下,提示用户显式运行 `/erp-workflow:erp-coding-start` 进入 B 阶段,**不直接派发任何 B 阶段 skill**。你不直接生成任何文件。 - -## 第一步:读取 docs/08 + 决定分发目标 + `mark_line` - -docs/08 § 一 是**Plan 阶段进度权威**(A0~A5 的 checkbox)。不做其他文件存在性检查——文件在不等于做完,只有 checkbox 是做完的证据。§ 二的模块元数据由 erp-coding-start 消费,本 skill 不读。 - -### 分发判定 - -1. **docs/08 是否存在** - 用 `Glob` 检查 `docs/08-模块任务管理.md`。 - - 不存在 → `target=erp-project-init`、`mark_line=A0`、`unchecked_line=""`(流程开始)。 - -2. **找 § 一 第一个未勾的 A 子项** - 用 `Grep`(pattern `^[[:space:]]*- \[ \].*A[0-5]`,`-n`)在 `docs/08-模块任务管理.md` 的 § 一 Plan 段搜索,取**最小行号**那一行作为 `unchecked_line`。 - 注:§ 二 的模块行是纯 bullet(形如 `- module_id ...`),不会被此 pattern 匹配。 - -3. **把 `unchecked_line` 映射到 `target_skill` + `mark_line`**: - -| `unchecked_line` 特征 | `target_skill` | `mark_line` | -|---|---|---| -| 无 docs/08 | `erp-project-init` | `A0` | -| 含 `A0` / A0 子项 | `erp-project-init` | `A0` | -| 含 `A1` / A1 子项 | `erp-scope-lock` | `A1` | -| 含 `A2` / A2 子项 | `erp-skeleton-gen` | `A2` | -| 含 `A3` / A3 子项 | `erp-db-init` | `A3` | -| 含 `A4` / A4 子项 | `erp-db-design-gen` | `A4` | -| 含 `A5` / A5 子项 | `erp-downstream-gen` | `A5` | -| 无命中(A 全勾,Plan 阶段结束) | **无分发** | `plan-done` | - -项目完成状态(B 阶段所有模块 MR merged)由 `erp-coding-start` 扫描 MR state 判定并打印,本 skill 不处理。 - -## 第二步:分发通知 + 调用目标 skill - -本入口**不画完整流程图**——目标 A skill 会在自己的步骤 0 打印带 `▶` 当前位置的流程图。本步骤只做分发决策与通知。 - -### 2.1 Plan 已完成(`mark_line=plan-done`) - -A 阶段所有 checkbox 均 `[x]`。因无下游 A skill 接手,本步骤**自行打印流程图**(`▶` 标在"规划阶段到此结束")并给出提示,然后**停下**;项目整体完成状态由 `erp-coding-start` 扫描 MR state 判定,本 skill 不负责: - -``` -┌──────────────────────────────────────────────────────┐ -│ 📋 阶段 A:规划(一次性) │ -│ │ -│ A0 初始化项目 → A1 锁范围(REQ 卡片) │ -│ ↓ │ -│ ⏸ 等你审阅 REQ,重新运行 /erp-plan-start 继续 │ -│ ↓ │ -│ A2 生成骨架 → A3 初始化 DB → A4 生成 DB 设计 → A5 生成下游文档│ -│ ↓ │ -│ ▶ 规划阶段到此结束 │ -└──────────────────────────────────────────────────────┘ - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - [erp-plan-start] ✅ Plan 阶段全部完成 - - ⚠️ 进入 B 阶段前必须完成: - 1. 人工通读 docs/01~10 + CLAUDE.md + sql/migrations/V1 + 各 scripts/* - - 2. 把全部 Plan 产物 commit: - git add -A && git commit -m "chore: plan phase A0~A5 done" - - 3. 推到远程: - git remote add origin # 若尚未添加 - git -c core.hooksPath=/dev/null push -u origin master - # 首次 push 本地 DB 尚未就位、scripts/test.sh 必然失败。 - # `-c core.hooksPath=/dev/null` 临时把 hooksPath 指到空目录, - # 跳过 .githooks/pre-push 但不动 repo 的 core.hooksPath 配置, - # 也不用 --no-verify(后者被 CC 的 deny-no-verify hook 硬拦)。 - # push 完成后到 GitLab UI 把 master(或 main)设为 protected - - 4. main(或 master)就绪后,再运行 /erp-workflow:erp-coding-start -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -``` - -不调任何下游 skill。 - -### 2.2 正常派发(`target_skill` 非空) - -打印简短分发通知: - -``` -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - [erp-plan-start] → 派发到 - 未勾项: -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -``` - -立即用 `Skill` 工具调用 `target_skill`。 - -## 参考 - -- `docs/08-模块任务管理.md`(唯一进度权威) -- `CLAUDE.md`(项目指令) -- 下游 skills(通过 `Skill` 工具按名称调用) diff --git a/skills/crosscut/erp-red-flag-check/SKILL.md b/skills/crosscut/erp-red-flag-check/SKILL.md deleted file mode 100644 index 6a6008d..0000000 --- a/skills/crosscut/erp-red-flag-check/SKILL.md +++ /dev/null @@ -1,49 +0,0 @@ ---- -name: erp-red-flag-check -description: 在每个功能循环步骤和生成重要制品前运行。检查 CLAUDE.md 中的 3 项红旗清单,命中任一项则追加 Blocker 到计划文件并停止。 -user-invocable: false -allowed-tools: Read Write Bash(mysql *) ---- - -**所有输出必须使用中文。** - -# erp-red-flag-check - -## 说明 - -验证 CLAUDE.md § 🚩 静默执行红旗清单中的 3 项均未触发。命中任一项则中断。 - -> 需求歧义 / schema 缺口 / 技术栈外组件引入等场景由各 feature-* skill 的 `AskUserQuestion` 流程承接,不进入本清单,不会在这里命中。 - -## 调用时机 - -- 每个功能循环步骤开始前(3.1-3.5) -- 生成模块级制品前(模块报告、MR 描述) -- 用户请求涉及外部依赖、环境凭据变更时 - -## 检查清单(3 项 — 权威来源:CLAUDE.md) - -1. **测试反复失败** — 同一功能中同一测试连续 10 次修复失败 -2. **要改密钥/账密/包名** — 涉及 `docs/07-环境配置.md` 中的人工填写字段 -3. **外部接口不可达** — 第三方 API / 证书 / 网络问题 - -## 执行步骤 - -1. 读取当前功能的规格/计划文件路径(从对话或 `docs/08` 获取)。 -2. 逐项检查 3 个红旗。如果全部未命中 → 输出 `red-flag-check: 通过`,退出。 -3. 命中时: - - 用 `Read` 读取 `${CLAUDE_SKILL_DIR}/templates/red-flag-block-template.md` - - 填充槽位(flag_number、flag_name、description、affected_scope、recommendation、decision_needed) - - 将渲染后的块追加到当前计划文件:`docs/superpowers/plans/YYYY-MM-DD-.md` - - 向会话打印一句话摘要 + 指向计划文件的路径 - - **停止** — 在用户决策前不调用任何后续 skill - -## 输出 - -`red-flag-check: 通过`(仅会话),或一个 `## 🚩 Blocker` 块追加到功能计划文件。 - -## 参考 - -- `${CLAUDE_SKILL_DIR}/templates/red-flag-block-template.md` -- `CLAUDE.md` § 🚩 静默执行红旗清单(权威 3 条) -- `CLAUDE.md` § 🟡 软规则(S2 跨模块改动,不触发红旗但需留痕) diff --git a/skills/crosscut/erp-red-flag-check/templates/red-flag-block-template.md b/skills/crosscut/erp-red-flag-check/templates/red-flag-block-template.md deleted file mode 100644 index b12dc35..0000000 --- a/skills/crosscut/erp-red-flag-check/templates/red-flag-block-template.md +++ /dev/null @@ -1,8 +0,0 @@ -## 🚩 Blocker - -**红旗编号**: {{flag_number}} (1-3,对应 CLAUDE.md 🚩 静默执行红旗清单) -**红旗名称**: {{flag_name}} -**问题描述**: {{description}} -**影响范围**: {{affected_scope}} -**我的建议**: {{recommendation}} -**等待决策**: {{decision_needed}} diff --git a/skills/crosscut/interrupt-check/SKILL.md b/skills/crosscut/interrupt-check/SKILL.md new file mode 100644 index 0000000..a16326c --- /dev/null +++ b/skills/crosscut/interrupt-check/SKILL.md @@ -0,0 +1,49 @@ +--- +name: interrupt-check +description: 在每个功能循环步骤和生成重要制品前运行。检查 CLAUDE.md 中的 3 项中断清单,触发任一项则追加 Blocker 到计划文件并停止。 +user-invocable: false +allowed-tools: Read Write Bash(mysql *) +--- + +**所有输出必须使用中文。** + +# interrupt-check + +## 说明 + +验证 CLAUDE.md § 🚩 中断机制中的 3 项均未触发。触发任一项则中断。 + +> 需求歧义 / schema 缺口 / 技术栈外组件引入等场景由各 feature-* skill 的 `AskUserQuestion` 流程承接,不进入本清单,不会在这里触发。 + +## 调用时机 + +- 每个功能循环步骤开始前(3.1-3.5) +- 生成模块级制品前(模块报告、MR 描述) +- 用户请求涉及外部依赖、环境凭据变更时 + +## 检查清单(3 项 — 权威来源:CLAUDE.md) + +1. **测试反复失败** — 同一功能中同一测试连续 10 次修复失败 +2. **要改密钥/账密/包名** — 涉及 `docs/07-环境配置.md` 中的人工填写字段 +3. **外部接口不可达** — 第三方 API / 证书 / 网络问题 + +## 执行步骤 + +1. 读取当前功能的规格/计划文件路径(从对话或 `docs/08` 获取)。 +2. 逐项检查 3 个中断。如果全部未触发 → 输出 `interrupt-check: 通过`,退出。 +3. 触发时: + - 用 `Read` 读取 `${CLAUDE_SKILL_DIR}/templates/interrupt-block-template.md` + - 填充槽位(interrupt_number、interrupt_name、description、affected_scope、recommendation、decision_needed) + - 将渲染后的块追加到当前计划文件:`docs/superpowers/plans/YYYY-MM-DD-.md` + - 向会话打印一句话摘要 + 指向计划文件的路径 + - **停止** — 在用户决策前不调用任何后续 skill + +## 输出 + +`interrupt-check: 通过`(仅会话),或一个 `## 🚩 Blocker` 块追加到功能计划文件。 + +## 参考 + +- `${CLAUDE_SKILL_DIR}/templates/interrupt-block-template.md` +- `CLAUDE.md` § 🚩 中断机制(权威 3 条) +- `CLAUDE.md` § 🟡 软规则(S2 跨模块改动,不触发中断但需留痕) diff --git a/skills/crosscut/interrupt-check/templates/interrupt-block-template.md b/skills/crosscut/interrupt-check/templates/interrupt-block-template.md new file mode 100644 index 0000000..3337d98 --- /dev/null +++ b/skills/crosscut/interrupt-check/templates/interrupt-block-template.md @@ -0,0 +1,8 @@ +## 🚩 Blocker + +**中断编号**: {{interrupt_number}} (1-3,对应 CLAUDE.md 🚩 中断机制) +**中断名称**: {{interrupt_name}} +**问题描述**: {{description}} +**影响范围**: {{affected_scope}} +**我的建议**: {{recommendation}} +**等待决策**: {{decision_needed}} diff --git a/skills/crosscut/plan-start/SKILL.md b/skills/crosscut/plan-start/SKILL.md new file mode 100644 index 0000000..af030d9 --- /dev/null +++ b/skills/crosscut/plan-start/SKILL.md @@ -0,0 +1,90 @@ +--- +name: plan-start +description: A 阶段(Plan)入口与分发器。根据 docs/08 § 一 的 checkbox 状态派发到 A0~A5 对应 skill。Plan 全部完成(A5 已勾)时打印提示让用户运行 /erp-workflow:coding-start 进入 B 阶段。 +user-invocable: true +allowed-tools: Skill Read Glob Grep +--- + +**所有输出必须使用中文。** + +你是 ERP 项目**规划阶段的编排器**。你**只派发 A 阶段(A0~A5)的 skill**;docs/08 § 一 全部勾选后即停下,提示用户显式运行 `/erp-workflow:coding-start` 进入 B 阶段。你不直接生成任何文件。 + +## 第一步:读取 docs/08 + 决定分发目标 + +docs/08 § 一 是**Plan 阶段进度追踪**(A0~A5 的 checkbox)。§ 二的模块元数据由 coding-start 读写,本 skill 不读。 + +### 分发判定 + +1. **docs/08 是否存在** + 用 `Glob` 检查 `docs/08-模块任务管理.md`。 + - 如果不存在 → 后续 = `project-init`。 + +2. **根据 § 一 找到当前进度** + +| `进度` | `后续` | `阶段` | +|---|---|---| +| 无 docs/08 | `project-init` | `A0` | +| 含 `A0` / `A0 子项` | `project-init` | `A0` | +| 含 `A1` / `A1 子项` | `scope-lock` | `A1` | +| 含 `A2` / `A2 子项` | `skeleton-gen` | `A2` | +| 含 `A3` / `A3 子项` | `db-design-gen` | `A3` | +| 含 `A4` / `A4 子项` | `db-init` | `A4` | +| 含 `A5` / `A5 子项` | `downstream-gen` | `A5` | +| `A` 全勾,Plan 阶段结束 | **无分发** | - | + +## 第二步:分发通知 + 调用目标 skill + +### 2.1 Plan 已完成 + +A 阶段所有 checkbox 均 `[x]`。无后续 skill,本步骤**自行打印流程图**,然后**停下**: + +``` +┌──────────────────────────────────────────────────────┐ +│ 📋 阶段 A:规划(一次性) │ +│ │ +│ A0 初始化项目 → A1 锁范围(REQ 卡片) │ +│ ↓ │ +│ ⏸ 等你审阅 REQ,重新运行 /plan-start 继续 │ +│ ↓ │ +│ A2 生成骨架 → A3 生成 DB 设计 → A4 初始化 DB → A5 生成下游文档│ +│ ↓ │ +│ ▶ 规划阶段到此结束 │ +└──────────────────────────────────────────────────────┘ + +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + [plan-start] ✅ Plan 阶段全部完成 + + ⚠️ 进入 B 阶段前必须完成: + 1. 人工通读 docs/* + CLAUDE.md + sql/migrations/V1 + 各 scripts/* + + 2. 把全部 Plan 产物 commit: + git add -A && git commit -m "chore: plan phase A0~A5 done" + + 3. 推到远程: + git remote add origin # 若尚未添加 + git -c core.hooksPath=/dev/null push -u origin master + + 4. main(或 master)就绪后,再运行 /erp-workflow:coding-start +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +``` + +不调任何下游 skill。 + +### 2.2 正常派发(`后续` 非空) + +打印简短分发通知: + +``` +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + [plan-start] → 派发到 <后续> + 未勾项: +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +``` + +立即用 `Skill` 工具调用 `后续`。 + +## 参考 + +- `docs/08-模块任务管理.md`(进度追踪) +- `CLAUDE.md`(项目指令) +- 后续 skills(通过 `Skill` 工具按名称调用) diff --git a/skills/internal/superpower-writing-plans/SKILL.md b/skills/internal/superpower-writing-plans/SKILL.md index 089fca2..3d2aa7c 100644 --- a/skills/internal/superpower-writing-plans/SKILL.md +++ b/skills/internal/superpower-writing-plans/SKILL.md @@ -6,7 +6,7 @@ user-invocable: false # Writing Plans (Internal, Gate-Free) -Write task-level implementation plans that tell the TDD executor **what to do**, not **how to write the code**. The executor is `erp-feature-tdd` (Claude itself with full context), not a mechanical copy-paster — so the plan captures file boundaries, test intent, API shapes and completion criteria, and lets the executor produce the actual code in the red-green cycle. DRY. YAGNI. TDD. Frequent commits. +Write task-level implementation plans that tell the TDD executor **what to do**, not **how to write the code**. The executor is `feature-tdd` (Claude itself with full context), not a mechanical copy-paster — so the plan captures file boundaries, test intent, API shapes and completion criteria, and lets the executor produce the actual code in the red-green cycle. DRY. YAGNI. TDD. Frequent commits. **Do NOT dump full file contents (pom.xml, entity classes, config files) into the plan.** The plan and the code end up as two sources of truth that drift; 2000+ line plans also waste context. Code is produced during TDD, not pre-written here. @@ -44,7 +44,7 @@ This structure informs the task decomposition. Each task should produce self-con ```markdown # [Feature Name] Implementation Plan -> **Execution:** Parent skill `erp-feature-tdd` executes this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. +> **Execution:** Parent skill `feature-tdd` executes this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** [One sentence describing what this builds] @@ -104,7 +104,7 @@ Every step must contain the actual content an engineer needs. These are **plan f - "Similar to Task N"(相似任务各自写清楚测试意图 + 完成判据,不互相链接) - References to types, functions, or methods not defined in any task(类/方法首次出现的 task 要给出 API 签名) -> 散文级"做什么"是 OK 的——执行器(erp-feature-tdd)会在 TDD 循环里决定"怎么写"。plan 的义务是**约束范围**,不是**替 TDD 写代码**。 +> 散文级"做什么"是 OK 的——执行器(feature-tdd)会在 TDD 循环里决定"怎么写"。plan 的义务是**约束范围**,不是**替 TDD 写代码**。 ## Remember diff --git a/skills/plan/db-design-gen/SKILL.md b/skills/plan/db-design-gen/SKILL.md new file mode 100644 index 0000000..18f6feb --- /dev/null +++ b/skills/plan/db-design-gen/SKILL.md @@ -0,0 +1,128 @@ +--- +name: db-design-gen +description: A3 DB 设计 + REQ 回填——基于 docs/01-需求清单 REQ 卡片正向设计 docs/03-数据库设计文档.md(业务实体 → 表 + 字段 + 索引 + 外键 + 业务注记),并把回填值写入 REQ 卡片的「依赖表: TBD(A3 自动补)」占位。生成完毕停下等人工审阅。 +user-invocable: false +allowed-tools: Read Write Edit Grep Glob Skill AskUserQuestion +--- + +**所有输出必须使用中文。** + +# db-design-gen + +## 前置条件 + +- A1 `scope-lock` 已完成:`docs/01-需求清单/-*.md` REQ 卡片存在,含 `TBD(A3 自动补)` 占位。 +- A2 `skeleton-gen` 已完成:`docs/04-技术规范.md § 一+` 命名规范已生成(本 skill 推导表/字段命名时严格遵循)。 + +## 执行步骤 + +### 步骤 0:打印当前位置流程图 + +向用户展示当前在 A 阶段流程中的位置(A-only,`▶` 标在 A3): + +``` +┌──────────────────────────────────────────────────────┐ +│ 📋 阶段 A:规划(一次性) │ +│ │ +│ A0 初始化项目 → A1 锁范围(REQ 卡片) │ +│ ↓ │ +│ ⏸ 等你审阅 REQ,重新运行 /plan-start 继续 │ +│ ↓ │ +│ A2 生成骨架 → ▶ A3 生成 DB 设计 → A4 初始化 DB → A5 生成下游文档│ +│ ↓ │ +│ ⏸ 等你审阅 docs/03,重新运行 /plan-start 继续 │ +└──────────────────────────────────────────────────────┘ +``` + +### A. 读取设计输入 + +用 `Read` / `Glob` 读取: + +- `docs/04-技术规范.md` § 一+ 命名规范(表名 / 字段名 / 索引名 / 外键名约定,及主键 / 时间戳 / 软删等审计列约定) +- `docs/01-需求清单/index.md` 模块索引(模块代码 ↔ 中文名) +- `docs/01-需求清单/*.md`(排除 `index.md`)所有 REQ 卡片,提取 `req_id` / `goal` / `input` / `output` / `rules` / `constraints` / `acceptance` + +### B. LLM 推导 schema + +基于步骤 A 读到的 REQ + 命名规范,**正向推导**业务实体 → 表 + 字段 + 索引 + 外键。要求: + +1. **表名 / 列名 / 索引名 / 外键名** 严格套用 `docs/04 § 一+` 的命名规范 +2. **审计列**:除明确不需要的辅助表外,每张业务表至少含 `created_at` / `updated_at`;如 `docs/04 § 一+` 约定了 `created_by` / `updated_by` / 软删 `deleted_at`,一并补全 +3. **主键**:默认 `id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT`,除非 REQ 明确要求复合主键 / UUID / 业务主键 +4. **外键**:依据 REQ 中的引用关系(如「订单引用客户」),明确列出 `ON DELETE` / `ON UPDATE` 策略;不能确定时默认 `RESTRICT` +5. **索引**:根据 REQ 的查询模式(如"按时间范围查"、"按状态筛选")推导业务索引;外键列默认建索引 +6. **业务注记**:对每张表用一两句话说明业务用途、关键约束、与其他表的关系 + +如果某 REQ 表述模糊以致无法推断关键 schema 细节(如:枚举值范围 / 字段长度上限 / 必填性),先按合理默认推导并在该字段「业务含义」列加 `[需用户审阅]` 标注,待步骤 E 用户审阅时调整;**不打断本次推导**。 + +### C. 渲染 docs/03 + +1. 用 `Read` 读取 `${CLAUDE_SKILL_DIR}/templates/docs-03-header-template.md`,填充 `schema_name`(从 `.env.local` 读 `DB_SCHEMA`,无则填 `【人工填写:DB_SCHEMA】`)、`er_overview`(基于步骤 B 表关系生成的纯文本 ER 概览)。 +2. 渲染「表清单」:每行 `- \`\` — <一句话用途>`。 +3. 对每张表:用 `Read` 读取 `${CLAUDE_SKILL_DIR}/templates/docs-03-table-template.md`,填充字段 / 索引 / 外键 / 业务注记。 +4. 用 `Write` 写入 `docs/03-数据库设计文档.md`。 + +### D. 回填模块头 + REQ 卡片的 TBD 字段 + +1. 用 `Glob` 列出 `docs/01-需求清单/*.md`(排除 `index.md`)。 +2. 用 `Grep` 在这些文件中搜索 `TBD(A3 自动补)` 的**行号**(不读全文)。两种行命中: + - `涉及表: TBD(A3 自动补)` → 模块级(文件头部,每文件一次) + - `依赖表: TBD(A3 自动补)` → REQ 级(每 REQ 一次) +3. 对每个命中行按类型回填: + - **模块级 `涉及表`**:用 `Read` 取该文件 `{{module_code}}` + `{{module_name}}`,聚合步骤 B 中所有归属该模块的表(多表用 `, ` 分隔);`Edit` 替换为 `涉及表: , , ...` + - **REQ 级 `依赖表`**:用 `Read` 仅读取该 REQ 卡片所在片段(标题前后约 20 行)取 `req_id`;根据步骤 B 推导结果定位该 REQ 关联的表;`Edit` 替换为 `依赖表: , ` + - **不动** `TBD(A5 自动补)` 的两种行(`依赖接口` REQ 级 / `依赖模块` 模块级)—— 由 A5 `downstream-gen` 生成 docs/05 + 完成模块 DAG 后回填 +4. 用 `Grep` 再次扫 `TBD(A3 自动补)` 应 0 命中;仍有残留则打印残留位置清单并停下。 +5. 打印回填统计:`A3 回填 处模块涉及表 + 处 REQ schema_refs`。 + +### E. 勾选 docs/08 自动项 + 停下等人工审阅 + +1. 用 `Edit` 在 `docs/08-模块任务管理.md` 勾选 2 个自动项(**不勾**第 3 个人工闸门,由用户审阅后自己勾): + - ` - [ ] docs/03-数据库设计文档.md 已生成` → `[x]` + - ` - [ ] docs/01 各 REQ 卡片"涉及数据表"已回填` → `[x]` + - ` - [ ] 用户已审阅 docs/03 表结构` 保持 `[ ]`(人工勾) + - `- [ ] A3 DB 设计 + REQ 回填 — db-design-gen` 保持 `[ ]`(最后一个子项勾后再勾父项) + +2. 输出 `db-design-gen: docs/03 已生成 + N 处 REQ 已回填依赖表`。 + +3. 打印停下横幅并**停下**(**不调** `Skill(db-init)`,A4 由用户审阅后手动恢复): + + ``` + ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + [db-design-gen] ✅ A3 DB 设计完成 + + 产出: + ✓ docs/03-数据库设计文档.md + ✓ docs/01-需求清单/-*.md 依赖表已回填 + + ⏸ 现在请你审阅 docs/03(表 / 字段 / 索引 / 外键 / 业务注记)。 + 重点关注: + - 业务实体覆盖是否完整 + - 字段类型 / 长度 / 是否可空 / 默认值是否合理 + - 索引是否覆盖主要查询模式 + - 外键 ON DELETE / ON UPDATE 策略是否符合业务 + - 字段「业务含义」列含 `[需用户审阅]` 标注的位置需逐一确认 + + 审阅完成后,到 docs/08 § 一 把 A3 的「用户已审阅 docs/03 表结构」 + 手动勾上(`[ ]` → `[x]`),然后再勾父项 `- [ ] A3 DB 设计 + REQ 回填`, + 再运行: + /erp-workflow:plan-start + + (入口会读取 docs/08 进度,自动派发到 A4 db-init) + ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + ``` + + **停止**,不调用任何下游 skill。 + +## 不变量 + +- 本 skill **不连接任何数据库**,纯文档驱动;MySQL 连接验证 / DDL apply 由 A4 `db-init` 负责 +- REQ 卡片的 `依赖接口` 字段不在此处填充,留给 A5 `downstream-gen` 在生成 docs/05 后按 `TBD(A5 自动补)` 回填 +- DB 设计与 REQ 卡片同等重要,必须留出人工审阅闸门,避免 LLM 推导的表结构未经把关就被 A4 翻译成 DDL 并 apply 到 MySQL + +## 参考 + +- `${CLAUDE_SKILL_DIR}/templates/docs-03-header-template.md` +- `${CLAUDE_SKILL_DIR}/templates/docs-03-table-template.md` +- `docs/04-技术规范.md` § 一+(命名规范输入) +- `docs/01-需求清单/*.md`(REQ 输入 + 回填目标) diff --git a/skills/plan/db-design-gen/templates/docs-03-header-template.md b/skills/plan/db-design-gen/templates/docs-03-header-template.md new file mode 100644 index 0000000..a88bd48 --- /dev/null +++ b/skills/plan/db-design-gen/templates/docs-03-header-template.md @@ -0,0 +1,14 @@ +# 03-数据库设计文档 + +Schema: `{{schema_name}}` +Migration 清单: `sql/migrations/V*.sql`(由 Flyway 顺序 apply) +生成方式: 由 A3 `db-design-gen` 基于 `docs/01-需求清单/*.md` REQ 卡片正向设计生成(schema SSoT)。 + +## ER 关系概览 + +{{er_overview}} + +## 表清单 +{{#each tables}} +- `{{table_name}}` — {{purpose}} +{{/each}} diff --git a/skills/plan/db-design-gen/templates/docs-03-table-template.md b/skills/plan/db-design-gen/templates/docs-03-table-template.md new file mode 100644 index 0000000..dfdc35a --- /dev/null +++ b/skills/plan/db-design-gen/templates/docs-03-table-template.md @@ -0,0 +1,22 @@ +## `{{table_name}}` — {{purpose}} + +### 字段 + +| 字段 | 类型 | Nullable | 默认 | 业务含义 | +|---|---|---|---|---| +{{#each columns}} +| {{name}} | {{type}} | {{nullable}} | {{default}} | {{business_meaning}} | +{{/each}} + +### 索引 +{{#each indexes}} +- `{{name}}` ({{type}}): {{columns}} +{{/each}} + +### 外键 +{{#each foreign_keys}} +- `{{name}}`: {{from_col}} → {{to_table}}.{{to_col}} ({{on_delete}}) +{{/each}} + +### 业务注记 +{{notes}} diff --git a/skills/plan/db-init/SKILL.md b/skills/plan/db-init/SKILL.md new file mode 100644 index 0000000..bf485cc --- /dev/null +++ b/skills/plan/db-init/SKILL.md @@ -0,0 +1,207 @@ +--- +name: db-init +description: A4 DB 初始化——LLM 解析 docs/03-数据库设计文档.md → 生成 sql/migrations/V1__initial_schema.sql(DDL only,Flyway 初始 migration)→ 全量校验 DDL ↔ docs/03 一致性 → 验证 MySQL 连接 → 调 scripts/setup-test-db.sh 复用三层防护并 DROP+CREATE 空库 → apply V1。 +user-invocable: false +allowed-tools: Read Write Edit Glob Skill Bash(mkdir *) Bash(mysql *) Bash(set *) Bash(. .env.local) Bash(sed *) Bash(cat *) Bash(grep *) Bash(./scripts/setup-test-db.sh) +--- + +**所有输出必须使用中文。** + +# db-init + +## 前置条件 + +- A3 `db-design-gen` 已完成:`docs/03-数据库设计文档.md` 已生成,用户已审阅,docs/08 § 一 A3 全部 checkbox 均 `[x]`。 +- A2 `skeleton-gen` 已完成:`.env.local` 已存在(含 `DB_HOST` / `DB_PORT` / `DB_USER` / `DB_PASSWORD` / `DB_SCHEMA`)。 + +## 执行步骤 + +### 步骤 0:打印当前位置流程图 + +向用户展示当前在 A 阶段流程中的位置(A-only,`▶` 标在 A4): + +``` +┌──────────────────────────────────────────────────────┐ +│ 📋 阶段 A:规划(一次性) │ +│ │ +│ A0 初始化项目 → A1 锁范围(REQ 卡片) │ +│ ↓ │ +│ ⏸ 等你审阅 REQ,重新运行 /plan-start 继续 │ +│ ↓ │ +│ A2 生成骨架 → A3 生成 DB 设计 → ▶ A4 初始化 DB → A5 生成下游文档│ +│ ↓ │ +│ 规划阶段最后一步:A5 由本 skill 末尾自动调起 │ +└──────────────────────────────────────────────────────┘ +``` + +### A. DDL 生成(不依赖数据库连接) + +#### A.1 读 docs/03 并 LLM 翻译为 DDL + +用 `Read` 读取 `docs/03-数据库设计文档.md`,按字段 / 索引 / 外键 / 业务注记**严格翻译**为: + +- 每张表一段 `CREATE TABLE \`\` (...) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='<业务用途>';` +- 字段顺序与 docs/03 表格行序一致;`Nullable` 列直接映射 `NOT NULL` / `NULL`;`默认` 列映射 `DEFAULT `;列尾用 `COMMENT '<业务含义>'` 写注释 +- 索引:在表创建后追加 `CREATE [UNIQUE] INDEX \`\` ON \`\` ();`(主键 / 唯一约束已在 CREATE TABLE 内联的不重复声明) +- 外键:在所有表创建完成后**统一追加**:`ALTER TABLE \`\` ADD CONSTRAINT \`\` FOREIGN KEY (\`\`) REFERENCES \`\` (\`\`) ON DELETE ;`(避免顺序问题) + +要求: +- **严禁臆造** docs/03 中没有的表 / 字段 / 索引 / 外键 +- **严禁省略** docs/03 中已有的列、注释或约束 +- 字符集统一 `utf8mb4` + `utf8mb4_unicode_ci`,引擎统一 `InnoDB`,除非 docs/03 业务注记明确要求其他设置 + +#### A.2 拼装 V1 文件 + +用 `Bash` 拼装最终文件: + +```bash +mkdir -p sql/migrations +PROJECT="<从 CLAUDE.md 读到的项目名称>" +TS="$(date -u +%FT%TZ)" +set -a; . .env.local; set +a +{ + sed -e "s|{{project_name}}|$PROJECT|g" \ + -e "s|{{timestamp}}|$TS|g" \ + -e "s|{{schema_name}}|$DB_SCHEMA|g" \ + "${CLAUDE_SKILL_DIR}/templates/migration-v1-header-template.sql" + echo "" + cat <<'DDL_EOF' +<把 A.1 推导出的 CREATE TABLE / CREATE INDEX / ALTER ADD FK 全部按顺序粘贴在此> +DDL_EOF +} > sql/migrations/V1__initial_schema.sql +``` + +#### A.3 全量校验 DDL ↔ docs/03 一致性 + +5 维度全量校验。**任一不一致** → 报错停下,**列出全部差异明细**;V1.sql 保留以便人工 diff。 + +1. **表名集合相等** + - `S_doc` = grep `^## \`\`` of docs/03 + - `S_sql` = grep `CREATE TABLE \`\`` of V1 + - `S_doc - S_sql` 非空(漏表)/ `S_sql - S_doc` 非空(多表)→ 报错列出差集 + +2. **每张表全列名 + 列序相等**(**遍历 S_sql 全部表,无抽样**) + - 对每张表 t: + - 从 docs/03 抽该表 `### 字段` 表格行序,得 `cols_doc[t]` + - 从 V1 抽该 `CREATE TABLE` 段内 `\`\`` 出现序,得 `cols_sql[t]` + - **数组相等**(含顺序);不等则列出 `
: docs=[...], sql=[...]` + +3. **每个字段类型 / Nullable / 默认值一致** + - 对每个 `
.`,归一化后字符串比对。归一化规则: + - 类型主词转小写(`BIGINT` → `bigint`) + - `UNSIGNED` 保留为小写 + - 显示宽度 `INT(11)` → `int`(去括号) + - Nullable:docs/03 `否` ↔ DDL `NOT NULL`;docs/03 `是` ↔ DDL 无 `NOT NULL` + - 默认值:去多余空格 + 统一大小写 + - **`COMMENT` / `COLLATE` / `CHARSET` 不参与比对**(避免装饰差异误报) + - 不一致 → 列出 `
.: docs=, ddl=` + +4. **每张表索引名集合相等** + - `idx_doc[t]` = docs/03 该表 `### 索引` 列表的名字 + - `idx_sql[t]` = V1 中归属该表的 `CREATE INDEX ` + inline `KEY \`\` / UNIQUE KEY \`\``(排除 `PRIMARY` 自动名) + - 集合不等 → 报错列出差集 + +5. **外键名集合相等**(全局,不分表) + - `fk_doc` = docs/03 各表 `### 外键` 列表的所有名字 + - `fk_sql` = V1 中所有 `ADD CONSTRAINT \`\` FOREIGN KEY` 的名字 + - 集合不等 → 报错列出差集 + +校验全部通过 → 进入步骤 B。**任一维度不通过都不许继续**;提示用户 diff `docs/03` ↔ `V1.sql` 后修正 docs/03(SSoT),重跑 A3 让 `db-design-gen` / 本 skill 重新生成 V1。 + +### B. 数据库环境检查 + +#### B.1 检查 .env.local 凭据 + +用 `Glob` 检查 `.env.local` 是否存在;不存在 → 提示用户重新运行 A2 `skeleton-gen` 重建并停下。 + +用 `Bash` 加载并校验 5 个必填字段非空: + +```bash +set -a; . .env.local; set +a +for v in DB_HOST DB_PORT DB_USER DB_PASSWORD DB_SCHEMA; do + eval val=\${$v:-} + [ -z "$val" ] && echo "MISSING: $v" +done +``` + +任一缺失 → 打印缺失字段名并停下,提示用户编辑 `.env.local` 后重跑。 + +> 注:密码中含 `$`、`` ` ``、空格、`!` 等字符时,`.env.local` 需用单引号包裹,例如 `DB_PASSWORD='p@ss$w0rd!'`。`set -a; . file; set +a` 与 `source` 行为一致但更明确,配合单引号可避免特殊字符被 shell 展开。 + +#### B.2 验证 MySQL 连接 + +```bash +set -a; . .env.local; set +a +mysql -h"$DB_HOST" -P"$DB_PORT" -u"$DB_USER" -p"$DB_PASSWORD" -e "SELECT 1;" +``` + +- **成功** → 进入步骤 C +- **失败** → 打印具体错误(认证 / 主机不可达 / 端口拒接等),提示检查 `.env.local`,**停下**。`sql/migrations/V1__initial_schema.sql` 已在步骤 A 落盘,用户可在修复连接后手动 `mysql < V1.sql`,无需重跑 A4 的 DDL 生成 + +### C. 自动导入 MySQL + +#### C.1 调 setup-test-db.sh 做防护 + DROP+CREATE 空库 + +A2 `skeleton-gen` 已生成 `scripts/setup-test-db.sh`,内置三层防护(**单一真相源,与 B 阶段 test.sh 共用同款规则**): +- 防护 1:host 白名单(默认 `localhost / 127.0.0.1 / ::1`,严格相等匹配;可通过 `.env.local` 的 `TEST_DB_ALLOWED_HOSTS` 显式扩展) +- 防护 2:schema 命名后缀检查(必须含 `test` 或以 `_dev / _local / _ci` 结尾) +- 防护 3:远程 host DROP 警告横幅 + +直接调用,由它处理凭据加载 + 三层防护 + DROP+CREATE: + +```bash +./scripts/setup-test-db.sh +``` + +任一防护失败 → 脚本自身停下并打印明细(host 不在白名单 / schema 名不像测试库 / `.env.local` 缺失等),本 skill **立即停下不做后续步骤**。 +`sql/migrations/V1__initial_schema.sql` 已在步骤 A 落盘,用户调整 `.env.local`(如 `TEST_DB_ALLOWED_HOSTS` 加 host)或 schema 命名后可直接重跑 A4,无需重新生成 V1。 + +#### C.2 把 V1 灌入已清空的 schema + +```bash +set -a; . .env.local; set +a +mysql -h"$DB_HOST" -P"$DB_PORT" -u"$DB_USER" -p"$DB_PASSWORD" "$DB_SCHEMA" \ + < sql/migrations/V1__initial_schema.sql +``` + +非零退出 → 报错停下,打印 mysql stderr。 + +#### C.3 自检 SHOW TABLES + +```bash +set -a; . .env.local; set +a +ACTUAL=$(mysql -N -B -h"$DB_HOST" -P"$DB_PORT" -u"$DB_USER" -p"$DB_PASSWORD" \ + -e "SHOW TABLES;" "$DB_SCHEMA" | wc -l | tr -d ' ') +EXPECTED=$(grep -c '^## `' docs/03-数据库设计文档.md) +[ "$ACTUAL" = "$EXPECTED" ] || { echo "MISMATCH: actual=$ACTUAL expected=$EXPECTED"; exit 1; } +``` + +行数不一致 → 报错停下;一致 → 进入步骤 D。 + +### D. 勾选 docs/08 进度 + 进入 A5 + +1. 用 `Edit` 在 `docs/08-模块任务管理.md` 勾选 5 个 checkbox(A4 的 4 个子项 + A4 父项): + - ` - [ ] sql/migrations/V1__initial_schema.sql 已生成` → `[x]` + - ` - [ ] .env.local 凭据已验证(mysql -e "SELECT 1" OK)` → `[x]` + - ` - [ ] setup-test-db.sh 防护通过 + DROP+CREATE + apply V1 已执行` → `[x]` + - ` - [ ] SHOW TABLES 行数 == docs/03 表数量` → `[x]` + - `- [ ] A4 DB 初始化 — db-init` → `[x]` + +2. 输出 `db-init: 完成(V1 ✓, schema=<名称>, tables=,已 apply 到本地 MySQL)`。 + +3. 立即调用 `Skill(downstream-gen)` 进入 A5,不等用户手动输入。 + +## 不变量 + +- **DDL 来源唯一**:V1 完全由 docs/03 翻译而来;docs/03 是 schema 单一真相源(SSoT)。后续 V2/V3 由 B 阶段 `feature-tdd` 在 REQ 实现时写入,并**同步**回写 docs/03 对应表小节 +- **测试夹具归属 B 阶段**:测试数据由 B 阶段每个 REQ 在自己的测试代码 / Spring `@Sql` / testcontainers fixture 中按需提供 +- **安全守护单一真相源**:DROP / 写操作的防护逻辑统一在 `scripts/setup-test-db.sh`(三层防护:host 白名单 + schema 命名后缀 + 远程 host 横幅),本 skill 与 B 阶段 `test.sh` 共用同一份规则;本 skill 不重复实现防护 +- **DDL 校验 fail-closed**:A.3 5 维度全量校验任一不通过都不许进入 apply 阶段 +- **失败可恢复**:每次重跑都从空库 `DROP+CREATE` 开始;中途失败重跑无状态残留 + +## 参考 + +- `${CLAUDE_SKILL_DIR}/templates/migration-v1-header-template.sql`(V1 头部注释) +- `docs/03-数据库设计文档.md`(DDL 翻译输入,SSoT) +- `.env.local`(DB 凭据) +- 产物:`sql/migrations/V1__initial_schema.sql`(由 Flyway 在 Spring Boot 启动时验证 / apply) diff --git a/skills/plan/db-init/templates/migration-v1-header-template.sql b/skills/plan/db-init/templates/migration-v1-header-template.sql new file mode 100644 index 0000000..3c5b01f --- /dev/null +++ b/skills/plan/db-init/templates/migration-v1-header-template.sql @@ -0,0 +1,8 @@ +-- Flyway migration V1 — initial schema for {{project_name}} +-- Generated: {{timestamp}} +-- Source: 由 A4 `db-init` 从 `docs/03-数据库设计文档.md` 翻译生成(schema SSoT 是 docs/03) +-- This is the FIRST migration; subsequent schema changes must be written +-- as new files sql/migrations/V2__.sql, V3__..., etc. +-- Apply: Flyway runs this automatically at Spring Boot startup. +-- Do not hand-edit this file after it is committed; write a new migration instead. +-- ========================================================= diff --git a/skills/plan/downstream-gen/SKILL.md b/skills/plan/downstream-gen/SKILL.md new file mode 100644 index 0000000..3c81708 --- /dev/null +++ b/skills/plan/downstream-gen/SKILL.md @@ -0,0 +1,235 @@ +--- +name: downstream-gen +description: A5 下游文档生成——基于 docs/01 和 docs/03 推导,一次性生成 docs/02 + docs/05 + docs/06 § 五 + docs/10,回填 REQ 卡片依赖接口,把模块清单追加到 docs/08 § 二。 +user-invocable: false +allowed-tools: Read Write Edit Glob Grep Skill AskUserQuestion Bash(cat *) Bash(git remote *) +--- + +**所有输出必须使用中文。** + +# downstream-gen + +## 前置条件 + +- `docs/01-需求清单/*.md` 完整 REQ 卡片已就绪(A1 生成 + 人工审阅过 + A3 已回填依赖表)。 +- `docs/03-数据库设计文档.md` 已就绪(A3 生成 + 人工审阅过)。 +- `sql/migrations/V1__initial_schema.sql` 已生成并 apply(A4 完成)。 +- `docs/05` / `docs/06 § 五` / `docs/10` 等下游文件尚不存在(本 skill 创建)。 + +## 执行步骤 + +### 步骤 0:打印当前位置流程图 + +向用户展示当前在 A 阶段流程中的位置(A-only,`▶` 标在 A5): + +``` +┌──────────────────────────────────────────────────────┐ +│ 📋 阶段 A:规划(一次性) │ +│ │ +│ A0 初始化项目 → A1 锁范围(REQ 卡片) │ +│ ↓ │ +│ ⏸ 等你审阅 REQ,重新运行 /plan-start 继续 │ +│ ↓ │ +│ A2 生成骨架 → A3 生成 DB 设计 → A4 初始化 DB → ▶ A5 生成下游文档│ +│ ↓ │ +│ 规划阶段到此结束 │ +└──────────────────────────────────────────────────────┘ +``` + +### A. docs/02 — 开发计划(含 REQ 级开发顺序清单,CC 分发权威) + +**清单粒度**:一行一个 REQ,同一模块的 REQ 必须**连续排列**。 + +1. 构建**模块依赖 DAG**: + - docs/03 中的外键(表 A → 表 B ⇒ A 的模块依赖 B 的模块) + - docs/01 index 中的显式 `depends_on` 提示 +2. 对模块 DAG 做拓扑排序得 `module_topo_order[]`。 +3. 对**每个模块内部**构建 REQ 间依赖(从 REQ 卡片 `goal` / `rules` / `依赖表` 推断 REQ-A 是 REQ-B 的前置),得到模块内 REQ 顺序。 +4. 合成 `req_order[]`:按 `module_topo_order[]` 依次铺开每个模块内的 REQ 序列(**同模块 REQ 连续**)。 +5. **环依赖打破**: + - **模块级**:若模块 DAG 存在环(module_A ↔ module_B),按启发式(字母序 / 被依赖次数多者先)破环排出 `module_topo_order`,并在**参与环的模块里第一个 REQ** 的 `note` 字段填入原因(如 "A↔B 互依赖:先做 A 的骨架")。 + - **REQ 级(同模块内)**:若模块内 REQ 互依赖,同样破环,`note` 填原因。 + - 非环 REQ `note` 留 `—`。 +6. 为 `req_order[]` 每项生成字段: + - `index`:行号(从 1 开始) + - `req_id`:如 `REQ-SYS-001` + - `module_id`:该 REQ 所属模块,如 `module_sys` + - `rationale`(一行**选中理由**):依赖驱动的简短描述,如 `所属模块无依赖,基础模块` / `依赖 REQ-SYS-001 已在前` / `所属模块依赖 module_sys 已在前` + - `note`(一行**备注**):默认 `—`;仅环依赖打破场景填原因 +7. 用 `Read` 读取 `${CLAUDE_SKILL_DIR}/templates/docs-02-template.md`,填充 `modules[]`(含 `id` / `name` / `deps` / `tables`)/ `req_order[]`(每项含 `index` / `req_id` / `module_id` / `rationale` / `note`)/ `notes`。 +8. 写入 `docs/02-开发计划.md`。 + +### B. docs/05 — API 接口契约 + +1. 用 `Read` 读取 `${CLAUDE_SKILL_DIR}/templates/docs-05-header-template.md`,写入 `docs/05-API接口契约.md` 头部。 +2. 对所有模块的每个 REQ:用 `Read` 读取 `${CLAUDE_SKILL_DIR}/templates/docs-05-endpoint-template.md`,推断 method / path / auth / permission / 请求和响应 schema(不明确的询问用户),追加到 docs/05。 + +### B2. 回填模块头 + REQ 卡片的 TBD(A5) 字段 + +1. 用 `Glob` 列出 `docs/01-需求清单/*.md`(排除 `index.md`)。 +2. 用 `Grep` 在这些文件中搜索 `TBD(A5 自动补)` 的行号(不读全文)。两种行命中: + - `依赖模块: TBD(A5 自动补)` → 模块级(文件头部,每文件一次) + - `依赖接口: TBD(A5 自动补)` → REQ 级(每 REQ 一次) +3. 对每个命中行按类型回填: + - **模块级 `依赖模块`**:用 `Read` 取该文件 `{{module_code}}` + `{{module_name}}`,从步骤 A 的 `module_topo_order[]` + DAG 查该模块的上游依赖(多模块用 `, ` 分隔);`Edit` 替换为 `依赖模块: , `(无依赖填 `—`) + - **REQ 级 `依赖接口`**:用 `Read` 仅读取该 REQ 卡片所在片段(REQ 标题行前后 20 行),提取 `req_id`;在步骤 B 刚生成的 `docs/05-API接口契约.md` 里 Grep 属于该 REQ 的 endpoint;`Edit` 替换为 `依赖接口: POST /api/xxx, GET /api/yyy`(多个用 `, ` 分隔) +4. 打印回填统计:`A5 回填 处模块依赖 + 处 REQ api_refs`。 + +### C. docs/06 — 页面清单 + +1. 对每个有前端页面的模块:用 `Read` 读取 `${CLAUDE_SKILL_DIR}/templates/docs-06-module-pagelist-template.md`,填充 `pages[]`(page_name、route、page_type、req_ids、menu_path、interactions)。 +2. 将每个渲染块追加到 `docs/06-UI交互规范.md` § 五。 + +### D. docs/08 § 二 — 追加模块清单(含 REQ 子项) + +docs/08 已由 A0 project-init 创建(含 Plan 进度骨架)。本步骤只往 § 二 追加模块行,**不重写整个文件**。 + +1. 用 `Read` 读取 `${CLAUDE_SKILL_DIR}/templates/docs-08-module-row-template.md`(单模块 bullet 行模板)。 +2. **按 `module_id` 字母序**对每个模块: + - 从步骤 A `req_order[]` 过滤出 `module_id` 匹配的 REQ 列表(保持步骤 A 算出的模块内 REQ 顺序)。 + - 对每个 REQ 从 `docs/01-需求清单/.md` 读出其一句话标题(REQ 卡片标题行或 `goal` 字段)。 + - 渲染 `{{req_checklist}}` 块:每行 ` - [ ] `(4 空格缩进对齐 `- 功能:`)。 + - 渲染整条 bullet,填充 `module_id` / `module_name` / `depends_on` / `path_scopes` / `req_checklist`。 + + > 注意一:docs/08 § 二 的**模块行序**不决定分发顺序——分发以 docs/02 § 二 REQ 清单为准,此处模块按字母序仅方便查找。 + > 注意二:REQ 子项的 `[ ]` 由 `feature-review` 在 `verdict=approve` 时自动勾选,作为功能级进度可视化;**模块完成判定仍由 `MR:` 字段 + GitLab API state 单独决定**,不依赖子项勾选状态。 +3. 所有模块行拼成一段文本,用 `Edit` 在 `docs/08-模块任务管理.md` 的 `## 二、Coding 阶段(按模块循环)` 标题后插入(定位用下一行注释"(A5 填入后..."作为锚,把模块清单插到该注释之前)。 + +### E. docs/10 — 验收清单 + +1. 用 `Read` 读取 `${CLAUDE_SKILL_DIR}/templates/docs-10-header-template.md`,写入 `docs/10-验收检查清单.md` 头部。 +2. 对每个模块:用 `Read` 读取 `${CLAUDE_SKILL_DIR}/templates/docs-10-module-template.md`,填充 `reqs[]`、`data_checks[]`、`ui_checks[]`,追加。 + +### F. 验证 + 勾选 docs/08 进度 + 终止 Plan 阶段 + +1. 一致性检查: + - docs/01 的每个 REQ 都出现在 docs/05(作为接口,如适用)、docs/10(作为验收项)。 + - `docs/02 § 二` 开发顺序清单的 `module_id` 集合 = `docs/08 § 二` 的 `module_id` 集合(数量、ID 全等);不相等 → 报错停下,列出差集。 + +2. **最终占位符扫描**(覆盖 Plan 阶段全部产出:`docs/01-需求清单/*.md` + `docs/02` / `docs/03` / `docs/05` / `docs/06` / `docs/10`): + + a. **`TBD` → CC 自动补齐**:用 `Grep` 搜索 `TBD(A3 自动补)` 和 `TBD(A5 自动补)`。有命中则按 A3 / B2 同样逻辑就地补填(A3 查 docs/03 填 `依赖表:`;A5 查 docs/05 按 REQ-ID 填 `依赖接口:`),再 Grep 确认 0 命中;仍残留报错停下。 + + b. **`【人工填写:...】` → QA 循环等用户补**(与 A2 skeleton-gen 步骤 E 同风格): + + 循环执行直到两个条件**同时满足**:(1) 扫描 0 命中;(2) 用户选「继续」 + + - **b.1 扫描**:用 `Grep` 在上述所有文件中搜索 `【人工填写:`,得到命中数 N 和残留位置清单(`<文件:行号> — <行内容摘要>`) + - **b.2 打印汇总横幅**: + ``` + ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + [downstream-gen] 最终占位符审阅 + + <N=0 时打印:✅ 全部填完> + <N>0 时打印:⚠️ 还有 N 处待填: + <文件:行号> — <行内容摘要> + ...> + + 需要调整 → 直接编辑对应文件 + 填完后 → 回来选「继续」放行完成 Plan + ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + ``` + - **b.3 弹出 QA**:用 `AskUserQuestion` 询问: + - **question**: `最终占位符补填完毕?` + - **options** (每项为对象): + - `{"label": "继续", "description": "放行完成 Plan 阶段"}` + - `{"label": "有疑问想先沟通", "description": "需要讨论或修改"}` + - **b.4 路由**: + - 选「有疑问想先沟通」→ 回答用户问题后**回 b.1 重新扫描** + - 选「继续」→ **回 b.1 重新扫描验证**: + - 新 N = 0 → 进入步骤 3 + - 新 N > 0 → 用户以为填完其实还有残留,回 b.2 打印新横幅并再次弹出 QA + + 关键:**每次弹出 QA 前都重新扫描一次**,用户看到的 N 始终是最新的;只有 N = 0 且选「继续」才放行。 + +3. 用 `Edit` 在 `docs/08-模块任务管理.md` 勾选 7 个 checkbox(A5 的 6 个子项 + A5 父项): + - ` - [ ] docs/02 开发计划已生成` → `[x]` + - ` - [ ] docs/05 API 契约已生成` → `[x]` + - ` - [ ] docs/06 § 五 页面清单已填入` → `[x]` + - ` - [ ] docs/10 验收清单已生成` → `[x]` + - ` - [ ] 下方模块列表已填入` → `[x]` + - ` - [ ] REQ 卡片依赖接口已回填` → `[x]` + - `- [ ] A5 下游文档生成 — downstream-gen` → `[x]` + +4. **从 `origin` 远程派生 GitLab 凭据并回填 `.env.local`** + + 仅当对应字段仍是 `TBD(A5 自动补)` 或空时回填;用户已手填为别的值一律不动。 + + a. 取远程 URL:`Bash`: `git remote get-url origin 2>/dev/null` → `REMOTE_URL`。为空 → 跳过本步骤,仅打印提示"未配置 origin 远程,`GITLAB_*` 留给用户手填"。 + b. 解析: + - `PROJECT_PATH` = 去掉 `<scheme>://<host>/` 或 `git@<host>:` 或 `ssh://<host>/` 前缀 + 去掉末尾 `.git`(如 `zhuzc/test`) + - `PROJECT_ID_ENC` = `PROJECT_PATH` 的 `/` 替换为 `%2F`(如 `zhuzc%2Ftest`) + - `HOST` = 远程主机名(如 `git.xlyprint.cn`) + - `SCHEME` 三分支(**绝不把 SSH remote 降级成 http**——Private Token 不能走明文): + - `REMOTE_URL` 以 `https://` 开头 → `https` + - `REMOTE_URL` 以 `http://` 开头 → `http`(明确声明,非推断) + - 其他(`git@` / `ssh://` / 异常)→ `https`(默认走安全侧) + - `API_URL_GUESS` = `<SCHEME>://<HOST>/api/v3` + c. 用 `Read` 读 `.env.local`: + - 若 `GITLAB_PROJECT_ID` 当前值为 `TBD(A5 自动补)` 或空 → 用 `Edit` 改为 `GITLAB_PROJECT_ID=<PROJECT_ID_ENC>` + - 若 `GITLAB_API_URL` 当前值为 `TBD(A5 自动补)` 或空 → `Edit` 改为 `GITLAB_API_URL=<API_URL_GUESS>` + - 上两字段若已被用户手改过(非 `TBD(A5 自动补)` 也非空)→ 不覆盖,仅核对打印 + - `GITLAB_TOKEN` 派生不了,占位保持 `【人工填写:...】`,用户去 GitLab Profile → Account → Private token 手填 + d. 打印回填摘要: + ``` + [downstream-gen] GitLab 凭据自动派生(从 origin 远程): + GITLAB_PROJECT_ID = <回填值 或「保留占位: 已手填 xxx」> + GITLAB_API_URL = <回填值 或「保留占位: 已手填 xxx」> + GITLAB_TOKEN = 保持占位 — 请去 GitLab Profile → Account → Private token 手填 + ``` + 若 `SCHEME` 是 `http`,额外提示:"⚠️ 本次派生用 `http://`——Private Token 将走明文;仅当你的 GitLab 部署真的没上 HTTPS 时可以保留,否则请手动改为 `https://`。" + 若 `SCHEME` 是推断来的 `https`(来自 ssh/git@ remote),额外提示:"API URL 的 scheme 是从 SSH remote 默认推成 `https`;如实际 API 走 http,请手动改 `GITLAB_API_URL`。" + +5. 输出:`downstream-gen: 写入 4 个文件 + <N> 个模块 + <M> 处 REQ 依赖接口回填。` + +6. 打印 Plan 阶段终止横幅并**停下**(不自动进入 B 阶段): + + ``` + ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + [downstream-gen] ✅ Plan 阶段(A0~A5)全部完成 + + 所有规划文档已就绪,docs/08 § 一 全部勾选。 + + ⚠️ 进入 B 阶段前必须完成: + 1. 人工通读 docs/01~10 + CLAUDE.md + sql/migrations/V1 + 各 scripts/* + + 2. 把全部 Plan 产物 commit: + git add -A && git commit -m "chore: plan phase A0~A5 done" + + 3. 推到远程,按仓库状态二选一: + + 情况 A — 远程仓库是全新的(尚无 main / master): + git remote add origin <gitlab-url> # 若尚未添加 + git -c core.hooksPath=/dev/null push -u origin master + # 首次 push 本地 DB 尚未就位、scripts/test.sh 必然失败。 + # `-c core.hooksPath=/dev/null` 只对本次 push 临时指向空的 hooksPath, + # 跳过 .githooks/pre-push,不动 repo 的 core.hooksPath 配置, + # 也不用 --no-verify(后者被 CC 的 deny-no-verify hook 硬拦)。 + # push 完成后到 GitLab UI 把 master(或 main)设为 protected + + 情况 B — 远程已有 main 需要走 MR 审核: + git checkout -b plan-init + git push -u origin plan-init + # 在 GitLab 打开 plan-init → main 的 MR,审核并合并 + + 4. 补齐 `.env.local`: + - `GITLAB_TOKEN`(必填):去 GitLab Profile → Account → Private token 生成后粘贴 + - `GITLAB_API_URL` / `GITLAB_PROJECT_ID`:步骤 4 已从 origin 远程自动回填(若仍显示 + `TBD(A5 自动补)`,说明 origin 没配,手动填;若 scheme 错请改 http↔https) + B 阶段 mr-create 用 token 通过 curl 创建 MR。 + + 5. main(或 master)就绪后,再运行 /erp-workflow:coding-start + 进入 B 阶段。届时 .env.local 应指向本地 MySQL(非共享远程 DB), + 否则 B 阶段每次测试闸门都会因 setup-test-db.sh 的防护失败。 + ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + ``` + +## 参考 + +- `${CLAUDE_SKILL_DIR}/templates/docs-02-template.md` +- `${CLAUDE_SKILL_DIR}/templates/docs-05-header-template.md` +- `${CLAUDE_SKILL_DIR}/templates/docs-05-endpoint-template.md` +- `${CLAUDE_SKILL_DIR}/templates/docs-06-module-pagelist-template.md` +- `${CLAUDE_SKILL_DIR}/templates/docs-08-module-row-template.md`(模块 bullet 行模板) +- `${CLAUDE_SKILL_DIR}/templates/docs-10-header-template.md` +- `${CLAUDE_SKILL_DIR}/templates/docs-10-module-template.md` diff --git a/skills/plan/downstream-gen/templates/docs-02-template.md b/skills/plan/downstream-gen/templates/docs-02-template.md new file mode 100644 index 0000000..3bfbb97 --- /dev/null +++ b/skills/plan/downstream-gen/templates/docs-02-template.md @@ -0,0 +1,24 @@ +# 02-开发计划 + +## 一、模块依赖表 + +| 模块 ID | 模块名 | 依赖模块 | 依赖表 | +|---|---|---|---| +{{#each modules}} +| {{id}} | {{name}} | {{deps}} | {{tables}} | +{{/each}} + +## 二、开发顺序清单(CC 分发权威) + +> 本清单由 A5 `downstream-gen` 一次性生成。**每行是一个 REQ**,不是模块。CC 按表格行序从上到下扫描,对每个 REQ 所属模块查 `docs/08 § 二` 的 `MR:` 字段 + GitLab API `state`:`merged` 跳过,其他(`—` / opened / closed / 查不到)选为当前模块;`module-start` 会把该模块的所有 REQ 一次做完。 +> +> **约束**:同一模块的所有 REQ 必须**连续排列**。允许打破依赖拓扑(如环依赖、业务必须先做),但必须在「备注」列写明原因。 + +| # | REQ | 所属模块 | 选中理由 | 备注 | +|---|-----|---------|---------|------| +{{#each req_order}} +| {{index}} | **{{req_id}}** | {{module_id}} | {{rationale}} | {{note}} | +{{/each}} + +## 三、关键说明 +{{notes}} diff --git a/skills/plan/downstream-gen/templates/docs-05-endpoint-template.md b/skills/plan/downstream-gen/templates/docs-05-endpoint-template.md new file mode 100644 index 0000000..1583d4e --- /dev/null +++ b/skills/plan/downstream-gen/templates/docs-05-endpoint-template.md @@ -0,0 +1,24 @@ +### {{req_id}} {{title}} + +- **Method**: {{method}} +- **Path**: `{{path}}` +- **Auth**: {{auth}} +- **Permission**: {{permission}} + +#### 请求参数 +{{request_params}} + +#### 请求体 +```json +{{request_body_schema}} +``` + +#### 响应体 +```json +{{response_body_schema}} +``` + +#### 错误码 +{{#each errors}} +- `{{code}}` — {{message}} +{{/each}} diff --git a/skills/plan/downstream-gen/templates/docs-05-header-template.md b/skills/plan/downstream-gen/templates/docs-05-header-template.md new file mode 100644 index 0000000..e89cc3d --- /dev/null +++ b/skills/plan/downstream-gen/templates/docs-05-header-template.md @@ -0,0 +1,30 @@ +# 05-API接口契约 + +BasePath: `{{base_path}}` +端口: `【人工填写:后端端口,默认 8080】` + +## 全局约定 + +### 响应格式 +```json +{"code": 200, "message": "操作成功", "data": {}, "timestamp": 1700000000000} +``` + +### 错误码 +| 范围 | 含义 | +|---|---| +| 200 | 成功 | +| 400xx | 客户端参数错误 | +| 401xx | 认证/授权错误 | +| 403xx | 权限不足 | +| 404xx | 资源不存在 | +| 500xx | 服务端内部错误 | + +### 鉴权 +{{auth_note}} + +### 分页参数 +{{pagination_note}} + +## 接口清单 +(各模块接口段落见下方,由 `downstream-gen` 按 REQ 填入) diff --git a/skills/plan/downstream-gen/templates/docs-06-module-pagelist-template.md b/skills/plan/downstream-gen/templates/docs-06-module-pagelist-template.md new file mode 100644 index 0000000..36f18a5 --- /dev/null +++ b/skills/plan/downstream-gen/templates/docs-06-module-pagelist-template.md @@ -0,0 +1,9 @@ +### {{module_id}} {{module_name}} + +{{#each pages}} +- **{{page_name}}** (`{{route}}`) + - 类型: {{page_type}} (列表页 / 表单页 / 详情页 / 树形管理页) + - 对应 REQ: {{req_ids}} + - 入口菜单: {{menu_path}} + - 主要交互: {{interactions}} +{{/each}} diff --git a/skills/plan/downstream-gen/templates/docs-08-module-row-template.md b/skills/plan/downstream-gen/templates/docs-08-module-row-template.md new file mode 100644 index 0000000..d11175d --- /dev/null +++ b/skills/plan/downstream-gen/templates/docs-08-module-row-template.md @@ -0,0 +1,6 @@ +- {{module_id}} {{module_name}} + - 依赖: {{depends_on}} + - 路径: {{path_scopes}} + - MR: — + - 功能: +{{req_checklist}} diff --git a/skills/plan/downstream-gen/templates/docs-10-header-template.md b/skills/plan/downstream-gen/templates/docs-10-header-template.md new file mode 100644 index 0000000..a4132b3 --- /dev/null +++ b/skills/plan/downstream-gen/templates/docs-10-header-template.md @@ -0,0 +1,14 @@ +# 10-验收检查清单 + +通用验收项(全项目适用): + +- [ ] `scripts/test.sh` 本地全绿 +- [ ] 所有 schema 改动都有对应 `sql/migrations/V_n__<desc>.sql` +- [ ] 所有新接口在 `docs/05` 中有契约定义 +- [ ] 所有新功能代码注释含 REQ-XXX-NNN +- [ ] 统一响应格式 `{code, message, data, timestamp}` +- [ ] 异常走全局处理器,不暴露堆栈到前端 +- [ ] 前端不存敏感信息到 localStorage + +## 模块专项 +(各模块验收段落见下方,由 `downstream-gen` 按模块填入) diff --git a/skills/plan/downstream-gen/templates/docs-10-module-template.md b/skills/plan/downstream-gen/templates/docs-10-module-template.md new file mode 100644 index 0000000..9342e2e --- /dev/null +++ b/skills/plan/downstream-gen/templates/docs-10-module-template.md @@ -0,0 +1,18 @@ +### {{module_id}} {{module_name}} + +#### 功能级验收(每个 REQ 对应可执行用例) +{{#each reqs}} +- [ ] {{req_id}} {{title}} + - 自动化用例: `{{test_file}}::{{test_name}}` + - 手动验收: {{manual_check}} +{{/each}} + +#### 数据级验收 +{{#each data_checks}} +- [ ] {{check}} +{{/each}} + +#### UI 级验收(若含前端) +{{#each ui_checks}} +- [ ] {{check}} +{{/each}} diff --git a/skills/plan/erp-db-design-gen/SKILL.md b/skills/plan/erp-db-design-gen/SKILL.md deleted file mode 100644 index aef92fe..0000000 --- a/skills/plan/erp-db-design-gen/SKILL.md +++ /dev/null @@ -1,110 +0,0 @@ ---- -name: erp-db-design-gen -description: A4 DB 设计生成 + REQ 回填——用 mysql CLI 反查 schema 生成 docs/03-数据库设计文档.md;然后用 Grep 在 docs/01-需求清单/*.md 定位 TBD(A4 自动补) 替换为实际表/字段引用。 -user-invocable: false -allowed-tools: Read Write Edit Grep Glob Skill Bash(mysql *) Bash(set *) Bash(. .env.local) ---- - -**所有输出必须使用中文。** - -# erp-db-design-gen - -## 前置条件 - -- `erp-db-init` 已完成:`.env.local` 凭据已填,`sql/migrations/V1__initial_schema.sql` 和 `sql/seed-data.sql` 都已生成。 -- `erp-scope-lock` 已完成:`docs/01-需求清单/<module>-*.md` REQ 卡片存在,含 `TBD(A4 自动补)` 占位。 - -## 执行步骤 - -### 步骤 0:打印当前位置流程图 - -向用户展示当前在 A 阶段流程中的位置(A-only,`▶` 标在 A4): - -``` -┌──────────────────────────────────────────────────────┐ -│ 📋 阶段 A:规划(一次性) │ -│ │ -│ A0 初始化项目 → A1 锁范围(REQ 卡片) │ -│ ↓ │ -│ ⏸ 等你审阅 REQ,重新运行 /erp-plan-start 继续 │ -│ ↓ │ -│ A2 生成骨架 → A3 初始化 DB → ▶ A4 生成 DB 设计 → A5 生成下游文档│ -│ ↓ │ -│ 规划阶段到此结束 │ -└──────────────────────────────────────────────────────┘ -``` - -### A. 查询实时 schema - -用 `Bash` 加载 `.env.local` 后查询(用 `set -a; . ...; set +a` 替代 `source`,避免密码中的 shell 特殊字符被展开): - -```bash -set -a; . .env.local; set +a -MYSQL_CMD="mysql -h${DB_HOST} -P${DB_PORT} -u${DB_USER} -p${DB_PASSWORD} -N -B" - -# 表列表 + 注释 -$MYSQL_CMD -e "SELECT table_name, table_comment FROM information_schema.tables WHERE table_schema='${DB_SCHEMA}' AND table_type='BASE TABLE' ORDER BY table_name;" - -# 字段详情 -$MYSQL_CMD -e "SELECT table_name, column_name, column_type, is_nullable, column_default, column_comment FROM information_schema.columns WHERE table_schema='${DB_SCHEMA}' ORDER BY table_name, ordinal_position;" - -# 外键 -$MYSQL_CMD -e "SELECT table_name, column_name, referenced_table_name, referenced_column_name FROM information_schema.key_column_usage WHERE table_schema='${DB_SCHEMA}' AND referenced_table_name IS NOT NULL;" - -# 索引 -$MYSQL_CMD -e "SELECT table_name, index_name, GROUP_CONCAT(column_name ORDER BY seq_in_index) AS cols, non_unique FROM information_schema.statistics WHERE table_schema='${DB_SCHEMA}' GROUP BY table_name, index_name, non_unique;" -``` - -在内存中将结果解析为结构化列表,**只保留表名、字段名与关键元信息,不把查询结果完整写入会话上下文**。 - -### B. 生成 docs/03 - -1. 用 `Read` 读取 `${CLAUDE_SKILL_DIR}/templates/docs-03-header-template.md`,填充 `schema_name`、`er_overview`、`tables[]`。 -2. 对每张表,用 `Read` 读取 `${CLAUDE_SKILL_DIR}/templates/docs-03-table-template.md`,填充并追加。 -3. 每个字段的业务含义: - - 如果 `column_comment` 非空,直接用 - - 否则从 A1 生成的 REQ 卡片上下文推断 -4. 用 `Write` 写入 `docs/03-数据库设计文档.md`。 - -### C. 回填 REQ 卡片的 TBD 字段 - -1. 用 `Glob` 列出 `docs/01-需求清单/*.md`(排除 `README.md`)。 -2. 用 `Grep` 在这些文件中搜索 `TBD(A4 自动补)` 的**行号**(不读全文)。 -3. 对每个命中的 REQ: - - 用 `Read` 仅读取该 REQ 卡片所在的片段(REQ 标题行前后 20 行) - - 根据 `goal` / `input` / `output` 推断引用的表 - - 用 `Edit`:`依赖表: TBD(A4 自动补)` → `依赖表: <table1>, <table2>`(具体表名) - - **不动** `依赖接口: TBD(A5 自动补)`——那行由 A5 `erp-downstream-gen` 生成 docs/05 后回填 -4. 打印回填统计:`A4 回填 N 处 schema_refs`。 - -### D. 一致性检查 - -1. 用 `Grep` 在 `docs/01-需求清单/*.md` 搜索 `依赖表:`,抽取所有表名。 -2. 用 `Grep` 在 `docs/03-数据库设计文档.md` 搜索表标题(每张表一行 `### table_name`)。 -3. 比对: - - REQ 提到但 docs/03 没有的表 → 报错停下(schema 与需求不一致;请确认是 REQ 理解错误还是需要新增 migration) - - docs/03 有但没 REQ 引用 → 警告但不停下(可能是未使用表) -4. 用 `Grep` 在 `docs/01-需求清单/*.md` 中搜索 `TBD(A4 自动补)`:应 0 命中(A4 已把所有 schema_refs 回填完);若仍有,打印残留 REQ 清单并停下。 - -### E. 勾选 docs/08 进度 + 进入 A5 - -用 `Edit` 在 `docs/08-模块任务管理.md` 勾选 4 个 checkbox(A4 的 3 个子项 + A4 父项): -- ` - [ ] docs/03 数据库设计已生成` → `[x]` -- ` - [ ] REQ 卡片依赖表已回填` → `[x]` -- ` - [ ] schema 一致性检查通过` → `[x]` -- `- [ ] A4 DB 设计 + REQ 回填 — erp-db-design-gen` → `[x]` - -输出 `db-design-gen: 完成(<T> 张表, <R> 个 REQ 已回填依赖表;依赖接口留给 A5)`。 - -立即调用 `Skill(erp-downstream-gen)` 进入 A5,不等用户手动输入。 - -## 不变量 - -- REQ 卡片的 `依赖接口` 字段不在此处填充,留给 A5 的 `erp-downstream-gen` 先生成 docs/05 API 契约后按 `TBD(A5 自动补)` 回填。 - -## 参考 - -- `${CLAUDE_SKILL_DIR}/templates/docs-03-header-template.md` -- `${CLAUDE_SKILL_DIR}/templates/docs-03-table-template.md` -- `.env.local`(DB 凭据) -- `docs/01-需求清单/*.md`(回填目标) diff --git a/skills/plan/erp-db-design-gen/templates/docs-03-header-template.md b/skills/plan/erp-db-design-gen/templates/docs-03-header-template.md deleted file mode 100644 index ff9bd9e..0000000 --- a/skills/plan/erp-db-design-gen/templates/docs-03-header-template.md +++ /dev/null @@ -1,14 +0,0 @@ -# 03-数据库设计文档 - -Schema: `{{schema_name}}` -Migration 清单: `sql/migrations/V*.sql`(由 Flyway 顺序 apply) -生成方式: 通过 `mysql` 命令行从 live schema 反查生成。 - -## ER 关系概览 - -{{er_overview}} - -## 表清单 -{{#each tables}} -- `{{table_name}}` — {{purpose}} -{{/each}} diff --git a/skills/plan/erp-db-design-gen/templates/docs-03-table-template.md b/skills/plan/erp-db-design-gen/templates/docs-03-table-template.md deleted file mode 100644 index dfdc35a..0000000 --- a/skills/plan/erp-db-design-gen/templates/docs-03-table-template.md +++ /dev/null @@ -1,22 +0,0 @@ -## `{{table_name}}` — {{purpose}} - -### 字段 - -| 字段 | 类型 | Nullable | 默认 | 业务含义 | -|---|---|---|---|---| -{{#each columns}} -| {{name}} | {{type}} | {{nullable}} | {{default}} | {{business_meaning}} | -{{/each}} - -### 索引 -{{#each indexes}} -- `{{name}}` ({{type}}): {{columns}} -{{/each}} - -### 外键 -{{#each foreign_keys}} -- `{{name}}`: {{from_col}} → {{to_table}}.{{to_col}} ({{on_delete}}) -{{/each}} - -### 业务注记 -{{notes}} diff --git a/skills/plan/erp-db-init/SKILL.md b/skills/plan/erp-db-init/SKILL.md deleted file mode 100644 index 5a30dbe..0000000 --- a/skills/plan/erp-db-init/SKILL.md +++ /dev/null @@ -1,163 +0,0 @@ ---- -name: erp-db-init -description: A3 验证 MySQL 连接 + 导出当前 schema 为 `sql/migrations/V1__initial_schema.sql`(Flyway 初始 migration,DDL only)+ 导出当前数据为 `sql/seed-data.sql`(INSERT only)。不执行任何 DDL。 -user-invocable: false -allowed-tools: Read Write Edit Glob Skill Bash(mkdir *) Bash(mysql *) Bash(mysqldump *) Bash(set *) Bash(. .env.local) Bash(sed *) Bash(cat *) Bash(rm sql/migrations/*.raw) Bash(rm sql/*.raw) Bash(grep *) ---- - -**所有输出必须使用中文。** - -# erp-db-init - -## 执行步骤 - -### 步骤 0:打印当前位置流程图 - -向用户展示当前在 A 阶段流程中的位置(A-only,`▶` 标在 A3): - -``` -┌──────────────────────────────────────────────────────┐ -│ 📋 阶段 A:规划(一次性) │ -│ │ -│ A0 初始化项目 → A1 锁范围(REQ 卡片) │ -│ ↓ │ -│ ⏸ 等你审阅 REQ,重新运行 /erp-plan-start 继续 │ -│ ↓ │ -│ A2 生成骨架 → ▶ A3 初始化 DB → A4 生成 DB 设计 → A5 生成下游文档│ -│ ↓ │ -│ 规划阶段到此结束 │ -└──────────────────────────────────────────────────────┘ -``` - -### A. 防御性检查 .env.local - -用 `Glob` 检查 `.env.local` 是否存在。 - -- **存在** → 进入步骤 B。 -- **不存在** → 向用户输出: - - ``` - ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - [erp-db-init] ⚠️ .env.local 缺失 - - 可能是被误删。请先重新运行 erp-skeleton-gen 重建, - 或手动从 .env.local.example 复制并填写 DB_HOST / DB_PORT / DB_USER / DB_PASSWORD / DB_SCHEMA。 - ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ``` - -### B. 验证 MySQL 连接 - -用 `Bash` 执行(先加载 `.env.local` 变量,用 `set -a; . ...; set +a` 避免 shell 展开密码中的特殊字符): - -```bash -set -a; . .env.local; set +a -mysql -h"$DB_HOST" -P"$DB_PORT" -u"$DB_USER" -p"$DB_PASSWORD" -e "USE \`$DB_SCHEMA\`; SHOW TABLES;" -``` - -> 注:密码中含 `$`、`` ` ``、空格、`!` 等字符时,`.env.local` 需用单引号包裹值,例如 `DB_PASSWORD='p@ss$w0rd!'`。`set -a; . file; set +a` 与 `source` 行为一致但更明确地声明"按 KEY=VALUE 加载并导出",配合单引号可避免展开。 - -- **成功** → 记录表列表,继续步骤 C。 -- **失败** → 向用户输出具体错误(认证失败 / schema 不存在 / 主机不可达等),提示检查 `.env.local`,**停下**。 - -### C. 导出当前 schema 为 V1 initial migration - -用 `Bash` 执行 mysqldump(**仅 DDL,不含数据**): - -```bash -mkdir -p sql/migrations -set -a; . .env.local; set +a -mysqldump --no-data --skip-comments -h"$DB_HOST" -P"$DB_PORT" -u"$DB_USER" -p"$DB_PASSWORD" "$DB_SCHEMA" > sql/migrations/V1__initial_schema.sql.raw -``` - -如果 `mysqldump` 命令不存在,向用户输出具体错误(提示安装 `mysql-client` / `brew install mysql-client` 等)并**停下**(mysql 和 mysqldump 是 A0 `erp-project-init` 的前置依赖,正常情况下应已就绪)。 - -### D. 加头部写入 V1 最终 migration 文件 - -**严禁**用 `Read` 读取 `.sql.raw`(dump 可能有几千行,会撑爆上下文)。用纯 shell 拼接: - -```bash -PROJECT="<从 CLAUDE.md 读到的项目名称>" -TS="$(date -u +%FT%TZ)" -set -a; . .env.local; set +a -{ - sed -e "s|{{project_name}}|$PROJECT|g" \ - -e "s|{{timestamp}}|$TS|g" \ - -e "s|{{schema_name}}|$DB_SCHEMA|g" \ - "${CLAUDE_SKILL_DIR}/templates/migration-v1-header-template.sql" - cat sql/migrations/V1__initial_schema.sql.raw -} > sql/migrations/V1__initial_schema.sql -rm sql/migrations/V1__initial_schema.sql.raw -``` - -说明: -- `sed` 替换 header 模板里的 3 个槽位 -- `cat` 追加 dump 内容 -- 全程不经过 LLM 上下文 - -### E. 导出当前数据为 seed-data.sql - -用 `Bash` 执行 mysqldump(**仅数据,INSERT only**): - -```bash -set -a; . .env.local; set +a -mysqldump --no-create-info --complete-insert --skip-comments --skip-extended-insert \ - -h"$DB_HOST" -P"$DB_PORT" -u"$DB_USER" -p"$DB_PASSWORD" "$DB_SCHEMA" > sql/seed-data.sql.raw -``` - -拼接 header 模板 + raw: - -```bash -PROJECT="<从 CLAUDE.md 读到的项目名称>" -TS="$(date -u +%FT%TZ)" -set -a; . .env.local; set +a -{ - sed -e "s|{{project_name}}|$PROJECT|g" \ - -e "s|{{timestamp}}|$TS|g" \ - -e "s|{{schema_name}}|$DB_SCHEMA|g" \ - "${CLAUDE_SKILL_DIR}/templates/seed-data-sql-template.sql" - echo "" - echo "SET FOREIGN_KEY_CHECKS = 0;" - echo "" - cat sql/seed-data.sql.raw - echo "" - echo "SET FOREIGN_KEY_CHECKS = 1;" -} > sql/seed-data.sql -rm sql/seed-data.sql.raw -``` - -说明: -- 本地 MySQL 里已有的数据就是测试数据集,直接 dump 下来 -- `--complete-insert` 让 INSERT 含列名,schema 演化后仍可读 -- `--skip-extended-insert` 让每行一条 INSERT,diff 友好 -- 全程不经过 LLM 上下文 - -### F. 验证 + 勾选 docs/08 进度 + 进入 A4 - -1. 用 `Bash` 执行 `grep -c "CREATE TABLE" sql/migrations/V1__initial_schema.sql` 统计表数量,与步骤 B 记录的表数对比。不一致 → 报错停下。 - -2. 用 `Bash` 执行 `grep -c "INSERT INTO" sql/seed-data.sql` 统计数据行数: - - > 0:正常 - - = 0:提示"本地 DB 无数据,seed-data.sql 为空(只有 header 注释);如需测试数据,请在本地 MySQL 插入后重新运行 A3",允许继续 - -3. 用 `Edit` 在 `docs/08-模块任务管理.md` 勾选 5 个 checkbox(A3 的 4 个子项 + A3 父项): - - ` - [ ] .env.local 凭据验证通过` → `[x]` - - ` - [ ] MySQL 连接验证通过` → `[x]` - - ` - [ ] V1 initial migration 已生成(sql/migrations/V1__initial_schema.sql,DDL only)` → `[x]` - - ` - [ ] sql/seed-data.sql 已导出(本地数据快照,INSERT only)` → `[x]` - - `- [ ] A3 DB 初始化 — erp-db-init` → `[x]` - -4. 输出 `db-init: 完成(schema=<名称>, tables=<T>, V1 migration ✓, seed rows=<R>)`。 - -5. 立即调用 `Skill(erp-db-design-gen)` 进入 A4,不等用户手动输入。 - -## 不变量 - -- 密码通过 `.env.local` 以 `set -a; . .env.local; set +a` 方式导出到环境变量,不硬编码在命令里;特殊字符需用单引号包裹。 -- 本 skill **只** 产生 V1 initial migration 和 seed-data.sql 快照;后续 V2/V3 及业务数据变化由 B 阶段 `erp-feature-tdd` 在 REQ 实现时写入。 - -## 参考 - -- `${CLAUDE_SKILL_DIR}/templates/migration-v1-header-template.sql` -- `${CLAUDE_SKILL_DIR}/templates/seed-data-sql-template.sql` -- 产物 1:`sql/migrations/V1__initial_schema.sql`(由 Flyway 在 Spring Boot 启动时自动 apply) -- 产物 2:`sql/seed-data.sql`(由开发者选一种方式装载:@Sql / R__seed / data.sql) diff --git a/skills/plan/erp-db-init/templates/migration-v1-header-template.sql b/skills/plan/erp-db-init/templates/migration-v1-header-template.sql deleted file mode 100644 index a5a1db2..0000000 --- a/skills/plan/erp-db-init/templates/migration-v1-header-template.sql +++ /dev/null @@ -1,8 +0,0 @@ --- Flyway migration V1 — initial schema for {{project_name}} --- Generated: {{timestamp}} --- Source: mysqldump --no-data {{schema_name}} --- This is the FIRST migration; subsequent schema changes must be written --- as new files sql/migrations/V2__<desc>.sql, V3__..., etc. --- Apply: Flyway runs this automatically at Spring Boot startup. --- Do not hand-edit this file after it is committed; write a new migration instead. --- ========================================================= diff --git a/skills/plan/erp-db-init/templates/seed-data-sql-template.sql b/skills/plan/erp-db-init/templates/seed-data-sql-template.sql deleted file mode 100644 index 5081596..0000000 --- a/skills/plan/erp-db-init/templates/seed-data-sql-template.sql +++ /dev/null @@ -1,10 +0,0 @@ --- sql/seed-data.sql — 初始测试数据(INSERT only,无 DDL) --- Project: {{project_name}} --- Generated: {{timestamp}} --- Source: mysqldump --no-create-info --complete-insert {{schema_name}} --- 由 A3 erp-db-init 从本地 MySQL 导出;本地即是测试数据集。 --- 装载方式由开发者选: --- (a) Spring Boot 测试基类 @Sql(scripts = "file:sql/seed-data.sql") --- (b) 改名 R__seed_data.sql 放到 sql/migrations/(Flyway repeatable) --- (c) classpath:data.sql(Spring Boot 启动自动应用) --- ========================================================== diff --git a/skills/plan/erp-downstream-gen/SKILL.md b/skills/plan/erp-downstream-gen/SKILL.md deleted file mode 100644 index 2595e2b..0000000 --- a/skills/plan/erp-downstream-gen/SKILL.md +++ /dev/null @@ -1,228 +0,0 @@ ---- -name: erp-downstream-gen -description: A5 下游文档生成——基于 docs/01 和 docs/03 推导,一次性生成 docs/02 + docs/05 + docs/06 § 五 + docs/10,回填 REQ 卡片依赖接口,把模块清单追加到 docs/08 § 二。 -user-invocable: false -allowed-tools: Read Write Edit Glob Grep Skill AskUserQuestion Bash(cat *) Bash(git remote *) ---- - -**所有输出必须使用中文。** - -# erp-downstream-gen - -## 前置条件 - -- `docs/01-需求清单/*.md` 完整 REQ 卡片已就绪(A1 生成 + 人工审阅过)。 -- `docs/03-数据库设计文档.md` 已就绪(A4 生成)。 -- `docs/05` / `docs/06` / `docs/10` / `sql/seed-data.sql` 等下游文件尚不存在(本 skill 创建)。 - -## 执行步骤 - -### 步骤 0:打印当前位置流程图 - -向用户展示当前在 A 阶段流程中的位置(A-only,`▶` 标在 A5): - -``` -┌──────────────────────────────────────────────────────┐ -│ 📋 阶段 A:规划(一次性) │ -│ │ -│ A0 初始化项目 → A1 锁范围(REQ 卡片) │ -│ ↓ │ -│ ⏸ 等你审阅 REQ,重新运行 /erp-plan-start 继续 │ -│ ↓ │ -│ A2 生成骨架 → A3 初始化 DB → A4 生成 DB 设计 → ▶ A5 生成下游文档│ -│ ↓ │ -│ 规划阶段到此结束 │ -└──────────────────────────────────────────────────────┘ -``` - -### A. docs/02 — 开发计划(含 REQ 级开发顺序清单,CC 分发权威) - -**清单粒度**:一行一个 REQ,同一模块的 REQ 必须**连续排列**。 - -1. 构建**模块依赖 DAG**: - - docs/03 中的外键(表 A → 表 B ⇒ A 的模块依赖 B 的模块) - - docs/01 README 中的显式 `depends_on` 提示 -2. 对模块 DAG 做拓扑排序得 `module_topo_order[]`。 -3. 对**每个模块内部**构建 REQ 间依赖(从 REQ 卡片 `goal` / `rules` / `依赖表` 推断 REQ-A 是 REQ-B 的前置),得到模块内 REQ 顺序。 -4. 合成 `req_order[]`:按 `module_topo_order[]` 依次铺开每个模块内的 REQ 序列(**同模块 REQ 连续**)。 -5. **环依赖打破**: - - **模块级**:若模块 DAG 存在环(module_A ↔ module_B),按启发式(字母序 / 被依赖次数多者先)破环排出 `module_topo_order`,并在**参与环的模块里第一个 REQ** 的 `note` 字段填入原因(如 "A↔B 互依赖:先做 A 的骨架")。 - - **REQ 级(同模块内)**:若模块内 REQ 互依赖,同样破环,`note` 填原因。 - - 非环 REQ `note` 留 `—`。 -6. 为 `req_order[]` 每项生成字段: - - `index`:行号(从 1 开始) - - `req_id`:如 `REQ-SYS-001` - - `module_id`:该 REQ 所属模块,如 `module_sys` - - `rationale`(一行**选中理由**):依赖驱动的简短描述,如 `所属模块无依赖,基础模块` / `依赖 REQ-SYS-001 已在前` / `所属模块依赖 module_sys 已在前` - - `note`(一行**备注**):默认 `—`;仅环依赖打破场景填原因 -7. 用 `Read` 读取 `${CLAUDE_SKILL_DIR}/templates/docs-02-template.md`,填充 `modules[]`(含 `id` / `name` / `deps` / `tables`)/ `req_order[]`(每项含 `index` / `req_id` / `module_id` / `rationale` / `note`)/ `notes`。 -8. 写入 `docs/02-开发计划.md`。 - -### B. docs/05 — API 接口契约 - -1. 用 `Read` 读取 `${CLAUDE_SKILL_DIR}/templates/docs-05-header-template.md`,写入 `docs/05-API接口契约.md` 头部。 -2. 对所有模块的每个 REQ:用 `Read` 读取 `${CLAUDE_SKILL_DIR}/templates/docs-05-endpoint-template.md`,推断 method / path / auth / permission / 请求和响应 schema(不明确的询问用户),追加到 docs/05。 - -### B2. 回填 REQ 卡片 依赖接口 - -1. 用 `Glob` 列出 `docs/01-需求清单/*.md`(排除 `README.md`)。 -2. 用 `Grep` 在这些文件中搜索 `TBD(A5 自动补)` 的行号(不读全文)。 -3. 对每个命中的 REQ: - - 用 `Read` 仅读取该 REQ 卡片所在的片段(REQ 标题行前后 20 行),提取 `req_id`。 - - 在步骤 B 刚生成的 `docs/05-API接口契约.md` 里 Grep 属于该 REQ 的 endpoint(通过 REQ 标签或 req_id 关联)。 - - 用 `Edit`:`依赖接口: TBD(A5 自动补)` → `依赖接口: POST /api/xxx, GET /api/yyy`(具体 method + path 列表,多个用 `,` 分隔)。 -4. 打印回填统计:`A5 回填 N 处 api_refs`。 - -### C. docs/06 — 页面清单 - -1. 对每个有前端页面的模块:用 `Read` 读取 `${CLAUDE_SKILL_DIR}/templates/docs-06-module-pagelist-template.md`,填充 `pages[]`(page_name、route、page_type、req_ids、menu_path、interactions)。 -2. 将每个渲染块追加到 `docs/06-UI交互规范.md` § 五。 - -### D. docs/08 § 二 — 追加模块清单 - -docs/08 已由 A0 erp-project-init 创建(含 Plan 进度骨架)。本步骤只往 § 二 追加模块行,**不重写整个文件**。 - -1. 用 `Read` 读取 `${CLAUDE_SKILL_DIR}/templates/docs-08-module-row-template.md`(单模块 bullet 行模板)。 -2. **按 `module_id` 字母序**对每个模块:渲染一行 bullet,填充 `module_id` / `module_name` / `depends_on` / `path_scopes`(不含 REQ 列表——REQ 级顺序以 docs/02 § 二 为准;模块完成信号由 `MR:` 字段 + GitLab API `state` 判定)。 - - > 注意:docs/08 § 二 的行序**不决定分发顺序**——分发以 docs/02 § 二 为准,此处按字母序仅方便查找。 -3. 所有模块行拼成一段文本,用 `Edit` 在 `docs/08-模块任务管理.md` 的 `## 二、Coding 阶段(按模块循环)` 标题后插入(定位用下一行注释"(A5 填入后..."作为锚,把模块清单插到该注释之前)。 - -### E. docs/10 — 验收清单 - -1. 用 `Read` 读取 `${CLAUDE_SKILL_DIR}/templates/docs-10-header-template.md`,写入 `docs/10-验收检查清单.md` 头部。 -2. 对每个模块:用 `Read` 读取 `${CLAUDE_SKILL_DIR}/templates/docs-10-module-template.md`,填充 `reqs[]`、`data_checks[]`、`ui_checks[]`,追加。 - -### F. 验证 + 勾选 docs/08 进度 + 终止 Plan 阶段 - -1. 一致性检查: - - docs/01 的每个 REQ 都出现在 docs/05(作为接口,如适用)、docs/10(作为验收项)。 - - `docs/02 § 二` 开发顺序清单的 `module_id` 集合 = `docs/08 § 二` 的 `module_id` 集合(数量、ID 全等);不相等 → 报错停下,列出差集。 - -2. **最终占位符扫描**(覆盖 Plan 阶段全部产出:`docs/01-需求清单/*.md` + `docs/02` / `docs/05` / `docs/06` / `docs/10` + `sql/seed-data.sql`): - - a. **`TBD` → CC 自动补齐**:用 `Grep` 搜索 `TBD(A4 自动补)` 和 `TBD(A5 自动补)`。有命中则按 A4 / B2 同样逻辑就地补填(A4 查 docs/03 填 `依赖表:`;A5 查 docs/05 按 REQ-ID 填 `依赖接口:`),再 Grep 确认 0 命中;仍残留报错停下。 - - b. **`【人工填写:...】` → QA 循环等用户补**(与 A2 erp-skeleton-gen 步骤 E 同风格): - - 循环执行直到两个条件**同时满足**:(1) 扫描 0 命中;(2) 用户选「继续」 - - - **b.1 扫描**:用 `Grep` 在上述所有文件中搜索 `【人工填写:`,得到命中数 N 和残留位置清单(`<文件:行号> — <行内容摘要>`) - - **b.2 打印汇总横幅**: - ``` - ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - [erp-downstream-gen] 最终占位符审阅 - - <N=0 时打印:✅ 全部填完> - <N>0 时打印:⚠️ 还有 N 处待填: - <文件:行号> — <行内容摘要> - ...> - - 需要调整 → 直接编辑对应文件 - 填完后 → 回来选「继续」放行完成 Plan - ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ``` - - **b.3 弹出 QA**:用 `AskUserQuestion` 询问: - - **question**: `最终占位符补填完毕?` - - **options** (每项为对象): - - `{"label": "继续", "description": "放行完成 Plan 阶段"}` - - `{"label": "有疑问想先沟通", "description": "需要讨论或修改"}` - - **b.4 路由**: - - 选「有疑问想先沟通」→ 回答用户问题后**回 b.1 重新扫描** - - 选「继续」→ **回 b.1 重新扫描验证**: - - 新 N = 0 → 进入步骤 3 - - 新 N > 0 → 用户以为填完其实还有残留,回 b.2 打印新横幅并再次弹出 QA - - 关键:**每次弹出 QA 前都重新扫描一次**,用户看到的 N 始终是最新的;只有 N = 0 且选「继续」才放行。 - -3. 用 `Edit` 在 `docs/08-模块任务管理.md` 勾选 7 个 checkbox(A5 的 6 个子项 + A5 父项): - - ` - [ ] docs/02 开发计划已生成` → `[x]` - - ` - [ ] docs/05 API 契约已生成` → `[x]` - - ` - [ ] docs/06 § 五 页面清单已填入` → `[x]` - - ` - [ ] docs/10 验收清单已生成` → `[x]` - - ` - [ ] 下方模块列表已填入` → `[x]` - - ` - [ ] REQ 卡片依赖接口已回填` → `[x]` - - `- [ ] A5 下游文档生成 — erp-downstream-gen` → `[x]` - -4. **从 `origin` 远程派生 GitLab 凭据并回填 `.env.local`** - - 仅当对应字段仍是 `TBD(A5 自动补)` 或空时回填;用户已手填为别的值一律不动。 - - a. 取远程 URL:`Bash`: `git remote get-url origin 2>/dev/null` → `REMOTE_URL`。为空 → 跳过本步骤,仅打印提示"未配置 origin 远程,`GITLAB_*` 留给用户手填"。 - b. 解析: - - `PROJECT_PATH` = 去掉 `<scheme>://<host>/` 或 `git@<host>:` 或 `ssh://<host>/` 前缀 + 去掉末尾 `.git`(如 `zhuzc/test`) - - `PROJECT_ID_ENC` = `PROJECT_PATH` 的 `/` 替换为 `%2F`(如 `zhuzc%2Ftest`) - - `HOST` = 远程主机名(如 `git.xlyprint.cn`) - - `SCHEME` 三分支(**绝不把 SSH remote 降级成 http**——Private Token 不能走明文): - - `REMOTE_URL` 以 `https://` 开头 → `https` - - `REMOTE_URL` 以 `http://` 开头 → `http`(明确声明,非推断) - - 其他(`git@` / `ssh://` / 异常)→ `https`(默认走安全侧) - - `API_URL_GUESS` = `<SCHEME>://<HOST>/api/v3` - c. 用 `Read` 读 `.env.local`: - - 若 `GITLAB_PROJECT_ID` 当前值为 `TBD(A5 自动补)` 或空 → 用 `Edit` 改为 `GITLAB_PROJECT_ID=<PROJECT_ID_ENC>` - - 若 `GITLAB_API_URL` 当前值为 `TBD(A5 自动补)` 或空 → `Edit` 改为 `GITLAB_API_URL=<API_URL_GUESS>` - - 上两字段若已被用户手改过(非 `TBD(A5 自动补)` 也非空)→ 不覆盖,仅核对打印 - - `GITLAB_TOKEN` 派生不了,占位保持 `【人工填写:...】`,用户去 GitLab Profile → Account → Private token 手填 - d. 打印回填摘要: - ``` - [downstream-gen] GitLab 凭据自动派生(从 origin 远程): - GITLAB_PROJECT_ID = <回填值 或「保留占位: 已手填 xxx」> - GITLAB_API_URL = <回填值 或「保留占位: 已手填 xxx」> - GITLAB_TOKEN = 保持占位 — 请去 GitLab Profile → Account → Private token 手填 - ``` - 若 `SCHEME` 是 `http`,额外提示:"⚠️ 本次派生用 `http://`——Private Token 将走明文;仅当你的 GitLab 部署真的没上 HTTPS 时可以保留,否则请手动改为 `https://`。" - 若 `SCHEME` 是推断来的 `https`(来自 ssh/git@ remote),额外提示:"API URL 的 scheme 是从 SSH remote 默认推成 `https`;如实际 API 走 http,请手动改 `GITLAB_API_URL`。" - -5. 输出:`downstream-gen: 写入 4 个文件 + <N> 个模块 + <M> 处 REQ 依赖接口回填。` - -6. 打印 Plan 阶段终止横幅并**停下**(不自动进入 B 阶段): - - ``` - ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - [erp-downstream-gen] ✅ Plan 阶段(A0~A5)全部完成 - - 所有规划文档已就绪,docs/08 § 一 全部勾选。 - - ⚠️ 进入 B 阶段前必须完成: - 1. 人工通读 docs/01~10 + CLAUDE.md + sql/migrations/V1 + 各 scripts/* - - 2. 把全部 Plan 产物 commit: - git add -A && git commit -m "chore: plan phase A0~A5 done" - - 3. 推到远程,按仓库状态二选一: - - 情况 A — 远程仓库是全新的(尚无 main / master): - git remote add origin <gitlab-url> # 若尚未添加 - git -c core.hooksPath=/dev/null push -u origin master - # 首次 push 本地 DB 尚未就位、scripts/test.sh 必然失败。 - # `-c core.hooksPath=/dev/null` 只对本次 push 临时指向空的 hooksPath, - # 跳过 .githooks/pre-push,不动 repo 的 core.hooksPath 配置, - # 也不用 --no-verify(后者被 CC 的 deny-no-verify hook 硬拦)。 - # push 完成后到 GitLab UI 把 master(或 main)设为 protected - - 情况 B — 远程已有 main 需要走 MR 审核: - git checkout -b plan-init - git push -u origin plan-init - # 在 GitLab 打开 plan-init → main 的 MR,审核并合并 - - 4. 补齐 `.env.local`: - - `GITLAB_TOKEN`(必填):去 GitLab Profile → Account → Private token 生成后粘贴 - - `GITLAB_API_URL` / `GITLAB_PROJECT_ID`:步骤 4 已从 origin 远程自动回填(若仍显示 - `TBD(A5 自动补)`,说明 origin 没配,手动填;若 scheme 错请改 http↔https) - B 阶段 erp-mr-create 用 token 通过 curl 创建 MR。 - - 5. main(或 master)就绪后,再运行 /erp-workflow:erp-coding-start - 进入 B 阶段。届时 .env.local 应指向本地 MySQL(非共享远程 DB), - 否则 B 阶段每次测试闸门都会因 setup-test-db.sh 的防护失败。 - ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ``` - -## 参考 - -- `${CLAUDE_SKILL_DIR}/templates/docs-02-template.md` -- `${CLAUDE_SKILL_DIR}/templates/docs-05-header-template.md` -- `${CLAUDE_SKILL_DIR}/templates/docs-05-endpoint-template.md` -- `${CLAUDE_SKILL_DIR}/templates/docs-06-module-pagelist-template.md` -- `${CLAUDE_SKILL_DIR}/templates/docs-08-module-row-template.md`(模块 bullet 行模板) -- `${CLAUDE_SKILL_DIR}/templates/docs-10-header-template.md` -- `${CLAUDE_SKILL_DIR}/templates/docs-10-module-template.md` diff --git a/skills/plan/erp-downstream-gen/templates/docs-02-template.md b/skills/plan/erp-downstream-gen/templates/docs-02-template.md deleted file mode 100644 index dedfa98..0000000 --- a/skills/plan/erp-downstream-gen/templates/docs-02-template.md +++ /dev/null @@ -1,24 +0,0 @@ -# 02-开发计划 - -## 一、模块依赖表 - -| 模块 ID | 模块名 | 依赖模块 | 依赖表 | -|---|---|---|---| -{{#each modules}} -| {{id}} | {{name}} | {{deps}} | {{tables}} | -{{/each}} - -## 二、开发顺序清单(CC 分发权威) - -> 本清单由 A5 `erp-downstream-gen` 一次性生成。**每行是一个 REQ**,不是模块。CC 按表格行序从上到下扫描,对每个 REQ 所属模块查 `docs/08 § 二` 的 `MR:` 字段 + GitLab API `state`:`merged` 跳过,其他(`—` / opened / closed / 查不到)选为当前模块;`erp-module-start` 会把该模块的所有 REQ 一次做完。 -> -> **约束**:同一模块的所有 REQ 必须**连续排列**。允许打破依赖拓扑(如环依赖、业务必须先做),但必须在「备注」列写明原因。 - -| # | REQ | 所属模块 | 选中理由 | 备注 | -|---|-----|---------|---------|------| -{{#each req_order}} -| {{index}} | **{{req_id}}** | {{module_id}} | {{rationale}} | {{note}} | -{{/each}} - -## 三、关键说明 -{{notes}} diff --git a/skills/plan/erp-downstream-gen/templates/docs-05-endpoint-template.md b/skills/plan/erp-downstream-gen/templates/docs-05-endpoint-template.md deleted file mode 100644 index 1583d4e..0000000 --- a/skills/plan/erp-downstream-gen/templates/docs-05-endpoint-template.md +++ /dev/null @@ -1,24 +0,0 @@ -### {{req_id}} {{title}} - -- **Method**: {{method}} -- **Path**: `{{path}}` -- **Auth**: {{auth}} -- **Permission**: {{permission}} - -#### 请求参数 -{{request_params}} - -#### 请求体 -```json -{{request_body_schema}} -``` - -#### 响应体 -```json -{{response_body_schema}} -``` - -#### 错误码 -{{#each errors}} -- `{{code}}` — {{message}} -{{/each}} diff --git a/skills/plan/erp-downstream-gen/templates/docs-05-header-template.md b/skills/plan/erp-downstream-gen/templates/docs-05-header-template.md deleted file mode 100644 index 6bcd293..0000000 --- a/skills/plan/erp-downstream-gen/templates/docs-05-header-template.md +++ /dev/null @@ -1,30 +0,0 @@ -# 05-API接口契约 - -BasePath: `{{base_path}}` -端口: `【人工填写:后端端口,默认 8080】` - -## 全局约定 - -### 响应格式 -```json -{"code": 200, "message": "操作成功", "data": {}, "timestamp": 1700000000000} -``` - -### 错误码 -| 范围 | 含义 | -|---|---| -| 200 | 成功 | -| 400xx | 客户端参数错误 | -| 401xx | 认证/授权错误 | -| 403xx | 权限不足 | -| 404xx | 资源不存在 | -| 500xx | 服务端内部错误 | - -### 鉴权 -{{auth_note}} - -### 分页参数 -{{pagination_note}} - -## 接口清单 -(各模块接口段落见下方,由 `erp-downstream-gen` 按 REQ 填入) diff --git a/skills/plan/erp-downstream-gen/templates/docs-06-module-pagelist-template.md b/skills/plan/erp-downstream-gen/templates/docs-06-module-pagelist-template.md deleted file mode 100644 index 36f18a5..0000000 --- a/skills/plan/erp-downstream-gen/templates/docs-06-module-pagelist-template.md +++ /dev/null @@ -1,9 +0,0 @@ -### {{module_id}} {{module_name}} - -{{#each pages}} -- **{{page_name}}** (`{{route}}`) - - 类型: {{page_type}} (列表页 / 表单页 / 详情页 / 树形管理页) - - 对应 REQ: {{req_ids}} - - 入口菜单: {{menu_path}} - - 主要交互: {{interactions}} -{{/each}} diff --git a/skills/plan/erp-downstream-gen/templates/docs-08-module-row-template.md b/skills/plan/erp-downstream-gen/templates/docs-08-module-row-template.md deleted file mode 100644 index 76cf552..0000000 --- a/skills/plan/erp-downstream-gen/templates/docs-08-module-row-template.md +++ /dev/null @@ -1,4 +0,0 @@ -- {{module_id}} {{module_name}} - - 依赖: {{depends_on}} - - 路径: {{path_scopes}} - - MR: — diff --git a/skills/plan/erp-downstream-gen/templates/docs-10-header-template.md b/skills/plan/erp-downstream-gen/templates/docs-10-header-template.md deleted file mode 100644 index 0587a54..0000000 --- a/skills/plan/erp-downstream-gen/templates/docs-10-header-template.md +++ /dev/null @@ -1,14 +0,0 @@ -# 10-验收检查清单 - -通用验收项(全项目适用): - -- [ ] `scripts/test.sh` 本地全绿 -- [ ] 所有 schema 改动都有对应 `sql/migrations/V_n__<desc>.sql` -- [ ] 所有新接口在 `docs/05` 中有契约定义 -- [ ] 所有新功能代码注释含 REQ-XXX-NNN -- [ ] 统一响应格式 `{code, message, data, timestamp}` -- [ ] 异常走全局处理器,不暴露堆栈到前端 -- [ ] 前端不存敏感信息到 localStorage - -## 模块专项 -(各模块验收段落见下方,由 `erp-downstream-gen` 按模块填入) diff --git a/skills/plan/erp-downstream-gen/templates/docs-10-module-template.md b/skills/plan/erp-downstream-gen/templates/docs-10-module-template.md deleted file mode 100644 index 9342e2e..0000000 --- a/skills/plan/erp-downstream-gen/templates/docs-10-module-template.md +++ /dev/null @@ -1,18 +0,0 @@ -### {{module_id}} {{module_name}} - -#### 功能级验收(每个 REQ 对应可执行用例) -{{#each reqs}} -- [ ] {{req_id}} {{title}} - - 自动化用例: `{{test_file}}::{{test_name}}` - - 手动验收: {{manual_check}} -{{/each}} - -#### 数据级验收 -{{#each data_checks}} -- [ ] {{check}} -{{/each}} - -#### UI 级验收(若含前端) -{{#each ui_checks}} -- [ ] {{check}} -{{/each}} diff --git a/skills/plan/erp-project-init/SKILL.md b/skills/plan/erp-project-init/SKILL.md deleted file mode 100644 index fdd1226..0000000 --- a/skills/plan/erp-project-init/SKILL.md +++ /dev/null @@ -1,94 +0,0 @@ ---- -name: erp-project-init -description: A0 项目初始化——从插件模板幂等地复制 CLAUDE.md / docs/01-需求清单/README.md / docs/08-模块任务管理.md(已存在则跳过),并初始化 Git(如未初始化)。session-start 在 docs/08 缺失时派发本 skill。 -user-invocable: false -allowed-tools: Glob Edit Skill Bash(mkdir *) Bash(cp -n *) Bash(git init) Bash(command -v *) Bash(uname *) Bash(brew *) Bash(export PATH=*) Bash(echo *) ---- - -**所有输出必须使用中文。** - -你负责在空/半空项目目录中创建初始文件结构。**本 skill 幂等**——已存在的文件不覆盖。 - -## 执行步骤 - -### 步骤 0:打印当前位置流程图 - -向用户展示当前在 A 阶段流程中的位置(A-only,`▶` 标在 A0): - -``` -┌──────────────────────────────────────────────────────┐ -│ 📋 阶段 A:规划(一次性) │ -│ │ -│ ▶ A0 初始化项目 → A1 锁范围(REQ 卡片) │ -│ ↓ │ -│ ⏸ 等你审阅 REQ,重新运行 /erp-plan-start 继续 │ -│ ↓ │ -│ A2 生成骨架 → A3 初始化 DB → A4 生成 DB 设计 → A5 生成下游文档│ -│ ↓ │ -│ 规划阶段到此结束 │ -└──────────────────────────────────────────────────────┘ -``` - -### A. 依赖检查 + 自动安装(命令行工具) - -用 `Bash` 检查 `mysql` / `mysqldump` 是否在 PATH 中: - -```bash -for cmd in mysql mysqldump; do - command -v "$cmd" >/dev/null 2>&1 || echo "MISSING: $cmd" -done -``` - -**全部在 PATH** → 进入 B。 - -**有缺失** → 尝试自动安装: -1. 用 `Bash` 探测环境(`uname -s`、是否有 `brew` / `apt` / `yum` / `apk` 等) -2. 根据当前系统选最合适的包管理器安装 mysql 客户端;若需要 sudo 但 CC 没有权限,打印手动安装命令让用户执行 -3. 装完后,把必要的 bin 路径加入本次会话 PATH(如 macOS 的 keg-only 路径) -4. 向用户提示如何把路径永久写入 shell 启动脚本 -5. 重新执行开头的 `command -v` 循环验证;仍缺失 → 打印错误并停下,等用户手动解决后重新运行入口 - -### B. 幂等复制模板文件 - -用 `Bash` 一次性完成。`cp -n` 表示"不覆盖已存在的文件": - -```bash -mkdir -p docs/01-需求清单 -cp -n "${CLAUDE_SKILL_DIR}/templates/CLAUDE-template.md" CLAUDE.md -cp -n "${CLAUDE_SKILL_DIR}/templates/docs-01-readme-template.md" docs/01-需求清单/README.md -cp -n "${CLAUDE_SKILL_DIR}/templates/docs-08-initial-template.md" docs/08-模块任务管理.md -``` - -故障恢复场景:如果用户上一次初始化中途中断(CLAUDE.md 已存在但 docs/08 缺失),`cp -n` 会保留 CLAUDE.md 原样,只补齐 docs/08。 - -### C. 初始化 Git(如尚未初始化) - -用 `Glob` 检查 `.git/` 目录是否存在。 -- 不存在 → 用 `Bash` 执行 `git init`。 -- 已存在 → 跳过。 - -### D. 勾选 docs/08 的 A0 进度 - -用 `Edit` 在 `docs/08-模块任务管理.md` 中勾选这两行: -- ` - [ ] 项目文件骨架已创建(CLAUDE.md + docs/01-需求清单/README.md)` → ` - [x] 项目文件骨架已创建(CLAUDE.md + docs/01-需求清单/README.md)` -- `- [ ] A0 项目初始化 — erp-project-init` → `- [x] A0 项目初始化 — erp-project-init` - -### E. 打印完成横幅并进入 A1 - -向用户输出: - -``` -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - [erp-project-init] 项目初始化完成 - - 已创建: - ✓ CLAUDE.md(从插件模板复制) - ✓ docs/01-需求清单/README.md(待人工填写模块索引) - ✓ docs/08-模块任务管理.md(全流程进度跟踪) - 已勾选:A0 项目初始化 - - 下一步:A1 erp-scope-lock(填写项目概述 + 技术栈 + 需求索引 + REQ 卡片) -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -``` - -立即调用 `Skill(erp-scope-lock)` 进入 A1,不等用户手动输入。 diff --git a/skills/plan/erp-project-init/templates/CLAUDE-template.md b/skills/plan/erp-project-init/templates/CLAUDE-template.md deleted file mode 100644 index 485925b..0000000 --- a/skills/plan/erp-project-init/templates/CLAUDE-template.md +++ /dev/null @@ -1,347 +0,0 @@ -# CLAUDE.md — ERP项目 Claude Code 主指令文件 - -> 本文件是 Claude Code 的"操作手册"。Claude Code 启动时会自动读取此文件。 - ---- - -## 🎯 项目概述 - -- **项目名称**: 【人工填写:公司 + 项目名,例如"XX 公司 ERP 管理系统"】 -- **项目简述**: 【人工填写:一句话描述项目目标,例如"面向中小制造企业的全流程 ERP,涵盖采购/库存/生产/销售/财务"】 -- **目标用户**: 【人工填写:谁会用,例如"企业内部管理人员(采购员、仓管员、生产主管、销售员、财务人员、管理层)"】 -- **部署方式**: 【人工填写:私有化部署 / 云部署 / Docker 容器化 等】 - ---- - -## ✅ 模块完成判定规则 - -`docs/08-模块任务管理.md § 二` 是**模块元数据表**——每个模块一行 bullet,记录依赖 / 路径 / MR iid。**模块完成由 `MR:` 字段 + `GitLab API state=merged` 判定**。 - -### 规则定义 - -每个模块在 docs/08 § 二 中长这样: - -```markdown -- module_0 系统管理 - - 依赖: — - - 路径: backend/module/sys/, frontend/pages/sys/ - - MR: — -``` - -`MR:` 字段由 `erp-mr-create` 在创建 MR 时从 `—` 改为 `!<iid>`。 - -### 模块状态语义 - -| `MR:` 字段 | `GitLab API state` | 含义 | 你(Claude Code)的行为 | -|---|---|---|---| -| `—` | — | 模块未开始(未创建 MR) | ✅ 开始本模块开发 | -| `!<iid>` | `opened` / `closed` | 模块开发中 / 打回 | ✅ 继续推进该模块 | -| `!<iid>` | `merged` | 模块**已完成** | 🟢 进入下一未完成模块 | - -### 工作流规则 - -- **开发顺序权威在 `docs/02-开发计划.md § 二 开发顺序清单`**,不是 `docs/08 § 二` 的物理行序 -- **下一个要做的模块** = `docs/02 § 二` 清单中**第一个所属模块 MR 状态非 merged 的 REQ** 的 `module_id`(由 `erp-coding-start` 步骤 3 扫描 `docs/08` 的 `MR:` 字段 + GitLab API state 判定) -- `docs/02 § 二` 清单由 A5 `erp-downstream-gen` 生成阶段一次性确定(会交互询问业务偏好),之后通常不改;若开发中途需要调整顺序,重新触发 A5 生成阶段而非直接编辑文件 -- **已完成模块**(`MR: !<iid>` + `GitLab API state=merged`):**默认不改**(不是禁止,是已交付无需改) -- 如果在当前模块开发中发现某个**已完成模块**(MR merged)有 bug: - - **不停下当前工作**,按软规则 S2 直接修复该模块代码;hook `log-cross-module.sh` 会自动留痕,调用 `erp-cross-module-log` 补「原因 / 影响评估」 - - 修复随当前模块 MR 一起合并——不需要改 `docs/08`(模块已是 merged 状态,本插件不会标记重开;修复是以"当前模块依赖他的代码"的方式进入) - - 在当前模块的《模块完成报告》第 ⑦ 节「跨模块改动」明确记录:哪个模块、哪个文件、什么问题、修复范围、影响评估 - -### 模块完成流程 - -``` -1. 对每个 REQ 跑完整功能循环: - brainstorm → plan → TDD(红绿循环,每步 commit)→ verify(子会话执行 REQ 级测试)→ 自审 -2. 所有 REQ 完成后,erp-local-test-gate 派子会话按顺序跑: - a. schema 一致性检查(erp-local-test-gate 步骤 1 内联,schema 未漂移)+ 占位符扫描 - b. scripts/test.sh 全套:build → lint → **unit + integration(全量重新运行当前模块所有 - REQ 的功能测试 + 所有已完成模块的回归测试)** → e2e - 任一失败停下修复再来 -3. 测试全绿 → erp-module-report 输出《模块完成报告》 -4. 自动 git push(.githooks/pre-push 会再执行一遍 scripts/test.sh 作为硬闸门) - + 通过 GitLab API (curl) 创建 MR,报告嵌入 MR 描述 -5. 人工 review MR → Approve + Merge(人工动作,唯一人工介入点) -6. 下次用户运行 `/erp-workflow:erp-coding-start` 时,入口自动检测到本模块 `GitLab API state=merged`,探测默认分支(main / master)后 `git checkout <默认分支> && git pull --ff-only` 同步远程 → 扫描下一模块并派发 -7. 你**不需要**手工 Edit docs/08(模块元数据不变;下次 coding-start 自动扫描 MR state 判定是否完成) -``` - -> 两道测试闸门:功能级(`erp-feature-tdd` + `erp-feature-verify`,每 REQ 一遍)+ 模块级(`erp-local-test-gate` + pre-push hook,每模块一遍)。所有测试/验证都派发到子会话执行,主会话只接收结构化结论。 - -### 模块完成报告 - -由 `erp-module-report` skill 产出,模板位于 由 erp-module-report skill 持有(12 节标准化,含跨模块改动等 CLAUDE.md 软规则映射节)。CC 不手写模块报告,仅填模板。 - ---- - -## 🏷️ 占位符统一约定(`【人工填写:...】`) - -所有"只有人工能决定"的位置(密钥 / 账密 / 包名 / 命名约定 / 小版本号 等)一律使用以下纯文本标记: - -``` -【人工填写:<简短说明>】 -``` - -### CC 行为规则 - -- **生成文档 / 模板时**:凡是项目专属值、敏感值、技术栈小版本号一律用此标记,不要自行编造 -- **不要用 HTML 注释**(`<!-- ... -->`),因为后者在 Obsidian 渲染视图被隐藏,开发者会漏填 -- **必须带简短说明**:例如 `【人工填写:JWT 签名密钥,256+ bit 随机串】`,而不是空 `【人工填写】` -- **项目专属标识**(Java 根包名 / C# 命名空间 / Python 顶层模块等)只在 `docs/07-环境配置.md` 引入一次占位,其他文件**复用**已有的占位,不重复创建 - ---- - -## 🔄 开发流程(模块循环 + 功能循环) - -两层嵌套循环的详细步骤**全部固化到 skills**,CLAUDE.md 不展开。入口调 `/erp-workflow:erp-coding-start`,自动分发: - -- **模块循环(外层,Layer 2)** → `erp-module-start` → `erp-local-test-gate`(commit test-gate.md)→ `erp-module-report`(commit 模块报告 + cross-module log)→ `erp-mr-create`(worktree clean 校验 → push → 创建 MR → 追加 MR URL 到报告并 commit → 写 `MR: !<iid>` 到 docs/08 并 commit → 再次 push)→ 人工 Approve+Merge → 下次运行 `/erp-workflow:erp-coding-start` 扫描到本模块 GitLab API `state=merged` → 探测默认分支并 `git pull --ff-only` → 推进下一模块 -- **功能循环(内层,Layer 3,每个 REQ-XXX-NNN 走一遍)** → `erp-feature-brainstorm` → `erp-feature-plan` → `erp-feature-tdd` → `erp-feature-verify` → `erp-feature-review` - -**本地测试闸门**: `erp-local-test-gate` 是 MR 前的唯一硬闸门,子会话执行 `scripts/test.sh`:脚本先由 `setup-test-db.sh` 清空库 → build / lint → 执行测试(Spring Boot 启动时 Flyway 自动 apply `sql/migrations/V*.sql`)→ e2e → 再次清库。详见 § 🧪 自测要求。`.githooks/pre-push` 在 push 时会再次执行 `scripts/test.sh` 作为兜底;`git push --no-verify` 被 hook `deny-no-verify.sh` 硬拦截。本项目不配置 GitLab CI/CD。 - -> 占位符扫描 / schema 一致性校验都不在此闸门:前者在 A 阶段 skill 生成期完成;schema 演化通过 Flyway migration 保证一致(每次测试启动,Spring Boot 的 Flyway 从空库按序 apply V1~Vn,不存在"漂移"概念)。hook 产生的 `TBD(CC 补)` 存根由 CC 自主调 `erp-cross-module-log` 补齐,并在 `erp-module-report` § ⑦ 硬验收(非人工填写)。 - ---- - -## 📐 编码行为约束 - -### 你必须做的 ✅ - -1. **严格遵循** `docs/04-技术规范.md` 中的命名和编码规范 -2. **严格遵循** `docs/09-项目目录结构.md` 中的目录规范,文件放对位置 -3. **每个后端接口** 必须先在 `docs/05-API接口契约.md` 中定义,再编码实现 -4. **每个功能** 必须可追溯到 `docs/01-需求清单.md` 中的需求编号 -5. **代码注释** 必须包含对应的需求编号,如 `// REQ-001: 用户登录` -6. **数据库 schema 走 migration**:所有业务 schema 改动(CREATE/ALTER/DROP TABLE/INDEX/VIEW)必须写成 `sql/migrations/V_n__<snake_case_desc>.sql` 文件,由 Flyway 顺序 apply;**禁止**在主会话直接 `mysql -e` 跑业务 DDL(只读查询 / 临时本地调试探索除外)。详见 § Schema 演化规约 -7. **提交代码前** 确保无编译错误、无明显运行时错误 -8. **每个Controller方法** 必须有统一的响应格式包装 -9. **异常处理** 使用全局异常处理器,不在业务代码中catch后吞掉异常 -10. **分页查询** 统一使用 MyBatis-Plus 的 Page 对象 - -### 你禁止做的 🚫 - -1. **默认禁止** 修改"非当前模块"(其他 REQ 所属模块)的代码;确为实现当前模块所必需时,按软规则 S2 执行(留痕 + 模块报告单列说明) -2. **禁止** 引入`docs/04-技术规范.md` 技术栈表以外的框架或中间件(如需要必须先报告) -3. **禁止** 硬编码配置(数据库连接、端口号等必须放在配置文件中) -4. **禁止** 在前端直接写SQL或直接操作数据库 -5. **禁止** 跳过模块开发(必须按顺序) -6. **禁止** 删除或覆盖他人代码(如有冲突必须报告) -7. **禁止** 使用 `SELECT *`,必须显式列出需要的字段 -8. **禁止** 在循环中执行数据库查询(N+1问题) -9. **禁止** 前端存储敏感信息到 localStorage -10. **禁止** 返回后端异常堆栈给前端 - -### Schema 演化规约(Flyway migration) - -1. **文件命名**:`sql/migrations/V<n>__<snake_case_desc>.sql`,例:`V5__add_user_email_unique_index.sql` -2. **版本号分配**:建文件前 `ls sql/migrations/V*.sql` 查当前最大 n,新文件 `n_max + 1` -3. **Apply 方式**:Spring Boot 启动 / 测试启动时 Flyway 自动 apply(项目必须在 `pom.xml` 声明 `flyway-core` + `flyway-mysql` 依赖)。`scripts/setup-test-db.sh` 只负责清空库,不做 apply -4. **已合并的 migration 永不修改**:发现错了写一个补救 migration(如 `V7__fix_V5_index_name.sql`),绝不编辑 git 历史里的旧 `V_n.sql` -5. **临时调试 DDL ≠ 业务 DDL**:临时在本地试字段/索引可手动 `mysql -e`,但不写 migration;下次 `setup-test-db.sh` 会 drop+create 清掉 -6. **A3 生成的 V1**:`V1__initial_schema.sql` 是 A 阶段由 `erp-db-init` 从人工初始化的 schema 导出的初始版本;后续 V2/V3/... 由 B 阶段每个 REQ 按需写入 - ---- - -## 🔄 统一响应格式 - -所有后端接口必须返回以下格式: - -```json -{ - "code": 200, - "message": "操作成功", - "data": {}, - "timestamp": 1700000000000 -} -``` - -错误响应: - -```json -{ - "code": 40001, - "message": "用户名或密码错误", - "data": null, - "timestamp": 1700000000000 -} -``` - -错误码规范: - -| 错误码范围 | 含义 | -|-----------|------| -| 200 | 成功 | -| 400xx | 客户端参数错误 | -| 401xx | 认证/授权错误 | -| 403xx | 权限不足 | -| 404xx | 资源不存在 | -| 500xx | 服务端内部错误 | - ---- - -## 🗂️ Git 提交规范 - -每次提交必须遵循以下格式: - -``` -<type>(<scope>): <subject> - -type: feat|fix|refactor|docs|style|test|chore -scope: 模块名,如 user, inventory, order -subject: 简短描述,中文可 - -示例: -feat(user): 实现用户登录接口 REQ-001 -fix(order): 修复订单金额计算精度问题 -refactor(common): 统一响应格式包装 -``` - ---- - -## 🧪 自测要求 - -- 所有测试与验证(`scripts/test.sh` / `mvn test` / `pnpm test` / DB 测试集 diff 等)**一律派发到全新子会话 via `Agent` 执行**,主会话只接收结构化结论(命令 / 退出码 / 通过数 / 失败项 / 关键 stdout ≤30 行)。不在主会话直接执行测试。 -- 由 `erp-feature-verify`(功能级)+ `erp-local-test-gate`(模块级)两道 skill 统一承接。前者每个 REQ 执行一次,后者模块闸门执行一次。 -- 声称"完成"前必须贴出子会话返回的 evidence(模板:由 erp-feature-verify skill 持有)。 - ---- - -## 🚩 静默执行红旗清单(中断机制) - -功能循环(每个功能 REQ-XXX 的 Brainstorm → Plan → TDD → Verify → AI 自审)默认 **静默跑不打扰人**,但命中以下任何一条必须**立刻停下、记录原因、等人决策**,不得自行绕过: - -| # | 红旗 | 例子 | -| - | --- | --- | -| 1 | **测试反复失败** | 同一测试同一功能内连续 **10 次**修复失败 | -| 2 | **要改密钥 / 账密 / 包名** | `docs/07-环境配置.md` 里由人工标注必须填的字段 | -| 3 | **外部接口不可达** | 第三方 API 无法连接、证书失效等环境问题 | - -> 其余需要人类判断的场景(需求歧义 / schema 缺口 / 技术栈外组件引入)一律走普通 `AskUserQuestion` Q&A,不升格为红旗、不写 Blocker 文件。见下方「📘 技术栈外组件的处理规则」与各 feature-* skill 的 Q&A 流程。 - -**命中红旗时的固定动作:** - -1. 在当前功能的 plan 文件里追加一节 `## 🚩 Blocker`,描述红旗编号、现象、初步判断 -2. 停止后续所有功能的静默执行 -3. 在主会话输出一句话摘要 + 指向 blocker 文件的路径,等人回复 - -**报告格式:** - -```markdown -## ⚠️ 需要人工决策 - -**红旗编号**: [1–3 中的某一条] -**问题描述**: [详细描述] -**影响范围**: [影响哪些模块 / 功能] -**我的建议**: [初步判断,可选] -**等待决策**: [需要人工做什么决定] -``` - ---- - -## 📘 技术栈外组件的处理规则 - -brainstorm / plan 阶段若发现需要 `docs/04-技术规范.md § 零` 技术栈表之外的框架、中间件或关键库: - -1. 用 `AskUserQuestion` 询问用户(选项至少含:接受引入 / 换方案 / 拒绝) -2. **接受** → 同会话直接在 `docs/04 § 零` 追加一行 → 继续流程 -3. **换方案 / 拒绝** → 视为常规歧义澄清,继续 Q&A 收敛 - -不写 Blocker 文件,不中断流程。 - ---- - -## 🟡 软规则(允许继续,但有强制后续动作) - -以下情况 **不触发中断**,CC 可自行继续推进,但必须在约定位置留痕,模块完成时统一审计。漏留痕 = 红旗。 - -| # | 软规则 | 允许动作 | 强制后续 | -| - | ----- | ------- | ------- | -| S2 | **跨模块改动**(动到非当前模块的代码——无论该模块是否已 MR merged) | 允许修改,但范围受限:仅为当前模块实现所必需 | ① 当次修改立即追加到 `docs/superpowers/module-reports/<current>-cross-module.md`(含文件路径、改动原因、对目标模块功能/API 的影响评估)② 《模块完成报告》必须单列「跨模块改动」节完整贴入 ③ 漏留痕或未评估影响 → 升级为红旗 | - ---- - -## 🧭 通用工作准则(General Principles) - -### 1. Think Before Coding - -**Don't assume. Don't hide confusion. Surface tradeoffs.** - -Before implementing: -- State your assumptions explicitly. If uncertain, ask. -- If multiple interpretations exist, present them - don't pick silently. -- If a simpler approach exists, say so. Push back when warranted. -- If something is unclear, stop. Name what's confusing. Ask. - -### 2. Simplicity First - -**Minimum code that solves the problem. Nothing speculative.** - -- No features beyond what was asked. -- No abstractions for single-use code. -- No "flexibility" or "configurability" that wasn't requested. -- No error handling for impossible scenarios. -- If you write 200 lines and it could be 50, rewrite it. - -Ask yourself: "Would a senior engineer say this is overcomplicated?" If yes, simplify. - -### 3. Surgical Changes - -**Touch only what you must. Clean up only your own mess.** - -When editing existing code: -- Don't "improve" adjacent code, comments, or formatting. -- Don't refactor things that aren't broken. -- Match existing style, even if you'd do it differently. -- If you notice unrelated dead code, mention it - don't delete it. - -When your changes create orphans: -- Remove imports/variables/functions that YOUR changes made unused. -- Don't remove pre-existing dead code unless asked. - -The test: Every changed line should trace directly to the user's request. - -### 4. Goal-Driven Execution - -**Define success criteria. Loop until verified.** - -Transform tasks into verifiable goals: -- "Add validation" → "Write tests for invalid inputs, then make them pass" -- "Fix the bug" → "Write a test that reproduces it, then make it pass" -- "Refactor X" → "Ensure tests pass before and after" - -For multi-step tasks, state a brief plan: -``` -1. [Step] → verify: [check] -2. [Step] → verify: [check] -3. [Step] → verify: [check] -``` - -Strong success criteria let you loop independently. Weak criteria ("make it work") require constant clarification. - ---- - -## ⚡ Skill & 模板入口索引 - -CC 会话启动请直接调 **`/erp-plan-start`** —— 顶层编排器会自动探测当前阶段(计划 / 模块循环 / 功能循环 / blocker)并分发到下一个 skill。 - -### Skills(20 个,详细动作见各 `SKILL.md` 正文) - -| Layer | Skill | -|---|---| -| **0 入口** | `erp-plan-start` / `erp-project-init` | -| **1 计划阶段** | `erp-scope-lock` / `erp-skeleton-gen` / `erp-db-init` / `erp-db-design-gen` / `erp-downstream-gen` | -| **2 模块循环(外)** | `erp-module-start` / `erp-local-test-gate` / `erp-module-report` / `erp-mr-create` | -| **3 功能循环(内)** | `erp-feature-brainstorm` / `erp-feature-plan` / `erp-feature-tdd` / `erp-feature-verify` / `erp-feature-review` | -| **4 横切守门** | `erp-red-flag-check` / `erp-cross-module-log`(软规则 S2) | - -### Hooks(3 个,由插件 `hooks/hooks.json` + `hooks/scripts/*.sh` 提供) - -- `deny-no-verify.sh` — 拒 `git push --no-verify` -- `log-cross-module.sh` — 跨模块改动自动留痕(S2) - -### 模板(分散在各 skill 的 插件 `skills/erp-*/templates/*`) - -每个生成文件都对应一个模板(设计原则 #5)。模板保持纯净(原则 #6),帮助文本由 skill 通过 `AskUserQuestion` 交互引导。模板按"谁用谁拥有"原则分散到各自的 skill 目录下,便于打包成 plugin。一份共享模板(`cross-module-log-template.md`)在 `erp-module-start` 与 `erp-cross-module-log` 中各有一份副本。 - diff --git a/skills/plan/erp-project-init/templates/docs-01-readme-template.md b/skills/plan/erp-project-init/templates/docs-01-readme-template.md deleted file mode 100644 index ed09a21..0000000 --- a/skills/plan/erp-project-init/templates/docs-01-readme-template.md +++ /dev/null @@ -1,16 +0,0 @@ -# 需求清单 - -> 本目录按模块组织所有功能需求。每个模块一个文件,由 CC 基于下方纲要扩展成 REQ-XXX-NNN 标准卡片。 - -## 模块索引 - -| 模块代码 | 模块名称 | 核心功能点(简要) | -|----------|----------|--------------------| -| SYS | 系统管理 | 【人工填写:用户/角色/权限/部门/字典 等】 | -| 【人工填写:模块代码】 | 【人工填写:模块名称】 | 【人工填写:核心功能点】 | - -## 填写说明 - -1. 每个模块占一行,`模块代码` 用大写英文缩写(如 SYS / PUR / INV / SAL / FIN / HR) -2. `核心功能点` 只需列关键词,CC 会基于此扩展成完整 REQ 卡片 -3. 填完后运行 `/erp-workflow:erp-plan-start`,CC 会自动检测并进入需求生成阶段 diff --git a/skills/plan/erp-project-init/templates/docs-08-initial-template.md b/skills/plan/erp-project-init/templates/docs-08-initial-template.md deleted file mode 100644 index a21c400..0000000 --- a/skills/plan/erp-project-init/templates/docs-08-initial-template.md +++ /dev/null @@ -1,51 +0,0 @@ -# 08-工作流进度 - -> 全流程进度跟踪。CC 每完成一项产出就勾选一项。 -> - **§ 一 Plan(A0~A5)**:`erp-plan-start` 找第一个未勾 A 子项分发到对应 skill -> - **§ 二 Coding(模块)**:分发以 `docs/02-开发计划.md § 二 开发顺序清单` 为准;`erp-coding-start` 按 docs/02 顺序扫描,对每个 REQ 所属模块查询本 § 二的 `MR:` 字段 + GitLab API `state`,找第一个非 merged 模块分发。本 § 二 行序无语义,仅作模块元数据表 - -## 一、Plan 阶段(一次性) - -- [ ] A0 项目初始化 — erp-project-init - - [ ] 项目文件骨架已创建(CLAUDE.md + docs/01-需求清单/README.md) - -- [ ] A1 范围锁定 — erp-scope-lock - - [ ] 项目概述已填写(CLAUDE.md § 🎯 项目概述) - - [ ] 技术栈已确认(docs/04 § 零) - - [ ] 需求清单索引已填写(docs/01-需求清单/README.md) - - [ ] REQ 卡片已生成(docs/01-需求清单/*.md,schema/api 字段标记为 TBD) - -- [ ] A2 骨架生成 — erp-skeleton-gen - - [ ] 架构文档已生成(docs/04 § 一+、docs/06、docs/07、docs/09) - - [ ] 工具脚本已生成(scripts/*.sh、.githooks/pre-push、.env.local) - - [ ] .gitignore 已配置 - -- [ ] A3 DB 初始化 — erp-db-init - - [ ] .env.local 凭据验证通过 - - [ ] MySQL 连接验证通过 - - [ ] V1 initial migration 已生成(sql/migrations/V1__initial_schema.sql,DDL only) - - [ ] sql/seed-data.sql 已导出(本地数据快照,INSERT only) - -- [ ] A4 DB 设计 + REQ 回填 — erp-db-design-gen - - [ ] docs/03 数据库设计已生成 - - [ ] REQ 卡片依赖表已回填 - - [ ] schema 一致性检查通过 - -- [ ] A5 下游文档生成 — erp-downstream-gen - - [ ] docs/02 开发计划已生成 - - [ ] docs/05 API 契约已生成 - - [ ] docs/06 § 五 页面清单已填入 - - [ ] docs/10 验收清单已生成 - - [ ] 下方模块列表已填入 - - [ ] REQ 卡片依赖接口已回填 - -## 二、Coding 阶段(按模块循环) - -(A5 填入后,每个模块一行 bullet。每个模块的 `MR:` 字段在 `—` 和 `!<iid>` 之间变化,完成由 GitLab API `state=merged` 判定。`erp-coding-start` 每次按 docs/02 REQ 序扫每模块的 MR state 决定派发。) - -<!-- 模块格式示例(由 A5 erp-downstream-gen 追加): -- module_0 系统管理 - - 依赖: — - - 路径: backend/module/sys/, frontend/pages/sys/ - - MR: — ---> diff --git a/skills/plan/erp-scope-lock/SKILL.md b/skills/plan/erp-scope-lock/SKILL.md deleted file mode 100644 index b6f2570..0000000 --- a/skills/plan/erp-scope-lock/SKILL.md +++ /dev/null @@ -1,234 +0,0 @@ ---- -name: erp-scope-lock -description: A1 计划范围锁定——引导用户填写项目概述 + 技术栈 + 需求索引,并自动扩展 REQ 卡片待人工评审。`schema_refs` 填 `TBD(A4 自动补)`(A4 回填依赖表),`api_refs` 填 `TBD(A5 自动补)`(A5 回填依赖接口)。 -user-invocable: false -allowed-tools: Read Write Edit Grep Skill AskUserQuestion ---- - -**所有输出必须使用中文。** - -# erp-scope-lock - -## 执行步骤 - -### 步骤 0:打印当前位置流程图 - -向用户展示当前在 A 阶段流程中的位置(A-only,`▶` 标在 A1): - -``` -┌──────────────────────────────────────────────────────┐ -│ 📋 阶段 A:规划(一次性) │ -│ │ -│ A0 初始化项目 → ▶ A1 锁范围(REQ 卡片) │ -│ ↓ │ -│ ⏸ 等你审阅 REQ,重新运行 /erp-plan-start 继续 │ -│ ↓ │ -│ A2 生成骨架 → A3 初始化 DB → A4 生成 DB 设计 → A5 生成下游文档│ -│ ↓ │ -│ 规划阶段到此结束 │ -└──────────────────────────────────────────────────────┘ -``` - -### A. 提示用户填写项目概述并等待 - -向用户输出: - -``` -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - [erp-scope-lock] 请填写项目概述 - - 📄 文件位置: ./CLAUDE.md - 📌 编辑位置: § 🎯 项目概述 - - 请将以下占位符替换为实际值: - - 项目名称 - - 项目简述 - - 目标用户 - - 部署方式 - 改完后回来选择「继续」。 -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -``` - -用 `AskUserQuestion` 询问: -- **question**: `项目概述填写完毕了吗?` -- **options** (每项为对象): - - `{"label": "继续", "description": "已完成检查"}` - - `{"label": "有疑问想先沟通", "description": "需要讨论或修改"}` - -- 用户选择「有疑问想先沟通」→ 回答用户问题后,再次弹出同样的 QA。 -- 用户选择「继续」→ 进入步骤 B。 - -### B. 保存默认技术栈到 docs/04 - -用 `Write` 将以下默认技术栈表写入 `docs/04-技术规范.md`: - -```markdown -# 04-技术规范 - -## 零、技术栈总览 - -| 分层模块 | 技术 | 版本要求 | 说明 | -|---|---|---|---| -| 前端基础框架 | React | 18.x | 构建前端应用 | -| 前端 UI 组件 | Ant Design | 5.x | 页面组件与交互控件 | -| 前端状态管理 | Redux Toolkit | 最新稳定版 | 管理全局状态 | -| 前端路由管理 | React Router | v6 | 页面路由与导航 | -| 前端工程化构建 | Vite | 最新稳定版 | 前端开发与打包构建 | -| 前端接口通信 | Axios | 最新稳定版 | 调用后端 API | -| 后端基础框架 | Spring Boot | 3.x | 构建后端服务 | -| 后端数据访问 | MyBatis-Plus | 最新稳定版 | 数据库访问与 ORM 增强 | -| 工作流引擎 | Activiti | 6.x | 审批流、流程流转 | -| 缓存服务 | Redis | 最新稳定版 | 缓存、会话、分布式能力 | -| 报表打印 | JXLS | 2.8.1 | 基于 Excel 模板生成报表 | -| Excel 导入导出 | EasyExcel | 4.0.3 | Excel 数据导入导出 | -| 关系型数据库 | MySQL | 8.x | 核心业务数据存储 | -| 数据库 schema 迁移 | Flyway (`flyway-core` + `flyway-mysql`) | 10.x / 最新稳定版 | `sql/migrations/V_n__*.sql` 顺序 apply;Spring Boot 启动时自动应用 | -| 接口风格 | RESTful API | 统一规范 | 前后端接口设计规范 | -| 权限认证 | Spring Security / JWT | 最新稳定版 | 登录认证、权限控制 | -| API 文档 | OpenAPI / Swagger | 最新稳定版 | 接口文档与调试 | -| 项目构建管理 | Maven | 3.9.x | Java 项目依赖与构建 | -| JDK 运行环境 | Java | 17 / 21 | Spring Boot 3 推荐版本 | -| 部署容器 | Docker | 最新稳定版 | 容器化部署 | -| Web 服务器 / 反向代理 | Nginx | 最新稳定版 | 前端托管、反向代理、负载分发 | -| 日志管理 | Logback | 默认集成 / 最新稳定版 | 应用日志输出 | -| 对象映射工具 | MapStruct | 最新稳定版 | DTO / VO / Entity 转换 | -| 工具类库 | Hutool / Apache Commons | 最新稳定版 | 常用工具方法支持 | - -> 本表由 erp-scope-lock 锁定。后续所有规范基于此表推导。 -``` - -### C. 提示用户检查并等待 - -向用户输出: - -``` -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - [erp-scope-lock] 技术栈已保存 - - 📄 文件位置: ./docs/04-技术规范.md - 📌 编辑位置: § 零、技术栈总览 - - 请检查技术栈表: - - 不需要的行直接删除(如纯后端项目删前端行) - - 需要替换的技术直接改 - - 需要新增的条目直接加行 - 改完后回来选择「继续」。 -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -``` - -用 `AskUserQuestion` 询问: -- **question**: `技术栈检查完毕了吗?` -- **options** (每项为对象): - - `{"label": "继续", "description": "已完成检查"}` - - `{"label": "有疑问想先沟通", "description": "需要讨论或修改"}` - -- 用户选择「有疑问想先沟通」→ 回答用户问题后,再次弹出同样的 QA。 -- 用户选择「继续」→ 进入步骤 D。 - -### D. 提示用户填写需求清单并等待 - -`docs/01-需求清单/README.md` 已由 `erp-project-init` 写入占位符模板,这里让用户补齐模块清单。 - -向用户输出: - -``` -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - [erp-scope-lock] 请填写需求清单模块索引 - - 📄 文件位置: ./docs/01-需求清单/README.md - 📌 编辑位置: § 模块索引(表格) - - 请按业务列出所有模块: - - 每行一个模块(如 SYS 系统管理 / PUR 采购 / SAL 销售) - - 「核心功能点」只需关键词,CC 会扩展为完整 REQ 卡片 - 改完后回来选择「继续」。 -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -``` - -用 `AskUserQuestion` 询问: -- **question**: `需求清单模块索引填写完毕了吗?` -- **options** (每项为对象): - - `{"label": "继续", "description": "已完成检查"}` - - `{"label": "有疑问想先沟通", "description": "需要讨论或修改"}` - -- 用户选择「有疑问想先沟通」→ 回答用户问题后,再次弹出同样的 QA。 -- 用户选择「继续」→ 进入步骤 E。 - -### E. 生成 REQ 卡片并等用户审阅 - -先用 `Grep` 在 `docs/01-需求清单/README.md` 搜索 `【人工填写:`,命中 → 提示残留行,回到步骤 D。通过后: - -1. 用 `Read` 读取 `docs/01-需求清单/README.md`,解析模块索引表(每行:模块代码 / 模块名 / 核心功能点)。 -2. 用 `Read` 读取两份模板: - - `${CLAUDE_SKILL_DIR}/templates/req-card-template.md` - - `${CLAUDE_SKILL_DIR}/templates/docs-01-module-template.md` -3. 对每个模块: - - 基于「核心功能点」关键词,LLM 扩展为若干 REQ-XXX-NNN 卡片(编号按模块递增) - - 每张卡片填充字段: - - `goal` / `input` / `output` / `rules` / `constraints` / `acceptance` —— LLM 基于功能点推断 - - `schema_refs` —— 填 `TBD(A4 自动补)`(A4 `erp-db-design-gen` 回填依赖表) - - `api_refs` —— 填 `TBD(A5 自动补)`(A5 `erp-downstream-gen` 回填依赖接口) - - 用 module 模板包装卡片列表 - - 用 `Write` 写入 `docs/01-需求清单/<module_code>-<module_name>.md` -4. 向用户输出(只打印,**不弹出 QA**,不等待): - -``` -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - [erp-scope-lock] REQ 卡片已生成 - - 📄 文件位置: ./docs/01-需求清单/<module>-*.md - ⚠️ 依赖表 = TBD(A4 自动补)(A4 阶段回填) / 依赖接口 = TBD(A5 自动补)(A5 阶段回填) - - 请人工审阅每张 REQ 卡片的功能字段: - - 目标 / 输入 / 输出 - - 业务规则 / 边界 - - 验收标准 - - 审阅是 Plan 阶段的关键人工关口,请认真逐张过一遍。 -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -``` - -5. 立即进入步骤 F(不等待用户任何输入)。 - -### F. 勾选 docs/08 进度 + 停下等人工审阅 - -1. 用 `Edit` 在 `docs/08-模块任务管理.md` 勾选 5 个 checkbox(A1 的 4 个子项 + A1 父项): - - ` - [ ] 项目概述已填写(CLAUDE.md § 🎯 项目概述)` → `[x]` - - ` - [ ] 技术栈已确认(docs/04 § 零)` → `[x]` - - ` - [ ] 需求清单索引已填写(docs/01-需求清单/README.md)` → `[x]` - - ` - [ ] REQ 卡片已生成(docs/01-需求清单/*.md,schema/api 字段标记为 TBD)` → `[x]` - - `- [ ] A1 范围锁定 — erp-scope-lock` → `[x]` - -2. 输出 `scope-lock: 完成(4 项产出已勾选)`。 - -3. 打印停下横幅并**停下**(**不调** `Skill(erp-skeleton-gen)`,A2 由用户手动恢复): - - ``` - ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - [erp-scope-lock] ✅ A1 范围锁定完成 - - 产出: - ✓ CLAUDE.md § 🎯 项目概述 - ✓ docs/04 § 零 技术栈 - ✓ docs/01-需求清单/README.md 模块索引 - ✓ docs/01-需求清单/<module>-*.md REQ 卡片 - - ⏸ 现在请你审阅 REQ 卡片(路径:`docs/01-需求清单/<module_code>-<module_name>.md`)。 - - 审阅完成后,运行以下命令继续进入 A2: - /erp-workflow:erp-plan-start - - (入口会读取 docs/08 进度,自动派发到 A2 erp-skeleton-gen) - ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ``` - - **停止**,不调用任何下游 skill。 - -## 参考 - -- `CLAUDE.md` § 🎯 项目概述(写入目标) -- `docs/04-技术规范.md`(技术栈输出,供 erp-skeleton-gen 读取使用) -- `docs/01-需求清单/README.md`(模块索引输入) -- `docs/01-需求清单/<module>-*.md`(REQ 卡片输出,A4 erp-db-design-gen 会回填 TBD 字段) -- `${CLAUDE_SKILL_DIR}/templates/req-card-template.md` -- `${CLAUDE_SKILL_DIR}/templates/docs-01-module-template.md` diff --git a/skills/plan/erp-scope-lock/templates/docs-01-module-template.md b/skills/plan/erp-scope-lock/templates/docs-01-module-template.md deleted file mode 100644 index 4534a7d..0000000 --- a/skills/plan/erp-scope-lock/templates/docs-01-module-template.md +++ /dev/null @@ -1,11 +0,0 @@ -# {{module_code}}-{{module_name}} - -模块简述: {{module_brief}} -依赖模块: {{depends_on}} -涉及表: {{tables}} - -## 功能清单 - -{{#each reqs}} -{{req_card}} -{{/each}} diff --git a/skills/plan/erp-scope-lock/templates/req-card-template.md b/skills/plan/erp-scope-lock/templates/req-card-template.md deleted file mode 100644 index a616c59..0000000 --- a/skills/plan/erp-scope-lock/templates/req-card-template.md +++ /dev/null @@ -1,10 +0,0 @@ -### {{req_id}} {{title}} - -- **目标**: {{goal}} -- **输入**: {{input}} -- **输出**: {{output}} -- **业务规则**: {{rules}} -- **边界**: {{constraints}} -- **依赖表**: {{schema_refs}} -- **依赖接口**: {{api_refs}} -- **验收**: {{acceptance}} diff --git a/skills/plan/erp-skeleton-gen/SKILL.md b/skills/plan/erp-skeleton-gen/SKILL.md deleted file mode 100644 index a6320e7..0000000 --- a/skills/plan/erp-skeleton-gen/SKILL.md +++ /dev/null @@ -1,304 +0,0 @@ ---- -name: erp-skeleton-gen -description: A2 骨架生成——基于 docs/04 § 零 技术栈 + docs/01-需求清单/README.md 模块索引,生成项目专属的架构文档(docs/04 § 一+、docs/06、docs/07、docs/09)和工具脚本。固定工具文件走 cp,架构文档由 LLM 按大纲生成。 -user-invocable: false -allowed-tools: Read Write Edit Skill Grep Glob AskUserQuestion Bash(mkdir *) Bash(cp *) Bash(touch *) Bash(chmod *) Bash(git config *) Bash(cat *) Bash(bash *) ---- - -**所有输出必须使用中文。** - -# erp-skeleton-gen - -## 前置条件 - -本 skill 从 docs/08 进度推进而来。 - -**输入文件**: -- `docs/04-技术规范.md § 零`:erp-scope-lock 写入的技术栈表。本 skill 基于它推导 § 一+ 编码规范、docs/07 依赖清单、docs/09 目录结构、scripts/test.sh 的构建/测试命令。 -- `docs/01-需求清单/`:A1 已产出 README.md(模块索引表)+ 每模块一份 REQ 卡片(`<code>-<name>.md`,用户已审阅确认)。A2 只用其中的**模块 ID 列表**生成 docs/09 的后端/前端模块目录树(`module/user/` / `module/order/` 等),REQ 卡片详情不在本 skill 使用(留给 A4 回填 schema、A5 生成 API/验收清单)。 -- `docs/08-模块任务管理.md`:末尾 Edit 勾选 A2 checkbox。 - -**产出覆盖提醒**: -- 本 skill 会 `Write` 覆盖以下文件:docs/04(拼接 § 零 + § 一+)、docs/06、docs/07、docs/09、scripts/test.sh、scripts/setup-test-db.sh、.githooks/pre-push、.env.local。 -- 如果之前运行过本 skill 且用户手动改过这些文件,**重新运行会覆盖修改**。 - -## 执行步骤 - -### 步骤 0:打印当前位置流程图 - -向用户展示当前在 A 阶段流程中的位置(A-only,`▶` 标在 A2): - -``` -┌──────────────────────────────────────────────────────┐ -│ 📋 阶段 A:规划(一次性) │ -│ │ -│ A0 初始化项目 → A1 锁范围(REQ 卡片) │ -│ ↓ │ -│ ⏸ 等你审阅 REQ,重新运行 /erp-plan-start 继续 │ -│ ↓ │ -│ ▶ A2 生成骨架 → A3 初始化 DB → A4 生成 DB 设计 → A5 生成下游文档│ -│ ↓ │ -│ 规划阶段到此结束 │ -└──────────────────────────────────────────────────────┘ -``` - -### A. 读取锁定的输入 - -用 `Read` 读取: -- `docs/04-技术规范.md` § 零 技术栈表 -- `docs/01-需求清单/README.md` 模块索引 - -这两份是本次生成的**唯一权威输入**,后续所有内容都基于它们推导。 - -### B.1 生成 3 个全新架构文档(docs/06 / 07 / 09) - -对下表每个目标文件: -1. 用 `Read` 读取对应的大纲模板(只含 section 标题 + HTML 注释形式的填写提示) -2. 基于步骤 A 的输入,按大纲生成项目专属内容 -3. **剥掉所有 `<!-- -->` 注释**(注释是给 LLM 的提示,不应出现在最终文档里) -4. 用 `Write` 写入目标路径 - -| 目标文件 | 大纲模板 | -|---|---| -| `docs/06-UI交互规范.md`(写 § 一 ~ 四,§ 五 占位) | `${CLAUDE_SKILL_DIR}/templates/docs-06-static-template.md` | -| `docs/07-环境配置.md` | `${CLAUDE_SKILL_DIR}/templates/docs-07-env-template.md` | -| `docs/09-项目目录结构.md` | `${CLAUDE_SKILL_DIR}/templates/docs-09-structure-template.md` | - -项目专属标识(根包名 / 命名空间)保留 `【人工填写:<说明>】` 占位,等人工在 docs/09 顶部补填一次后,其他文件复用。 - -### B.2 追加 docs/04 § 一+(保留 § 零 不覆盖) - -docs/04 已由 erp-scope-lock 写入 § 零。本步骤追加 § 一 ~ 三。 - -1. 用 `Read` 读取 `docs/04-技术规范.md`(拿现有 § 零 完整内容)。 -2. 用 `Read` 读取 `${CLAUDE_SKILL_DIR}/templates/docs-04-skeleton-template.md`(§ 一+ 大纲)。 -3. 基于步骤 A 技术栈,按大纲生成 § 一 ~ 三 的项目专属内容,剥掉 HTML 注释。 -4. 拼接 `<§ 零 原文>\n\n<新生成的 § 一+>` → 用 `Write` 写回 `docs/04-技术规范.md`。 - -### C. 生成工具脚本 - -#### C.1 零槽位文件:纯 `cp` - -```bash -mkdir -p scripts .githooks sql/migrations -touch sql/migrations/.gitkeep -cp "${CLAUDE_SKILL_DIR}/templates/env-local-template" .env.local -cp "${CLAUDE_SKILL_DIR}/templates/githooks-pre-push-template.sh" .githooks/pre-push -cp "${CLAUDE_SKILL_DIR}/templates/scripts-setup-test-db-template.sh" scripts/setup-test-db.sh -``` - -说明: -- `sql/migrations/` 是 Flyway migration 目录。A3 `erp-db-init` 会在此生成 `V1__initial_schema.sql`,后续 B 阶段每个 REQ 的业务 DDL 也写在这(`V2__xxx.sql` / `V3__xxx.sql` ...) -- `setup-test-db.sh` 只做 **drop + create 空库**,schema 由 **Flyway 在 Spring Boot 启动时自动应用** -- **硬依赖**:项目 `pom.xml` 必须包含 `flyway-core` + `flyway-mysql` 依赖(已列入 docs/04 § 零 技术栈);否则 Spring 启动不会 apply migration,测试会因表不存在而失败 -- seed 数据(`sql/seed-data.sql`)由 A3 `erp-db-init` 从本地 MySQL 导出,开发者选一种装载方式(Spring `@Sql` / Flyway `R__seed.sql` / `data.sql`);setup-test-db.sh 只负责清空库 - -#### C.2 `scripts/test.sh` —— 直接 Write - -基于步骤 A 的技术栈推断 build / lint / unit+integration / e2e 四条命令,直接 `Write` 完整 `scripts/test.sh`。 - -骨架如下(CC 把 4 个 `<推断的 ... 命令>` 替换成实际值后 Write): - -```bash -#!/usr/bin/env bash -# scripts/test.sh —— 合并到默认分支(main / master)前的唯一硬闸门。 -# 顺序:setup-db → build → lint → unit+integration → e2e → reset-db -# 由 .githooks/pre-push 和 erp-local-test-gate skill(通过子会话)调用。 - -set -euo pipefail - -PROJECT_ROOT="$(cd "$(dirname "$0")/.." && pwd)" -cd "$PROJECT_ROOT" - -echo "[test.sh] 1/6 setup test db" -./scripts/setup-test-db.sh - -echo "[test.sh] 2/6 build" -<推断的 build 命令,如:(cd backend && mvn -DskipTests clean package) && (cd frontend && pnpm build)> - -echo "[test.sh] 3/6 lint" -<推断的 lint 命令> - -echo "[test.sh] 4/6 unit + integration" -<推断的 unit+integration 命令> - -echo "[test.sh] 5/6 E2E" -<推断的 e2e 命令> - -echo "[test.sh] 6/6 reset test db" -./scripts/setup-test-db.sh - -echo "[test.sh] GREEN" -``` - -#### C.3 赋权 + 配置 git hooks - -```bash -chmod +x scripts/*.sh .githooks/pre-push -git config core.hooksPath .githooks -``` - -### D. 追加 .gitignore 忽略项 - -调用脚本完成合并: - -```bash -bash "${CLAUDE_SKILL_DIR}/scripts/merge-gitignore.sh" "${CLAUDE_SKILL_DIR}/templates/gitignore-append-template" -``` - -脚本行为: -- 若项目根无 `.gitignore` → 直接 `cp` 整份模板 -- 若已有 → 读模板每一行,跳过注释/空行,用 `grep -xF` 整行精确匹配判重(避免 `.env` 误匹配 `.env.local`、通配符 `*.iml` 被当正则),只追加缺失的规则 - -### E. 占位符智能填充 + `.env.local` 独立提示 + QA 循环验证 - -目标:减少用户重复编辑。同一"逻辑占位"(如根包名出现多处)只问用户一次,CC 批量填;派生占位(如 Java 路径从根包名派生)由 CC 自己推断。敏感占位(`.env.local` 凭据 / 密钥)不进会话上下文,让用户自己去文件里填。 - -循环执行直到**两个条件同时满足**: -(a) 所有占位符已填(重新扫描命中数 N = 0) -(b) 用户选「继续」 - -#### E.1 扫描 + 分组 - -用 `Grep` 在以下 8 个路径下扫描 `【人工填写:`,记录每处命中(文件 + 行号 + 说明文字): -- `docs/04-技术规范.md` -- `docs/06-UI交互规范.md` -- `docs/07-环境配置.md` -- `docs/09-项目目录结构.md` -- `scripts/*.sh` -- `.githooks/pre-push` -- `.gitignore` -- `.env.local` - -对每个命中提取 `【人工填写:<说明>】` 的 `<说明>`,**分两组**: - -- **敏感组**:`.env.local` 路径下的全部命中(密码 / 密钥 / 账号等)。**不**通过 `AskUserQuestion` 问——留给 E.4 提示用户手动编辑。 -- **非敏感组**:其他文件的命中。按语义聚合成"逻辑占位": - - **说明文字完全相同** → 同一个根占位(多处共用同一值),如"根包名"出现 3 次 - - **说明表达派生关系** → 派生占位,派生自某根占位(如"后端 java 根包路径"派生自"根包名") - - **无法归类** → 视作独立根占位单独问 - -若总 N=0(无任何占位)→ 直接跳 E.5 验证。 - -#### E.2 向用户询问非敏感"根占位" - -对每个非派生根占位用 `AskUserQuestion` 询问: - -- **question**: `请输入 <说明>(将填充到 <N> 处)` -- **options**(给**默认值候选 + 自由输入**,供用户快速选择;"Other" 由 CC 运行时自动提供,无需显式列): - - `{"label": "<合理默认值>", "description": "示例默认值"}` - - (可选)`{"label": "<第二个常见默认>", "description": "..."}` - -示例(根包名): -``` -question: "请输入 Java 根包名(将填充到 3 处)" -options: - - {"label": "com.example.erp", "description": "示例默认"} -``` - -- 用户选默认值 → 取该值 -- 用户选 Other → 用户输入的字符串为该值 - -**派生占位不问用户**——由 CC 在 E.3 自行推断。 - -#### E.3 CC 批量 Edit 填充 - -1. 对每个根占位:遍历所有命中位置,用 `Edit` 把 `【人工填写:<说明>】` 替换为 E.2 用户输入的值。 - -2. 对每个派生占位:CC 基于说明文字 + 根占位值**自行推断**派生值,用 `Edit` 填入。例如: - - 根 `根包名 = com.xly.erp` → 派生 `后端 java 根包路径 = backend/src/main/java/com/xly/erp/` - - 根 `根包名 = com.xly.erp` → 派生 `测试 java 根包路径 = backend/src/test/java/com/xly/erp/` - -3. 若 CC 对某派生占位无法可靠推断(说明不清 / 上下文不足),**回退**:把该占位当作独立根占位,弹 `AskUserQuestion` 问用户。 - -#### E.4 `.env.local` 敏感占位提示(不弹出 QA) - -若敏感组非空,打印提示横幅(只打印,不问): - -``` -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - [erp-skeleton-gen] ⚠️ 敏感占位需你亲自填 - - 📄 文件: ./.env.local - 待填字段(<N> 个): - <列出实际命中的字段名,如 DB_HOST / DB_PORT / DB_USER / DB_PASSWORD / DB_SCHEMA / JWT_SECRET> - - 这些是凭据 / 密钥,CC 不通过会话询问(避免写入聊天记录)。 - 请直接编辑 .env.local 填入实际值。 -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -``` - -#### E.5 验证 + QA 循环 - -1. 用 `Grep` **重新扫** `【人工填写:` 于所有 8 个路径,得新命中数 N 和残留清单。 - -2. 打印汇总横幅: - - ``` - ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - [erp-skeleton-gen] 骨架生成完成,请审阅 - - 📄 架构文档: - ✓ docs/04-技术规范.md (§ 一 ~ 三) - ✓ docs/06-UI交互规范.md (§ 一 ~ 四) - ✓ docs/07-环境配置.md - ✓ docs/09-项目目录结构.md - - 📄 工具文件: - ✓ scripts/test.sh - ✓ scripts/setup-test-db.sh - ✓ .githooks/pre-push - ✓ .env.local - ✓ .gitignore(新建 / 追加 / 跳过) - ✓ sql/migrations/.gitkeep - - 占位符状态: - <N=0 时打印:✅ 全部填完> - <N>0 时打印:⚠️ 还有 N 处待填: - <文件:行号> — <行内容摘要> - ...> - - 需要调整 → 直接编辑对应文件(尤其 .env.local 敏感字段) - 填完后 → 选「继续」放行 A3 - ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ``` - -3. 用 `AskUserQuestion` 询问: - - **question**: `架构文档审阅 & 占位符补填完毕?` - - **options**: - - `{"label": "继续", "description": "进入 A3 数据库配置"}` - - `{"label": "有疑问想先沟通", "description": "需要讨论或修改"}` - -4. 路由: - - 选「有疑问想先沟通」→ 回答用户问题后**回 E.5.1 重新扫描** - - 选「继续」→ **回 E.5.1 重新扫描验证**: - - 新 N = 0 → 进入步骤 F(放行 A3) - - 新 N > 0 → 用户以为填完其实还有残留,回 E.5.2 打印新横幅并再次弹出 QA - -关键点:**每次弹出 QA 前都重新扫描一次**,用户看到的 N 始终是最新的;只有 N = 0 且选「继续」才放行。 - -### F. 勾选 docs/08 进度 + 进入 A3 - -1. 用 `Edit` 在 `docs/08-模块任务管理.md` 勾选 4 个 checkbox(A2 的 3 个子项 + A2 父项): - - ` - [ ] 架构文档已生成(docs/04 § 一+、docs/06、docs/07、docs/09)` → `[x]` - - ` - [ ] 工具脚本已生成(scripts/*.sh、.githooks/pre-push、.env.local)` → `[x]` - - ` - [ ] .gitignore 已配置` → `[x]` - - `- [ ] A2 骨架生成 — erp-skeleton-gen` → `[x]` - -2. 输出 `skeleton-gen: 完成(docs/04 § 一+ / docs/06 / docs/07 / docs/09 + scripts/*.sh + .githooks/pre-push + .env.local + .gitignore)`。 - -3. 立即调用 `Skill(erp-db-init)` 进入 A3,不等用户手动输入。 - -## 参考 - -- `docs/04-技术规范.md` § 零(技术栈输入) -- `docs/01-需求清单/README.md`(模块索引输入) -- `${CLAUDE_SKILL_DIR}/templates/docs-04-skeleton-template.md`(大纲) -- `${CLAUDE_SKILL_DIR}/templates/docs-06-static-template.md`(大纲) -- `${CLAUDE_SKILL_DIR}/templates/docs-07-env-template.md`(大纲) -- `${CLAUDE_SKILL_DIR}/templates/docs-09-structure-template.md`(大纲) -- `${CLAUDE_SKILL_DIR}/templates/scripts-setup-test-db-template.sh`(0 槽位) -- `${CLAUDE_SKILL_DIR}/templates/githooks-pre-push-template.sh`(0 槽位) -- `${CLAUDE_SKILL_DIR}/templates/env-local-template`(0 槽位) -- `${CLAUDE_SKILL_DIR}/templates/gitignore-append-template`(0 槽位) -- `${CLAUDE_SKILL_DIR}/scripts/merge-gitignore.sh`(.gitignore 逐行判重合并脚本) diff --git a/skills/plan/erp-skeleton-gen/scripts/merge-gitignore.sh b/skills/plan/erp-skeleton-gen/scripts/merge-gitignore.sh deleted file mode 100755 index 02fd0da..0000000 --- a/skills/plan/erp-skeleton-gen/scripts/merge-gitignore.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/env bash -# merge-gitignore.sh -# 把模板里的忽略规则合并到项目根的 .gitignore: -# - 若 .gitignore 不存在 → 直接 cp 模板(含注释头和结构) -# - 若已存在 → 逐行判重,只追加模板里缺失的规则行(跳过注释/空行) -# -# 用法:merge-gitignore.sh <template_path> [<target_gitignore_path>] -# template_path 模板文件绝对路径(由 erp-skeleton-gen skill 传入) -# target_gitignore_path 目标 .gitignore 路径,默认为当前工作目录下的 .gitignore -# -# 判重:grep -xF 整行精确匹配 + 字面字符串(非正则),避免 .env 误匹配 .env.local, -# 也避免 *.class / *.iml 等通配符被当作 regex。 - -set -euo pipefail - -template="${1:?usage: merge-gitignore.sh <template_path> [<target_gitignore_path>]}" -target="${2:-.gitignore}" - -if [ ! -f "$template" ]; then - echo "[merge-gitignore] ERROR: template not found: $template" >&2 - exit 1 -fi - -if [ ! -f "$target" ]; then - cp "$template" "$target" - echo "[merge-gitignore] created $target from template" - exit 0 -fi - -added=0 -while IFS= read -r line; do - case "$line" in ""|"#"*) continue ;; esac - if ! grep -qxF "$line" "$target"; then - echo "$line" >> "$target" - added=$((added + 1)) - fi -done < "$template" - -echo "[merge-gitignore] $target updated (+$added rules)" diff --git a/skills/plan/erp-skeleton-gen/templates/docs-04-skeleton-template.md b/skills/plan/erp-skeleton-gen/templates/docs-04-skeleton-template.md deleted file mode 100644 index 24bd1fb..0000000 --- a/skills/plan/erp-skeleton-gen/templates/docs-04-skeleton-template.md +++ /dev/null @@ -1,50 +0,0 @@ -<!-- -本文件是 docs/04-技术规范.md 的 § 一+ 大纲。 -skeleton-gen 读取 docs/04 § 零(技术栈表)和 docs/01-需求清单/README.md(模块索引), -按下述大纲生成本项目专属的规范内容。LLM 不要原样拷贝提示文字,只保留 section 标题。 ---> - -## 一、后端规范 - -### 1.1 分层结构 -<!-- 按 § 零 的后端框架定层次:controller/service/mapper 等;每层职责一句话。 --> - -### 1.2 命名约定 -<!-- 包名(根包用【人工填写:根包名】占位)/ 类名 / 方法名 / 常量的大小写规则,含 2 个示例。 --> - -### 1.3 统一响应格式 -<!-- 成功/失败的 JSON 结构,错误码段位划分。 --> - -### 1.4 异常处理 -<!-- 全局异常处理器的使用方式;哪些异常要 catch,哪些禁止。 --> - -### 1.5 事务 -<!-- 事务边界(通常 service 层);跨服务调用的禁止/替代方案。 --> - -### 1.6 认证 -<!-- 基于 § 零 认证方案推导:token 生命周期、刷新机制、密钥管理。 --> - -## 二、前端规范 - -### 2.1 目录约定 -<!-- 基于 § 零 前端框架推导:api/components/pages/store/hooks/utils 的职责。 --> - -### 2.2 状态管理 -<!-- 基于 § 零 状态管理技术推导:全局 vs 局部、服务端数据的存放。 --> - -### 2.3 请求封装 -<!-- HTTP 客户端的拦截器、超时、错误重试、鉴权注入。 --> - -### 2.4 错误处理 -<!-- 网络错误 / 业务错误 / 页面级错误的分层处理。 --> - -## 三、共同约定 - -### 3.1 Git 提交 -`<type>(<scope>): <subject> REQ-XXX-NNN` - -### 3.2 分页查询 -<!-- 后端分页对象 + 前端分页组件,入参出参约定。 --> - -### 3.3 日期与金额 -<!-- 后端类型(如 LocalDateTime / BigDecimal)+ 前端展示工具;金额精度约定。 --> diff --git a/skills/plan/erp-skeleton-gen/templates/docs-06-static-template.md b/skills/plan/erp-skeleton-gen/templates/docs-06-static-template.md deleted file mode 100644 index 6896010..0000000 --- a/skills/plan/erp-skeleton-gen/templates/docs-06-static-template.md +++ /dev/null @@ -1,47 +0,0 @@ -<!-- -本文件是 docs/06-UI交互规范.md 的 § 一~四 大纲(§ 五由 erp-downstream-gen 追加)。 -skeleton-gen 读取 docs/04 § 零 和 docs/01 README,按下述大纲生成项目专属内容。 -UI 细节(布局参数、颜色、组件选型)来自 § 零 前端 UI 组件库。 ---> - -# 06-UI交互规范 - -## 一、整体布局 - -### 1.1 页面框架 -<!-- 基于 § 零 UI 组件库(如 Ant Design Layout)描述整体骨架:Header / Sider / Content。 --> - -### 1.2 布局参数 -<!-- 表格形式:Header 高度 / Sidebar 宽度 / 内边距 / 最小分辨率,给出默认值。 --> - -## 二、标准页面类型 -<!-- 根据 docs/01 README 的模块索引推断业务可能出现的页面类型(通常列表/表单/详情/树形 4 类,根据项目裁剪)。 --> - -### 2.1 列表页 -<!-- 顶部操作区 + 搜索栏 + 表格 + 分页,关键组件选型。 --> - -### 2.2 表单页 -<!-- Drawer 还是独立页;校验时机;提交按钮位置。 --> - -### 2.3 详情页 -<!-- Descriptions + Tabs 的组合方式。 --> - -### 2.4 树形管理页 -<!-- 如项目有组织架构/权限树/分类树才生成此节,否则删除。 --> - -## 三、通用交互规则 - -### 3.1 操作反馈 -<!-- 成功/失败消息;危险操作二次确认;长耗时按钮 loading 态。 --> - -### 3.2 数据展示 -<!-- 空状态 / 加载 / 异常 的统一组件与文案。 --> - -### 3.3 权限控制(前端) -<!-- 菜单级 / 按钮级 / 路由级的控制方式,关联后端 RBAC。 --> - -## 四、主题与颜色 -<!-- 基于 § 零 UI 库的主题 token;主色 / 成功 / 警告 / 错误 色值。 --> - -## 五、页面清单(CC 生成) -(由 `erp-downstream-gen` 按模块追加段落) diff --git a/skills/plan/erp-skeleton-gen/templates/docs-07-env-template.md b/skills/plan/erp-skeleton-gen/templates/docs-07-env-template.md deleted file mode 100644 index 9613d3f..0000000 --- a/skills/plan/erp-skeleton-gen/templates/docs-07-env-template.md +++ /dev/null @@ -1,26 +0,0 @@ -<!-- -本文件是 docs/07-环境配置.md 的大纲。 -skeleton-gen 基于 docs/04 § 零 技术栈表推导各节内容: - § 一 依赖清单 → 从技术栈的每一行技术推导运行时和构建依赖 - § 二 端口约定 → 从后端/前端/数据库/缓存/反向代理 各取默认端口 - § 四 常用命令 → 基于构建工具、包管理器、MR 工具给出开发者最常用命令 ---> - -# 07-环境配置 - -## 一、依赖清单 - -<!-- 表格:| 层 | 依赖 | 版本 | 说明 |;覆盖 运行时 / 构建 / 容器 / CLI 工具。 --> - -## 二、端口约定 - -<!-- 表格:| 服务 | 端口 | 说明 |;至少列 后端 HTTP / 前端 dev / 数据库 / 缓存 / 反代。 --> - -## 三、环境变量 - -运行时凭据(数据库连接、JWT 密钥等)全部放在仓库根的 `.env.local`,不入 git。 -字段清单与占位符见该文件,真实值由开发者本地填写。 - -## 四、常用命令 - -<!-- 表格:| 命令 | 说明 |;包含 启动后端 / 启动前端 / 打包 / 运行测试 / 重置测试数据 / 创建 MR。 --> diff --git a/skills/plan/erp-skeleton-gen/templates/docs-09-structure-template.md b/skills/plan/erp-skeleton-gen/templates/docs-09-structure-template.md deleted file mode 100644 index cc0e921..0000000 --- a/skills/plan/erp-skeleton-gen/templates/docs-09-structure-template.md +++ /dev/null @@ -1,45 +0,0 @@ -<!-- -本文件是 docs/09-项目目录结构.md 的大纲。 -skeleton-gen 基于 docs/04 § 零 技术栈推导目录树: - § 二 后端目录 → 按后端框架的惯例(如 Spring Boot 的 src/main/java) - § 三 前端目录 → 按前端框架的惯例(如 Vite + React 的 src/) - § 四 docs 目录 → 沿用插件标准 - § 五 命名约定 → 按后端语言的包/命名空间习惯 - -模块划分参考 docs/01-需求清单/README.md 的模块索引,将业务模块落到代码目录。 ---> - -# 09-项目目录结构 - -## 一、仓库顶层 - -<!-- 用代码块画出顶层目录树,含 CLAUDE.md / README.md / .env.local / .githooks / scripts / docs / sql / backend / frontend 等。 --> - -## 二、后端目录 - -<!-- 基于后端框架的目录树;按 docs/01 README 的模块代码把业务模块列出(module/user/、module/order/ 等)。 --> - -## 三、前端目录 - -<!-- 基于前端框架的目录树;pages/ 下按业务模块建子目录。 --> - -## 四、docs/ 结构 - -``` -docs/ -├── 01-需求清单/ # REQ 卡片按模块分文件 -├── 02-开发计划.md -├── 03-数据库设计文档.md -├── 04-技术规范.md -├── 05-API接口契约.md -├── 06-UI交互规范.md -├── 07-环境配置.md -├── 08-模块任务管理.md -├── 09-项目目录结构.md -├── 10-验收检查清单.md -└── superpowers/ # CC 运行时产物 -``` - -## 五、命名与放置约定 - -<!-- 根包 / 命名空间用【人工填写:】占位;Controller / Service / Mapper / DTO / VO / 前端组件 / 前端页面 的放置规则。 --> diff --git a/skills/plan/erp-skeleton-gen/templates/env-local-template b/skills/plan/erp-skeleton-gen/templates/env-local-template deleted file mode 100644 index 9395092..0000000 --- a/skills/plan/erp-skeleton-gen/templates/env-local-template +++ /dev/null @@ -1,36 +0,0 @@ -# .env.local — 本地开发凭据(入 .gitignore,不提交) -# -# 规则: -# 1. 值含 `$`、反引号、空格、`!` 等 shell 特殊字符时,必须用单引号包裹: -# DB_PASSWORD='p@ss$w0rd!' -# 否则 `set -a; . .env.local; set +a` 会做变量展开导致密码错乱。 -# 2. DB_HOST 建议保持 localhost / 127.0.0.1;非本地 host 默认会被 scripts/setup-test-db.sh 防护拒绝。 -# 若必须用远程测试库,把 host 列入下方 TEST_DB_ALLOWED_HOSTS。 -# 3. DB_SCHEMA 建议命名含 test / _dev / _local / _ci,避免与生产库同名。 - -DB_HOST=【人工填写:MySQL host,推荐 localhost】 -DB_PORT=【人工填写:MySQL port,默认 3306】 -DB_USER=【人工填写:开发账号名】 -DB_PASSWORD=【人工填写:对应密码,含特殊字符时用单引号包裹】 -DB_SCHEMA=【人工填写:schema 名,推荐含 test/_dev/_local,例如 erp_dev】 -JWT_SECRET=【人工填写:JWT 签名密钥,256+ bit 随机串】 - -# 可选:额外允许 DROP CREATE 的远程 host(空格或逗号分隔)。仅当 DB_HOST 指向公司测试 MySQL 等 -# 非本地服务器时填写;留空表示只允许 localhost / 127.0.0.1 / ::1。 -# 示例:TEST_DB_ALLOWED_HOSTS="118.178.19.35 test-mysql.internal" -# -# ⚠️ 列入后该 host 每次 test.sh 都会被 DROP CREATE(无二次确认)。 -# 仅用于你完全可控的测试库;生产/共享库/多人共享的 staging 库**千万别列**。 -# (防护 2 还会检查 schema 名须含 test/_dev/_local/_ci,独立兜底。) -TEST_DB_ALLOWED_HOSTS= - -# GitLab REST API 接入(erp-mr-create / erp-coding-start / erp-module-start 用 curl 调用,无需 glab CLI): -# - GITLAB_API_URL:GitLab API base。本项目服务器用 v3。A5 `erp-downstream-gen` 从 `git remote get-url origin` -# 自动派生为 `<scheme>://<host>/api/v3`;如派生的 scheme 错(例如远程是 ssh 但实际 web 走 https),手动改掉即可 -# - GITLAB_TOKEN:GitLab v3 的 **Private Token**(用户 Profile → Account → Private token 生成;HTTP 调用仍用 -# `PRIVATE-TOKEN` 头。v3 token 是全权限、无细粒度 scope)。**无法派生,必须人工填** -# - GITLAB_PROJECT_ID:A5 从 origin 远程路径自动派生为 URL-encoded 形式(如 `zhuzc/test` → `zhuzc%2Ftest`); -# 也可手动改成项目数字 ID(GitLab 项目设置页可见) -GITLAB_API_URL=TBD(A5 自动补) -GITLAB_TOKEN=【人工填写:GitLab Private Token(Profile → Account → Private token)】 -GITLAB_PROJECT_ID=TBD(A5 自动补) diff --git a/skills/plan/erp-skeleton-gen/templates/githooks-pre-push-template.sh b/skills/plan/erp-skeleton-gen/templates/githooks-pre-push-template.sh deleted file mode 100644 index 8289050..0000000 --- a/skills/plan/erp-skeleton-gen/templates/githooks-pre-push-template.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/env bash -# .githooks/pre-push — run scripts/test.sh before every push. -# No --no-verify: the claude-code hook deny-no-verify.sh also blocks it. - -set -euo pipefail - -cd "$(git rev-parse --show-toplevel)" - -./scripts/test.sh diff --git a/skills/plan/erp-skeleton-gen/templates/gitignore-append-template b/skills/plan/erp-skeleton-gen/templates/gitignore-append-template deleted file mode 100644 index 70540c4..0000000 --- a/skills/plan/erp-skeleton-gen/templates/gitignore-append-template +++ /dev/null @@ -1,32 +0,0 @@ -# ==== ERP 插件推荐忽略项(erp-skeleton-gen 追加) ==== -# 本地运行时配置(含真实凭据,严禁入库) -.env.local -.env.*.local - -# Java / Maven -target/ -*.class - -# Node / 前端构建产物 -node_modules/ -dist/ -build/ -coverage/ - -# IDE -.idea/ -.vscode/ -*.iml - -# OS -.DS_Store -Thumbs.db - -# 日志 -*.log -logs/ - -# 插件运行时临时文件 -.tmp/ -*.raw -# ==== 结束 ==== diff --git a/skills/plan/erp-skeleton-gen/templates/scripts-setup-test-db-template.sh b/skills/plan/erp-skeleton-gen/templates/scripts-setup-test-db-template.sh deleted file mode 100644 index 41a3970..0000000 --- a/skills/plan/erp-skeleton-gen/templates/scripts-setup-test-db-template.sh +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/env bash -# scripts/setup-test-db.sh — 数据库重置脚本:drop + create 空库。 -# schema apply 由 Flyway 在 Spring Boot 启动时自动处理(见 docs/04 技术栈 + sql/migrations/V*.sql)。 -# seed 数据由测试框架负责(Spring @Sql / Flyway R__seed.sql / data.sql)。 -# -# 使用场景: -# - scripts/test.sh 开头:清空库,让 Spring 启动时 Flyway 从 V1 开始重放所有 migration -# - scripts/test.sh 结尾:清空库,避免测试遗留污染下次运行 -# - 手动调试时:reset 到零状态 -# -# 防护:本脚本只允许在本地 host + 测试库名上执行;非预期目标会被拒绝, -# 避免 .env.local 误指向 staging/prod 时触发不可逆 DROP。 - -set -euo pipefail - -ENV_FILE="$(dirname "$0")/../.env.local" -[ -f "$ENV_FILE" ] || { echo "[setup-test-db] ⚠️ .env.local 不存在($ENV_FILE)" >&2; exit 1; } - -# 用 set -a 加载,让 KEY=VALUE 导出为环境变量;密码中含特殊字符时 .env.local 请用单引号包裹 -set -a; . "$ENV_FILE"; set +a - -# 防护 1:默认只允许本地 host(localhost / 127.0.0.1 / ::1)。 -# 若要为本项目额外允许某些远程 host(如公司测试 MySQL),在 .env.local 里设: -# TEST_DB_ALLOWED_HOSTS="118.178.19.35 test-mysql.internal" # 空格或逗号分隔 -# 被列入者可直接 DROP CREATE,不再需要 TEST_DB_ALLOW_REMOTE=1。 -ALLOWED_HOSTS="localhost 127.0.0.1 ::1 ${TEST_DB_ALLOWED_HOSTS//,/ }" -host_allowed=0 -for h in $ALLOWED_HOSTS; do - [ "${DB_HOST:-}" = "$h" ] && { host_allowed=1; break; } -done -if [ "$host_allowed" -ne 1 ]; then - echo "[setup-test-db] ⚠️ 拒绝在非白名单 host (${DB_HOST}) 上执行 DROP DATABASE" >&2 - echo " 当前白名单:${ALLOWED_HOSTS}" >&2 - echo " 加入 host:在 .env.local 追加 TEST_DB_ALLOWED_HOSTS=\"<host1> <host2>\"" >&2 - echo " 一次性绕过:TEST_DB_ALLOW_REMOTE=1 $0" >&2 - [ "${TEST_DB_ALLOW_REMOTE:-0}" = "1" ] || exit 1 -fi - -# 防护 2:schema 名需像测试/开发库(含 test / _dev / _local),否则要求显式确认 -case "${DB_SCHEMA:-}" in - *test*|*_dev|*_local|*_ci) - ;; - *) - echo "[setup-test-db] ⚠️ schema '${DB_SCHEMA}' 不像测试库(期望命名含 test / _dev / _local / _ci)" >&2 - echo " 如确为期望行为,请显式声明:TEST_DB_ALLOW_PROD_NAME=1 $0" >&2 - [ "${TEST_DB_ALLOW_PROD_NAME:-0}" = "1" ] || exit 1 - ;; -esac - -# 防护 3:显式 banner,让人看见自己在 drop 什么;远程 host 额外提示白名单内容 -echo "[setup-test-db] 即将 DROP + CREATE \`${DB_SCHEMA}\` on ${DB_HOST}:${DB_PORT}" -case "${DB_HOST:-}" in - localhost|127.0.0.1|::1) ;; - *) - echo "[setup-test-db] ⚠️ 目标是 **远程** host(已在 TEST_DB_ALLOWED_HOSTS 白名单中,每次 test.sh 都会 DROP)" - echo "[setup-test-db] 当前白名单: ${ALLOWED_HOSTS}" - echo "[setup-test-db] 若不希望每次自动 DROP,从 .env.local 的 TEST_DB_ALLOWED_HOSTS 删掉此 host" - ;; -esac - -MYSQL_CMD="mysql -h${DB_HOST} -P${DB_PORT} -u${DB_USER} -p${DB_PASSWORD}" - -$MYSQL_CMD -e "DROP DATABASE IF EXISTS \`${DB_SCHEMA}\`; CREATE DATABASE \`${DB_SCHEMA}\` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;" - -echo "[setup-test-db] done — schema will be applied by Flyway when Spring Boot starts" diff --git a/skills/plan/project-init/SKILL.md b/skills/plan/project-init/SKILL.md new file mode 100644 index 0000000..5c4f3bd --- /dev/null +++ b/skills/plan/project-init/SKILL.md @@ -0,0 +1,91 @@ +--- +name: project-init +description: A0 项目初始化——从插件模板幂等地复制 CLAUDE.md / docs/01-需求清单/index.md / docs/04-技术规范.md / docs/08-模块任务管理.md(已存在则跳过),并初始化 Git(如未初始化)。session-start 在 docs/08 缺失时派发本 skill。 +user-invocable: false +allowed-tools: Glob Edit Skill Bash(mkdir *) Bash(cp -n *) Bash(git init) Bash(command -v *) Bash(uname *) Bash(brew *) Bash(apt *) Bash(apt-get *) Bash(yum *) Bash(apk *) Bash(export PATH=*) Bash(echo *) +--- + +**所有输出必须使用中文。** + +你负责在项目目录中创建初始文件结构,已存在的文件不覆盖。 + +## 执行步骤 + +### 步骤 0:打印当前位置流程图 + +向用户展示当前在 A 阶段流程中的位置: + +``` +┌──────────────────────────────────────────────────────┐ +│ 📋 阶段 A:规划(一次性) │ +│ │ +│ ▶ A0 初始化项目 → A1 锁范围(REQ 卡片) │ +│ ↓ │ +│ 等你审阅 REQ,重新运行 /plan-start 继续 │ +│ ↓ │ +│ A2 生成骨架 → A3 生成 DB 设计 → A4 初始化 DB → A5 生成下游文档│ +│ ↓ │ +│ 规划阶段到此结束 │ +└──────────────────────────────────────────────────────┘ +``` + +### A. 幂等复制模板文件 + +用 `Bash` 一次性完成。`cp -n` 表示"不覆盖已存在的文件": + +```bash +mkdir -p docs/01-需求清单 +cp -n "${CLAUDE_SKILL_DIR}/templates/CLAUDE-template.md" CLAUDE.md +cp -n "${CLAUDE_SKILL_DIR}/templates/docs-01-index-template.md" docs/01-需求清单/index.md +cp -n "${CLAUDE_SKILL_DIR}/templates/docs-04-stack-template.md" docs/04-技术规范.md +cp -n "${CLAUDE_SKILL_DIR}/templates/docs-08-initial-template.md" docs/08-模块任务管理.md +``` + +完成后,用 `Edit` 在 `docs/08-模块任务管理.md` 中勾选: +- ` - [ ] 项目文件骨架已创建(CLAUDE.md + docs/01-需求清单/index.md + docs/04-技术规范.md)` + +### B. 依赖检查 + 自动安装(命令行工具) + +对 **git、mysql** 两个工具依次执行以下流程。 + 1. 如果缺失,尝试自动安装。 + 2. 如果检测到不在 PATH,尝试添加进 PATH,并加载。 + +全部通过后打印单行汇总再进入步骤 C: + +``` +[project-init] 依赖检查: git ✓ mysql ✓ +``` + +完成后,用 `Edit` 在 `docs/08-模块任务管理.md` 中勾选: +- ` - [ ] 依赖检查通过` + +### C. 初始化 Git(如尚未初始化) + +用 `Glob` 检查 `.git/` 目录是否存在。 +- 不存在 → 用 `Bash` 执行 `git init`。 +- 已存在 → 跳过。 + +完成后,用 `Edit` 在 `docs/08-模块任务管理.md` 中勾选(A0 子项 + A0 顶层): +- ` - [ ] Git 已初始化` +- `- [ ] A0 项目初始化 — project-init` + +### D. 打印完成横幅并进入 A1 + +向用户输出: + +``` +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + [project-init] 项目初始化完成 + + 已创建: + ✓ CLAUDE.md(从插件模板复制) + ✓ docs/01-需求清单/index.md(待人工填写模块索引) + ✓ docs/04-技术规范.md(默认技术栈,A1 让用户确认) + ✓ docs/08-模块任务管理.md(全流程进度跟踪) + 已勾选:A0 项目初始化 + + 下一步:A1 scope-lock(填写项目概述 + 技术栈 + 需求索引 + REQ 卡片) +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +``` + +立即调用 `Skill(scope-lock)` 进入 A1,不等用户手动输入。 diff --git a/skills/plan/project-init/templates/CLAUDE-template.md b/skills/plan/project-init/templates/CLAUDE-template.md new file mode 100644 index 0000000..9c2d181 --- /dev/null +++ b/skills/plan/project-init/templates/CLAUDE-template.md @@ -0,0 +1,218 @@ +# CLAUDE.md — ERP项目 Claude Code 主指令文件 + +> 本文件是 Claude Code 的"操作手册"。Claude Code 启动时会自动读取此文件。 + +--- + +## 🎯 项目概述 + +- **项目名称**: 【人工填写:公司 + 项目名,例如"XX 公司 ERP 管理系统"】 +- **项目简述**: 【人工填写:一句话描述项目目标,例如"面向中小制造企业的全流程 ERP,涵盖采购/库存/生产/销售/财务"】 +- **目标用户**: 【人工填写:谁会用,例如"企业内部管理人员(采购员、仓管员、生产主管、销售员、财务人员、管理层)"】 +- **部署方式**: 【人工填写:私有化部署 / 云部署 / Docker 容器化 等】 + +--- + +## 🔄 B 阶段开发流程(模块循环 + 功能循环) + +两层嵌套循环**全部固化到 skills**。入口:`/erp-workflow:coding-start`。 + +- **模块循环(外)**:`module-start` → `test-gate` → `module-report` → `mr-create` → 人工 Approve MR → 下一模块 +- **功能循环(内,每 REQ-XXX-NNN 一遍)**:`feature-brainstorm` → `feature-plan` → `feature-tdd` → `feature-verify` → `feature-review` + +MR 前测试闸门: + - `test-gate`(子会话跑 `scripts/test.sh` 全量——本模块所有 REQ + 已完成模块回归); + - `.githooks/pre-push` 兜底 + - `git push --no-verify` 被 `deny-no-verify.sh` 硬拦。 + +--- + +## ✅ 模块完成判定规则 + +`docs/08-模块任务管理.md § 二` 是**模块元数据表**——每个模块记录依赖 / 路径 / MR iid / 功能(REQ)子项清单。**模块完成由 `MR:` 字段 + `GitLab API state=merged` 判定**;功能子项勾选只作可视化进度,不参与模块完成判定。 + +### 规则定义 + +每个模块在 docs/08 § 二 中长这样: + +```markdown +- module_0 系统管理 + - 依赖: — + - 路径: backend/module/sys/, frontend/pages/sys/ + - MR: — + - 功能: + - [ ] REQ-SYS-001 用户登录 + - [ ] REQ-SYS-002 用户注册 +``` + +- `MR:` 字段由 `mr-create` 在创建 MR 时从 `—` 改为 `!<iid>`。 +- 每个 `REQ-*` 子项由 `feature-review` 在 `verdict=approve` 时自动勾选为 `[x]` +- 子项全部勾选不等于模块完成,模块完成判定仍以 `MR:` + GitLab API state 为准。 + +### 模块状态语义 + +| `MR:` 字段 | `GitLab API state` | 含义 | 你(Claude Code)的行为 | +|---|---|---|---| +| `—` | — | 模块未开始(未创建 MR) | ✅ 开始本模块开发 | +| `!<iid>` | `opened` / `closed` | 模块开发中 / 打回 | ✅ 继续推进该模块 | +| `!<iid>` | `merged` | 模块**已完成** | 🟢 进入下一未完成模块 | + +### 模块完成报告 + +由 `module-report` skill 产出,模板位于 由 module-report skill 持有(12 节标准化,含跨模块改动等 CLAUDE.md 软规则映射节)。CC 不手写模块报告,仅填模板。 + +--- + +## 🏷️ 占位符统一约定 + +项目文档里有 **2 种填写占位** + **1 种提示占位**: + +| 格式 | 谁填 | 使用阶段 | 说明 | +|------|-----|---------|------| +| `【人工填写:<简短说明>】` | 人 | 仅 A 阶段文档 | 密钥 / 账密 / 包名 / 命名约定 / 小版本号等人工才能决定的值;B 阶段 plan/spec 禁止出现,查不到真值时用 `AskUserQuestion` 问用户 | +| `TBD(<责任人>)` | CC 自动 | A 或 B | 后缀附带责任方(如 `TBD(A3 自动补)` / `TBD(A5 自动补)`);由对应 skill 就地补填,`module-report` § ⑦ 检查 `TBD(CC 补)` 残留 | + +**HTML 注释 `<!-- ... -->`**:提示占位,是**插件内部大纲模板**里给 LLM 的**填空提示 / 章节引导**,指引 LLM 按结构填实际内容。skill 生成时会**剥除**这些注释,最终产物里注释不会保留。 + +--- + +## 📐 编码行为约束 + +### 你必须做的 ✅ + +1. **严格遵循** `docs/04-技术规范.md`——命名 / 编码 / 统一响应 / 异常处理 / 数据访问 / 配置与安全 等项目专属技术规约全部在此 +2. **严格遵循** `docs/09-项目目录结构.md`——文件放对位置 +3. **每个后端接口** 必须先在 `docs/05-API接口契约.md` 定义,再编码实现 +4. **每个功能可追溯到 `REQ-XXX-NNN`**——commit tag + 代码注释(如 `// REQ-SYS-001: 用户登录`)+ plan/spec 文件名均用此 tag +5. **遇到跨模块改动**(动到非当前模块的代码)——按 § 🟡 软规则 **S2** 执行(允许改,但必须留痕) +6. **遇到技术栈外组件引入**(`docs/04 § 零` 技术栈表外的框架 / 中间件 / 关键库),按 § 🟡 软规则 **S1** 执行(允许引入,但必须先 AskUserQuestion) + +### 你禁止做的 🚫 + +1. **主会话直接 `mysql -e` 跑业务 DDL**(只读查询 / 临时本地调试除外)——业务 schema 必须走 `sql/migrations/V_n__*.sql`,详见下方 Schema 演化规约 +2. **手动 Edit `docs/08 § 二` 的 `MR:` 字段**,必须要由 `mr-create` 自动回写 + +### Schema 演化规约(Flyway migration) + +1. **文件命名**:`sql/migrations/V<n>__<snake_case_desc>.sql`,例:`V5__add_user_email_unique_index.sql` +2. **版本号分配**:建文件前 `ls sql/migrations/V*.sql` 查当前最大 n,新文件 `n_max + 1` +3. **Apply 方式**:Spring Boot 启动 / 测试启动时 Flyway 自动 apply(项目必须在 `pom.xml` 声明 `flyway-core` + `flyway-mysql` 依赖)。`scripts/setup-test-db.sh` 只负责清空库,不做 apply +4. **已合并的 migration 永不修改**:发现错了写一个补救 migration(如 `V7__fix_V5_index_name.sql`),旧 `V_n.sql` +5. **临时调试 DDL**:临时在本地试字段/索引可手动 `mysql -e`,但不写 migration;下次 `setup-test-db.sh` 会 drop+create 清掉 +6. **A4 生成的 V1**:`V1__initial_schema.sql` 是 A 阶段由 `db-init` 从 `docs/03-数据库设计文档.md`(A3 正向设计的 schema SSoT)翻译生成的初始版本;后续 V2/V3/... 由 B 阶段每个 REQ 按需写入,**同时**反向同步更新 docs/03 对应表小节以保持 SSoT 一致 + +--- + +## 🗂️ Git 提交规范 + +每次提交必须遵循以下格式: + +``` +<type>(<scope>): <subject> +``` + +- `scope`: 模块名,如 `user` / `inventory` / `order` +- `subject`: 简短描述;业务类(feat / fix / test)必须带 `REQ-XXX-NNN` 后缀 + +`type` 含义: + +| type | 看到它意味着 | +|-----|-------------| +| `feat` | **新能力上线**——用户多了一个功能、接口、页面或业务规则 | +| `fix` | **修 bug**——原来行为错了,这次改对 | +| `refactor` | **重构**——外部行为不变,只改代码结构 / 命名 / 抽象 | +| `docs` | **文档改动**——只动 Markdown / 代码注释,不动实现 | +| `style` | **格式调整**——空白 / 缩进 / import 顺序,逻辑 0 变化 | +| `test` | **只动测试代码**——补用例 / 修 fixture,不碰实现 | +| `chore` | **流程维护**——构建 / 依赖 / 工具 / 证据档案 / MR 元数据等非业务动作 | + +--- + +## 🚩 中断机制 + +功能循环(每个功能 REQ-XXX 的 Brainstorm → Plan → TDD → Verify → AI 自审)默认 **静默编程**,但触发以下任何一条必须**立刻停下、记录原因、等人决策**,不得自行绕过: + +| # | 中断 | 例子 | +| - | --- | --- | +| 1 | **测试反复失败** | 同一测试同一功能内连续 **10 次**修复失败 | +| 2 | **要改密钥 / 账密 / 包名** | `docs/07-环境配置.md` 里由人工标注必须填的字段 | +| 3 | **外部接口不可达** | 第三方 API 无法连接、证书失效等环境问题,并无法自行解决 | + +> 其余需要人类判断的场景一律走普通 `AskUserQuestion` Q&A,不中断、不写 Blocker 文件。 + +**触发中断时的固定动作:** + +1. 在当前功能的 plan 文件里追加一节 `## 🚩 Blocker`(报告格式由 `interrupt-check` 的 `interrupt-block-template.md` 持有) +2. 停止后续所有功能的静默执行 +3. 在主会话输出一句话摘要 + 指向 blocker 文件的路径,等人回复 + +--- + +## 🟡 软规则(允许继续,但有强制后续动作) + +以下情况 **不触发中断**,CC 可自行继续推进,但必须在约定位置留痕,模块完成时统一审计。 + +| # | 软规则 | 允许动作 | 强制后续 | +| - | ----- | ------- | ------- | +| S1 | **技术栈外组件引入** | 用 `AskUserQuestion` 给用户三选一:接受引入 / 换方案 / 拒绝 | ① **接受** → 同会话直接在 `docs/04 § 零` 追加一行 → 继续流程 ② **换方案 / 拒绝** → 视为常规歧义澄清,继续 Q&A 收敛 ③ 不写 Blocker、不中断流程 | +| S2 | **跨模块改动** | **默认不改**,仅为当前模块实现所必需时允许修改 | ① hook `log-cross-module.sh` 自动落存根 ② `module-report` 一次性调用 `cross-module-log` skill 批量补齐「原因 / 影响评估」+ 「跨模块改动」节完整贴入《模块完成报告》 | + +--- + +## 🧭 通用工作准则(General Principles) + +### 1. Think Before Coding + +**Don't assume. Don't hide confusion. Surface tradeoffs.** + +Before implementing: +- State your assumptions explicitly. If uncertain, ask. +- If multiple interpretations exist, present them - don't pick silently. +- If a simpler approach exists, say so. Push back when warranted. +- If something is unclear, stop. Name what's confusing. Ask. + +### 2. Simplicity First + +**Minimum code that solves the problem. Nothing speculative.** + +- No features beyond what was asked. +- No abstractions for single-use code. +- No "flexibility" or "configurability" that wasn't requested. +- No error handling for impossible scenarios. +- If you write 200 lines and it could be 50, rewrite it. + +Ask yourself: "Would a senior engineer say this is overcomplicated?" If yes, simplify. + +### 3. Surgical Changes + +**Touch only what you must. Clean up only your own mess.** + +When editing existing code: +- Don't "improve" adjacent code, comments, or formatting. +- Don't refactor things that aren't broken. +- Match existing style, even if you'd do it differently. +- If you notice unrelated dead code, mention it - don't delete it. + +When your changes create orphans: +- Remove imports/variables/functions that YOUR changes made unused. +- Don't remove pre-existing dead code unless asked. + +The test: Every changed line should trace directly to the user's request. + +### 4. Goal-Driven Execution + +**Define success criteria. Loop until verified.** + +Transform tasks into verifiable goals: +- "Add validation" → "Write tests for invalid inputs, then make them pass" +- "Fix the bug" → "Write a test that reproduces it, then make it pass" +- "Refactor X" → "Ensure tests pass before and after" + +For multi-step tasks, state a brief plan: +``` +1. [Step] → verify: [check] +2. [Step] → verify: [check] +3. [Step] → verify: [check] +``` + +Strong success criteria let you loop independently. Weak criteria ("make it work") require constant clarification. diff --git a/skills/plan/project-init/templates/docs-01-index-template.md b/skills/plan/project-init/templates/docs-01-index-template.md new file mode 100644 index 0000000..16b8002 --- /dev/null +++ b/skills/plan/project-init/templates/docs-01-index-template.md @@ -0,0 +1,16 @@ +# 需求清单 + +> 本目录按模块组织所有功能需求。每个模块一个文件,由 CC 基于下方纲要扩展成 REQ-XXX-NNN 标准卡片。 + +## 模块索引 + +| 模块代码 | 模块名称 | 核心功能点(简要) | +|----------|----------|--------------------| +| 【人工填写:模块代码】 | 【人工填写:模块名称】 | 【人工填写:核心功能点】 | +| SYS | 系统管理 | 用户/角色/权限/部门/字典 等 | + +## 填写说明 + +1. 每个模块占一行,`模块代码` 用大写英文缩写(如 SYS / PUR / INV / SAL / FIN / HR) +2. `核心功能点` 只需列关键词,CC 会基于此扩展成完整 REQ 卡片 +3. 填完后运行 `/erp-workflow:plan-start`,CC 会自动检测并进入需求生成阶段 diff --git a/skills/plan/project-init/templates/docs-04-stack-template.md b/skills/plan/project-init/templates/docs-04-stack-template.md new file mode 100644 index 0000000..234b200 --- /dev/null +++ b/skills/plan/project-init/templates/docs-04-stack-template.md @@ -0,0 +1,32 @@ +# 04-技术规范 + +## 零、技术栈总览 + +| 分层模块 | 技术 | 版本要求 | 说明 | +|---|---|---|---| +| 前端基础框架 | React | 18.x | 构建前端应用 | +| 前端 UI 组件 | Ant Design | 5.x | 页面组件与交互控件 | +| 前端状态管理 | Redux Toolkit | 最新稳定版 | 管理全局状态 | +| 前端路由管理 | React Router | v6 | 页面路由与导航 | +| 前端工程化构建 | Vite | 最新稳定版 | 前端开发与打包构建 | +| 前端接口通信 | Axios | 最新稳定版 | 调用后端 API | +| 后端基础框架 | Spring Boot | 3.x | 构建后端服务 | +| 后端数据访问 | MyBatis-Plus | 最新稳定版 | 数据库访问与 ORM 增强 | +| 工作流引擎 | Activiti | 6.x | 审批流、流程流转 | +| 缓存服务 | Redis | 最新稳定版 | 缓存、会话、分布式能力 | +| 报表打印 | JXLS | 2.8.1 | 基于 Excel 模板生成报表 | +| Excel 导入导出 | EasyExcel | 4.0.3 | Excel 数据导入导出 | +| 关系型数据库 | MySQL | 8.x | 核心业务数据存储 | +| 数据库 schema 迁移 | Flyway (`flyway-core` + `flyway-mysql`) | 10.x / 最新稳定版 | `sql/migrations/V_n__*.sql` 顺序 apply;Spring Boot 启动时自动应用 | +| 接口风格 | RESTful API | 统一规范 | 前后端接口设计规范 | +| 权限认证 | Spring Security / JWT | 最新稳定版 | 登录认证、权限控制 | +| API 文档 | OpenAPI / Swagger | 最新稳定版 | 接口文档与调试 | +| 项目构建管理 | Maven | 3.9.x | Java 项目依赖与构建 | +| JDK 运行环境 | Java | 17 / 21 | Spring Boot 3 推荐版本 | +| 部署容器 | Docker | 最新稳定版 | 容器化部署 | +| Web 服务器 / 反向代理 | Nginx | 最新稳定版 | 前端托管、反向代理、负载分发 | +| 日志管理 | Logback | 默认集成 / 最新稳定版 | 应用日志输出 | +| 对象映射工具 | MapStruct | 最新稳定版 | DTO / VO / Entity 转换 | +| 工具类库 | Hutool / Apache Commons | 最新稳定版 | 常用工具方法支持 | + +> 本表由 scope-lock 锁定。后续所有规范基于此表推导。 diff --git a/skills/plan/project-init/templates/docs-08-initial-template.md b/skills/plan/project-init/templates/docs-08-initial-template.md new file mode 100644 index 0000000..67a74fb --- /dev/null +++ b/skills/plan/project-init/templates/docs-08-initial-template.md @@ -0,0 +1,57 @@ +# 08-工作流进度 + +> 全流程进度跟踪。CC 每完成一项产出就勾选一项。 +> - **§ 一 Plan(A0~A5)**:`plan-start` 找第一个未勾 A 子项分发到对应 skill +> - **§ 二 Coding(模块)**:分发以 `docs/02-开发计划.md § 二 开发顺序清单` 为准;`coding-start` 按 docs/02 顺序扫描,对每个 REQ 所属模块查询本 § 二的 `MR:` 字段 + GitLab API `state`,找第一个非 merged 模块分发。本 § 二 行序无语义,仅作模块元数据表 + +## 一、Plan 阶段(一次性) + +- [ ] A0 项目初始化 — project-init + - [ ] 依赖检查通过 + - [ ] 项目文件骨架已创建(CLAUDE.md + docs/01-需求清单/index.md + docs/04-技术规范.md) + - [ ] Git 已初始化 + +- [ ] A1 范围锁定 — scope-lock + - [ ] 项目概述已填写(CLAUDE.md § 🎯 项目概述) + - [ ] 技术栈已确认(docs/04 § 零) + - [ ] 需求清单索引已填写(docs/01-需求清单/index.md) + - [ ] REQ 卡片已生成(docs/01-需求清单/*.md,schema/api 字段标记为 TBD) + +- [ ] A2 骨架生成 — skeleton-gen + - [ ] 架构文档已生成(docs/04 § 一+、docs/06、docs/07、docs/09) + - [ ] 工具脚本已生成(scripts/*.sh、.githooks/pre-push、.env.local) + - [ ] .gitignore 已配置 + +- [ ] A3 DB 设计 + REQ 回填 — db-design-gen + - [ ] docs/03-数据库设计文档.md 已生成 + - [ ] docs/01 各 REQ 卡片"涉及数据表"已回填 + - [ ] 用户已审阅 docs/03 表结构 + +- [ ] A4 DB 初始化 — db-init + - [ ] sql/migrations/V1__initial_schema.sql 已生成 + - [ ] DDL 与 docs/03 全量一致(5 维度校验通过) + - [ ] .env.local 凭据已验证(mysql -e "SELECT 1" OK) + - [ ] setup-test-db.sh 防护通过 + DROP+CREATE + apply V1 已执行 + - [ ] SHOW TABLES 行数 == docs/03 表数量 + +- [ ] A5 下游文档生成 — downstream-gen + - [ ] docs/02 开发计划已生成 + - [ ] docs/05 API 契约已生成 + - [ ] docs/06 § 五 页面清单已填入 + - [ ] docs/10 验收清单已生成 + - [ ] 下方模块列表已填入 + - [ ] REQ 卡片依赖接口已回填 + +## 二、Coding 阶段(按模块循环) + +(A5 填入后,每行一个模块。每个模块的 `MR:` 字段在 `—` 和 `!<iid>` 之间变化,完成由 GitLab API `state=merged` 判定。`coding-start` 每次按 docs/02 REQ 序扫每模块的 MR state 决定派发。) + +<!-- 模块格式示例(由 A5 downstream-gen 追加;功能子项由 feature-review 在 approve 时勾选): +- module_0 系统管理 + - 依赖: — + - 路径: backend/module/sys/, frontend/pages/sys/ + - MR: — + - 功能: + - [ ] REQ-SYS-001 用户登录 + - [ ] REQ-SYS-002 用户注册 +--> diff --git a/skills/plan/scope-lock/SKILL.md b/skills/plan/scope-lock/SKILL.md new file mode 100644 index 0000000..dab2ecd --- /dev/null +++ b/skills/plan/scope-lock/SKILL.md @@ -0,0 +1,157 @@ +--- +name: scope-lock +description: A1 计划范围锁定——引导用户填写项目概述 + 技术栈 + 需求索引,并自动扩展 REQ 卡片待人工评审(依赖表 / 依赖接口两字段由模板写死 `TBD(...)` 占位,A3/A5 后续回填)。 +user-invocable: false +allowed-tools: Read Write Edit Grep Skill AskUserQuestion +--- + +**所有输出必须使用中文。** + +# scope-lock + +## 执行步骤 + +### 步骤 0:打印当前位置流程图 + +向用户展示当前在 A 阶段流程中的位置: + +``` +┌──────────────────────────────────────────────────────┐ +│ 📋 阶段 A:规划(一次性) │ +│ │ +│ A0 初始化项目 → ▶ A1 锁范围(REQ 卡片) │ +│ ↓ │ +│ ⏸ 等你审阅 REQ,重新运行 /plan-start 继续 │ +│ ↓ │ +│ A2 生成骨架 → A3 生成 DB 设计 → A4 初始化 DB → A5 生成下游文档│ +│ ↓ │ +│ 规划阶段到此结束 │ +└──────────────────────────────────────────────────────┘ +``` + +### A. 提示用户填写项目概述并等待 + +向用户输出: + +``` +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + [scope-lock] 请填写项目概述 + + 📄 文件位置: ./CLAUDE.md + 📌 编辑位置: § 🎯 项目概述 + + 请将以下占位符替换为实际值: + - 项目名称 + - 项目简述 + - 目标用户 + - 部署方式 + 改完后回来选择「继续」。 +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +``` + +用 `AskUserQuestion` 询问: +- **question**: `项目概述填写完毕了吗?` + - 用户选择「继续」→ 用 `Grep` 在 `CLAUDE.md` 搜索 `【人工填写:`(限定 § 🎯 项目概述 节)。命中 → 打印残留行 + 路径,重新弹出同样的 AskUserQuestion;0 命中 → 勾选并进入步骤 B。 + - 用户选择「有疑问想先沟通」→ 回答用户问题后,再次弹出同样的 QA。 + +0 命中后,用 `Edit` 在 `docs/08-模块任务管理.md` 中勾选: +- ` - [ ] 项目概述已填写(CLAUDE.md § 🎯 项目概述)` + +### B. 提示用户检查默认技术栈并等待 + +`docs/04-技术规范.md` 已由 A0 `project-init` 用模板复制(默认技术栈,见 `project-init/templates/docs-04-stack-template.md`)。本步骤让用户检查 / 调整 § 零。 + +向用户输出: + +``` +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + [scope-lock] 技术栈已保存 + + 📄 文件位置: ./docs/04-技术规范.md(由 A0 模板生成) + 📌 编辑位置: § 零、技术栈总览 + + 请检查技术栈表: + - 不需要的行直接删除(如纯后端项目删前端行) + - 需要替换的技术直接改 + - 需要新增的条目直接加行 + 改完后回来选择「继续」。 +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +``` + +用 `AskUserQuestion` 询问: +- **question**: `技术栈检查完毕了吗?` + - 用户选择「继续」→ 进入步骤 C。 + - 用户选择「有疑问想先沟通」→ 回答用户问题后,再次弹出同样的 QA。 + +完成后,用 `Edit` 在 `docs/08-模块任务管理.md` 中勾选: +- ` - [ ] 技术栈已确认(docs/04 § 零)` + +### C. 提示用户填写需求清单并等待 + +`docs/01-需求清单/index.md` 已由 `project-init` 写入占位符模板,这里让用户补齐模块清单。 + +向用户输出: + +``` +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + [scope-lock] 请填写需求清单模块索引 + + 📄 文件位置: ./docs/01-需求清单/index.md + 📌 编辑位置: § 模块索引(表格) + + 请按业务列出所有模块: + - 每行一个模块(如 SYS 系统管理 / PUR 采购 / SAL 销售) + - 「核心功能点」只需关键词,CC 会扩展为完整 REQ 卡片 + 改完后回来选择「继续」。 +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +``` + +用 `AskUserQuestion` 询问: +- **question**: `需求清单模块索引填写完毕了吗?` + - 用户选择「继续」→ 进入步骤 D。 + - 用户选择「有疑问想先沟通」→ 回答用户问题后,再次弹出同样的 QA。 + +完成后,用 `Edit` 在 `docs/08-模块任务管理.md` 中勾选: +- ` - [ ] 需求清单索引已填写(docs/01-需求清单/index.md)` + +### D. 生成 REQ 卡片并停下等人工审阅 + +1. 用 `Grep` 校验 `docs/01-需求清单/index.md` 无 `【人工填写:` 残留;有则回步骤 C。 +2. 用 `Read` 读 `index.md` 解析模块索引。 +3. 对每个模块: + - 基于「核心功能点」扩展若干 REQ-XXX-NNN 卡片 + - 用 `${CLAUDE_SKILL_DIR}/templates/req-card-template.md` 渲染每张(渲染约定见模板顶部 HTML 注释)。 + - 用 `${CLAUDE_SKILL_DIR}/templates/docs-01-module-template.md` 包装卡片列表,用 `Write` 写入 `docs/01-需求清单/<module_code>-<module_name>.md`。 +4. 用 `Edit` 在 `docs/08-模块任务管理.md` 勾选(A1 子项 + A1 顶层): + - ` - [ ] REQ 卡片已生成(docs/01-需求清单/*.md,schema/api 字段标记为 TBD)` + - `- [ ] A1 范围锁定 — scope-lock` +5. 打印停下横幅并**停止**: + +``` +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + [scope-lock] ✅ A1 范围锁定完成 + + 产出: + ✓ CLAUDE.md § 🎯 项目概述 + ✓ docs/04 § 零 技术栈 + ✓ docs/01-需求清单/index.md 模块索引 + ✓ docs/01-需求清单/<module>-*.md REQ 卡片 + + ⏸ 现在请你审阅每张 REQ 卡片(路径:`docs/01-需求清单/<module_code>-<module_name>.md`) + + 审阅是 Plan 阶段的关键人工关口,请认真逐张过一遍。 + 审阅完成后,运行以下命令继续进入 A2: + /erp-workflow:plan-start + + (入口会读取 docs/08 进度,自动派发到 A2 skeleton-gen) +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +``` + +## 参考 + +- `CLAUDE.md` § 🎯 项目概述(写入目标) +- `docs/04-技术规范.md`(技术栈输出,供 skeleton-gen 读取使用) +- `docs/01-需求清单/index.md`(模块索引输入) +- `docs/01-需求清单/<module>-*.md`(REQ 卡片输出,A3 db-design-gen 会回填 TBD 字段) +- `${CLAUDE_SKILL_DIR}/templates/req-card-template.md` +- `${CLAUDE_SKILL_DIR}/templates/docs-01-module-template.md` diff --git a/skills/plan/scope-lock/templates/docs-01-module-template.md b/skills/plan/scope-lock/templates/docs-01-module-template.md new file mode 100644 index 0000000..97966d7 --- /dev/null +++ b/skills/plan/scope-lock/templates/docs-01-module-template.md @@ -0,0 +1,11 @@ +# {{module_code}}-{{module_name}} + +模块简述: {{module_brief}} +依赖模块: TBD(A5 自动补) +涉及表: TBD(A3 自动补) + +## 功能清单 + +{{#each reqs}} +{{req_card}} +{{/each}} diff --git a/skills/plan/scope-lock/templates/req-card-template.md b/skills/plan/scope-lock/templates/req-card-template.md new file mode 100644 index 0000000..45239aa --- /dev/null +++ b/skills/plan/scope-lock/templates/req-card-template.md @@ -0,0 +1,29 @@ +<!-- +req-card-template:单张 REQ 卡片结构(三段式)。 +1) 标题 + 目标引言:`### {{req_id}} {{title}}` + 一行 `**目标**: {{goal}}` +2) 字段表(7 列 × N 行):UI 字段 / API 参数的结构化清单 + - 是多行块占位,每个字段一行,LLM 根据本 REQ 实际字段数**复制该行 N 次**,每行填实际值 + - `{{field_rules}}` 是**字段级**规则(例:"13 位数字"、"至少 1 个"、"员工名选择后显示");多条用 `;` 分割 + - `{{source}}` 若来自 DB 表用反引号包裹(如 `` `职员表` ``) + - 若本 REQ 无表单字段(纯后台任务),schema 行填占位:`| — | — | — | — | — | — | 无表单输入 |` +3) REQ 级元数据(bullet list): + - `**跨字段规则**: {{rules}}` = **REQ 级** 跨字段 / 业务流程规则,与字段表 `{{field_rules}}` 区分 + - `TBD(A3 自动补)` 由 A3 `db-design-gen` 回填 + - `TBD(A5 自动补)` 由 A5 `downstream-gen` 回填 + - REQ 级槽位由 LLM 基于功能点推断。 +渲染时 scope-lock skill 会**剥掉本 HTML 注释**,最终 REQ 卡片不保留。 +--> +### {{req_id}} {{title}} + +**目标**: {{goal}} + +| 字段 | 类型 | 必填 | 输入方式 | 显示来源 | 默认值 | 业务规则 | +|---|---|---|---|---|---|---| +| {{field}} | {{type}} | {{required}} | {{input_method}} | {{source}} | {{default}} | {{field_rules}} | + +- **输出**: {{output}} +- **跨字段规则**: {{rules}} +- **边界**: {{constraints}} +- **验收**: {{acceptance}} +- **依赖表**: TBD(A3 自动补) +- **依赖接口**: TBD(A5 自动补) diff --git a/skills/plan/skeleton-gen/SKILL.md b/skills/plan/skeleton-gen/SKILL.md new file mode 100644 index 0000000..a11eded --- /dev/null +++ b/skills/plan/skeleton-gen/SKILL.md @@ -0,0 +1,166 @@ +--- +name: skeleton-gen +description: A2 骨架生成——基于 docs/04 § 零 技术栈 + docs/01-需求清单/index.md 模块索引,生成项目专属的架构文档(docs/04 § 一+、docs/06、docs/07、docs/09)和工具脚本。固定工具文件走 cp,架构文档由 LLM 按大纲生成。 +user-invocable: false +allowed-tools: Read Write Edit Skill Grep Glob AskUserQuestion Bash(mkdir *) Bash(cp *) Bash(touch *) Bash(chmod *) Bash(git config *) Bash(cat *) Bash(bash *) +--- + +**所有输出必须使用中文。** + +# skeleton-gen + +## 执行步骤 + +### 步骤 0:打印当前位置流程图 + +向用户展示当前在 A 阶段流程中的位置: + +``` +┌──────────────────────────────────────────────────────┐ +│ 📋 阶段 A:规划(一次性) │ +│ │ +│ A0 初始化项目 → A1 锁范围(REQ 卡片) │ +│ ↓ │ +│ ⏸ 等你审阅 REQ,重新运行 /plan-start 继续 │ +│ ↓ │ +│ ▶ A2 生成骨架 → A3 生成 DB 设计 → A4 初始化 DB → A5 生成下游文档│ +│ ↓ │ +│ 规划阶段到此结束 │ +└──────────────────────────────────────────────────────┘ +``` + +### A. 读取锁定的输入 + +用 `Read` 读取: +- `docs/04-技术规范.md` § 零 技术栈表 +- `docs/01-需求清单/index.md` 需求索引 +- `docs/01-需求清单/` 需求卡片 + +后续所有内容都基于它们推导。 + +### B.1 生成 3 个全新架构文档(docs/06 / 07 / 09) + +对下表每个目标文件: +1. 读取对应的大纲模板 +2. 基于步骤 A 的输入,按大纲生成项目专属内容 +3. 剥掉 HTML 注释(注释是给 LLM 的提示,不应出现在最终文档里) +4. 写入目标路径 + +| 目标文件 | 大纲模板 | +|---|---| +| `docs/06-UI交互规范.md`(§ 一 ~ 四,§ 五 占位) | `${CLAUDE_SKILL_DIR}/templates/docs-06-static-template.md` | +| `docs/07-环境配置.md` | `${CLAUDE_SKILL_DIR}/templates/docs-07-env-template.md` | +| `docs/09-项目目录结构.md` | `${CLAUDE_SKILL_DIR}/templates/docs-09-structure-template.md` | + +项目专属标识(根包名 / 命名空间)保留 `【人工填写:<说明>】` 占位,等人工在 docs/09 顶部补填一次后,其他文件复用。 + +### B.2 追加 docs/04 § 一+(保留 § 零 不覆盖) + +docs/04 已由 scope-lock 写入 § 零。本步骤追加 § 一 ~ 三。 + +1. 读取 `docs/04-技术规范.md`(现有 § 零 完整内容)。 +2. 读取 `${CLAUDE_SKILL_DIR}/templates/docs-04-skeleton-template.md`。 +3. 基于技术栈,按大纲生成 § 一 ~ 三 的项目专属内容,剥掉 HTML 注释。 +4. 拼接原有内容和新生成内容,写回 `docs/04-技术规范.md`。 + +完成后,用 `Edit` 在 `docs/08-模块任务管理.md` 中勾选: +- ` - [ ] 架构文档已生成(docs/04 § 一+、docs/06、docs/07、docs/09)` + +### C. 生成工具脚本 + +#### C.1 复制 + +```bash +mkdir -p scripts .githooks sql/migrations +touch sql/migrations/.gitkeep +cp "${CLAUDE_SKILL_DIR}/templates/env-local-template" .env.local +cp "${CLAUDE_SKILL_DIR}/templates/githooks-pre-push-template.sh" .githooks/pre-push +cp "${CLAUDE_SKILL_DIR}/templates/scripts-setup-test-db-template.sh" scripts/setup-test-db.sh +``` + +#### C.2 渲染 scripts/test.sh + +读取 `${CLAUDE_SKILL_DIR}/templates/scripts-test-template.sh`,基于步骤 A 的技术栈(docs/04)推断命令后写到 `scripts/test.sh`: + +- `{{build_cmd}}` 构建 +- `{{lint_cmd}}` lint +- `{{test_cmd}}` unit + integration +- `{{e2e_cmd}}` E2E(无 E2E 则填 `echo "[test.sh] e2e 略"`) + +> 双端项目(backend + frontend)用 `(cd backend && <cmd>) && (cd frontend && <cmd>)` 串联;单端直接写一条。 + +#### C.3 赋权 + 配置 git hooks + +```bash +chmod +x scripts/*.sh .githooks/pre-push +git config core.hooksPath .githooks +``` + +完成后,用 `Edit` 在 `docs/08-模块任务管理.md` 中勾选: +- ` - [ ] 工具脚本已生成(scripts/*.sh、.githooks/pre-push、.env.local)` + +### D. 追加 .gitignore 忽略项 + +调用脚本完成合并: + +```bash +bash "${CLAUDE_SKILL_DIR}/scripts/merge-gitignore.sh" "${CLAUDE_SKILL_DIR}/templates/gitignore-append-template" +``` + +完成后,用 `Edit` 在 `docs/08-模块任务管理.md` 中勾选: +- ` - [ ] .gitignore 已配置` + +### E. 占位符补填 + QA 闸门 + +#### E.1 扫描 + 分组 + +用 `Grep` 在以下 8 个路径扫 `【人工填写:`,记录命中(文件 / 行号 / 说明): +- `docs/04-技术规范.md` / `docs/06-UI交互规范.md` / `docs/07-环境配置.md` / `docs/09-项目目录结构.md` +- `scripts/*.sh` / `.githooks/pre-push` / `.gitignore` +- `.env.local` + +分两组: +- **敏感组**:`.env.local` 路径命中(凭据 / 密钥)。**不弹 QA**(凭据不进会话),E.3 提示用户自填。 +- **非敏感组**:其余文件。按说明文字聚合为「根占位」(相同说明 = 同一值,多处共用)或「派生占位」(说明表达派生关系,如"后端 java 根包路径"派生自"根包名")。 + +无命中 → 跳 E.4。 + +#### E.2 问根占位 + 推派生 + 批量 Edit + +- 每个根占位用 `AskUserQuestion` 问(给合理默认值 + 自由输入),用 `Edit` 批量替换所有命中位置 +- 派生占位**不问**,CC 基于根占位值推断后 `Edit`;不能可靠推断则回退当独立根占位问 + +#### E.3 敏感占位提示(不弹 QA) + +若敏感组非空:打印提示横幅,列出 `.env.local` 待填字段名 + 告诉用户"直接编辑文件,凭据不进会话"。 + +#### E.4 验证 + QA 闸门 + +循环直到两条件**同时**满足: +(a) `Grep` 重新扫 8 路径,0 命中 +(b) 用户 `AskUserQuestion` 选「继续」 + +每次弹 QA 前重扫;有残留则打印残留位置清单(文件:行号 — 说明)+ 再弹 QA。 + +QA 横幅涵盖:产出文件清单(docs/04 / 06 / 07 / 09 + scripts/*.sh + .githooks/pre-push + .env.local + .gitignore)、占位状态(N=0 或待填清单)、「继续」/「有疑问先沟通」两选项。 + +通过后(N=0 且用户选「继续」),用 `Edit` 在 `docs/08-模块任务管理.md` 中勾选: +- `- [ ] A2 骨架生成 — skeleton-gen` + +### F. 进入 A3 + +输出 `skeleton-gen: 完成`,立即调用 `Skill(db-design-gen)`。 + +## 参考 + +- `docs/04-技术规范.md` § 零(技术栈输入) +- `docs/01-需求清单/index.md`(模块索引输入) +- `${CLAUDE_SKILL_DIR}/templates/docs-04-skeleton-template.md`(大纲) +- `${CLAUDE_SKILL_DIR}/templates/docs-06-static-template.md`(大纲) +- `${CLAUDE_SKILL_DIR}/templates/docs-07-env-template.md`(大纲) +- `${CLAUDE_SKILL_DIR}/templates/docs-09-structure-template.md`(大纲) +- `${CLAUDE_SKILL_DIR}/templates/scripts-setup-test-db-template.sh`(0 槽位) +- `${CLAUDE_SKILL_DIR}/templates/githooks-pre-push-template.sh`(0 槽位) +- `${CLAUDE_SKILL_DIR}/templates/env-local-template`(0 槽位) +- `${CLAUDE_SKILL_DIR}/templates/gitignore-append-template`(0 槽位) +- `${CLAUDE_SKILL_DIR}/scripts/merge-gitignore.sh`(.gitignore 逐行判重合并脚本) diff --git a/skills/plan/skeleton-gen/scripts/merge-gitignore.sh b/skills/plan/skeleton-gen/scripts/merge-gitignore.sh new file mode 100755 index 0000000..cfff18c --- /dev/null +++ b/skills/plan/skeleton-gen/scripts/merge-gitignore.sh @@ -0,0 +1,39 @@ +#!/usr/bin/env bash +# merge-gitignore.sh +# 把模板里的忽略规则合并到项目根的 .gitignore: +# - 若 .gitignore 不存在 → 直接 cp 模板(含注释头和结构) +# - 若已存在 → 逐行判重,只追加模板里缺失的规则行(跳过注释/空行) +# +# 用法:merge-gitignore.sh <template_path> [<target_gitignore_path>] +# template_path 模板文件绝对路径(由 skeleton-gen skill 传入) +# target_gitignore_path 目标 .gitignore 路径,默认为当前工作目录下的 .gitignore +# +# 判重:grep -xF 整行精确匹配 + 字面字符串(非正则),避免 .env 误匹配 .env.local, +# 也避免 *.class / *.iml 等通配符被当作 regex。 + +set -euo pipefail + +template="${1:?usage: merge-gitignore.sh <template_path> [<target_gitignore_path>]}" +target="${2:-.gitignore}" + +if [ ! -f "$template" ]; then + echo "[merge-gitignore] ERROR: template not found: $template" >&2 + exit 1 +fi + +if [ ! -f "$target" ]; then + cp "$template" "$target" + echo "[merge-gitignore] created $target from template" + exit 0 +fi + +added=0 +while IFS= read -r line; do + case "$line" in ""|"#"*) continue ;; esac + if ! grep -qxF "$line" "$target"; then + echo "$line" >> "$target" + added=$((added + 1)) + fi +done < "$template" + +echo "[merge-gitignore] $target updated (+$added rules)" diff --git a/skills/plan/skeleton-gen/templates/docs-04-skeleton-template.md b/skills/plan/skeleton-gen/templates/docs-04-skeleton-template.md new file mode 100644 index 0000000..0284285 --- /dev/null +++ b/skills/plan/skeleton-gen/templates/docs-04-skeleton-template.md @@ -0,0 +1,57 @@ +<!-- +本文件是 docs/04-技术规范.md 的 § 一+ 大纲。 +skeleton-gen 读取 docs/04 § 零(技术栈表)和 docs/01-需求清单/index.md(模块索引), +按下述大纲生成本项目专属的规范内容。LLM 不要原样拷贝提示文字,只保留 section 标题。 +--> + +## 一、后端规范 + +### 1.1 分层结构 +<!-- 按 § 零 的后端框架定层次:controller/service/mapper 等;每层职责一句话。 --> + +### 1.2 命名约定 +<!-- 包名(根包用【人工填写:根包名】占位)/ 类名 / 方法名 / 常量的大小写规则,含 2 个示例。 --> + +### 1.3 统一响应格式 +<!-- 成功/失败的 JSON 结构,错误码段位划分。 --> + +### 1.4 异常处理 +<!-- 全局异常处理器的使用方式;哪些异常要 catch,哪些禁止;**接口响应禁止回显后端异常堆栈**(返用户友好错误码 + 文案)。 --> + +### 1.5 事务 +<!-- 事务边界(通常 service 层);跨服务调用的禁止/替代方案。 --> + +### 1.6 认证 +<!-- 基于 § 零 认证方案推导:token 生命周期、刷新机制、密钥管理。 --> + +## 二、前端规范 + +### 2.1 目录约定 +<!-- 基于 § 零 前端框架推导:api/components/pages/store/hooks/utils 的职责;**前端禁止直接写 SQL / 操作 DB**,所有数据访问走 api/ 层统一封装。 --> + +### 2.2 状态管理 +<!-- 基于 § 零 状态管理技术推导:全局 vs 局部、服务端数据的存放。 --> + +### 2.3 请求封装 +<!-- HTTP 客户端的拦截器、超时、错误重试、鉴权注入。 --> + +### 2.4 错误处理 +<!-- 网络错误 / 业务错误 / 页面级错误的分层处理。 --> + +## 三、共同约定 + +### 3.1 Git 提交 +`<type>(<scope>): <subject> REQ-XXX-NNN` + +### 3.2 分页查询 +<!-- 后端分页对象 + 前端分页组件,入参出参约定。 --> + +### 3.3 日期与金额 +<!-- 后端类型(如 LocalDateTime / BigDecimal)+ 前端展示工具;金额精度约定。 --> + +### 3.4 数据访问规约 +<!-- 基于 § 零 数据访问技术(MyBatis-Plus / JPA 等):SELECT 字段显式列举,**禁止 `SELECT *`**;循环中不得执行 DB 查询(**N+1 反模式**),改用批量查 / IN 子句 / JOIN;Mapper XML 里字段与表名用常量或引用,避免拼字符串。 --> + +### 3.5 配置与安全 +<!-- 配置:DB 连接 / 端口 / 密钥 / 第三方 URL 等一律放 `application.yml` + `.env.local`,代码里**禁止硬编码**。 + 前端安全:`localStorage` 不存敏感信息(token / 身份 / 个人数据),推荐 HttpOnly Cookie 或 内存 + 刷新 token 模式;接口响应禁止回显后端异常堆栈(与 § 1.4 一致)。 --> diff --git a/skills/plan/skeleton-gen/templates/docs-06-static-template.md b/skills/plan/skeleton-gen/templates/docs-06-static-template.md new file mode 100644 index 0000000..ed1baf3 --- /dev/null +++ b/skills/plan/skeleton-gen/templates/docs-06-static-template.md @@ -0,0 +1,47 @@ +<!-- +本文件是 docs/06-UI交互规范.md 的 § 一~四 大纲(§ 五由 downstream-gen 追加)。 +skeleton-gen 读取 docs/04 § 零 和 docs/01 index,按下述大纲生成项目专属内容。 +UI 细节(布局参数、颜色、组件选型)来自 § 零 前端 UI 组件库。 +--> + +# 06-UI交互规范 + +## 一、整体布局 + +### 1.1 页面框架 +<!-- 基于 § 零 UI 组件库(如 Ant Design Layout)描述整体骨架:Header / Sider / Content。 --> + +### 1.2 布局参数 +<!-- 表格形式:Header 高度 / Sidebar 宽度 / 内边距 / 最小分辨率,给出默认值。 --> + +## 二、标准页面类型 +<!-- 根据 docs/01 index 的模块索引推断业务可能出现的页面类型(通常列表/表单/详情/树形 4 类,根据项目裁剪)。 --> + +### 2.1 列表页 +<!-- 顶部操作区 + 搜索栏 + 表格 + 分页,关键组件选型。 --> + +### 2.2 表单页 +<!-- Drawer 还是独立页;校验时机;提交按钮位置。 --> + +### 2.3 详情页 +<!-- Descriptions + Tabs 的组合方式。 --> + +### 2.4 树形管理页 +<!-- 如项目有组织架构/权限树/分类树才生成此节,否则删除。 --> + +## 三、通用交互规则 + +### 3.1 操作反馈 +<!-- 成功/失败消息;危险操作二次确认;长耗时按钮 loading 态。 --> + +### 3.2 数据展示 +<!-- 空状态 / 加载 / 异常 的统一组件与文案。 --> + +### 3.3 权限控制(前端) +<!-- 菜单级 / 按钮级 / 路由级的控制方式,关联后端 RBAC。 --> + +## 四、主题与颜色 +<!-- 基于 § 零 UI 库的主题 token;主色 / 成功 / 警告 / 错误 色值。 --> + +## 五、页面清单(CC 生成) +(由 `downstream-gen` 按模块追加段落) diff --git a/skills/plan/skeleton-gen/templates/docs-07-env-template.md b/skills/plan/skeleton-gen/templates/docs-07-env-template.md new file mode 100644 index 0000000..9613d3f --- /dev/null +++ b/skills/plan/skeleton-gen/templates/docs-07-env-template.md @@ -0,0 +1,26 @@ +<!-- +本文件是 docs/07-环境配置.md 的大纲。 +skeleton-gen 基于 docs/04 § 零 技术栈表推导各节内容: + § 一 依赖清单 → 从技术栈的每一行技术推导运行时和构建依赖 + § 二 端口约定 → 从后端/前端/数据库/缓存/反向代理 各取默认端口 + § 四 常用命令 → 基于构建工具、包管理器、MR 工具给出开发者最常用命令 +--> + +# 07-环境配置 + +## 一、依赖清单 + +<!-- 表格:| 层 | 依赖 | 版本 | 说明 |;覆盖 运行时 / 构建 / 容器 / CLI 工具。 --> + +## 二、端口约定 + +<!-- 表格:| 服务 | 端口 | 说明 |;至少列 后端 HTTP / 前端 dev / 数据库 / 缓存 / 反代。 --> + +## 三、环境变量 + +运行时凭据(数据库连接、JWT 密钥等)全部放在仓库根的 `.env.local`,不入 git。 +字段清单与占位符见该文件,真实值由开发者本地填写。 + +## 四、常用命令 + +<!-- 表格:| 命令 | 说明 |;包含 启动后端 / 启动前端 / 打包 / 运行测试 / 重置测试数据 / 创建 MR。 --> diff --git a/skills/plan/skeleton-gen/templates/docs-09-structure-template.md b/skills/plan/skeleton-gen/templates/docs-09-structure-template.md new file mode 100644 index 0000000..1c60393 --- /dev/null +++ b/skills/plan/skeleton-gen/templates/docs-09-structure-template.md @@ -0,0 +1,45 @@ +<!-- +本文件是 docs/09-项目目录结构.md 的大纲。 +skeleton-gen 基于 docs/04 § 零 技术栈推导目录树: + § 二 后端目录 → 按后端框架的惯例(如 Spring Boot 的 src/main/java) + § 三 前端目录 → 按前端框架的惯例(如 Vite + React 的 src/) + § 四 docs 目录 → 沿用插件标准 + § 五 命名约定 → 按后端语言的包/命名空间习惯 + +模块划分参考 docs/01-需求清单/index.md 的模块索引,将业务模块落到代码目录。 +--> + +# 09-项目目录结构 + +## 一、仓库顶层 + +<!-- 用代码块画出顶层目录树,含 CLAUDE.md / README.md / .env.local / .githooks / scripts / docs / sql / backend / frontend 等。 --> + +## 二、后端目录 + +<!-- 基于后端框架的目录树;按 docs/01 index 的模块代码把业务模块列出(module/user/、module/order/ 等)。 --> + +## 三、前端目录 + +<!-- 基于前端框架的目录树;pages/ 下按业务模块建子目录。 --> + +## 四、docs/ 结构 + +``` +docs/ +├── 01-需求清单/ # REQ 卡片按模块分文件 +├── 02-开发计划.md +├── 03-数据库设计文档.md +├── 04-技术规范.md +├── 05-API接口契约.md +├── 06-UI交互规范.md +├── 07-环境配置.md +├── 08-模块任务管理.md +├── 09-项目目录结构.md +├── 10-验收检查清单.md +└── superpowers/ # CC 运行时产物 +``` + +## 五、命名与放置约定 + +<!-- 根包 / 命名空间用【人工填写:】占位;Controller / Service / Mapper / DTO / VO / 前端组件 / 前端页面 的放置规则。 --> diff --git a/skills/plan/skeleton-gen/templates/env-local-template b/skills/plan/skeleton-gen/templates/env-local-template new file mode 100644 index 0000000..7e2505f --- /dev/null +++ b/skills/plan/skeleton-gen/templates/env-local-template @@ -0,0 +1,36 @@ +# .env.local — 本地开发凭据(入 .gitignore,不提交) +# +# 规则: +# 1. 值含 `$`、反引号、空格、`!` 等 shell 特殊字符时,必须用单引号包裹: +# DB_PASSWORD='p@ss$w0rd!' +# 否则 `set -a; . .env.local; set +a` 会做变量展开导致密码错乱。 +# 2. DB_HOST 建议保持 localhost / 127.0.0.1;非本地 host 默认会被 scripts/setup-test-db.sh 防护拒绝。 +# 若必须用远程测试库,把 host 列入下方 TEST_DB_ALLOWED_HOSTS。 +# 3. DB_SCHEMA 建议命名含 test / _dev / _local / _ci,避免与生产库同名。 + +DB_HOST=【人工填写:MySQL host,推荐 localhost】 +DB_PORT=【人工填写:MySQL port,默认 3306】 +DB_USER=【人工填写:开发账号名】 +DB_PASSWORD=【人工填写:对应密码,含特殊字符时用单引号包裹】 +DB_SCHEMA=【人工填写:schema 名,推荐含 test/_dev/_local,例如 erp_dev】 +JWT_SECRET=【人工填写:JWT 签名密钥,256+ bit 随机串】 + +# 可选:额外允许 DROP CREATE 的远程 host(空格或逗号分隔)。仅当 DB_HOST 指向公司测试 MySQL 等 +# 非本地服务器时填写;留空表示只允许 localhost / 127.0.0.1 / ::1。 +# 示例:TEST_DB_ALLOWED_HOSTS="118.178.19.35 test-mysql.internal" +# +# ⚠️ 列入后该 host 每次 test.sh 都会被 DROP CREATE(无二次确认)。 +# 仅用于你完全可控的测试库;生产/共享库/多人共享的 staging 库**千万别列**。 +# (防护 2 还会检查 schema 名须含 test/_dev/_local/_ci,独立兜底。) +TEST_DB_ALLOWED_HOSTS= + +# GitLab REST API 接入(mr-create / coding-start / module-start 用 curl 调用,无需 glab CLI): +# - GITLAB_API_URL:GitLab API base。本项目服务器用 v3。A5 `downstream-gen` 从 `git remote get-url origin` +# 自动派生为 `<scheme>://<host>/api/v3`;如派生的 scheme 错(例如远程是 ssh 但实际 web 走 https),手动改掉即可 +# - GITLAB_TOKEN:GitLab v3 的 **Private Token**(用户 Profile → Account → Private token 生成;HTTP 调用仍用 +# `PRIVATE-TOKEN` 头。v3 token 是全权限、无细粒度 scope)。**无法派生,必须人工填** +# - GITLAB_PROJECT_ID:A5 从 origin 远程路径自动派生为 URL-encoded 形式(如 `zhuzc/test` → `zhuzc%2Ftest`); +# 也可手动改成项目数字 ID(GitLab 项目设置页可见) +GITLAB_API_URL=TBD(A5 自动补) +GITLAB_TOKEN=【人工填写:GitLab Private Token(Profile → Account → Private token)】 +GITLAB_PROJECT_ID=TBD(A5 自动补) diff --git a/skills/plan/skeleton-gen/templates/githooks-pre-push-template.sh b/skills/plan/skeleton-gen/templates/githooks-pre-push-template.sh new file mode 100644 index 0000000..8289050 --- /dev/null +++ b/skills/plan/skeleton-gen/templates/githooks-pre-push-template.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +# .githooks/pre-push — run scripts/test.sh before every push. +# No --no-verify: the claude-code hook deny-no-verify.sh also blocks it. + +set -euo pipefail + +cd "$(git rev-parse --show-toplevel)" + +./scripts/test.sh diff --git a/skills/plan/skeleton-gen/templates/gitignore-append-template b/skills/plan/skeleton-gen/templates/gitignore-append-template new file mode 100644 index 0000000..ac39aa6 --- /dev/null +++ b/skills/plan/skeleton-gen/templates/gitignore-append-template @@ -0,0 +1,32 @@ +# ==== ERP 插件推荐忽略项(skeleton-gen 追加) ==== +# 本地运行时配置(含真实凭据,严禁入库) +.env.local +.env.*.local + +# Java / Maven +target/ +*.class + +# Node / 前端构建产物 +node_modules/ +dist/ +build/ +coverage/ + +# IDE +.idea/ +.vscode/ +*.iml + +# OS +.DS_Store +Thumbs.db + +# 日志 +*.log +logs/ + +# 插件运行时临时文件 +.tmp/ +*.raw +# ==== 结束 ==== diff --git a/skills/plan/skeleton-gen/templates/scripts-setup-test-db-template.sh b/skills/plan/skeleton-gen/templates/scripts-setup-test-db-template.sh new file mode 100644 index 0000000..41a3970 --- /dev/null +++ b/skills/plan/skeleton-gen/templates/scripts-setup-test-db-template.sh @@ -0,0 +1,65 @@ +#!/usr/bin/env bash +# scripts/setup-test-db.sh — 数据库重置脚本:drop + create 空库。 +# schema apply 由 Flyway 在 Spring Boot 启动时自动处理(见 docs/04 技术栈 + sql/migrations/V*.sql)。 +# seed 数据由测试框架负责(Spring @Sql / Flyway R__seed.sql / data.sql)。 +# +# 使用场景: +# - scripts/test.sh 开头:清空库,让 Spring 启动时 Flyway 从 V1 开始重放所有 migration +# - scripts/test.sh 结尾:清空库,避免测试遗留污染下次运行 +# - 手动调试时:reset 到零状态 +# +# 防护:本脚本只允许在本地 host + 测试库名上执行;非预期目标会被拒绝, +# 避免 .env.local 误指向 staging/prod 时触发不可逆 DROP。 + +set -euo pipefail + +ENV_FILE="$(dirname "$0")/../.env.local" +[ -f "$ENV_FILE" ] || { echo "[setup-test-db] ⚠️ .env.local 不存在($ENV_FILE)" >&2; exit 1; } + +# 用 set -a 加载,让 KEY=VALUE 导出为环境变量;密码中含特殊字符时 .env.local 请用单引号包裹 +set -a; . "$ENV_FILE"; set +a + +# 防护 1:默认只允许本地 host(localhost / 127.0.0.1 / ::1)。 +# 若要为本项目额外允许某些远程 host(如公司测试 MySQL),在 .env.local 里设: +# TEST_DB_ALLOWED_HOSTS="118.178.19.35 test-mysql.internal" # 空格或逗号分隔 +# 被列入者可直接 DROP CREATE,不再需要 TEST_DB_ALLOW_REMOTE=1。 +ALLOWED_HOSTS="localhost 127.0.0.1 ::1 ${TEST_DB_ALLOWED_HOSTS//,/ }" +host_allowed=0 +for h in $ALLOWED_HOSTS; do + [ "${DB_HOST:-}" = "$h" ] && { host_allowed=1; break; } +done +if [ "$host_allowed" -ne 1 ]; then + echo "[setup-test-db] ⚠️ 拒绝在非白名单 host (${DB_HOST}) 上执行 DROP DATABASE" >&2 + echo " 当前白名单:${ALLOWED_HOSTS}" >&2 + echo " 加入 host:在 .env.local 追加 TEST_DB_ALLOWED_HOSTS=\"<host1> <host2>\"" >&2 + echo " 一次性绕过:TEST_DB_ALLOW_REMOTE=1 $0" >&2 + [ "${TEST_DB_ALLOW_REMOTE:-0}" = "1" ] || exit 1 +fi + +# 防护 2:schema 名需像测试/开发库(含 test / _dev / _local),否则要求显式确认 +case "${DB_SCHEMA:-}" in + *test*|*_dev|*_local|*_ci) + ;; + *) + echo "[setup-test-db] ⚠️ schema '${DB_SCHEMA}' 不像测试库(期望命名含 test / _dev / _local / _ci)" >&2 + echo " 如确为期望行为,请显式声明:TEST_DB_ALLOW_PROD_NAME=1 $0" >&2 + [ "${TEST_DB_ALLOW_PROD_NAME:-0}" = "1" ] || exit 1 + ;; +esac + +# 防护 3:显式 banner,让人看见自己在 drop 什么;远程 host 额外提示白名单内容 +echo "[setup-test-db] 即将 DROP + CREATE \`${DB_SCHEMA}\` on ${DB_HOST}:${DB_PORT}" +case "${DB_HOST:-}" in + localhost|127.0.0.1|::1) ;; + *) + echo "[setup-test-db] ⚠️ 目标是 **远程** host(已在 TEST_DB_ALLOWED_HOSTS 白名单中,每次 test.sh 都会 DROP)" + echo "[setup-test-db] 当前白名单: ${ALLOWED_HOSTS}" + echo "[setup-test-db] 若不希望每次自动 DROP,从 .env.local 的 TEST_DB_ALLOWED_HOSTS 删掉此 host" + ;; +esac + +MYSQL_CMD="mysql -h${DB_HOST} -P${DB_PORT} -u${DB_USER} -p${DB_PASSWORD}" + +$MYSQL_CMD -e "DROP DATABASE IF EXISTS \`${DB_SCHEMA}\`; CREATE DATABASE \`${DB_SCHEMA}\` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;" + +echo "[setup-test-db] done — schema will be applied by Flyway when Spring Boot starts" diff --git a/skills/plan/skeleton-gen/templates/scripts-test-template.sh b/skills/plan/skeleton-gen/templates/scripts-test-template.sh new file mode 100644 index 0000000..924ce58 --- /dev/null +++ b/skills/plan/skeleton-gen/templates/scripts-test-template.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +# scripts/test.sh —— 合并到默认分支(main / master)前的测试闸门。 +# 顺序:setup-db → build → lint → unit+integration → e2e → reset-db +# 由 .githooks/pre-push 和 test-gate skill(通过子会话)调用。 + +set -euo pipefail + +PROJECT_ROOT="$(cd "$(dirname "$0")/.." && pwd)" +cd "$PROJECT_ROOT" + +echo "[test.sh] 1/6 setup test db" +./scripts/setup-test-db.sh + +echo "[test.sh] 2/6 build" +{{build_cmd}} + +echo "[test.sh] 3/6 lint" +{{lint_cmd}} + +echo "[test.sh] 4/6 unit + integration" +{{test_cmd}} + +echo "[test.sh] 5/6 E2E" +{{e2e_cmd}} + +echo "[test.sh] 6/6 reset test db" +./scripts/setup-test-db.sh + +echo "[test.sh] GREEN" -- libgit2 0.22.2