@dev-workflow/skill 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +80 -0
  3. package/bin/cli.mjs +9 -0
  4. package/package.json +39 -0
  5. package/skills/artifact/README.md +23 -0
  6. package/skills/execution/devFlow/SKILL.md +341 -0
  7. package/skills/execution/devFlow/agents/openai.yaml +7 -0
  8. package/skills/execution/devFlow/domains/backend/references/api-tech.md +173 -0
  9. package/skills/execution/devFlow/domains/backend/scripts/check_api_tech_doc.mjs +170 -0
  10. package/skills/execution/devFlow/domains/backend/scripts/check_api_tech_doc.test.mjs +89 -0
  11. package/skills/execution/devFlow/domains/backend/templates/api-tech.md +164 -0
  12. package/skills/execution/devFlow/domains/frontend/references/contract-check.md +270 -0
  13. package/skills/execution/devFlow/domains/frontend/references/foundation-freeze.md +92 -0
  14. package/skills/execution/devFlow/domains/frontend/references/lightweight-flow.md +55 -0
  15. package/skills/execution/devFlow/domains/frontend/references/page-build.md +268 -0
  16. package/skills/execution/devFlow/domains/frontend/references/page-tech.md +414 -0
  17. package/skills/execution/devFlow/domains/frontend/references/product-design-specs/field-common.md +69 -0
  18. package/skills/execution/devFlow/domains/frontend/references/product-design-specs/fields-complex.md +105 -0
  19. package/skills/execution/devFlow/domains/frontend/references/product-design-specs/fields-id-code.md +44 -0
  20. package/skills/execution/devFlow/domains/frontend/references/product-design-specs/fields-number-date.md +106 -0
  21. package/skills/execution/devFlow/domains/frontend/references/product-design-specs/fields-relation.md +144 -0
  22. package/skills/execution/devFlow/domains/frontend/references/product-design-specs/fields-selectors.md +102 -0
  23. package/skills/execution/devFlow/domains/frontend/references/product-design-specs/fields-text.md +130 -0
  24. package/skills/execution/devFlow/domains/frontend/references/product-design-specs/index.md +42 -0
  25. package/skills/execution/devFlow/domains/frontend/references/product-design-specs/interaction.md +61 -0
  26. package/skills/execution/devFlow/domains/frontend/scripts/check_page_tech_doc.mjs +82 -0
  27. package/skills/execution/devFlow/domains/frontend/scripts/contract_check_static.mjs +145 -0
  28. package/skills/execution/devFlow/domains/frontend/scripts/generate_foundation_summary.mjs +224 -0
  29. package/skills/execution/devFlow/domains/frontend/templates/contract-report.md +66 -0
  30. package/skills/execution/devFlow/domains/frontend/templates/mini-plan-l0.md +7 -0
  31. package/skills/execution/devFlow/domains/frontend/templates/mini-plan-l1.md +9 -0
  32. package/skills/execution/devFlow/domains/frontend/templates/page-build/component.tsx.tpl +8 -0
  33. package/skills/execution/devFlow/domains/frontend/templates/page-build/constants.ts.tpl +5 -0
  34. package/skills/execution/devFlow/domains/frontend/templates/page-build/index.ts.tpl +1 -0
  35. package/skills/execution/devFlow/domains/frontend/templates/page-build/route.tsx.tpl +11 -0
  36. package/skills/execution/devFlow/domains/frontend/templates/page-build/service.ts.tpl +17 -0
  37. package/skills/execution/devFlow/domains/frontend/templates/page-build/types.ts.tpl +11 -0
  38. package/skills/execution/devFlow/domains/frontend/templates/page-tech.md +103 -0
  39. package/skills/execution/devFlow/domains/requirement/references/prd-review.md +129 -0
  40. package/skills/execution/devFlow/domains/requirement/templates/prd-review.md +57 -0
  41. package/skills/execution/figmaSync/SKILL.md +349 -0
  42. package/skills/execution/figmaSync/chapters/apply.md +177 -0
  43. package/skills/execution/figmaSync/chapters/plan.md +359 -0
  44. package/skills/execution/figmaSync/chapters/prepare.md +47 -0
  45. package/skills/execution/figmaSync/examples/native-css.md +129 -0
  46. package/skills/execution/figmaSync/examples/plan-doc-sample.md +39 -0
  47. package/skills/execution/figmaSync/scripts/_shared/session-log.mjs +82 -0
  48. package/skills/execution/figmaSync/scripts/_shared/token-resolver.mjs +132 -0
  49. package/skills/execution/figmaSync/scripts/_shared/token-source.mjs +145 -0
  50. package/skills/execution/figmaSync/scripts/figma-sync-report.mjs +448 -0
  51. package/skills/execution/figmaSync/scripts/icon-inventory.mjs +165 -0
  52. package/skills/execution/figmaSync/scripts/lookup-var.mjs +184 -0
  53. package/skills/execution/figmaSync/scripts/match-token.mjs +210 -0
  54. package/skills/execution/figmaSync/scripts/prepare-check.mjs +290 -0
  55. package/skills/execution/figmaSync/scripts/verify-plan.mjs +458 -0
  56. package/skills/execution/figmaSync/snapshots/README.md +13 -0
  57. package/skills/execution/figmaSync/snapshots/last-sync.md +1538 -0
  58. package/skills/execution/figmaSync/templates/PLAN.md.tpl +227 -0
  59. package/skills/review/consistency-checker/SKILL.md +112 -0
  60. package/skills/review/consistency-checker/rules/README.md +16 -0
  61. package/src/cli/agents.mjs +16 -0
  62. package/src/cli/copy.mjs +95 -0
  63. package/src/cli/install.mjs +131 -0
  64. package/src/cli/prompts.mjs +66 -0
  65. package/tools/lark/README.md +78 -0
  66. package/tools/lark/references/lark-doc.md +156 -0
  67. package/tools/lark/references/lark-read.md +235 -0
  68. package/tools/lark/references/prepare.md +147 -0
  69. package/tools/lark/scripts/lark_api.mjs +404 -0
  70. package/tools/lark/scripts/lark_api.test.mjs +63 -0
  71. package/tools/lark/scripts/lark_check_permissions.mjs +52 -0
  72. package/tools/lark/scripts/lark_publish_doc.mjs +299 -0
  73. package/tools/lark/scripts/lark_read_docx.mjs +328 -0
  74. package/tools/lark/scripts/markdown_to_lark_blocks.mjs +397 -0
