@gordon.gan/specflow 1.8.4-beta → 1.8.5-beta

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 (29) hide show
  1. package/dist/cli/commands/document-run.js +2 -2
  2. package/dist/core/document/engine.js +7 -1
  3. package/dist/core/document/gates.js +7 -1
  4. package/dist/core/document/lint.d.ts +11 -1
  5. package/dist/core/document/lint.js +79 -3
  6. package/dist/core/document/render.d.ts +3 -7
  7. package/dist/core/document/render.js +28 -43
  8. package/package.json +1 -1
  9. package/prompts/document/map/api-design.md +11 -19
  10. package/prompts/document/map/architecture.md +1 -1
  11. package/prompts/document/map/core-logic.md +10 -3
  12. package/prompts/document/map/data-model.md +2 -2
  13. package/prompts/document/map/requirement.md +6 -1
  14. package/prompts/document/map/test-strategy.md +1 -1
  15. package/prompts/document/outline/general.md +5 -2
  16. package/prompts/document/shared/grounding.md +1 -1
  17. package/prompts/shared/artifact-language.md +9 -0
  18. package/skills/specflow-techdoc-synth/SKILL.md +2 -2
  19. package/templates/document/chapters/api-design.yaml +6 -18
  20. package/templates/document/chapters/architecture.yaml +1 -2
  21. package/templates/document/chapters/core-logic.yaml +8 -6
  22. package/templates/document/chapters/data-model.yaml +9 -5
  23. package/templates/document/chapters/mvp-boundary.yaml +0 -3
  24. package/templates/document/chapters/requirement.yaml +5 -7
  25. package/templates/document/chapters/tech-selection.yaml +0 -3
  26. package/templates/document/chapters/test-strategy.yaml +2 -5
  27. package/templates/document/chapters/ui-design.yaml +0 -3
  28. package/templates/document/profiles/approve.yaml +3 -2
  29. package/templates/document/profiles/feature.yaml +1 -1
@@ -719,11 +719,11 @@ function buildSynthRules(dirs) {
719
719
  `1. **统一大纲**:一次生成一份 outline,章节覆盖所有仓,不按仓分章(跨仓对比/汇总放进对应章节)。`,
720
720
  `2. **契约单一定义**:同一物理端点(method+path)只定义一个契约实体,用 \`side\`(console/worker/internal)与 \`consumers\`/\`producers\`(仓名)标注面与消费方/生产方;\`<repo>_<id>\` 前缀仅作为追溯别名保留,禁止为不同仓重复定义同一接口(validate 会以 \`duplicate_contract\` 拦截)。`,
721
721
  `3. **整体性组织(替代按仓分节)**:每章按主题写成一段整体叙述,仓归属用内联 \`[${repoList.split('、').join('] / [')}]\` 标注或表格「归属」列;**禁止**为无内容的仓写占位小节(如「某仓无 UI」);若确需 \`### <repo>\` 小节,小节必须有实质内容(validate 会以 \`repo_section_stub\` 拦截空壳)。`,
722
- `4. **全局视角**(若所选 profile 包含对应章节):goal 写多仓总目标与边界;tech-selection 对比各仓技术方案;**接口与数据合并为「接口与数据设计」章**(接口总览 逐接口明细数据模型与契约-表映射 → 存量回滚,DDL 就近引用附录),含契约-表映射表(每接口 ↔ 读写表/列);closed-loop 跨仓统一闭环检查;implementability 跨仓统一可实施性评估。`,
722
+ `4. **全局视角**(若所选 profile 包含对应章节):goal 写多仓总目标与边界;tech-selection 对比各仓技术方案;**接口与数据分工**——接口契约内联进「接口与数据设计」章(接口明细),**数据库表必须由「数据模型」章组件承载**(DDL/存量 G3/回滚 G4),契约-表映射写数据模型章,两章按「接口与数据设计数据模型」顺序并列;closed-loop 跨仓统一闭环检查;implementability 跨仓统一可实施性评估。`,
723
723
  `5. **跨仓依赖/风险**:涉及仓间依赖(接口调用/数据共享/发布顺序)时显式标注「跨仓依赖」。`,
724
724
  `6. **按需加载规约(重要)**:写某个仓的小节时,**只读取该仓**的规约/IDE rules/guidance(该仓的 \`docs/\`、\`.cursor\`、\`.claude\`、\`.agents\` 等),**禁止一次性读取全部仓的规约**;只有写跨仓内容(接口对接/数据共享/发布顺序)时才读取**涉及仓**的规约。未读取的仓规约不得臆测,必要时标注「未读取该仓规约,待确认」。`,
725
725
  `7. **输入归属**:每段输入带「来源仓」标记,段 id 携带仓前缀(如 \`seg-repo1-proposal-01\`);引用原文时按段 id 精确取回对应仓的片段,不整篇重读。`,
726
- `8. **完整性骨架**:合成文档必须含术语与约定表、非目标汇总、风险与开放问题、决策记录(ADR,正文用 \`[D#]\` 引用,决策先定义后引用,validate 以 \`forward_decision_ref\` 提示前向引用)。`,
726
+ `8. **完整性骨架**:合成文档必须含术语与约定表、非目标汇总、风险与开放问题章节。**不设决策记录(ADR)章、不使用 \`[D#]\` 引用**——决策理由沉淀在技术选型(否决/备选列)与风险章。`,
727
727
  `9. **示例与字段表**:接口实体必须填 \`request_example\`/\`success_response_example\`/\`failure_response_example\`(真实 JSON body,无请求体方法显式标注「无请求体」);请求字段与响应字段分列填写;错误表按 \`backend\`(gRPC→HTTP 映射)/ \`guard\`(前端守卫行为)/ \`internal\`(Worker 内部语义)分类。`,
728
728
  `10. **主流程必须含图**:主业务流程章输出整体流程图(含失败分支)+ 时序图 + 失败路径决策图,图必须有文字说明(validate 以 diagram 门禁拦截缺图)。`,
729
729
  ].join('\n');
@@ -17,7 +17,7 @@ import { renderDocument, renderHtml } from './render.js';
17
17
  import { runGates } from './gates.js';
18
18
  import { resolvePaths, reposPath, chapterPath } from './paths.js';
19
19
  import { parseEntitiesLenient } from './schemas.js';
20
- import { lintNarrative, checkRepoCoverage, checkRepoSectionStub, checkDuplicateContract, checkExamplePresence, checkForwardDecisionRef, checkUnverifiedNumber, checkDataContractMapping } from './lint.js';
20
+ import { lintNarrative, checkRepoCoverage, checkRepoSectionStub, checkDuplicateContract, checkExamplePresence, checkForwardDecisionRef, checkUnverifiedNumber, checkDataContractMapping, checkBareIdentifiers, checkTextHeavyNoDiagram } from './lint.js';
21
21
  import { checkStructuredCoverage } from './coverage.js';
22
22
  import { resolveProjectConventionPaths } from '../project-conventions.js';
23
23
  import { extractContracts, EMPTY_CONTRACTS } from './extract.js';
@@ -708,6 +708,12 @@ export async function validateWork(options) {
708
708
  for (const d of checkUnverifiedNumber(chId, narrative)) {
709
709
  diags.push({ gate: 'lint', code: d.code, severity: d.severity, message: d.message, chapter: chId });
710
710
  }
711
+ for (const d of checkBareIdentifiers(chId, narrative)) {
712
+ diags.push({ gate: 'lint', code: d.code, severity: d.severity, message: d.message, chapter: chId });
713
+ }
714
+ for (const d of checkTextHeavyNoDiagram(chId, narrative)) {
715
+ diags.push({ gate: 'lint', code: d.code, severity: d.severity, message: d.message, chapter: chId });
716
+ }
711
717
  }
