@gordon.gan/specflow 1.8.0-beta → 1.8.2-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 (181) hide show
  1. package/README.md +7 -5
  2. package/dist/cli/commands/document-run.d.ts +98 -0
  3. package/dist/cli/commands/document-run.js +1064 -0
  4. package/dist/cli/index.js +2 -2
  5. package/dist/core/artifact-language.js +11 -1
  6. package/dist/core/document/asset-paths.d.ts +15 -0
  7. package/dist/core/document/asset-paths.js +38 -0
  8. package/dist/core/document/chapters.d.ts +6 -0
  9. package/dist/core/document/chapters.js +38 -0
  10. package/dist/core/document/coverage.d.ts +25 -0
  11. package/dist/core/document/coverage.js +49 -0
  12. package/dist/core/document/digests.d.ts +40 -0
  13. package/dist/core/document/digests.js +144 -0
  14. package/dist/core/document/engine.d.ts +101 -0
  15. package/dist/core/document/engine.js +722 -0
  16. package/dist/core/document/extract.d.ts +61 -0
  17. package/dist/core/document/extract.js +437 -0
  18. package/dist/core/{approval → document}/forbidden-patterns.d.ts +4 -2
  19. package/dist/core/document/forbidden-patterns.js +36 -0
  20. package/dist/core/document/gates.d.ts +39 -0
  21. package/dist/core/document/gates.js +75 -0
  22. package/dist/core/document/input-digest.d.ts +63 -0
  23. package/dist/core/document/input-digest.js +200 -0
  24. package/dist/core/document/input-features.d.ts +43 -0
  25. package/dist/core/document/input-features.js +161 -0
  26. package/dist/core/document/lint.d.ts +39 -0
  27. package/dist/core/document/lint.js +147 -0
  28. package/dist/core/document/llm.d.ts +28 -0
  29. package/dist/core/document/llm.js +22 -0
  30. package/dist/core/document/map.d.ts +52 -0
  31. package/dist/core/document/map.js +296 -0
  32. package/dist/core/document/outline.d.ts +29 -0
  33. package/dist/core/document/outline.js +171 -0
  34. package/dist/core/document/paths.d.ts +23 -0
  35. package/dist/core/document/paths.js +36 -0
  36. package/dist/core/document/profile-validator.d.ts +23 -0
  37. package/dist/core/document/profile-validator.js +155 -0
  38. package/dist/core/document/profiles.d.ts +23 -0
  39. package/dist/core/document/profiles.js +76 -0
  40. package/dist/core/document/render.d.ts +61 -0
  41. package/dist/core/document/render.js +243 -0
  42. package/dist/core/document/review.d.ts +57 -0
  43. package/dist/core/document/review.js +202 -0
  44. package/dist/core/document/scene-detect.d.ts +32 -0
  45. package/dist/core/document/scene-detect.js +237 -0
  46. package/dist/core/document/schemas.d.ts +1111 -0
  47. package/dist/core/document/schemas.js +191 -0
  48. package/dist/integrations/shared/capability-evidence.js +4 -9
  49. package/dist/integrations/shared/command-catalog.js +2 -1
  50. package/dist/integrations/shared/parity-manifest.js +4 -9
  51. package/package.json +2 -1
  52. package/prompts/apply/phase-a-plan.md +1 -1
  53. package/prompts/document/map/acceptance.md +9 -0
  54. package/prompts/document/map/anti-ai.md +29 -0
  55. package/prompts/document/map/api-design.md +26 -0
  56. package/prompts/document/map/architecture.md +27 -0
  57. package/prompts/document/map/benchmark.md +26 -0
  58. package/prompts/document/map/closed-loop.md +9 -0
  59. package/prompts/document/map/compat-migration.md +31 -0
  60. package/prompts/document/map/component-design.md +30 -0
  61. package/prompts/document/map/config-runtime.md +9 -0
  62. package/prompts/document/map/core-flow.md +62 -0
  63. package/prompts/document/map/core-logic.md +9 -0
  64. package/prompts/document/map/data-model.md +18 -0
  65. package/prompts/document/map/deploy.md +26 -0
  66. package/prompts/document/map/fix.md +8 -0
  67. package/prompts/document/map/frontend-architecture.md +35 -0
  68. package/prompts/document/map/goal.md +8 -0
  69. package/prompts/document/map/impact.md +8 -0
  70. package/prompts/document/map/implementability.md +9 -0
  71. package/prompts/document/map/migration-guide.md +36 -0
  72. package/prompts/document/map/mvp-boundary.md +8 -0
  73. package/prompts/document/map/non-goals.md +8 -0
  74. package/prompts/document/map/ops.md +33 -0
  75. package/prompts/document/map/performance.md +32 -0
  76. package/prompts/document/map/poc-demo.md +25 -0
  77. package/prompts/document/map/regression.md +8 -0
  78. package/prompts/document/map/reproduce.md +8 -0
  79. package/prompts/document/map/requirement.md +8 -0
  80. package/prompts/document/map/research.md +25 -0
  81. package/prompts/document/map/root-cause.md +8 -0
  82. package/prompts/document/map/signoff.md +9 -0
  83. package/prompts/document/map/state-management.md +23 -0
  84. package/prompts/document/map/tech-selection.md +29 -0
  85. package/prompts/document/map/test-strategy.md +24 -0
  86. package/prompts/document/map/ui-design.md +21 -0
  87. package/prompts/document/outline/general.md +46 -0
  88. package/prompts/document/review/ai-review.md +57 -0
  89. package/prompts/document/shared/grounding.md +84 -0
  90. package/prompts/explore/explore-session.md +1 -1
  91. package/prompts/propose/design-draft.md +1 -1
  92. package/prompts/propose/proposal.md +1 -1
  93. package/prompts/propose/specs.md +1 -1
  94. package/prompts/propose/tasks-draft.md +1 -1
  95. package/prompts/refine/design-output.md +1 -1
  96. package/prompts/refine/update-artifacts.md +2 -0
  97. package/prompts/shared/artifact-language.md +13 -0
  98. package/skills/specflow-techdoc/SKILL.md +143 -0
  99. package/skills/specflow-techdoc-synth/SKILL.md +115 -0
  100. package/templates/document/chapters/acceptance.yaml +16 -0
  101. package/templates/document/chapters/api-design.yaml +29 -0
  102. package/templates/document/chapters/architecture.yaml +21 -0
  103. package/templates/document/chapters/benchmark.yaml +20 -0
  104. package/templates/document/chapters/closed-loop.yaml +22 -0
  105. package/templates/document/chapters/compat-migration.yaml +21 -0
  106. package/templates/document/chapters/component-design.yaml +22 -0
  107. package/templates/document/chapters/config-runtime.yaml +16 -0
  108. package/templates/document/chapters/core-flow.yaml +27 -0
  109. package/templates/document/chapters/core-logic.yaml +16 -0
  110. package/templates/document/chapters/data-model.yaml +25 -0
  111. package/templates/document/chapters/deploy.yaml +22 -0
  112. package/templates/document/chapters/fix.yaml +18 -0
  113. package/templates/document/chapters/frontend-architecture.yaml +22 -0
  114. package/templates/document/chapters/goal.yaml +17 -0
  115. package/templates/document/chapters/impact.yaml +16 -0
  116. package/templates/document/chapters/implementability.yaml +22 -0
  117. package/templates/document/chapters/migration-guide.yaml +21 -0
  118. package/templates/document/chapters/mvp-boundary.yaml +20 -0
  119. package/templates/document/chapters/non-goals.yaml +17 -0
  120. package/templates/document/chapters/ops.yaml +25 -0
  121. package/templates/document/chapters/performance.yaml +21 -0
  122. package/templates/document/chapters/poc-demo.yaml +22 -0
  123. package/templates/document/chapters/regression.yaml +16 -0
  124. package/templates/document/chapters/reproduce.yaml +16 -0
  125. package/templates/document/chapters/requirement.yaml +18 -0
  126. package/templates/document/chapters/research.yaml +22 -0
  127. package/templates/document/chapters/root-cause.yaml +18 -0
  128. package/templates/document/chapters/signoff.yaml +15 -0
  129. package/templates/document/chapters/state-management.yaml +22 -0
  130. package/templates/document/chapters/tech-selection.yaml +23 -0
  131. package/templates/document/chapters/test-strategy.yaml +23 -0
  132. package/templates/document/chapters/ui-design.yaml +28 -0
  133. package/templates/document/profiles/0to1.yaml +44 -0
  134. package/templates/document/profiles/approve.yaml +22 -0
  135. package/templates/document/profiles/bugfix.yaml +15 -0
  136. package/templates/document/profiles/feature.yaml +23 -0
  137. package/templates/document/profiles/frontend-0to1.yaml +47 -0
  138. package/templates/document/profiles/migration.yaml +42 -0
  139. package/templates/document/profiles/poc.yaml +46 -0
  140. package/dist/cli/commands/approval-assemble.d.ts +0 -64
  141. package/dist/cli/commands/approval-assemble.js +0 -408
  142. package/dist/core/approval/assemble.d.ts +0 -10
  143. package/dist/core/approval/assemble.js +0 -384
  144. package/dist/core/approval/bundle.d.ts +0 -9
  145. package/dist/core/approval/bundle.js +0 -172
  146. package/dist/core/approval/forbidden-patterns.js +0 -40
  147. package/dist/core/approval/index-schema.d.ts +0 -676
  148. package/dist/core/approval/index-schema.js +0 -193
  149. package/dist/core/approval/index.d.ts +0 -12
  150. package/dist/core/approval/index.js +0 -9
  151. package/dist/core/approval/lint.d.ts +0 -10
  152. package/dist/core/approval/lint.js +0 -302
  153. package/dist/core/approval/paths.d.ts +0 -13
  154. package/dist/core/approval/paths.js +0 -43
  155. package/dist/core/approval/pipeline.d.ts +0 -28
  156. package/dist/core/approval/pipeline.js +0 -146
  157. package/dist/core/approval/playbook-schema.d.ts +0 -182
  158. package/dist/core/approval/playbook-schema.js +0 -51
  159. package/dist/core/approval/render.d.ts +0 -20
  160. package/dist/core/approval/render.js +0 -210
  161. package/dist/core/approval/review-pack.d.ts +0 -26
  162. package/dist/core/approval/review-pack.js +0 -205
  163. package/dist/core/approval/types.d.ts +0 -223
  164. package/dist/core/approval/types.js +0 -1
  165. package/prompts/approval/acp-pipeline.md +0 -106
  166. package/prompts/approval/ai-review.md +0 -145
  167. package/prompts/approval/api-guidance.md +0 -179
  168. package/prompts/approval/database-guidance.md +0 -105
  169. package/prompts/approval/frontend-guidance.md +0 -249
  170. package/prompts/approval/generate.md +0 -1596
  171. package/prompts/approval/multi-repo-guidance.md +0 -263
  172. package/prompts/approval/multi-repo-spoke-subagent.md +0 -94
  173. package/prompts/approval/project-conventions-guidance.md +0 -171
  174. package/prompts/approval/runtime-guidance.md +0 -64
  175. package/prompts/approval/segmented-generation.md +0 -157
  176. package/skills/specflow-approval/SKILL.md +0 -778
  177. package/templates/approval-index.yaml +0 -93
  178. package/templates/approval-part.md +0 -15
  179. package/templates/approval-playbook-talos-scenario-job-compile.yaml +0 -29
  180. package/templates/approval-playbook.yaml +0 -28
  181. package/templates/approval.md +0 -261