@@ -0,0 +1,173 @@
1
+ # api-tech 子命令
2
+
3
+ `api-tech` 生成后端技术方案文档。它不是仓库调研报告,不是项目入门说明,不是开发排期,也不生成后端代码骨架(不产出
4
+ controller / service / dto / entity 代码文件)。
5
+
6
+ ## 代码事实优先
7
+
8
+ - 后端仓库可用时,接口、实体、schema 必须基于真实代码;写清具体文件路径与关键片段引用。
9
+ - 后端仓库不可用时,不写具体文件路径,不声称某资源存在,涉及具体接口 / 表的字段一律标记为待确认。
10
+ - 飞书 PRD / 需求与仓库代码冲突时,保留冲突并写入「风险与待确认项」,不擅自二选一。
11
+
12
+ ## 工作流程
13
+
14
+ 1. 收集上下文:PRD / 需求(优先用 `lark-read` 读取飞书文档)、可用的后端仓库代码。
15
+ 2. 确认章节:必写章节自动纳入;可选章节逐项让用户勾选。
16
+ 3. 用 `domains/backend/templates/api-tech.md` 作为骨架,只生成必写 + 选中可选章节。
17
+ 4. 生成正式文档时删除模板中的 HTML 注释(含【必写】/【可选】标记)。
18
+ 5. 生成后运行交付前自检。
19
+
20
+ ## 选择式骨架
21
+
22
+ 必写章节(总是生成):
23
+
24
+ - 接口设计
25
+ - 数据模型 / 数据库设计
26
+ - 核心流程 / 时序
27
+ - 边界与异常
28
+ - 风险与待确认项
29
+
30
+ 可选章节(由用户勾选,未选不生成、不写“不涉及”占位):
31
+
32
+ - 背景与目标
33
+ - 范围与非目标
34
+ - 依赖与非功能性
35
+ - 完成标准
36
+
37
+ 启动时先列出上述清单让用户确认要包含哪些可选章节,再生成。
38
+
39
+ ## 标题与编号硬规则
40
+
41
+ - 分节一律用原生 Markdown 标题:章 `#`、节 `##`、小节 `###`,最多三级。
42
+ - **不写编号**:飞书「标题自动编号」是文档级 UI 显示开关、Open API 不可设置;也不要手写序号。需要编号时由用户在文档里开启。
43
+
44
+ ## 排版与飞书呈现规范(定稿模板)
45
+
46
+ 排版遵循 [tools/lark/references/lark-doc.md](../../../../../../tools/lark/references/lark-doc.md) 的「排版与飞书呈现规范(定稿模板)」。以下为 `api-tech` 在通用规则之上追加的硬规则。
47
+
48
+ ## 数据结构硬规则
49
+
50
+ 实体 / 表用「字段表格 + TypeScript interface」双给:
51
+
52
+ - 字段表格列固定:字段、类型、必填、说明(默认 / 约束并入说明,保持 4 列、行矮)。
53
+ - 实体说明(collection、extends 等)写在表格上方的**引用块** `> …`。
54
+ - TypeScript interface:可空字段用 `?`,时间等注明单位(如 `// epoch ms`)。
55
+
56
+ ## 接口呈现硬规则
57
+
58
+ 接口设计章节每个接口条目按以下结构、label 全部加粗:
59
+
60
+ 1. **用途**:用 bullet 列出能力点(多能力时),不写成一长段。
61
+ 2. **入参**:4 列表格(参数、类型、必填、说明)**+** TypeScript DTO interface。
62
+ 3. **出参**:TypeScript data interface(描述 `data` 结构),不贴 JSON 示例。
63
+ 4. **说明**:用 bullet 列要点(副作用、事务、mock 口径等)。
64
+ 5. **错误码**:内联文本,如 `` `40001` 参数校验失败 | `40301` 登录态失效 ``;有业务码则补全。
65
+
66
+ ## 章节规则
67
+
68
+ - 接口设计:先用引用块写统一约定(方法、Content-Type、返回体、鉴权、时间单位),再逐接口按上面的接口呈现硬规则写。
69
+ - 数据模型 / 数据库设计:每个实体 / 表给字段表格 + TS,并说明索引与 migration 影响;仓库可用时基于真实 entity /
70
+ schema,不可用时标记为待确认。
71
+ - 核心流程 / 时序:业务流程超过 4 步或多服务调用时画 Mermaid(`sequenceDiagram` /
72
+ `flowchart`),说明事务边界与幂等 / 并发。
73
+ - 边界与异常:覆盖空数据、失败、无权限、重复提交、并发冲突、部分数据缺失、回滚 / 重试 / 降级。
74
+ - 风险与待确认项:必写,收敛 PRD / 接口 / 仓库代码冲突,每条具体到可直接提问。
75
+
76
+ ## Mermaid 风格规则
77
+
78
+ Mermaid 图必须提高技术评审效率,不做装饰。生成时优先保证语义清晰,其次保证层次和可读性。
79
+
80
+ ### sequenceDiagram 调用链模板
81
+
82
+ 接口调用链、多服务协作、前后端链路默认用 `sequenceDiagram`,并遵守:
83
+
84
+ - 开头使用 `autonumber`。
85
+ - 用户端用 `actor`,系统和服务用 `participant`。
86
+ - participant 别名使用业务可读名称,例如 `supplier-portal · 前端`、`supplier-server · 门户后端`。
87
+ - 按业务阶段使用 `rect rgb(...)` 分组,每个阶段用 `Note over` 写清阶段名和边界。
88
+ - 阶段颜色使用柔和浅色,推荐:
89
+ - 蓝色 `rgb(219, 234, 254)`:入口 / 登录 / 初始化。
90
+ - 黄色 `rgb(254, 243, 199)`:填写 / 暂存 / 草稿。
91
+ - 绿色 `rgb(220, 252, 231)`:提交 / 成功 / 主链路完成。
92
+ - 紫色 `rgb(243, 232, 255)`:审核 / 回流 / 异步状态。
93
+ - 红色 `rgb(254, 226, 226)`:失败 / 驳回 / 异常分支。
94
+ - 每个阶段 4-8 条交互为宜;超过 8 条时拆阶段,不把所有细节堆进一块。
95
+ - 消息文案写业务动作和关键接口名,不写长 JSON。
96
+ - 必须表达信任边界、签名验签、事务边界、状态机、回调 / pull 模式等关键架构约束。
97
+
98
+ 示例结构:
99
+
100
+ ```mermaid
101
+ sequenceDiagram
102
+ autonumber
103
+ actor U as 用户浏览器
104
+ participant FE as xxx-portal · 前端
105
+ participant BE as xxx-server · 后端
106
+ participant AD as admin-be · 管理后台
107
+
108
+ rect rgb(219, 234, 254)
109
+ Note over U,BE: 阶段 1 · 入口 / 登录(止于门户)
110
+ U->>FE: 进入页面
111
+ FE->>BE: check-session
112
+ BE-->>FE: { profileStatus }
113
+ end
114
+
115
+ rect rgb(220, 252, 231)
116
+ Note over U,AD: 阶段 2 · 提交(后端签名访问管理后台)
117
+ U->>FE: 点击提交
118
+ FE->>BE: submit-profile
119
+ BE->>AD: AdminClient.submit(x-signature 验签)
120
+ AD-->>BE: { auditStatus: PENDING }
121
+ BE-->>FE: SUBMITTED
122
+ end
123
+ ```
124
+
125
+ ### flowchart 业务流程模板
126
+
127
+ 事务分支、幂等、异常处理、状态判断默认用 `flowchart TD`,并遵守:
128
+
129
+ - 使用 `subgraph` 表达层次:入口、校验、核心处理、外部依赖、结果。
130
+ - 节点文本保持短句,复杂规则放正文,不塞进节点。
131
+ - 使用 `classDef` 区分类型:入口/成功/风险/外部依赖。
132
+ - 分支条件写在连线上,避免多个菱形连续堆叠。
133
+
134
+ 示例结构:
135
+
136
+ ```mermaid
137
+ flowchart TD
138
+ classDef entry fill:#dbeafe,stroke:#60a5fa,color:#1e3a8a
139
+ classDef success fill:#dcfce7,stroke:#22c55e,color:#14532d
140
+ classDef warn fill:#fef3c7,stroke:#f59e0b,color:#78350f
141
+ classDef risk fill:#fee2e2,stroke:#ef4444,color:#7f1d1d
142
+
143
+ A[接收提交请求]:::entry --> B{幂等键存在?}
144
+ B -->|是| C[返回已有处理结果]:::warn
145
+ B -->|否| D[参数与权限校验]
146
+ D --> E{校验通过?}
147
+ E -->|否| F[返回业务错误码]:::risk
148
+ E -->|是| G[开启事务并写入主表]
149
+ G --> H[提交事务]:::success
150
+ ```
151
+
152
+ ### 图放在哪些章节
153
+
154
+ - `核心流程 / 时序`:至少保留一张 Mermaid 图。主链路优先 `sequenceDiagram`;存在复杂分支时补充 `flowchart TD`。
155
+ - `数据模型 / 数据库设计`:只有实体关系复杂时补充 `erDiagram`,不要替代表格 + TypeScript。
156
+ - `边界与异常`:异常路径多于 3 类时可补充异常流程 `flowchart TD`。
157
+ - `依赖与非功能性`:存在 MQ、缓存、第三方服务、回调 / pull 策略时可补充依赖链路图。
158
+
159
+ ## 飞书上下文规则
160
+
161
+ 如果用户提供飞书 PRD / 设计 / 接口链接,必须先用 `lark-read`
162
+ 读取并结构化,再写方案;不得只凭链接标题或转述猜测。读取失败时停止依赖该文档的生成并说明原因。飞书内容与仓库代码冲突时写入风险与待确认项。
163
+
164
+ ## 交付前自检
165
+
166
+ 落地为 Markdown 文件后运行:
167
+
168
+ ```bash
169
+ node .agent/skills/devFlow/domains/backend/scripts/check_api_tech_doc.mjs --file <markdown-file> --optional "<本次选中的可选章节,逗号分隔>"
170
+ ```
171
+
172
+ 自检覆盖:必写章节齐全、选中可选章节存在、数据模型含表格 + TS、接口设计含表格与 TS 代码块、核心流程含
173
+ Mermaid、风险与待确认项非空、标题为 `#`/`##`/`###` 且无手写序号。脚本输出 JSON,最终回复只摘必要状态。
@@ -0,0 +1,170 @@
1
+ import { readFileSync } from 'node:fs'
2
+
3
+ const REQUIRED_SECTIONS = [
4
+ '接口设计',
5
+ '数据模型 / 数据库设计',
6
+ '核心流程 / 时序',
7
+ '边界与异常',
8
+ '风险与待确认项'
9
+ ]
10
+
11
+ const OPTIONAL_SECTIONS = ['背景与目标', '范围与非目标', '依赖与非功能性', '完成标准']
12
+
13
+ function escapeRegExp(value) {
14
+ return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
15
+ }
16
+
17
+ function hasSection(markdown, title) {
18
+ return new RegExp(`^#{1,3}\\s+${escapeRegExp(title)}\\s*$`, 'm').test(markdown)
19
+ }
20
+
21
+ function getSection(markdown, title) {
22
+ const pattern = new RegExp(`^(#{1,3})\\s+${escapeRegExp(title)}\\s*$`, 'm')
23
+ const match = pattern.exec(markdown)
24
+ if (!match) return ''
25
+
26
+ const level = match[1].length
27
+ const start = match.index + match[0].length
28
+ const rest = markdown.slice(start)
29
+ const lines = rest.split('\n')
30
+ const collected = []
31
+
32
+ // 收集到下一个同级或更高级标题为止,保留章节内的 ## / ### 子节内容。
33
+ for (const line of lines) {
34
+ const heading = /^(#{1,6})\s+/.exec(line)
35
+ if (heading && heading[1].length <= level) break
36
+ collected.push(line)
37
+ }
38
+
39
+ return collected.join('\n')
40
+ }
41
+
42
+ function hasTable(section) {
43
+ return /\|.+\|\s*\n\|[\s:|-]+\|/.test(section)
44
+ }
45
+
46
+ function hasTsBlock(section) {
47
+ return /```(typescript|ts)[\s\S]*?```/.test(section)
48
+ }
49
+
50
+ function hasMermaid(section) {
51
+ return /```mermaid[\s\S]*?```/.test(section)
52
+ }
53
+
54
+ export function checkApiTechDoc(markdown, options = {}) {
55
+ const optional = options.optional || []
56
+ const issues = []
57
+
58
+ for (const title of REQUIRED_SECTIONS) {
59
+ if (!hasSection(markdown, title)) {
60
+ issues.push(`缺少必写章节:${title}`)
61
+ }
62
+ }
63
+
64
+ for (const title of optional) {
65
+ if (!OPTIONAL_SECTIONS.includes(title)) {
66
+ issues.push(`未知可选章节名:${title}`)
67
+ continue
68
+ }
69
+ if (!hasSection(markdown, title)) {
70
+ issues.push(`已选可选章节缺失:${title}`)
71
+ }
72
+ }
73
+
74
+ const apiSection = getSection(markdown, '接口设计')
75
+ if (apiSection) {
76
+ if (!hasTable(apiSection)) {
77
+ issues.push('接口设计缺少入参表格')
78
+ }
79
+ if (!hasTsBlock(apiSection)) {
80
+ issues.push('接口设计缺少 TypeScript 代码块(入参 DTO / 出参 data 结构)')
81
+ }
82
+ }
83
+
84
+ const modelSection = getSection(markdown, '数据模型 / 数据库设计')
85
+ if (modelSection) {
86
+ if (!hasTable(modelSection)) {
87
+ issues.push('数据模型缺少字段表格')
88
+ }
89
+ if (!hasTsBlock(modelSection)) {
90
+ issues.push('数据模型缺少 TypeScript 代码块')
91
+ }
92
+ }
93
+
94
+ const flowSection = getSection(markdown, '核心流程 / 时序')
95
+ if (flowSection && !hasMermaid(flowSection)) {
96
+ issues.push('核心流程 / 时序缺少 Mermaid 图')
97
+ }
98
+
99
+ const riskSection = getSection(markdown, '风险与待确认项')
100
+ if (riskSection && riskSection.trim().length < 10) {
101
+ issues.push('风险与待确认项为空')
102
+ }
103
+
104
+ const lines = markdown.split('\n')
105
+ let inFence = false
106
+ for (const line of lines) {
107
+ if (/^```/.test(line)) {
108
+ inFence = !inFence
109
+ continue
110
+ }
111
+ if (inFence) continue
112
+
113
+ const heading = /^(#{1,6})\s+(.+?)\s*$/.exec(line)
114
+ if (!heading) continue
115
+
116
+ if (heading[1].length > 3) {
117
+ issues.push(`标题层级超过三级(飞书仅支持 H1-H3):${line.trim()}`)
118
+ }
119
+ if (/^\s*\d+\s*[.、)]/.test(heading[2])) {
120
+ issues.push(`标题不得手写序号:${heading[2]}`)
121
+ }
122
+ }
123
+
124
+ return { ok: issues.length === 0, issues }
125
+ }
126
+
127
+ function parseFlags(argv) {
128
+ const args = {}
129
+ for (let index = 0; index < argv.length; index += 1) {
130
+ const item = argv[index]
131
+ if (!item.startsWith('--')) continue
132
+ const key = item.slice(2)
133
+ const next = argv[index + 1]
134
+ if (!next || next.startsWith('--')) {
135
+ args[key] = true
136
+ continue
137
+ }
138
+ args[key] = next
139
+ index += 1
140
+ }
141
+ return args
142
+ }
143
+
144
+ function main() {
145
+ const args = parseFlags(process.argv.slice(2))
146
+ if (!args.file || args.file === true) {
147
+ console.error('Usage: node check_api_tech_doc.mjs --file <markdown> [--optional "背景与目标,完成标准"]')
148
+ process.exit(2)
149
+ }
150
+
151
+ const optional =
152
+ typeof args.optional === 'string'
153
+ ? args.optional.split(',').map((value) => value.trim()).filter(Boolean)
154
+ : []
155
+
156
+ const markdown = readFileSync(args.file, 'utf8')
157
+ const result = checkApiTechDoc(markdown, { optional })
158
+
159
+ if (result.ok) {
160
+ console.log(JSON.stringify(result, null, 2))
161
+ process.exit(0)
162
+ }
163
+
164
+ console.error(JSON.stringify(result, null, 2))
165
+ process.exit(1)
166
+ }
167
+
168
+ if (import.meta.url === `file://${process.argv[1]}`) {
169
+ main()
170
+ }
@@ -0,0 +1,89 @@
1
+ import { test } from 'node:test'
2
+ import assert from 'node:assert/strict'
3
+
4
+ import { checkApiTechDoc } from './check_api_tech_doc.mjs'
5
+
6
+ const API_DTO = '```typescript\ninterface ListDto { page: number }\n```'
7
+ const API_RESP = '```typescript\ninterface ListData { total: number }\n```'
8
+ const MODEL_TS = '```typescript\ninterface Entity { id: string }\n```'
9
+
10
+ const GOOD = `# 接口设计
11
+
12
+ > 统一约定:POST,返回体 { code, data }。
13
+
14
+ ### 列表查询 · POST /api/x
15
+
16
+ **入参**
17
+
18
+ | 参数 | 类型 | 必填 | 说明 |
19
+ | --- | --- | --- | --- |
20
+ | page | number | 否 | 页码 |
21
+
22
+ ${API_DTO}
23
+
24
+ **出参**
25
+
26
+ ${API_RESP}
27
+
28
+ **错误码**:\`40001\` 参数校验失败
29
+
30
+ # 数据模型 / 数据库设计
31
+
32
+ | 字段 | 类型 | 必填 | 说明 |
33
+ | --- | --- | --- | --- |
34
+ | id | string | 是 | 主键 |
35
+
36
+ ${MODEL_TS}
37
+
38
+ # 核心流程 / 时序
39
+
40
+ \`\`\`mermaid
41
+ sequenceDiagram
42
+ A->>B: x
43
+ \`\`\`
44
+
45
+ # 边界与异常
46
+
47
+ - 空数据返回空列表。
48
+
49
+ # 风险与待确认项
50
+
51
+ - 待确认 X 字段来源。
52
+ `
53
+
54
+ test('合规文档通过', () => {
55
+ const r = checkApiTechDoc(GOOD)
56
+ assert.equal(r.ok, true, JSON.stringify(r.issues))
57
+ })
58
+
59
+ test('缺必写章节报错', () => {
60
+ const md = GOOD.replace('# 边界与异常', '# 其他')
61
+ const r = checkApiTechDoc(md)
62
+ assert.equal(r.ok, false)
63
+ assert.ok(r.issues.some((i) => i.includes('边界与异常')))
64
+ })
65
+
66
+ test('标题手写序号报错', () => {
67
+ const md = GOOD.replace('# 接口设计', '# 2. 接口设计')
68
+ const r = checkApiTechDoc(md)
69
+ assert.ok(r.issues.some((i) => i.includes('手写序号')))
70
+ })
71
+
72
+ test('数据模型缺 TS 报错', () => {
73
+ const md = GOOD.replace(MODEL_TS, '')
74
+ const r = checkApiTechDoc(md)
75
+ assert.ok(r.issues.some((i) => i.includes('数据模型') && i.includes('TypeScript')))
76
+ })
77
+
78
+ test('接口缺 TS 报错', () => {
79
+ const md = GOOD.replace(API_DTO, '').replace(API_RESP, '')
80
+ const r = checkApiTechDoc(md)
81
+ assert.ok(r.issues.some((i) => i.includes('接口设计') && i.includes('TypeScript')))
82
+ })
83
+
84
+ test('已选可选章节缺失报错,未选的不报', () => {
85
+ const missing = checkApiTechDoc(GOOD, { optional: ['完成标准'] })
86
+ assert.ok(missing.issues.some((i) => i.includes('完成标准')))
87
+ const none = checkApiTechDoc(GOOD)
88
+ assert.equal(none.ok, true, JSON.stringify(none.issues))
89
+ })
@@ -0,0 +1,164 @@
1
+ <!-- devFlow domains/backend api-tech 模板(定稿格式)。章节用 HTML 注释标【必写】/【可选】,生成正式文档时删除所有 HTML 注释。 -->
2
+ <!-- 飞书排版语法:> 引用块;> [!WARNING]/[!TIP]/[!NOTE] 高亮块;--- 分隔线;**x** 粗体;表格自动灰底表头+自适应列宽。标题不写编号。 -->
3
+
4
+ # 背景与目标
5
+ <!-- 【可选】 -->
6
+
7
+ 说明本次后端要解决的问题与服务级目标。不写项目背景与技术栈罗列。
8
+
9
+ # 范围与非目标
10
+ <!-- 【可选】 -->
11
+
12
+ - 涉及的服务 / 模块。
13
+ - 明确不做的部分(非目标)。
14
+
15
+ # 接口设计
16
+ <!-- 【必写】 -->
17
+
18
+ > 统一约定:`POST`,`Content-Type: application/json`,返回体 `{ code, data }`,时间字段统一 epoch ms。鉴权:Admin 登录态。
19
+
20
+ ## <模块名>
21
+
22
+ ### <接口名> · POST /api/<module>/<action>
23
+
24
+ **用途**:用 bullet 列出能力点:
25
+
26
+ - 能力点 1
27
+ - 能力点 2
28
+
29
+ **入参**
30
+
31
+ | 参数 | 类型 | 必填 | 说明 |
32
+ | --- | --- | --- | --- |
33
+ | page | number | 是 | 页码(≥ 1) |
34
+ | pageSize | number | 是 | 每页条数(1–100) |
35
+
36
+ ```typescript
37
+ interface ExampleDto {
38
+ page: number
39
+ pageSize: number
40
+ }
41
+ ```
42
+
43
+ > [!WARNING] 标注本期为 mock / 跨模块依赖的字段,需在此提示。
44
+
45
+ **出参**(data 结构)
46
+
47
+ ```typescript
48
+ interface ExampleData {
49
+ total: number
50
+ list: ExampleItem[]
51
+ }
52
+ ```
53
+
54
+ **说明**
55
+
56
+ - 副作用 / 事务 / mock 口径等要点,逐条 bullet。
57
+
58
+ **错误码**:`40001` 参数校验失败 | `40301` 登录态失效
59
+
60
+ ---
61
+
62
+ # 数据模型 / 数据库设计
63
+ <!-- 【必写】 -->
64
+
65
+ ## <实体 / 表名>
66
+
67
+ > 集合 <name>(用途)。extends Base: sys_status;timestamps。
68
+
69
+ | 字段 | 类型 | 必填 | 说明 |
70
+ | --- | --- | --- | --- |
71
+ | _id | ObjectId | 是 | 主键 |
72
+ | name | string | 是 | 名称,查重唯一 |
73
+ | createdAt | number | 是 | 创建时间,epoch ms |
74
+
75
+ ```typescript
76
+ interface Entity {
77
+ _id: string
78
+ name: string
79
+ createdAt: number // epoch ms
80
+ }
81
+ ```
82
+
83
+ 索引与 migration 影响:说明新增/变更的索引、唯一约束、迁移注意点。
84
+
85
+ # 核心流程 / 时序
86
+ <!-- 【必写】 -->
87
+
88
+ 说明关键业务流程、调用链、事务边界与幂等 / 并发。状态流转用 Mermaid(源码)。生成正式文档时按实际场景保留必要图,不要机械保留所有示例。
89
+
90
+ **主链路时序图**
91
+
92
+ ```mermaid
93
+ sequenceDiagram
94
+ autonumber
95
+ actor U as 用户浏览器
96
+ participant FE as xxx-portal · 前端
97
+ participant BE as xxx-server · 后端
98
+ participant AD as admin-be · 管理后台
99
+
100
+ rect rgb(219, 234, 254)
101
+ Note over U,BE: 阶段 1 · 入口 / 初始化(说明边界)
102
+ U->>FE: 进入页面 / 触发操作
103
+ FE->>BE: check-session / load-profile
104
+ BE-->>FE: { profileStatus }
105
+ end
106
+
107
+ rect rgb(254, 243, 199)
108
+ Note over U,BE: 阶段 2 · 暂存 / 校验(说明数据落点)
109
+ U->>FE: 填写信息
110
+ FE->>BE: save-draft / validate
111
+ BE->>BE: 参数校验 / 幂等检查
112
+ BE-->>FE: { saved: true }
113
+ end
114
+
115
+ rect rgb(220, 252, 231)
116
+ Note over U,AD: 阶段 3 · 提交 / 生效(说明事务与外部依赖)
117
+ U->>FE: 点击提交
118
+ FE->>BE: submit
119
+ BE->>AD: AdminClient.submit(x-signature 验签)
120
+ AD->>AD: 查重 / 状态机 / 审计
121
+ AD-->>BE: { status }
122
+ BE-->>FE: { code, data }
123
+ end
124
+ ```
125
+
126
+ **关键分支流程图**(存在事务、幂等、异常分支时保留)
127
+
128
+ ```mermaid
129
+ flowchart TD
130
+ classDef entry fill:#dbeafe,stroke:#60a5fa,color:#1e3a8a
131
+ classDef success fill:#dcfce7,stroke:#22c55e,color:#14532d
132
+ classDef warn fill:#fef3c7,stroke:#f59e0b,color:#78350f
133
+ classDef risk fill:#fee2e2,stroke:#ef4444,color:#7f1d1d
134
+
135
+ A[接收提交请求]:::entry --> B{幂等键存在?}
136
+ B -->|是| C[返回已有处理结果]:::warn
137
+ B -->|否| D[参数与权限校验]
138
+ D --> E{校验通过?}
139
+ E -->|否| F[返回业务错误码]:::risk
140
+ E -->|是| G[开启事务并写入主表]
141
+ G --> H[提交事务]:::success
142
+ ```
143
+
144
+ # 依赖与非功能性
145
+ <!-- 【可选】 -->
146
+
147
+ - 中间件 / 第三方 / MQ / 缓存。
148
+ - 限流、性能、安全与权限。
149
+
150
+ # 边界与异常
151
+ <!-- 【必写】 -->
152
+
153
+ - 空数据、请求失败、无权限、重复提交、并发冲突、部分数据缺失的处理与返回。
154
+ - 回滚、重试、降级策略。
155
+
156
+ # 完成标准
157
+ <!-- 【可选】 -->
158
+
159
+ 说明后端做到什么程度算完成。保持简短,不写测试用例与排期。
160
+
161
+ # 风险与待确认项
162
+ <!-- 【必写】 -->
163
+
164
+ - 收敛 PRD / 接口 / 仓库代码冲突,每条具体到可直接问产品、前端或负责人。