712
718
  if (synthRepos.length >= 2) {
713
719
  for (const d of checkDataContractMapping(narrativeMap, allEntities)) {
@@ -2,7 +2,7 @@
2
2
  * Document Engine — gate orchestration (T10.4).
3
3
  * Runs lint → structured coverage → review check → budget → zod, collecting diagnostics.
4
4
  */
5
- import { lintNarrative, checkBudget, checkDiagramPresence, checkNumericPresence, checkGoldenSignals, checkRepoCoverage, checkRepoSectionStub, checkDuplicateContract, checkExamplePresence, checkForwardDecisionRef, checkUnverifiedNumber, checkDataContractMapping, } from './lint.js';
5
+ import { lintNarrative, checkBudget, checkDiagramPresence, checkNumericPresence, checkGoldenSignals, checkRepoCoverage, checkRepoSectionStub, checkDuplicateContract, checkExamplePresence, checkForwardDecisionRef, checkUnverifiedNumber, checkDataContractMapping, checkBareIdentifiers, checkTextHeavyNoDiagram, } from './lint.js';
6
6
  import { checkStructuredCoverage } from './coverage.js';
7
7
  import { checkReviewResult } from './review.js';
8
8
  export async function runGates(input) {
@@ -74,6 +74,12 @@ export async function runGates(input) {
74
74
  for (const d of checkUnverifiedNumber(chId, narrative)) {
75
75
  diags.push({ gate: 'lint', code: d.code, severity: d.severity, message: d.message, chapter: chId });
76
76
  }
77
+ for (const d of checkBareIdentifiers(chId, narrative)) {
78
+ diags.push({ gate: 'lint', code: d.code, severity: d.severity, message: d.message, chapter: chId });
79
+ }
80
+ for (const d of checkTextHeavyNoDiagram(chId, narrative)) {
81
+ diags.push({ gate: 'lint', code: d.code, severity: d.severity, message: d.message, chapter: chId });
82
+ }
77
83
  }
78
84
  if (input.repos && input.repos.length >= 2) {
79
85
  for (const d of checkDataContractMapping(input.chapterNarratives, input.entities)) {
@@ -59,7 +59,17 @@ export declare function checkForwardDecisionRef(narratives: ReadonlyMap<string,
59
59
  }>): RepoSectionDiagnostic[];
60
60
  /** 性能章目标数字必须标注来源/待实测(P10)。 */
61
61
  export declare function checkUnverifiedNumber(chapterId: string, narrative: string): RepoSectionDiagnostic[];
62
- /** 接口与数据整合(P11):synth 模式下有表实体时,接口章必须含契约-表映射表。 */
62
+ /** 接口与数据对齐(P11):有表实体时,数据模型章(或接口章)必须含契约-表映射表。 */
63
63
  export declare function checkDataContractMapping(narratives: ReadonlyMap<string, string>, entities: {
64
64
  tables?: unknown[];
65
65
  }): RepoSectionDiagnostic[];
66
+ /**
67
+ * 正文中文化(warning):叙述行(非代码块/非表格/非标题)出现裸代码标识符时提示用中文业务术语替代。
68
+ * 术语与约定章(glossary)放行——那里本就登记标识符。
69
+ */
70
+ export declare function checkBareIdentifiers(chapterId: string, narrative: string): RepoSectionDiagnostic[];
71
+ /**
72
+ * 图文结合(warning):叙述正文(非表格/非标题/非代码块)超过阈值行数但整章无 Mermaid 图 →
73
+ * 提示补充图(流程/状态/结构类内容必须配图 + 文字说明)。术语表放行。
74
+ */
75
+ export declare function checkTextHeavyNoDiagram(chapterId: string, narrative: string, minProseLines?: number): RepoSectionDiagnostic[];
@@ -247,16 +247,92 @@ export function checkUnverifiedNumber(chapterId, narrative) {
247
247
  }
248
248
  return [];
249
249
  }
250
- /** 接口与数据整合(P11):synth 模式下有表实体时,接口章必须含契约-表映射表。 */
250
+ /** 接口与数据对齐(P11):有表实体时,数据模型章(或接口章)必须含契约-表映射表。 */
251
251
  export function checkDataContractMapping(narratives, entities) {
252
252
  if ((entities.tables?.length ?? 0) === 0)
253
253
  return [];
254
- const narrative = narratives.get('api-design') ?? '';
254
+ const narrative = narratives.get('data-model') ?? narratives.get('api-design') ?? '';
255
255
  if (!/契约-表映射|映射表|接口.*表.*映射|表.*接口.*映射/.test(narrative)) {
256
256
  return [{
257
257
  code: 'data_contract_mapping_missing',
258
258
  severity: 'warning',
259
- message: '接口与数据应整合呈现:api-design 章缺少「契约-表映射」(每接口 ↔ 读写表/列),接口约定与数据库仍游离',
259
+ message: '接口与数据应通过契约-表映射对齐:数据模型章缺少「契约-表映射」(每接口 ↔ 读写表/列),接口约定与数据库仍游离',
260
+ }];
261
+ }
262
+ return [];
263
+ }
264
+ // ============= 正文中文化 lint(可读性整改:代码标识符只允许出现在术语表/字段表/示例) =============
265
+ /** 正文叙述中禁止裸用代码标识符的清单(术语表/字段表/JSON 示例/代码块除外)。 */
266
+ const BARE_IDENTIFIERS = [
267
+ 'runtime_payload', 'execution_jobs', 'scenario_cases', 'scenario_steps', 'scenario_step_results',
268
+ 'param_overrides', 'lease_epoch', 'ref_type', 'step_count', 'job_type', 'execution_mode',
269
+ 'step_uid', 'step_order', 'schema_version', 'request_id', 'EnsureCaseResult', 'CompileScenario',
270
+ 'ExecuteCase', 'StartDebugExecution', 'SubmitStepResult', 'ListScenarioStepResults', 'ReplaceScenarioSteps',
271
+ 'pollJobUntilTerminal', 'case_result_uid', 'execution_job_uid',
272
+ ];
273
+ /**
274
+ * 正文中文化(warning):叙述行(非代码块/非表格/非标题)出现裸代码标识符时提示用中文业务术语替代。
275
+ * 术语与约定章(glossary)放行——那里本就登记标识符。
276
+ */
277
+ export function checkBareIdentifiers(chapterId, narrative) {
278
+ if (/term|glossary|约定|术语/i.test(chapterId))
279
+ return [];
280
+ const diags = [];
281
+ let inFence = false;
282
+ for (const raw of narrative.split('\n')) {
283
+ const line = raw.trimStart();
284
+ if (line.startsWith('```')) {
285
+ inFence = !inFence;
286
+ continue;
287
+ }
288
+ if (inFence)
289
+ continue;
290
+ if (line.startsWith('|'))
291
+ continue; // 表格行(字段表)保留原名
292
+ if (/^#{1,6}\s/.test(line))
293
+ continue; // 标题
294
+ for (const id of BARE_IDENTIFIERS) {
295
+ if (new RegExp(`\\b${id}\\b`).test(line)) {
296
+ diags.push({
297
+ code: 'bare_identifier',
298
+ severity: 'warning',
299
+ chapter: chapterId,
300
+ message: `Chapter "${chapterId}" 正文出现裸代码标识符「${id}」——正文应用中文业务术语(如「运行时信封」替代 runtime_payload);标识符只允许在术语表、字段表、JSON/HTTP 示例、代码块中出现`,
301
+ });
302
+ break;
303
+ }
304
+ }
305
+ }
306
+ return diags;
307
+ }
308
+ // ============= 图文结合 lint(可读性整改:叙述多的章节必须有图) =============
309
+ /**
310
+ * 图文结合(warning):叙述正文(非表格/非标题/非代码块)超过阈值行数但整章无 Mermaid 图 →
311
+ * 提示补充图(流程/状态/结构类内容必须配图 + 文字说明)。术语表放行。
312
+ */
313
+ export function checkTextHeavyNoDiagram(chapterId, narrative, minProseLines = 30) {
314
+ if (/term|glossary|约定|术语/i.test(chapterId))
315
+ return [];
316
+ let prose = 0;
317
+ let inFence = false;
318
+ for (const raw of narrative.split('\n')) {
319
+ const line = raw.trimStart();
320
+ if (line.startsWith('```')) {
321
+ inFence = !inFence;
322
+ continue;
323
+ }
324
+ if (inFence)
325
+ continue;
326
+ if (line.startsWith('|') || /^#{1,6}\s/.test(line) || line.trim() === '')
327
+ continue;
328
+ prose += 1;
329
+ }
330
+ if (prose >= minProseLines && !/```mermaid/.test(narrative)) {
331
+ return [{
332
+ code: 'text_heavy_no_diagram',
333
+ severity: 'warning',
334
+ chapter: chapterId,
335
+ message: `Chapter "${chapterId}" 叙述较多(${prose} 行)但无图——建议图文结合:流程/状态流转/结构/决策分支用 Mermaid 图(flowchart/sequenceDiagram/stateDiagram-v2)+ 文字说明,叙述分条输出`,
260
336
  }];
261
337
  }
262
338
  return [];
@@ -16,14 +16,10 @@ export declare function escapeFenceContent(s: string): string;
16
16
  export declare function escapeInline(s: string): string;
17
17
  export declare function renderInterface(i: InterfaceEntity): string;
18
18
  export declare function renderTable(t: TableEntity): string;
19
- export declare function renderDecisions(decisions: Array<{
20
- id: string;
21
- text: string;
22
- background?: string;
23
- alternative?: string;
24
- }>): string;
25
- /** 契约实体按「面」分组渲染(Console 面 / 内部与 Worker 面),替代平铺。 */
26
19
  export declare function renderEntities(entities: Entities): string;
20
+ /** 契约实体按「面」分组渲染(Console 面 / 内部与 Worker 面),供接口与数据设计章就地展开。 */
21
+ export declare function renderInterfaces(interfaces: InterfaceEntity[]): string;
22
+ export declare function renderTables(tables: TableEntity[]): string;
27
23
  export interface RenderDocumentInput {
28
24
  outline: Outline;
29
25
  entities: Entities;
@@ -83,22 +83,14 @@ export function renderTable(t) {
83
83
  ...(t.rollback ? ['**回滚兼容**', '', t.rollback, ''] : []),
84
84
  ].join('\n');
85
85
  }
86
- export function renderDecisions(decisions) {
87
- if (decisions.length === 0)
88
- return '';
89
- return [
90
- '## 决策记录(ADR)',
91
- '',
92
- '| 决策 | 背景 | 结论 | 备选(已否决) |',
93
- '|------|------|------|------|',
94
- ...decisions.map((d) => `| ${escapeTableCell(d.id)} | ${escapeTableCell(d.background ?? '')} | ${escapeTableCell(d.text)} | ${escapeTableCell(d.alternative ?? '')} |`),
95
- ].join('\n');
96
- }
97
- /** 契约实体按「面」分组渲染(Console 面 / 内部与 Worker 面),替代平铺。 */
98
86
  export function renderEntities(entities) {
87
+ return [renderInterfaces(entities.interfaces), renderTables(entities.tables)].filter(Boolean).join('\n\n');
88
+ }
89
+ /** 契约实体按「面」分组渲染(Console 面 / 内部与 Worker 面),供接口与数据设计章就地展开。 */
90
+ export function renderInterfaces(interfaces) {
99
91
  const parts = [];
100
92
  const groups = new Map();
101
- for (const i of entities.interfaces) {
93
+ for (const i of interfaces) {
102
94
  const key = i.side ?? 'other';
103
95
  if (!groups.has(key))
104
96
  groups.set(key, []);
@@ -116,10 +108,11 @@ export function renderEntities(entities) {
116
108
  continue;
117
109
  parts.push(`### ${sideTitle[key]}`, '', list.map(renderInterface).join('\n\n'));
118
110
  }
119
- for (const t of entities.tables)
120
- parts.push(renderTable(t));
121
111
  return parts.join('\n\n');
122
112
  }
113
+ export function renderTables(tables) {
114
+ return tables.map(renderTable).join('\n\n');
115
+ }
123
116
  /** Strip engine repair notes (`<!-- review-fix ... -->`) from the FINAL render. The audit trail
124
117
  * stays in `chapters/<id>.md` and `review-result.json`; the deliverable document must not show
125
118
  * internal fix notes. */
@@ -216,44 +209,36 @@ export function renderDocument(input) {
216
209
  if (meta.length > 0) {
217
210
  body.push('| 项 | 值 |', '|------|------|', ...meta, '');
218
211
  }
219
- // 目录(P7):按大纲章节序确定性生成;接口与数据合并时 data-model 不单列。
220
- const apiDesignIdx = outline.chapters.findIndex((c) => c.id === 'api-design');
221
- const dataModelIdx = outline.chapters.findIndex((c) => c.id === 'data-model');
222
- const mergeDataModel = apiDesignIdx >= 0 && dataModelIdx > apiDesignIdx;
212
+ // 目录(P7):按大纲章节序确定性生成。
223
213
  body.push('## 目录', '');
224
- outline.chapters.forEach((ch, idx) => {
225
- if (mergeDataModel && ch.id === 'data-model')
226
- return;
227
- body.push(`${idx + 1}. ${escapeInline(ch.title)}`);
214
+ let tocNo = 0;
215
+ outline.chapters.forEach((ch) => {
216
+ tocNo += 1;
217
+ body.push(`${tocNo}. ${escapeInline(ch.title)}`);
228
218
  });
229
219
  body.push('');
230
- for (const [idx, ch] of outline.chapters.entries()) {
231
- if (mergeDataModel && ch.id === 'data-model')
232
- continue; // 已并入「接口与数据设计」章
220
+ // 契约明细按章节组件落位:
221
+ // - 接口实体(请求/响应字段表、示例、错误表)内联进「接口与数据设计」章(接口明细);
222
+ // - 数据库表(DDL/存量填充/回滚)必须由「数据模型」章组件承载(数据表),不并入接口章。
223
+ const interfacesMd = renderInterfaces(entities.interfaces);
224
+ const tablesMd = renderTables(entities.tables);
225
+ const hasApiDesign = outline.chapters.some((c) => c.id === 'api-design');
226
+ const hasDataModel = outline.chapters.some((c) => c.id === 'data-model');
227
+ for (const ch of outline.chapters) {
233
228
  body.push(`## ${escapeInline(ch.title)}`, '');
234
229
  // 依次净化:剥内嵌契约 JSON 块(机器中间格式)→ 剥与章节标题重复的首行 H1 → 剥引擎修复注记,
235
230
  // 再把叙述内标题降级一级(章节头已占 H2,叙述小节 H2→H3),保证目录层级正确。
236
231
  const narrative = demoteHeadings(stripLeadingTitle(stripEntityJsonBlocks(stripReviewNotes(narratives.get(ch.id) ?? '')), ch.title));
237
232
  if (narrative.trim())
238
233
  body.push(narrative.trim(), '');
239
- // 接口与数据整合(P11):data-model 紧随 api-design 时并入其下为小节,不再单独成章。
240
- if (mergeDataModel && ch.id === 'api-design') {
241
- const dm = outline.chapters[dataModelIdx];
242
- const dmNarrative = demoteHeadings(stripLeadingTitle(stripEntityJsonBlocks(stripReviewNotes(narratives.get(dm.id) ?? '')), dm.title));
243
- if (dmNarrative.trim())
244
- body.push('### 数据模型', '', dmNarrative.trim(), '');
245
- }
246
- }
247
- // 决策记录(ADR)独立成节(P6):不再埋在契约实体末尾。
248
- const decisionsMd = renderDecisions(entities.decisions);
249
- if (decisionsMd.trim()) {
250
- body.push('---', '', decisionsMd, '');
234
+ if (ch.id === 'api-design' && interfacesMd.trim())
235
+ body.push('### 接口明细', '', interfacesMd, '');
236
+ if (ch.id === 'data-model' && tablesMd.trim())
237
+ body.push('### 数据表', '', tablesMd, '');
251
238
  }
252
- // Contract entities: append to the chapters that reference them (simplified: append in a
253
- // final "附录 A" section, since entities are cross-chapter).
254
- const contractMd = renderEntities(entities);
255
- if (contractMd.trim()) {
256
- body.push('---', '', '## 附录 A:契约实体明细', '', contractMd, '');
239
+ // api-design / data-model 章时的兜底(如 bugfix profile 的契约实体仍须呈现)。
240
+ if (!hasApiDesign && !hasDataModel && (interfacesMd.trim() || tablesMd.trim())) {
241
+ body.push('---', '', '## 附录 A:契约实体明细', '', [interfacesMd, tablesMd].filter(Boolean).join('\n\n'), '');
257
242
  }
258
243
  // 产物溯源附录(P8):默认不渲染(synth 下每章来源雷同,属噪声);--signoff/调试时开启。
259
244
  if (includeProvenance) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gordon.gan/specflow",
3
- "version": "1.8.4-beta",
3
+ "version": "1.8.5-beta",
4
4
  "type": "module",
5
5
  "description": "SpecFlow — unified spec-driven development: OpenSpec planning + Superpowers execution in one CLI and cross-IDE workflow",
6
6
  "keywords": [
@@ -1,20 +1,19 @@
1
- # 章节填充:api-design(接口与数据设计 · 契约 + 数据模型 + 前端对接)
1
+ # 章节填充:api-design(接口与数据设计 · 接口契约 + 前端对接)
2
2
 
3
3
  你是方案文档撰写员。按大纲要点"填空题"式展开本章,逐要点填充,不自由发挥。
4
4
  - kind=entity|mixed 的要点 → 产出结构化契约实体(JSON 块 ```json {"interfaces": [...], "tables": [...], "decisions": [...]} ```)
5
5
  - kind=narrative|mixed 的要点 → 产出叙述 Markdown
6
- - 遵循 prompts/shared/artifact-language.md 的中文叙述规范(简要;怎么做用 1. 2. 3.)
6
+ - 遵循 prompts/shared/artifact-language.md 的中文叙述规范(简要;怎么做用 1. 2. 3.;**正文中文化**;**叙述分条 + 图文结合**)
7
7
  - 禁止 stub(TODO/待补充/此处省略);禁止含糊词
8
8
  - **事实从工程数据源提取,意图向用户询问,推理由你完成**(见 `prompts/document/shared/grounding.md`):本章涉及的接口字段/表列/组件名/依赖版本必须来自工程,缺失的关键信息列入缺口清单一次性询问用户,禁止编造
9
9
 
10
- ## 本章定位:接口与数据整合呈现(P11)
10
+ ## 本章定位:接口契约承载(P11/P13
11
11
 
12
- 本章同时承载**接口契约**与**数据模型**,二者不得游离:
12
+ 本章承载**接口契约**(渲染为「接口明细」),与「数据模型」章分工:
13
13
 
14
- 1. 固定顺序:接口总览(含面/消费方/生产方)→ 请求字段表 → 请求示例 → 响应字段表 → 响应示例 → 失败示例 → 错误表(按类别)→ **数据流总览与契约-表映射**(每接口 ↔ 读写表/列)→ 表结构与 DDL → 存量填充(G3)→ 回滚兼容(G4)。
15
- 2. **契约-表映射表(强制)**:每个接口一行,列 = 契约 / 读写 / 表·列 / 关键说明。例:`step-results → 写 scenario_step_results(幂等键 execution_job_uid+step_order)`。契约字段与表列必须对得上,禁止接口讲接口、表讲表。
16
- 3. DDL 就近:表结构在本章给出说明,完整 CREATE TABLE 可放附录并交叉引用(零 DDL 迭代必须显式声明「零迁移」,并展示现网 DDL 参考,禁止假装不涉及数据库)。
17
- 4. **跨仓合成(≥2 仓)**:接口**单一定义**——同一 method+path 只定义一个实体,用 `side`(console/worker/internal)与 `consumers`/`producers`(仓名)标注;`<repo>_<id>` 仅作追溯别名,禁止按仓重复。仓归属用 `[repo]` 内联标注或表格「归属」列。
14
+ 1. 固定顺序:接口总览(含面/消费方/生产方)→ 请求字段表 → 请求示例 → 响应字段表 → 响应示例 → 失败示例 → 错误表(按类别)。
15
+ 2. **数据库表不由本章承载**:表结构与 DDL、存量填充(G3)、回滚兼容(G4)、**契约-表映射**全部由「数据模型」章给出;本章在涉及表实体时给一句指引(如"契约-表映射见数据模型章"),**不**在本章写建表语句。
16
+ 3. **跨仓合成(≥2 仓)**:接口**单一定义**——同一 method+path 只定义一个实体,用 `side`(console/worker/internal)与 `consumers`/`producers`(仓名)标注;`<repo>_<id>` 仅作追溯别名,禁止按仓重复。仓归属用 `[repo]` 内联标注或表格「归属」列。
18
17
 
19
18
  ## 接口章节硬规则(借鉴 approval api-guidance + F1/F2 前端对接合并)
20
19
 
@@ -24,19 +23,12 @@
24
23
  4. **G2 失败示例(强制)**:清单中每个接口(含「不变」)除成功示例外,必须 ≥1 组失败示例(参数校验失败/租约过期/未认证),附完整 HTTP 或等价示例。只有错误码表不合格。
25
24
  5. **固定顺序**:元信息(面/消费方/生产方)→ **请求字段表** → **请求示例(真实 JSON body,禁止空壳;无请求体方法显式标注「无请求体」)** → **响应字段表** → **成功响应示例(真实 JSON)** → **失败示例(G2,可附失败响应 body)** → **错误表(backend/guard/internal 分类)**。
26
25
  6. **接口清单稳定编号**:`In` 稳定,供页面引用与跨章交叉引用。
27
- 7. **契约-表映射**:见上文「本章定位」第 2 条,接口清单后紧跟映射表。
28
-
29
- ## 数据模型硬规则(G3/G4)
30
-
31
- 8. 每张表必须有完整 CREATE TABLE(含 ENGINE/CHARSET)与字段说明。
32
- 9. JSON/新列必须有存量填充策略(G3);必须有回滚数据兼容说明(G4)。
33
- 10. 零 DDL 迭代仍须展示现网 DDL(禁止假装不涉及数据库),并显式声明「零迁移」。
34
26
 
35
27
  ## 前端对接维度(O5–O7,F1 §2.2 合并「契约+对接」)
36
28
 
37
- 11. **前端请求封装**:统一请求层(拦截器:token 注入/统一错误处理/超时/重试策略/缓存),DTO → VO 映射层。禁止「每个页面自己 fetch + 自己处理错误」。
38
- 12. **前端错误处理统一**:后端错误码 → 前端统一错误态映射(Loading-Empty-Error),禁止前后端各写一套错误码约定。
39
- 13. **接口 Mock 与契约先行**:前端并行开发用 Mock,Mock 的数据结构必须与冻结契约一致(R5);联调时切换真实接口不改变前端代码结构。
40
- 14. **优先级**:项目约定 + 现网 OpenAPI/proto > SpecFlow 骨架 > LLM。
29
+ 7. **前端请求封装**:统一请求层(拦截器:token 注入/统一错误处理/超时/重试策略/缓存),DTO → VO 映射层。禁止「每个页面自己 fetch + 自己处理错误」。
30
+ 8. **前端错误处理统一**:后端错误码 → 前端统一错误态映射(Loading-Empty-Error),禁止前后端各写一套错误码约定。
31
+ 9. **接口 Mock 与契约先行**:前端并行开发用 Mock,Mock 的数据结构必须与冻结契约一致(R5);联调时切换真实接口不改变前端代码结构。
32
+ 10. **优先级**:项目约定 + 现网 OpenAPI/proto > SpecFlow 骨架 > LLM。
41
33
 
42
34
  > 前后端契约一致性是本章最高门禁:字段名、错误码、DTO 结构前后端必须对齐,禁止各写各的。
@@ -18,7 +18,7 @@
18
18
 
19
19
  3. **C4 分层(AR4)**:按需给 Context(系统上下文,外部系统/用户)/ Container(可部署单元:Web/API/DB/消息)/ Component(模块组件)分层;每层给依赖方向。与 core-flow 的组件层交互时序对接(R5,交叉引用冻结 id)。
20
20
 
21
- 4. **ADR 决策记录(AR5)**:把 tech-selection 的关键决策沉淀为 ADR——背景 / 决策 / 后果 / 备选(为什么不用备选)。引用 tech-selection 的 decisions 实体 id,不另起名。
21
+ 4. **决策理由就地沉淀(AR5,可读性整改)**:关键取舍(如"为什么不用备选方案")写在技术选型章的否决/备选列与风险章的缓解列,**不设独立的 ADR/决策记录章节**。
22
22
 
23
23
  5. **架构一致性自检(AR3)**:对照目标(可扩展/可维护/性能),检查架构是否满足,给出自检结论。
24
24
 
@@ -1,9 +1,16 @@
1
- # 章节填充:core-logic
1
+ # 章节填充:core-logic(关键实现规则)
2
2
 
3
3
  你是方案文档撰写员。按大纲要点"填空题"式展开本章,逐要点填充,不自由发挥。
4
- - kind=entity|mixed 的要点 → 产出结构化契约实体(JSON 块 ```json {"interfaces": [...], "tables": [...], "decisions": [...]} ```)
5
4
  - kind=narrative|mixed 的要点 → 产出叙述 Markdown
6
- - 遵循 prompts/shared/artifact-language.md 的中文叙述规范(简要;怎么做用 1. 2. 3.)
5
+ - 遵循 prompts/shared/artifact-language.md 的中文叙述规范(简要;怎么做用 1. 2. 3.;**正文中文化**)
7
6
  - 禁止 stub(TODO/待补充/此处省略);禁止含糊词
8
7
  - **事实从工程数据源提取,意图向用户询问,推理由你完成**(见 `prompts/document/shared/grounding.md`):本章涉及的接口字段/表列/组件名/依赖版本必须来自工程,缺失的关键信息列入缺口清单一次性询问用户,禁止编造
9
8
  - 涉及项目规约/DB/API/前端约束时,遵循「项目约定 > SpecFlow guidance > LLM」优先级
9
+
10
+ ## 关键实现规则章节硬规则(可读性整改:承接主流程、只写图中未覆盖的规则)
11
+
12
+ 1. **开头必须承接上下文(禁孤立开头)**:第一段用一两句话说明"本章规则承接主业务流程(核心链路/失败分支),回答'每一步在实现上怎么落地'"。禁止直接从"校验 xxx"开始。
13
+ 2. **只写主流程图/时序图未覆盖的细节**:链路、失败分支、幂等并发已在主业务流程章画图并说明的,本章**不得整段重复**——重复内容改用交叉引用(如"失败分叉见主业务流程·失败路径决策图")。
14
+ 3. **按环节分节**:编译规则(排序/展开/校验/信封冻结)→ 执行规则(信封校验/共享变量/失败策略细节)→ 上报规则(写入顺序/幂等键/abort 语义)。每节 1. 2. 3. 编号,一条一句。
15
+ 4. **正文中文化**:正文用中文业务术语(如「运行时信封」「步骤序号」「租约世代」),代码标识符只允许在术语表/字段表/示例中(见 artifact-language.md)。
16
+ 5. **位置**:本章属于主业务流程的"下一环节"——渲染时紧随主业务流程之后;若你发现本章内容 90% 以上已在别章讲过,则应大幅精简并只保留真正新增的规则。
@@ -1,6 +1,6 @@
1
- # 章节填充:data-model(数据结构/数据模型变更)
1
+ # 章节填充:data-model(数据结构/数据模型变更 —— 数据库表的唯一承载章节组件)
2
2
 
3
- > **整合说明(P11)**:跨仓合成(≥2 仓)时,本章内容并入「接口与数据设计」章(api-design)——接口、数据模型与契约-表映射同章呈现,不单独成章。单仓文档可继续独立使用本章。无论哪种形态,**契约-表映射**(每接口读写表/列)都必须给出,禁止接口讲接口、表讲表。
3
+ > **分工说明(P11/P13)**:涉及数据库的表时本组件必选。表结构与 DDL、存量填充(G3)、回滚兼容(G4)、**契约-表映射**全部由本章承载;接口契约本体在「接口与数据设计」章(接口明细)。无论是否跨仓合成,**契约-表映射**(每接口读写表/列)都必须在本章给出,禁止接口讲接口、表讲表。
4
4
 
5
5
  你是方案文档撰写员。按大纲要点"填空题"式展开本章,逐要点填充,不自由发挥。
6
6
  - kind=entity|mixed 的要点 → 产出结构化契约实体(JSON 块 ```json {"interfaces": [...], "tables": [...], "decisions": [...]} ```)
@@ -3,6 +3,11 @@
3
3
  你是方案文档撰写员。按大纲要点"填空题"式展开本章,逐要点填充,不自由发挥。
4
4
  - kind=entity|mixed 的要点 → 产出结构化契约实体(JSON 块 ```json {"interfaces": [...], "tables": [...], "decisions": [...]} ```)
5
5
  - kind=narrative|mixed 的要点 → 产出叙述 Markdown
6
- - 遵循 prompts/shared/artifact-language.md 的中文叙述规范(简要;怎么做用 1. 2. 3.)
6
+ - 遵循 prompts/shared/artifact-language.md 的中文叙述规范(简要;怎么做用 1. 2. 3.;**正文中文化**)
7
7
  - 禁止 stub(TODO/待补充/此处省略);禁止含糊词
8
8
  - **事实从工程数据源提取,意图向用户询问,推理由你完成**(见 `prompts/document/shared/grounding.md`):本章涉及的接口字段/表列/组件名/依赖版本必须来自工程,缺失的关键信息列入缺口清单一次性询问用户,禁止编造
9
+
10
+ ## 需求章节硬规则
11
+
12
+ 1. **不写 Given-When-Then 验收小节**:验收标准已从方案文档移除(可读性整改);验收断言由「测试策略」章承接。本章只写功能需求描述、目标与边界(MVP 范围、跨仓依赖、约束)。
13
+ 2. **目标可验证**:每个目标一句"做成什么状态",但验证落在测试策略章,不在本章列验收表。
@@ -13,7 +13,7 @@
13
13
 
14
14
  2. **测试环境与数据(T2)**:测试环境地址、测试数据准备(fixture/seed/工厂)、Mock 说明(接口 Mock/第三方 Mock)。
15
15
 
16
- 3. **与验收标准映射(T3)**:每条验收标准(GWT)对应到至少一个测试层级,形成可追踪矩阵。
16
+ 3. **验收断言承接(T3,可读性整改)**:验收标准不再单独成章——把 Given-When-Then 断言**折叠进本表**,每行测试加「验收依据」列(如「运行 → 恰一个作业(job_count=1)」「非法引用类型 → 报错且不入队」),确保需求章的目标可验证且可追溯。
17
17
 
18
18
  4. **前端测试金字塔(T4)**:单元 60% / 组件 30% / E2E 10% 的投入比例;组件测试方式写明——Snapshot + 交互(render + fireEvent/userEvent 断言行为),关键组件/页面覆盖率目标。
19
19
 
@@ -44,8 +44,11 @@
44
44
  5. **source_segments**:要点尽量标注来源段 id(来自全局摘要的段 id)。
45
45
  6. **每要点引用 ≤3 个实体**。
46
46
  7. **要点数量**:每章 2-5 个要点,覆盖该章必须覆盖的维度。
47
- 8. **接口与数据整合(P11)**:当 `api-design` 与 `data-model` 同时被选中时,合并为单一「接口与数据设计」章(id 用 `api-design`),数据模型作为该章小节(数据流总览 契约-表映射 → 表结构/DDL → 存量填充 G3 → 回滚 G4),不再单列 `data-model` 章;DDL 可放附录并交叉引用。
48
- 9. **完整性骨架(P7)**:涉及 ≥2 仓的合成文档必须含 `术语与约定`、`非目标汇总`、`风险与开放问题`、`决策记录(ADR)` 章节位(决策在正文用 `[D#]` 引用,先定义后引用)。
47
+ 8. **接口与数据分工(P11/P13)**:`api-design` 与 `data-model` 同时被选中时按「接口与数据设计数据模型」顺序并列两章,**不合并**:
48
+ - 接口契约(请求/响应字段表、示例、错误表)内联进「接口与数据设计」章(渲染为「接口明细」);
49
+ - **数据库表必须由「数据模型」章节组件承载**(表结构与 DDL、字段说明、存量填充 G3、回滚 G4、契约-表映射)——涉及持久化时必须选入 `data-model` 章,禁止把表塞进接口章或忽略;
50
+ - 契约-表映射(每接口 ↔ 读写表/列)写在「数据模型」章,接口约定与数据库通过映射表对齐。
51
+ 9. **完整性骨架(P7)**:涉及 ≥2 仓的合成文档必须含 `术语与约定`、`非目标汇总`、`风险与开放问题` 章节位。**不设决策记录(ADR)章节**——决策理由沉淀在技术选型(否决/备选列)与风险章即可,正文不得使用 `[D#]` 引用。
49
52
  10. **实体注册表增强**:接口实体注册时记录 `side`(console/worker/internal)、`consumers`、`producers`(仓名);同一 method+path 只注册一个实体,`<repo>_<id>` 前缀仅作追溯别名(防 `duplicate_contract`)。
50
53
  11. **主流程含图(P12)**:`core-flow` 章必须输出整体流程图(含失败分支)+ 时序图 + 失败路径决策图,图必须有文字说明。
51
54
  12. **文档头与目录**:最终文档由引擎确定性渲染元信息头(标题/参与仓/生成时间)与目录;大纲只决定章节序与要点,不写文档头。
@@ -85,7 +85,7 @@ OpenAPI(`openapi.yaml`/`swagger.json` 等)、proto3(`*.proto`)、SQL DDL
85
85
 
86
86
  ## 七、整体性文档写作约定(P9/P11,所有章节通用)
87
87
 
88
- 1. **首次定义、后续引用**:术语、决策(`[D#]`)、关键事实(幂等键、零 DDL、禁直连等)只在首次出现处定义,后续一律引用,禁止跨章重复整段(防 P9 重复)。
88
+ 1. **首次定义、后续引用**:术语、关键事实(幂等键、零 DDL、禁直连等)只在首次出现处定义,后续一律引用,禁止跨章重复整段(防 P9 重复)。**不设决策记录(ADR)章、不使用 `[D#]` 引用**——决策理由沉淀在技术选型(否决/备选列)与风险章。
89
89
  2. **接口与数据同源**:接口字段与表列来自同一工程数据源;写契约-表映射时,字段↔列必须一一对齐,禁止接口讲接口、表讲表(P11)。
90
90
  3. **主流程必有图**:涉及多步流程的章节(core-flow 等)必须给出 mermaid 图(整体流程图/时序图),图必须有文字说明(P12)。
91
91
  4. **某仓无内容则不出现**:跨仓写作时,某仓在某维度无内容(如后端无 UI 组件)就**不写该仓的占位小节**,只写真实存在的内容(防"无 X"占位)。
@@ -45,5 +45,14 @@ When `artifacts.language` is `zh-CN`:
45
45
  1. **简要** — 一句一事;禁止套话与大段散文。
46
46
  2. **有条理** — 「怎么做 / 怎么走 / 怎么处理」写成 **1. 2. 3.**,每步一句。
47
47
  3. **不改结构** — 表格、Mermaid、DDL、HTTP 示例、协议标记保持原样。
48
+ 4. **正文中文化(可读性整改)** — 正文叙述必须用**中文业务术语**替代代码标识符:
49
+ - 接口/表用中文名(如「调试执行接口」「逐步结果上报接口」「场景资产表」「作业表」),编号(I1/T3)只出现在接口总览表与字段表。
50
+ - 字段/配置用中文(`ref_type`→引用类型、`step_count`→步骤数、`job_type`→作业类型、`runtime_payload`→运行时信封、`param_overrides`→参数覆盖、`lease_epoch`→租约世代、`step_uid`→步骤标识、`step_order`→步骤序号)。
51
+ - 代码标识符只允许出现在:术语与约定表、接口字段表、JSON/HTTP 示例、代码块内。
52
+ - 首次出现确需给出原名时用括号注(如「运行时信封(runtime_payload)」)。
53
+ 5. **有条理 + 图文结合(可读性整改)**:
54
+ - 叙述内容多的章节**分条输出**:涉及步骤/规则/流程用 **1. 2. 3.** 编号,一句一条,禁止大段散文堆砌。
55
+ - 流程 / 状态流转 / 结构 / 决策分支类内容**必须配 Mermaid 图**(flowchart / sequenceDiagram / stateDiagram-v2),图紧跟一段文字说明——**图文成对**,禁止只有图没有文字、也禁止长叙述没有任何图。
56
+ - 图粒度:一图一事,多流程拆多图。
48
57
 
49
58
  `en`: keep prose brief; numbered steps for how-to. Same table/diagram exception.
@@ -98,9 +98,9 @@ run [--workspace-root <root>]
98
98
  1. **统一大纲**:一次生成一份 outline,章节覆盖所有仓,**不按仓分章**(跨仓对比/汇总放进对应章节)。
99
99
  2. **契约单一定义**:同一物理端点(method+path)只定义一个实体,用 `side`(console/worker/internal)与 `consumers`/`producers`(仓名)标注面与消费方/生产方;`<repo>_<id>` 前缀仅作**追溯别名**,禁止不同仓重复定义同一接口(validate 以 `duplicate_contract` 拦截)。
100
100
  3. **整体性组织(替代按仓分节)**:每章按主题写成一段整体叙述,仓归属用内联 `[repo]` 标注或表格「归属」列;**禁止**为无内容的仓写占位小节(如「某仓无 UI」,validate 以 `repo_section_stub` 拦截);validate 以全文级 `repo_coverage_missing` 防某仓被概括掉。
101
- 4. **全局视角**(若所选 profile 包含对应章节):goal 写多仓总目标与边界;tech-selection 对比各仓技术方案;**接口与数据合并为「接口与数据设计」章**(含契约-表映射表:每接口 读写表/列);closed-loop 跨仓统一闭环检查;implementability 跨仓统一可实施性评估。其他场景章节(如 reproduce/root-cause/fix、requirement/test-strategy、research/poc-demo/benchmark)同样给出跨仓结论。
101
+ 4. **全局视角**(若所选 profile 包含对应章节):goal 写多仓总目标与边界;tech-selection 对比各仓技术方案;**接口与数据分工**——接口契约内联进「接口与数据设计」章(接口明细),**数据库表必须由「数据模型」章组件承载**(DDL/存量 G3/回滚 G4),契约-表映射写数据模型章;closed-loop 跨仓统一闭环检查;implementability 跨仓统一可实施性评估。其他场景章节(如 reproduce/root-cause/fix、requirement/test-strategy、research/poc-demo/benchmark)同样给出跨仓结论。
102
102
  5. **跨仓依赖/风险**:涉及仓间依赖(接口调用/数据共享/发布顺序)时显式标注「跨仓依赖」。
103
- 6. **完整性骨架**:合成文档必须含术语与约定表、非目标汇总、风险与开放问题、决策记录(ADR,正文用 `[D#]` 引用且先定义后引用)。
103
+ 6. **完整性骨架**:合成文档必须含术语与约定表、非目标汇总、风险与开放问题。**不设决策记录(ADR)章节、不用 `[D#]` 引用**——决策理由沉淀在技术选型(否决/备选列)与风险章。
104
104
  7. **契约质量**:接口示例带真实 JSON body(空壳示例拦截)、请求/响应字段分列、错误表按 backend/guard/internal 分类。
105
105
  8. **主流程必须含图**:主业务流程章输出整体流程图(含失败分支)+ 时序图 + 失败路径决策图。
106
106
 
@@ -1,10 +1,10 @@
1
1
  # 接口与数据设计(候选;依赖架构)
2
- # 整合呈现:接口契约(分层契约 + 前端对接)与数据模型(DDL/G3/G4)同章,含契约-表映射表。
3
- # 跨仓合成时遵循 buildSynthRules:接口单一定义(side/consumers/producers)、字段表请求/响应分列、
4
- # 示例带真实 JSON body、错误表按 backend/guard/internal 分类。
2
+ # 接口契约(分层契约 + 前端对接)在本章内联呈现(渲染为「接口明细」);数据库表由「数据模型」章组件承载,
3
+ # 契约-表映射写「数据模型」章。跨仓合成遵循 buildSynthRules:接口单一定义(side/consumers/producers)、
4
+ # 字段表请求/响应分列、示例带真实 JSON body、错误表按 backend/guard/internal 分类。
5
5
  id: api-design
6
6
  title: 接口与数据设计
7
- when: input.containsApiChange || input.hasPersistence
7
+ when: input.containsApiChange
8
8
  depends_on: [architecture]
9
9
  outline_points:
10
10
  - { id: O1, text: 接口总览与调用方/鉴权(含面/消费方/生产方), required: true, kind: narrative }
@@ -14,11 +14,6 @@ outline_points:
14
14
  - { id: O5, text: 前端请求封装(拦截器/重试/缓存/DTO→VO), required: false, kind: narrative }
15
15
  - { id: O6, text: 前端错误处理(错误码统一/Loading-Empty-Error 状态), required: false, kind: narrative }
16
16
  - { id: O7, text: 接口 Mock 与联调(Mock 策略/契约先行,前端可并行开发), required: false, kind: narrative }
17
- - { id: DM1, text: 数据流总览与契约-表映射(每接口 ↔ 读写表/列), required: true, kind: mixed }
18
- - { id: DM2, text: 表结构与 DDL(既有表参考标注), required: true, kind: entity }
19
- - { id: DM3, text: 字段说明 + 本迭代用法, required: true, kind: entity }
20
- - { id: DM4, text: 存量填充策略(G3), required: true, kind: narrative }
21
- - { id: DM5, text: 回滚数据兼容(G4), required: true, kind: narrative }
22
17
  entities:
23
18
  interfaces:
24
19
  required: [id, name, method, path, errors]
@@ -27,11 +22,6 @@ entities:
27
22
  errors_table: required
28
23
  request_example: required
29
24
  success_response_example: required
30
- tables:
31
- required: [id, name, ddl]
32
- each:
33
- migration: required
34
- rollback: required
35
25
  narratives:
36
26
  design_notes: required
37
27
  gates:
@@ -43,8 +33,6 @@ gates:
43
33
  - 错误表按 backend(gRPC→HTTP 映射)/ guard(前端守卫行为)/ internal(Worker 内部语义)分类
44
34
  - 涉及前端对接时,请求封装与错误码统一方案必须与契约对齐(R5,字段名/错误码禁各写各的)
45
35
  - 前端接口 Mock 必须与契约一致(禁 Mock 一套、真实接口另一套)
46
- - 有表实体时必须给出「契约-表映射」(每接口 ↔ 读写表/列)
47
- - 每张表必须有完整 CREATE TABLE(含 ENGINE/CHARSET);零 DDL 迭代仍须展示现网 DDL(禁止假装不涉及数据库)
48
- - JSON/新列必须有存量填充策略(G3);必须有回滚数据兼容说明(G4)
36
+ - 涉及表实体时,契约-表映射由「数据模型」章给出(本处指引引用,不在本章写表 DDL)
49
37
  map_prompt: prompts/document/map/api-design.md
50
- output_budget_tokens: 12000
38
+ output_budget_tokens: 8000
@@ -1,4 +1,4 @@
1
- # 架构设计(0→1 候选;依赖技术选型;扩展:C4 分层 + ADR 决策记录)
1
+ # 架构设计(0→1 候选;依赖技术选型;扩展:C4 分层)
2
2
  id: architecture
3
3
  title: 架构设计
4
4
  when: input.hasLogic && input.hasBackend
@@ -8,7 +8,6 @@ outline_points:
8
8
  - { id: AR2, text: 核心组件与职责边界, required: true, kind: narrative }
9
9
  - { id: AR3, text: 架构一致性自检, required: false, kind: narrative }
10
10
  - { id: AR4, text: C4 分层(Context 系统上下文 / Container 容器 / Component 组件),标注层级与依赖方向, required: false, kind: narrative }
11
- - { id: AR5, text: 关键架构决策记录(ADR:背景/决策/后果/备选,沉淀 tech-selection 的 decisions), required: false, kind: narrative }
12
11
  entities: {}
13
12
  narratives:
14
13
  architecture_notes: required
@@ -1,16 +1,18 @@
1
- # 核心算法 / 逻辑说明
1
+ # 关键实现规则(候选;依赖主业务流程——渲染紧随其后的"下一环节";可读性整改:承接上下文、只写图中未覆盖规则)
2
2
  id: core-logic
3
- title: 核心算法/逻辑
3
+ title: 关键实现规则
4
4
  when: input.hasLogic
5
- depends_on: [architecture]
5
+ depends_on: [core-flow]
6
6
  outline_points:
7
- - { id: LOG1, text: 核心算法/流程说明, required: true, kind: narrative }
8
- - { id: LOG2, text: 边界与异常处理, required: true, kind: narrative }
7
+ - { id: LOG1, text: 编译规则(排序/展开/校验/信封冻结), required: true, kind: narrative }
8
+ - { id: LOG2, text: 执行与上报规则(信封校验/共享变量/失败策略细节/写入顺序/幂等键/abort), required: true, kind: narrative }
9
9
  entities: {}
10
10
  narratives:
11
11
  core_logic: required
12
12
  gates:
13
+ - 开头必须承接主业务流程上下文(一句话说明本规则回答"每一步实现怎么落地"),禁止孤立开头
14
+ - 只写主流程图未覆盖的细节;与主流程/接口章重复的内容必须用交叉引用
13
15
  - 超 5 行流程必须 Mermaid(G1)
14
- - 复杂交互页状态机用 stateDiagram-v2
16
+ - 正文中文化(代码标识符只允许在术语表/字段表/示例)
15
17
  map_prompt: prompts/document/map/core-logic.md
16
18
  output_budget_tokens: 3000
@@ -1,13 +1,16 @@
1
- # 数据模型(候选;依赖接口设计)
1
+ # 数据模型(候选;依赖接口设计)——数据库表的唯一承载章节组件
2
+ # 涉及数据库的表时本组件必选(when hasPersistence):表结构与 DDL、字段说明、存量填充 G3、回滚 G4、
3
+ # 契约-表映射。接口契约本体在「接口与数据设计」章(接口明细),本章通过映射表与接口对齐。
2
4
  id: data-model
3
5
  title: 数据模型
4
6
  when: input.hasPersistence
5
7
  depends_on: [api-design]
6
8
  outline_points:
7
- - { id: DM1, text: 表结构与 DDL, required: true, kind: entity }
8
- - { id: DM2, text: 字段说明 + 本迭代用法, required: true, kind: entity }
9
- - { id: DM3, text: 存量填充策略(G3), required: true, kind: narrative }
10
- - { id: DM4, text: 回滚数据兼容(G4), required: true, kind: narrative }
9
+ - { id: DM1, text: 数据流总览 + 契约-表映射(每接口 ↔ 读写表/列), required: true, kind: mixed }
10
+ - { id: DM2, text: 表结构与 DDL, required: true, kind: entity }
11
+ - { id: DM3, text: 字段说明 + 本迭代用法, required: true, kind: entity }
12
+ - { id: DM4, text: 存量填充策略(G3), required: true, kind: narrative }
13
+ - { id: DM5, text: 回滚数据兼容(G4), required: true, kind: narrative }
11
14
  entities:
12
15
  tables:
13
16
  required: [id, name, ddl]
@@ -18,6 +21,7 @@ narratives:
18
21
  data_notes: required
19
22
  gates:
20
23
  - 每张表必须有完整 CREATE TABLE(含 ENGINE/CHARSET)
24
+ - 有接口实体时必须给出「契约-表映射」(每接口 ↔ 读写表/列),禁止接口讲接口、表讲表
21
25
  - JSON/新列必须有存量填充策略(G3)
22
26
  - 必须有回滚数据兼容说明(G4)
23
27
  - 零 DDL 迭代仍须展示现网 DDL(禁止假装不涉及数据库)
@@ -7,9 +7,6 @@ outline_points:
7
7
  - { id: MVP1, text: MVP 核心功能清单, required: true, kind: entity }
8
8
  - { id: MVP2, text: 后续版本功能, required: true, kind: narrative }
9
9
  - { id: MVP3, text: 预估复杂度与开发阶段, required: true, kind: narrative }
10
- entities:
11
- decisions:
12
- required: [id, text]
13
10
  narratives:
14
11
  mvp_notes: required
15
12
  gates:
@@ -1,18 +1,16 @@
1
- # 需求(feature 必选)
1
+ # 需求(feature 必选;可读性整改:不写验收小节,验证由测试策略承接)
2
2
  id: requirement
3
3
  title: 需求
4
4
  when: null
5
5
  depends_on: []
6
6
  outline_points:
7
7
  - { id: REQ1, text: 功能需求描述, required: true, kind: narrative }
8
- - { id: REQ2, text: 验收标准(Given-When-Then), required: true, kind: mixed }
9
- entities:
10
- decisions:
11
- required: [id, text]
8
+ - { id: REQ2, text: 目标与边界(MVP 范围/跨仓依赖/约束;不写 Given-When-Then 验收), required: true, kind: narrative }
9
+ entities: {}
12
10
  narratives:
13
11
  requirement_notes: required
14
12
  gates:
15
- - 需求必须可验证(有明确验收标准)
16
- - 禁止含糊需求(如「更好的体验」)
13
+ - 需求聚焦目标与边界,禁止含糊需求(如「更好的体验」)
14
+ - 不写 Given-When-Then 验收小节(验收断言由测试策略章承接)
17
15
  map_prompt: prompts/document/map/requirement.md
18
16
  output_budget_tokens: 3000
@@ -8,9 +8,6 @@ outline_points:
8
8
  - { id: TS2, text: 后端/数据库/基础设施选型与理由, required: true, kind: mixed }
9
9
  - { id: TS3, text: 选型理由(为何不用备选), required: true, kind: narrative }
10
10
  - { id: TS4, text: 综合评估矩阵(候选方案 × 评估维度 × 得分 × 权重;F5 预研/选型用), required: false, kind: mixed }
11
- entities:
12
- decisions:
13
- required: [id, text]
14
11
  narratives:
15
12
  selection_reason: required
16
13
  gates:
@@ -6,16 +6,13 @@ depends_on: [api-design, data-model]
6
6
  outline_points:
7
7
  - { id: T1, text: 分层测试矩阵, required: true, kind: entity }
8
8
  - { id: T2, text: 测试环境与数据, required: true, kind: narrative }
9
- - { id: T3, text: 与验收标准的映射, required: true, kind: narrative }
9
+ - { id: T3, text: 验收断言承接(Given-When-Then 折叠进本表,每行加「验收依据」列), required: true, kind: narrative }
10
10
  - { id: T4, text: 前端测试金字塔(单元 60% / 组件 30% / E2E 10%,含组件测试 Snapshot+交互), required: false, kind: narrative }
11
11
  - { id: T5, text: 回归测试范围(对应影响面,覆盖受影响功能), required: false, kind: narrative }
12
- entities:
13
- decisions:
14
- required: [id, text]
15
12
  narratives:
16
13
  test_notes: required
17
14
  gates:
18
- - 每个测试层级必须映射到具体验收标准/场景
15
+ - 每个测试层级必须给出验收依据(承接需求章目标;验收不再单独成章)
19
16
  - 每个层级有工具/框架 + 可验证目标
20
17
  - 不涉及测试变更时显式标注
21
18
  - 涉及前端时,测试金字塔比例与组件测试方式必须写明(禁「跑单测」空话)
@@ -12,9 +12,6 @@ outline_points:
12
12
  - { id: UI6, text: 路由守卫/懒加载(权限/登录态/动态 import), required: false, kind: narrative }
13
13
  - { id: UI7, text: 埋点(页面曝光/点击事件 + 参数), required: false, kind: narrative }
14
14
  - { id: UI8, text: 浏览器兼容策略(版本 + 降级手段,README §1.4), required: false, kind: narrative }
15
- entities:
16
- decisions:
17
- required: [id, text]
18
15
  narratives:
19
16
  ui_notes: required
20
17
  gates:
@@ -12,11 +12,12 @@ required:
12
12
  - implementability # 可实施性评估(7 维)
13
13
  optional_candidates:
14
14
  - ui-design # 前端/UI(条件: uiInScope)
15
- - core-logic # 核心算法/逻辑
15
+ - core-logic # 关键实现规则(依赖闭合用 core-flow)
16
16
  - config-runtime # 配置与运行环境
17
17
  - compat-migration # 兼容性与迁移
18
18
  - acceptance # 验收标准
19
19
  - deploy # 部署/发布/回滚
20
20
  - signoff # 审批意见(签字栏)
21
21
  forbidden: [reproduce, root-cause, impact, fix, regression]
22
- shared: []
22
+ shared:
23
+ - core-flow # 仅依赖闭合:core-logic 依赖 core-flow,approve 不渲染主流程章
@@ -20,4 +20,4 @@ optional_candidates:
20
20
  shared: # 仅闭合允许、不渲染:impact 依赖 root-cause;前端链依赖 frontend-architecture
21
21
  - root-cause
22
22
  - frontend-architecture
23
- forbidden: [reproduce, root-cause, fix, regression, goal, mvp-boundary, non-goals, research, poc-demo, benchmark, migration-guide, deploy, ops, closed-loop, implementability, config-runtime, acceptance]
23
+ forbidden: [reproduce, root-cause, fix, regression, goal, mvp-boundary, research, poc-demo, benchmark, migration-guide, deploy, ops, closed-loop, implementability, config-runtime, acceptance]