@@ -1,205 +0,0 @@
1
- import { createHash } from 'node:crypto';
2
- import { promises as fs } from 'node:fs';
3
- import { parseApprovalReviewResult } from './playbook-schema.js';
4
- import { readApprovalIndex } from './assemble.js';
5
- import { lintApprovalDocument } from './lint.js';
6
- import { getApprovalPartPath, getApprovalReviewPath, getApprovalReviewPacketPath, } from './paths.js';
7
- const AI_REVIEW_CHECKLIST = [
8
- 'Cross-part naming: same entity/id canonical across §2, §4, diagrams, index.yaml (no 暂定/TBD for listed ids)',
9
- 'Decision traceability: each §2/decisions[] row reflected with concrete behavior in §4',
10
- 'Inventory ↔ body: every index table/interface/page/design_point has substantive content in its part',
11
- 'Depth parity: sibling parts / feature_slices have comparable depth (no one-line stubs next to full sections)',
12
- 'Cross-reference integrity: refs use stable ids (§4.5 In, P*, Page*, T*); targets exist',
13
- 'Diagram ↔ prose: sequence/flow diagrams match adjacent text (actors, messages, errors)',
14
- 'Contract completeness: listed interfaces/page-apis meet Part E minimum (incl. failure example when api_in_scope)',
15
- 'Enum/state closure: status/enum sets explicit and closed where defined (no open-ended 「等」)',
16
- 'Unclosed branches: every mentioned retry/cancel/timeout/idempotency path has outcome or [待 refine 澄清]',
17
- 'UI ↔ API alignment: §4.6 fields and api refs match §4.5 when ui_in_scope',
18
- 'Multi-repo parity: each in-scope repo slice has proportionate depth when multi_repo.enabled',
19
- 'Stub purge: no TODO/待补充/placeholder-only parts',
20
- 'Verdict coherence: §9 readiness matches §4 depth',
21
- ];
22
- function sha256(content) {
23
- return createHash('sha256').update(content, 'utf8').digest('hex');
24
- }
25
- export async function computeReviewPartHashes(changeDir, partIds) {
26
- const hashes = [];
27
- for (const partId of partIds) {
28
- try {
29
- const content = await fs.readFile(getApprovalPartPath(changeDir, partId), 'utf-8');
30
- hashes.push({ id: partId, sha256: sha256(content) });
31
- }
32
- catch {
33
- // missing part handled elsewhere
34
- }
35
- }
36
- return hashes;
37
- }
38
- export async function generateReviewPacket(options) {
39
- const diagnostics = [];
40
- const { changeDir } = options;
41
- let index;
42
- try {
43
- index = await readApprovalIndex(changeDir);
44
- }
45
- catch (error) {
46
- const message = error instanceof Error ? error.message : String(error);
47
- return {
48
- ok: false,
49
- diagnostics: [
50
- { code: 'missing_index', severity: 'error', message: `Cannot read index: ${message}` },
51
- ],
52
- };
53
- }
54
- const lintResult = await lintApprovalDocument({ changeDir, strict: false });
55
- const parts = [];
56
- for (const partId of index.parts_order) {
57
- try {
58
- const content = await fs.readFile(getApprovalPartPath(changeDir, partId), 'utf-8');
59
- parts.push({
60
- id: partId,
61
- sha256: sha256(content),
62
- bytes: Buffer.byteLength(content, 'utf8'),
63
- });
64
- }
65
- catch {
66
- diagnostics.push({
67
- code: 'review_part_missing',
68
- severity: 'warning',
69
- message: `Part "${partId}" missing for review packet`,
70
- part: partId,
71
- });
72
- }
73
- }
74
- const packet = {
75
- schema: 'specflow.approval.review-packet/v1',
76
- change: index.change,
77
- generated_at: new Date().toISOString(),
78
- index_summary: {
79
- interfaces: index.interfaces.length,
80
- pages: index.pages.length,
81
- tables: index.tables.length,
82
- parts: parts.length,
83
- },
84
- lint_diagnostics: lintResult.diagnostics,
85
- parts,
86
- checklist: [...AI_REVIEW_CHECKLIST],
87
- instructions: [
88
- 'Stage 12e AI Review: Read prompts/approval/ai-review.md',
89
- '1. Read approval/review-packet.json and all parts listed',
90
- '2. Fix issues in parts (not in assembled approval.md)',
91
- '3. Write approval/review-result.json with findings + part_hashes (specflow approval review-hashes <change> --json)',
92
- '4. Re-run: specflow approval finalize <change>',
93
- ].join('\n'),
94
- };
95
- const packetPath = getApprovalReviewPacketPath(changeDir);
96
- await fs.writeFile(packetPath, JSON.stringify(packet, null, 2), 'utf-8');
97
- return { ok: true, packet, packetPath, diagnostics };
98
- }
99
- export async function checkApprovalReview(options) {
100
- const diagnostics = [];
101
- const { changeDir, requirePass = true } = options;
102
- let index;
103
- try {
104
- index = await readApprovalIndex(changeDir);
105
- }
106
- catch (error) {
107
- const message = error instanceof Error ? error.message : String(error);
108
- return {
109
- ok: false,
110
- diagnostics: [
111
- { code: 'missing_index', severity: 'error', message: `Cannot read index: ${message}` },
112
- ],
113
- };
114
- }
115
- const reviewRequired = options.forceRequire === true ||
116
- index.acp?.review?.required_pass === true ||
117
- index.acp?.review?.enabled === true;
118
- let review;
119
- try {
120
- const raw = JSON.parse(await fs.readFile(getApprovalReviewPath(changeDir), 'utf-8'));
121
- review = parseApprovalReviewResult(raw);
122
- }
123
- catch {
124
- if (reviewRequired && requirePass) {
125
- return {
126
- ok: false,
127
- diagnostics: [
128
- {
129
- code: 'review_missing',
130
- severity: 'error',
131
- message: 'approval/review-result.json missing; run AI review (Stage 12e) and write review-result.json',
132
- },
133
- ],
134
- };
135
- }
136
- return { ok: true, diagnostics: [] };
137
- }
138
- if (review.change !== index.change) {
139
- diagnostics.push({
140
- code: 'review_change_mismatch',
141
- severity: 'error',
142
- message: `review-result change "${review.change}" != index change "${index.change}"`,
143
- });
144
- }
145
- const openFindings = review.findings.filter((f) => f.status === 'open');
146
- for (const f of openFindings) {
147
- diagnostics.push({
148
- code: 'review_finding_open',
149
- severity: f.severity === 'critical' ? 'error' : 'warning',
150
- message: `[${f.id}] ${f.message}`,
151
- part: f.part,
152
- });
153
- }
154
- const waivedWithoutReason = review.findings.filter((f) => f.status === 'waived' && !f.waiver_reason?.trim());
155
- for (const f of waivedWithoutReason) {
156
- diagnostics.push({
157
- code: 'review_waiver_missing_reason',
158
- severity: 'error',
159
- message: `[${f.id}] waived finding must include waiver_reason`,
160
- part: f.part,
161
- });
162
- }
163
- if (review.verdict === 'fail') {
164
- diagnostics.push({
165
- code: 'review_verdict_fail',
166
- severity: 'error',
167
- message: 'review-result verdict is fail',
168
- });
169
- }
170
- if (review.part_hashes && review.part_hashes.length > 0) {
171
- for (const entry of review.part_hashes) {
172
- try {
173
- const content = await fs.readFile(getApprovalPartPath(changeDir, entry.id), 'utf-8');
174
- const current = sha256(content);
175
- if (current !== entry.sha256) {
176
- diagnostics.push({
177
- code: 'review_part_stale',
178
- severity: 'error',
179
- message: `Part "${entry.id}" changed after AI review; re-run Stage 12e and update review-result.json part_hashes`,
180
- part: entry.id,
181
- });
182
- }
183
- }
184
- catch {
185
- diagnostics.push({
186
- code: 'review_part_missing',
187
- severity: 'error',
188
- message: `Part "${entry.id}" in review-result.part_hashes not found on disk`,
189
- part: entry.id,
190
- });
191
- }
192
- }
193
- }
194
- else if (reviewRequired) {
195
- diagnostics.push({
196
- code: 'review_part_hashes_missing',
197
- severity: 'error',
198
- message: 'review-result.json must include part_hashes[] (sha256 of each part after fixes); see ai-review.md §4',
199
- });
200
- }
201
- const lintResult = await lintApprovalDocument({ changeDir, strict: true });
202
- diagnostics.push(...lintResult.diagnostics);
203
- const hasError = diagnostics.some((d) => d.severity === 'error');
204
- return { ok: !hasError, review, diagnostics };
205
- }
@@ -1,223 +0,0 @@
1
- export type ApprovalGenerationMode = 'segmented' | 'monolithic';
2
- export type ApprovalPartStatus = 'draft' | 'ok' | 'retry';
3
- export interface ApprovalOptionalChapters {
4
- readonly s5: boolean;
5
- readonly s7: boolean;
6
- readonly s8: boolean;
7
- }
8
- export interface ApprovalBatching {
9
- readonly tables_per_call: number;
10
- readonly interfaces_per_call: number;
11
- readonly pages_per_call: number;
12
- readonly capabilities_per_call: number;
13
- }
14
- export type ApprovalRepoRole = 'platform' | 'web' | 'worker' | 'hub' | 'other';
15
- export type ApprovalDocumentMode = 'unified' | 'per_repo';
16
- export interface ApprovalMultiRepoEntry {
17
- readonly id: string;
18
- readonly label: string;
19
- readonly role?: ApprovalRepoRole;
20
- readonly change: string;
21
- readonly root_hint?: string;
22
- }
23
- export interface ApprovalOutputRef {
24
- readonly repo: string;
25
- readonly change: string;
26
- readonly path: string;
27
- }
28
- export interface ApprovalMultiRepoBundle {
29
- readonly enabled?: boolean;
30
- readonly playbook?: string;
31
- readonly output?: string;
32
- readonly readonly?: boolean;
33
- }
34
- export interface ApprovalMultiRepo {
35
- readonly enabled: boolean;
36
- readonly document_mode?: ApprovalDocumentMode;
37
- readonly primary_repo?: string;
38
- readonly repos: readonly ApprovalMultiRepoEntry[];
39
- readonly outputs?: {
40
- readonly unified?: ApprovalOutputRef;
41
- readonly per_repo?: readonly ApprovalOutputRef[];
42
- };
43
- readonly bundle?: ApprovalMultiRepoBundle;
44
- }
45
- export interface ApprovalFeatureSlice {
46
- readonly id: string;
47
- readonly repos?: readonly string[];
48
- readonly interfaces?: readonly string[];
49
- readonly pages?: readonly string[];
50
- readonly design_points?: readonly string[];
51
- readonly parts: readonly string[];
52
- }
53
- export interface ApprovalAcpReview {
54
- readonly enabled?: boolean;
55
- readonly required_pass?: boolean;
56
- }
57
- export interface ApprovalAcpBlock {
58
- readonly pipeline?: 'acp/v1' | 'acp/v2';
59
- readonly context_budget_tokens?: number;
60
- readonly output_budget_tokens?: number;
61
- readonly feature_slices?: readonly ApprovalFeatureSlice[];
62
- readonly review?: ApprovalAcpReview;
63
- }
64
- export interface ApprovalTableRef {
65
- readonly id: string;
66
- readonly name: string;
67
- readonly action: string;
68
- readonly part: string;
69
- readonly repo?: string;
70
- }
71
- export interface ApprovalInterfaceFrozen {
72
- readonly rpc?: string;
73
- readonly http_path?: string;
74
- readonly status_enum?: readonly string[];
75
- }
76
- export interface ApprovalInterfaceRef {
77
- readonly id: string;
78
- readonly short: string;
79
- readonly change: string;
80
- readonly part: string;
81
- readonly repo?: string;
82
- readonly layers?: readonly string[];
83
- readonly pairs_with?: string;
84
- readonly feature_slice?: string;
85
- readonly frozen?: ApprovalInterfaceFrozen;
86
- }
87
- export interface ApprovalPageRef {
88
- readonly id: string;
89
- readonly route: string;
90
- readonly apis: readonly string[];
91
- readonly part: string;
92
- readonly repo?: string;
93
- }
94
- export interface ApprovalCapabilityRef {
95
- readonly id: string;
96
- readonly part: string;
97
- }
98
- export interface ApprovalConventionsResolved {
99
- readonly architecture?: readonly string[];
100
- readonly database?: readonly string[];
101
- readonly api?: readonly string[];
102
- readonly frontend?: readonly string[];
103
- }
104
- export interface ApprovalIndex {
105
- readonly schema: 'specflow.approval.index/v1';
106
- readonly change: string;
107
- readonly generated_at: string;
108
- readonly mode: ApprovalGenerationMode;
109
- readonly ui_in_scope: boolean;
110
- readonly db_in_scope: boolean;
111
- readonly api_in_scope: boolean;
112
- readonly optional: ApprovalOptionalChapters;
113
- readonly parts_order: readonly string[];
114
- readonly design_points: readonly string[];
115
- readonly decisions: readonly string[];
116
- readonly tables: readonly ApprovalTableRef[];
117
- readonly interfaces: readonly ApprovalInterfaceRef[];
118
- readonly pages: readonly ApprovalPageRef[];
119
- readonly capabilities: readonly ApprovalCapabilityRef[];
120
- readonly batching: ApprovalBatching;
121
- readonly conventions: ApprovalConventionsResolved;
122
- readonly multi_repo?: ApprovalMultiRepo;
123
- readonly acp?: ApprovalAcpBlock;
124
- readonly meta?: {
125
- readonly language?: string;
126
- readonly tech_stack?: string;
127
- readonly project_mode?: string;
128
- };
129
- }
130
- export interface ApprovalManifestPart {
131
- readonly id: string;
132
- readonly path: string;
133
- readonly status: ApprovalPartStatus;
134
- readonly sha256?: string;
135
- readonly updated_at?: string;
136
- }
137
- export interface ApprovalManifest {
138
- readonly schema: 'specflow.approval.manifest/v1';
139
- readonly change: string;
140
- readonly parts: readonly ApprovalManifestPart[];
141
- readonly assembled_at?: string;
142
- readonly approval_sha256?: string;
143
- }
144
- export type ApprovalDiagnosticSeverity = 'error' | 'warning';
145
- export interface ApprovalDiagnostic {
146
- readonly code: string;
147
- readonly severity: ApprovalDiagnosticSeverity;
148
- readonly message: string;
149
- readonly part?: string;
150
- }
151
- export interface ApprovalReviewFinding {
152
- readonly id: string;
153
- readonly severity: 'critical' | 'important' | 'minor';
154
- readonly category: string;
155
- readonly message: string;
156
- readonly part?: string;
157
- readonly status: 'open' | 'fixed' | 'waived';
158
- readonly waiver_reason?: string;
159
- }
160
- export interface ApprovalReviewResult {
161
- readonly schema: 'specflow.approval.review/v1';
162
- readonly change: string;
163
- readonly reviewed_at: string;
164
- readonly reviewer: 'ai' | 'human';
165
- readonly findings: readonly ApprovalReviewFinding[];
166
- readonly verdict: 'pass' | 'fail' | 'pass_with_waivers';
167
- readonly summary?: string;
168
- readonly part_hashes?: readonly {
169
- readonly id: string;
170
- readonly sha256: string;
171
- }[];
172
- }
173
- export interface ApprovalReviewPacket {
174
- readonly schema: 'specflow.approval.review-packet/v1';
175
- readonly change: string;
176
- readonly generated_at: string;
177
- readonly index_summary: {
178
- readonly interfaces: number;
179
- readonly pages: number;
180
- readonly tables: number;
181
- readonly parts: number;
182
- };
183
- readonly lint_diagnostics: readonly ApprovalDiagnostic[];
184
- readonly parts: readonly {
185
- readonly id: string;
186
- readonly sha256: string;
187
- readonly bytes: number;
188
- }[];
189
- readonly checklist: readonly string[];
190
- readonly instructions: string;
191
- }
192
- export interface ApprovalPlaybookSource {
193
- readonly repo: string;
194
- readonly change: string;
195
- readonly include_parts?: 'all' | readonly string[];
196
- readonly root?: string;
197
- }
198
- export interface ApprovalPlaybook {
199
- readonly schema: 'specflow.approval.playbook/v1';
200
- readonly change: string;
201
- readonly title: string;
202
- readonly primary_repo: string;
203
- readonly sources: readonly ApprovalPlaybookSource[];
204
- readonly overlay?: readonly string[];
205
- readonly assemble: {
206
- readonly inject_headers?: boolean;
207
- readonly dedupe_appendix?: boolean;
208
- readonly output: string;
209
- readonly readonly?: boolean;
210
- };
211
- }
212
- export interface ApprovalBundleResult {
213
- readonly ok: boolean;
214
- readonly outputPath?: string;
215
- readonly diagnostics: readonly ApprovalDiagnostic[];
216
- readonly markdown?: string;
217
- }
218
- export interface ApprovalAssembleResult {
219
- readonly markdown?: string;
220
- readonly outputPath?: string;
221
- readonly diagnostics: readonly ApprovalDiagnostic[];
222
- readonly ok: boolean;
223
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,106 +0,0 @@
1
- # Approval · ACP Pipeline (Approval Compiler Pipeline)
2
-
3
- > Router for `/specflow:approval` **Stage 12** when `acp.pipeline=acp/v2` (recommended for non-lightweight changes).
4
- > Legacy segmented flow remains valid; ACP adds **lint**, **AI review**, and **bundle** gates.
5
-
6
- ---
7
-
8
- ## Pipeline (hard order)
9
-
10
- ```text
11
- Phase 1 Analyze → analysis.json + IR planner (chat gate)
12
- Phase 2 IR Freeze → index.yaml (+ interfaces[].frozen, feature_slices, acp.review)
13
- Phase 3 Skeleton → parts 01–03, 04-detail-core, 06/09/10
14
- Phase 4 Slot Map → batched parts 04.4–04.9 (vertical slice first)
15
- Phase 5 AI Review → Stage 12e in-session (prompts/approval/ai-review.md) — **inside /specflow-approval**
16
- Phase 6 finalize → specflow approval finalize <change> [--bundle] [--render]
17
- Phase 7 render → specflow approval render <change> [--input] [--output]
18
-
19
- **Preferred**: one `finalize` after Map + AI review. Subcommands (`lint`, `assemble`, …) are for CI/debug only.
20
- ```
21
-
22
- **Never** skip Phase 6a–6b with LLM paste. **Never** write `approval-unified.md` by hand when bundle is enabled.
23
-
24
- ---
25
-
26
- ## index.yaml ACP block
27
-
28
- ```yaml
29
- acp:
30
- pipeline: acp/v2
31
- context_budget_tokens: 40000
32
- output_budget_tokens: 8000
33
- feature_slices:
34
- - id: step-reporting
35
- parts: [04.5-api-worker, 04.5-api-east, 04-detail-core]
36
- interfaces: [I13, I14, I16, I17]
37
- review:
38
- enabled: true
39
- required_pass: true
40
- ```
41
-
42
- ## interfaces[].frozen (IR freeze before Map)
43
-
44
- ```yaml
45
- interfaces:
46
- - id: I14
47
- short: SubmitStepResult
48
- change: scenario-job-compile
49
- part: 04.5-api-worker
50
- pairs_with: I13
51
- layers: [L3]
52
- frozen:
53
- rpc: scheduler.Scheduler.SubmitStepResult
54
- http_path: POST /internal/v1/tasks/{job_id}/step-results
55
- status_enum: [passed, failed, skipped, error]
56
- ```
57
-
58
- ---
59
-
60
- ## Multi-repo default
61
-
62
- - **True source**: `per_repo` — each repo `approval/` + `approval.md`
63
- - **Read-only view**: `approval bundle` from `approval-playbook.yaml`
64
- - Do **not** LLM-unify three repos into one primary `approval/parts`
65
-
66
- See `multi-repo-guidance.md` + `templates/approval-playbook.yaml` (+ example `templates/approval-playbook-talos-scenario-job-compile.yaml`).
67
-
68
- **Orchestration**: multi-repo mode A uses **Stage 1c** subagent parallel dispatch (`multi-repo-spoke-subagent.md`) — not a single-repo `finalize` across repos.
69
-
70
- ---
71
-
72
- ## Context packet (Map batch)
73
-
74
- Read only:
75
-
76
- 1. `index.yaml` subset for this batch (ids + frozen fields)
77
- 2. `analysis.json` verdicts (not full Pass essays)
78
- 3. design/spec **snippets** for batch entities
79
- 4. 1–2 anchor files for this batch
80
- 5. guidance router (path only, not full paste)
81
-
82
- Do **not** reload entire four-artifact sets each batch.
83
-
84
- ---
85
-
86
- ## CLI reference
87
-
88
- | Command | Purpose |
89
- |---------|---------|
90
- | `approval render` | MD → standalone HTML (tables, GFM, mermaid via CDN) |
91
- | `approval finalize` | **Preferred** — full lint → review-check → check → assemble → bundle |
92
- | `approval lint` | Cross-part consistency (CI / debug) |
93
- | `approval review-pack` | Emit `review-packet.json` (debug; finalize auto-runs when needed) |
94
- | `approval review-check` | Validate `review-result.json` (debug) |
95
- | `approval check` | Part presence + lazy stub (debug) |
96
- | `approval assemble` | Deterministic Reduce (debug) |
97
- | `approval bundle` | Multi-repo readonly merge (debug; finalize can auto-run) |
98
-
99
- ---
100
-
101
- ## Related guidance
102
-
103
- - `segmented-generation.md` — Map anti-lazy L1–L10
104
- - `ai-review.md` — Stage 12e AI approval/revision
105
- - `runtime-guidance.md` — optional async/lease/cancel (when in scope)
106
- - `api-guidance.md` — optional multi-layer API contracts (when api_in_scope)
@@ -1,145 +0,0 @@
1
- # Approval · Stage 12e AI Review (审批 / 修订)
2
-
3
- > Runs **after** Map parts written, **before** `specflow approval finalize` completes.
4
- > Purpose: catch **long-document / multi-part semantic drift** that mechanical lint cannot judge; **revise parts in place**.
5
-
6
- **Scope**: checks apply to **any** segmented approval — not tied to a specific product, repo, or domain.
7
- Use `index.yaml` + `analysis.json` as the contract; do not inject checks from unrelated case studies.
8
-
9
- ---
10
-
11
- ## 0. Trigger
12
-
13
- Run when **any**:
14
-
15
- - `acp.review.enabled=true` in `index.yaml` (default for non-lightweight)
16
- - User asks for AI 审批 / 方案审查 / 一致性检查
17
- - `specflow approval finalize` paused at `review-required`
18
-
19
- ---
20
-
21
- ## 1. Prep (hard)
22
-
23
- ```bash
24
- specflow approval finalize <change> # pauses + writes review-packet.json if needed
25
- ```
26
-
27
- Read:
28
-
29
- - `approval/review-packet.json` (checklist + lint diagnostics)
30
- - `approval/index.yaml` (inventory, design_points, frozen fields, parts_order)
31
- - `approval/analysis.json` (Pass verdicts — gaps to close)
32
- - **All** `approval/parts/*.md` in `parts_order`
33
-
34
- Optional domain packs (only when design **actually** touches that topic):
35
-
36
- - `runtime-guidance.md` — async job / lease / retry / cancel semantics
37
- - `api-guidance.md` — multi-layer API contracts
38
- - `frontend-guidance.md` — §4.6 depth
39
-
40
- ---
41
-
42
- ## 2. Review dimensions (long-document generic)
43
-
44
- These target **failure modes of long, batched documents** — inconsistency across parts written at different times.
45
-
46
- | ID | Category | Check (generic) |
47
- |----|----------|-----------------|
48
- | R1 | **Cross-part naming** | Same entity (service, table, interface, page, enum) uses **one** canonical name/id across §2, §4, diagrams, and `index.yaml`. No 「暂定 / 实现时 / 如 Xxx / TBD」 for listed inventory ids. |
49
- | R2 | **Decision traceability** | Each `decisions[]` / §2 row appears in §4 with concrete behavior — not only repeated in summary. |
50
- | R3 | **Inventory ↔ body** | Every `tables[]` / `interfaces[]` / `pages[]` / `design_points[]` entry in index has **substantive** content in its assigned `part`. No orphan ids; no body content for ids missing from index. |
51
- | R4 | **Depth parity** | Parts in the same `feature_slices` or batch have **comparable** depth. No pattern of one part fully detailed while sibling parts are one-line stubs. |
52
- | R5 | **Cross-reference integrity** | Internal refs use stable ids (`§4.5 I2`, `P3`, `Page·列表`, `T1`) — not bare 「详见 design/tasks」. Ref targets exist and match. |
53
- | R6 | **Diagram ↔ prose** | Sequence / flow diagrams agree with adjacent prose (actors, message names, order, error branches). |
54
- | R7 | **Contract completeness** | Each listed interface/page-api has minimum skeleton from Part E (fields, success example, **failure example**, error table) — depth scaled to `api_in_scope` / `ui_in_scope`. |
55
- | R8 | **Enum / state closure** | Status, enum, and terminal-state sets are **explicit and closed** wherever the doc defines them — no 「等」 or open-ended lists unless explicitly extensible by design. |
56
- | R9 | **Unclosed branches** | Every **mentioned** branch (retry, cancel, timeout, idempotency, rollback, concurrency) has a documented outcome — or is flagged `[待 refine 澄清: …]` with owner. Do **not** assume domain-specific branches (e.g. lease reclaim) unless design/analysis mentions them. |
57
- | R10 | **UI ↔ API alignment** | When `ui_in_scope`: §4.6 field names, types, and api refs align with §4.5 / `pages[].apis`. |
58
- | R11 | **Multi-repo parity** | When `multi_repo.enabled`: each repo slice in scope has proportionate depth; no 「主仓详、他仓 stub」 unless explicitly out of scope. |
59
- | R12 | **Stub purge** | No `TODO` / `待补充` / `此处省略` / placeholder-only sections in parts slated for assemble. |
60
- | R13 | **Verdict coherence** | §9 implementability / readiness matches §4 depth — no READY alongside unexplained NEEDS REFINEMENT or contradictory gates. |
61
-
62
- **Not in default scope**: product-specific rules (talos lease wipe, ingest whitelist, L2/L3 layering) — load the matching guidance pack **only** when the change design requires it.
63
-
64
- ---
65
-
66
- ## 3. Revision rules (hard)
67
-
68
- 1. **Edit `approval/parts/*.md` only** — never edit assembled `approval.md` directly
69
- 2. **Update `index.yaml` first** when changing frozen ids, rpc names, or inventory
70
- 3. Each finding → fix in named `part` OR waive (`minor` only) with `waiver_reason`
71
- 4. Re-run:
72
-
73
- ```bash
74
- specflow approval finalize <change>
75
- ```
76
-
77
- ---
78
-
79
- ## 4. Write review-result.json
80
-
81
- Path: `approval/review-result.json`
82
-
83
- ```json
84
- {
85
- "schema": "specflow.approval.review/v1",
86
- "change": "<change-name>",
87
- "reviewed_at": "2026-08-26T12:00:00Z",
88
- "reviewer": "ai",
89
- "verdict": "pass",
90
- "summary": "Fixed cross-part naming for I3; expanded P2 error path in 04-detail-core",
91
- "part_hashes": [
92
- { "id": "04.5-api", "sha256": "<sha256-after-fixes>" },
93
- { "id": "04-detail-core", "sha256": "<sha256-after-fixes>" }
94
- ],
95
- "findings": [
96
- {
97
- "id": "F1",
98
- "severity": "critical",
99
- "category": "cross_part_naming",
100
- "message": "I3 RPC name differs between §2 and 04.5-api",
101
- "part": "04.5-api",
102
- "status": "fixed"
103
- },
104
- {
105
- "id": "F2",
106
- "severity": "important",
107
- "category": "unclosed_branch",
108
- "message": "Retry path mentioned in §4.3 but no terminal outcome",
109
- "part": "04-detail-core",
110
- "status": "fixed"
111
- }
112
- ]
113
- }
114
- ```
115
-
116
- | verdict | When |
117
- |---------|------|
118
- | `pass` | All findings `fixed`; strict lint pass; **`part_hashes` match current parts** |
119
- | `pass_with_waivers` | Only `minor` waived with `waiver_reason` |
120
- | `fail` | Any `critical` / `important` still `open` |
121
-
122
- **Waive policy**: only `minor` may be waived; critical/important must fix or escalate to user.
123
-
124
- **part_hashes (required when `acp.review.enabled`)**: After fixing parts, run `specflow approval review-hashes <change> --json` and copy the array into `review-result.json`. `review-check` fails if parts change after review without updating review-result.
125
-
126
- ---
127
-
128
- ## 5. User gate
129
-
130
- When a finding requires a **product/architecture choice** the artifacts do not resolve:
131
-
132
- ```text
133
- [待用户确认] <topic>: options A / B / C — record choice as new decision + update affected parts
134
- ```
135
-
136
- Stop finalize until user chooses; do not invent policy.
137
-
138
- ---
139
-
140
- ## 6. Announce
141
-
142
- ```text
143
- AI Review: findings=<n> fixed=<n> waived=<n> verdict=pass|fail
144
- Next: specflow approval finalize <change>
145
- ```