@prd-improve/cli 1.0.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 (209) hide show
  1. package/README.md +38 -0
  2. package/dist/anchor-slicer.d.ts +18 -0
  3. package/dist/anchor-slicer.js +114 -0
  4. package/dist/anchor-slicer.js.map +1 -0
  5. package/dist/api/client.d.ts +68 -0
  6. package/dist/api/client.js +175 -0
  7. package/dist/api/client.js.map +1 -0
  8. package/dist/changelog.d.ts +9 -0
  9. package/dist/changelog.js +34 -0
  10. package/dist/changelog.js.map +1 -0
  11. package/dist/cli.d.ts +2 -0
  12. package/dist/cli.js +258 -0
  13. package/dist/cli.js.map +1 -0
  14. package/dist/commands/admin/_adminJson.d.ts +18 -0
  15. package/dist/commands/admin/_adminJson.js +27 -0
  16. package/dist/commands/admin/_adminJson.js.map +1 -0
  17. package/dist/commands/admin/_authResolve.d.ts +8 -0
  18. package/dist/commands/admin/_authResolve.js +56 -0
  19. package/dist/commands/admin/_authResolve.js.map +1 -0
  20. package/dist/commands/admin/index.d.ts +22 -0
  21. package/dist/commands/admin/index.js +100 -0
  22. package/dist/commands/admin/index.js.map +1 -0
  23. package/dist/commands/admin/io.d.ts +15 -0
  24. package/dist/commands/admin/io.js +30 -0
  25. package/dist/commands/admin/io.js.map +1 -0
  26. package/dist/commands/admin/member.d.ts +43 -0
  27. package/dist/commands/admin/member.js +362 -0
  28. package/dist/commands/admin/member.js.map +1 -0
  29. package/dist/commands/admin/project.d.ts +40 -0
  30. package/dist/commands/admin/project.js +182 -0
  31. package/dist/commands/admin/project.js.map +1 -0
  32. package/dist/commands/admin/team.d.ts +31 -0
  33. package/dist/commands/admin/team.js +157 -0
  34. package/dist/commands/admin/team.js.map +1 -0
  35. package/dist/commands/admin/teamMember.d.ts +33 -0
  36. package/dist/commands/admin/teamMember.js +262 -0
  37. package/dist/commands/admin/teamMember.js.map +1 -0
  38. package/dist/commands/admin/token.d.ts +29 -0
  39. package/dist/commands/admin/token.js +125 -0
  40. package/dist/commands/admin/token.js.map +1 -0
  41. package/dist/commands/admin/user.d.ts +2 -0
  42. package/dist/commands/admin/user.js +85 -0
  43. package/dist/commands/admin/user.js.map +1 -0
  44. package/dist/commands/config.d.ts +9 -0
  45. package/dist/commands/config.js +178 -0
  46. package/dist/commands/config.js.map +1 -0
  47. package/dist/commands/context.d.ts +11 -0
  48. package/dist/commands/context.js +235 -0
  49. package/dist/commands/context.js.map +1 -0
  50. package/dist/commands/diff.d.ts +6 -0
  51. package/dist/commands/diff.js +208 -0
  52. package/dist/commands/diff.js.map +1 -0
  53. package/dist/commands/freeze.d.ts +10 -0
  54. package/dist/commands/freeze.js +269 -0
  55. package/dist/commands/freeze.js.map +1 -0
  56. package/dist/commands/init.d.ts +24 -0
  57. package/dist/commands/init.js +229 -0
  58. package/dist/commands/init.js.map +1 -0
  59. package/dist/commands/login.d.ts +26 -0
  60. package/dist/commands/login.js +241 -0
  61. package/dist/commands/login.js.map +1 -0
  62. package/dist/commands/logout.d.ts +6 -0
  63. package/dist/commands/logout.js +75 -0
  64. package/dist/commands/logout.js.map +1 -0
  65. package/dist/commands/migrate-yaml.d.ts +17 -0
  66. package/dist/commands/migrate-yaml.js +288 -0
  67. package/dist/commands/migrate-yaml.js.map +1 -0
  68. package/dist/commands/project.d.ts +7 -0
  69. package/dist/commands/project.js +87 -0
  70. package/dist/commands/project.js.map +1 -0
  71. package/dist/commands/pull.d.ts +16 -0
  72. package/dist/commands/pull.js +197 -0
  73. package/dist/commands/pull.js.map +1 -0
  74. package/dist/commands/push.d.ts +9 -0
  75. package/dist/commands/push.js +392 -0
  76. package/dist/commands/push.js.map +1 -0
  77. package/dist/commands/refresh.d.ts +9 -0
  78. package/dist/commands/refresh.js +123 -0
  79. package/dist/commands/refresh.js.map +1 -0
  80. package/dist/commands/status.d.ts +7 -0
  81. package/dist/commands/status.js +190 -0
  82. package/dist/commands/status.js.map +1 -0
  83. package/dist/commands/team.d.ts +6 -0
  84. package/dist/commands/team.js +84 -0
  85. package/dist/commands/team.js.map +1 -0
  86. package/dist/commands/validate.d.ts +5 -0
  87. package/dist/commands/validate.js +129 -0
  88. package/dist/commands/validate.js.map +1 -0
  89. package/dist/commands/whoami.d.ts +6 -0
  90. package/dist/commands/whoami.js +81 -0
  91. package/dist/commands/whoami.js.map +1 -0
  92. package/dist/config/adminBackend.d.ts +43 -0
  93. package/dist/config/adminBackend.js +33 -0
  94. package/dist/config/adminBackend.js.map +1 -0
  95. package/dist/config/rc.d.ts +70 -0
  96. package/dist/config/rc.js +148 -0
  97. package/dist/config/rc.js.map +1 -0
  98. package/dist/config/schema.d.ts +132 -0
  99. package/dist/config/schema.js +36 -0
  100. package/dist/config/schema.js.map +1 -0
  101. package/dist/diff/engine.d.ts +35 -0
  102. package/dist/diff/engine.js +305 -0
  103. package/dist/diff/engine.js.map +1 -0
  104. package/dist/diff/render.d.ts +18 -0
  105. package/dist/diff/render.js +129 -0
  106. package/dist/diff/render.js.map +1 -0
  107. package/dist/formatter/colors.d.ts +17 -0
  108. package/dist/formatter/colors.js +35 -0
  109. package/dist/formatter/colors.js.map +1 -0
  110. package/dist/formatter/human.d.ts +7 -0
  111. package/dist/formatter/human.js +70 -0
  112. package/dist/formatter/human.js.map +1 -0
  113. package/dist/fs/atomicWrite.d.ts +7 -0
  114. package/dist/fs/atomicWrite.js +37 -0
  115. package/dist/fs/atomicWrite.js.map +1 -0
  116. package/dist/i18n/dispatch.d.ts +19 -0
  117. package/dist/i18n/dispatch.js +27 -0
  118. package/dist/i18n/dispatch.js.map +1 -0
  119. package/dist/i18n/en.d.ts +3 -0
  120. package/dist/i18n/en.js +275 -0
  121. package/dist/i18n/en.js.map +1 -0
  122. package/dist/i18n/help.d.ts +3 -0
  123. package/dist/i18n/help.en.d.ts +149 -0
  124. package/dist/i18n/help.en.js +150 -0
  125. package/dist/i18n/help.en.js.map +1 -0
  126. package/dist/i18n/help.js +7 -0
  127. package/dist/i18n/help.js.map +1 -0
  128. package/dist/i18n/help.zh.d.ts +149 -0
  129. package/dist/i18n/help.zh.js +150 -0
  130. package/dist/i18n/help.zh.js.map +1 -0
  131. package/dist/i18n/helpFormat.d.ts +7 -0
  132. package/dist/i18n/helpFormat.js +51 -0
  133. package/dist/i18n/helpFormat.js.map +1 -0
  134. package/dist/i18n/helpGroups.d.ts +3 -0
  135. package/dist/i18n/helpGroups.js +11 -0
  136. package/dist/i18n/helpGroups.js.map +1 -0
  137. package/dist/i18n/index.d.ts +16 -0
  138. package/dist/i18n/index.js +46 -0
  139. package/dist/i18n/index.js.map +1 -0
  140. package/dist/i18n/peekLang.d.ts +1 -0
  141. package/dist/i18n/peekLang.js +16 -0
  142. package/dist/i18n/peekLang.js.map +1 -0
  143. package/dist/i18n/zh.d.ts +680 -0
  144. package/dist/i18n/zh.js +288 -0
  145. package/dist/i18n/zh.js.map +1 -0
  146. package/dist/parser/discover.d.ts +2 -0
  147. package/dist/parser/discover.js +69 -0
  148. package/dist/parser/discover.js.map +1 -0
  149. package/dist/parser/load-yaml.d.ts +11 -0
  150. package/dist/parser/load-yaml.js +25 -0
  151. package/dist/parser/load-yaml.js.map +1 -0
  152. package/dist/pkgVersion.d.ts +9 -0
  153. package/dist/pkgVersion.js +22 -0
  154. package/dist/pkgVersion.js.map +1 -0
  155. package/dist/renderer/context-md.d.ts +27 -0
  156. package/dist/renderer/context-md.js +444 -0
  157. package/dist/renderer/context-md.js.map +1 -0
  158. package/dist/renderer/refresh-md.d.ts +18 -0
  159. package/dist/renderer/refresh-md.js +93 -0
  160. package/dist/renderer/refresh-md.js.map +1 -0
  161. package/dist/schema/index.d.ts +2 -0
  162. package/dist/schema/index.js +3 -0
  163. package/dist/schema/index.js.map +1 -0
  164. package/dist/schema/modules.d.ts +461 -0
  165. package/dist/schema/modules.js +184 -0
  166. package/dist/schema/modules.js.map +1 -0
  167. package/dist/schema/prd.d.ts +1018 -0
  168. package/dist/schema/prd.js +65 -0
  169. package/dist/schema/prd.js.map +1 -0
  170. package/dist/sync/cliRcHelpers.d.ts +25 -0
  171. package/dist/sync/cliRcHelpers.js +62 -0
  172. package/dist/sync/cliRcHelpers.js.map +1 -0
  173. package/dist/sync/conflicts.d.ts +7 -0
  174. package/dist/sync/conflicts.js +72 -0
  175. package/dist/sync/conflicts.js.map +1 -0
  176. package/dist/sync/headProbe.d.ts +1 -0
  177. package/dist/sync/headProbe.js +95 -0
  178. package/dist/sync/headProbe.js.map +1 -0
  179. package/dist/sync/normalize.d.ts +10 -0
  180. package/dist/sync/normalize.js +13 -0
  181. package/dist/sync/normalize.js.map +1 -0
  182. package/dist/sync/syncJson.d.ts +18 -0
  183. package/dist/sync/syncJson.js +42 -0
  184. package/dist/sync/syncJson.js.map +1 -0
  185. package/dist/types.d.ts +70 -0
  186. package/dist/types.js +21 -0
  187. package/dist/types.js.map +1 -0
  188. package/dist/validators/blocking.d.ts +2 -0
  189. package/dist/validators/blocking.js +25 -0
  190. package/dist/validators/blocking.js.map +1 -0
  191. package/dist/validators/duplicate-ids.d.ts +2 -0
  192. package/dist/validators/duplicate-ids.js +58 -0
  193. package/dist/validators/duplicate-ids.js.map +1 -0
  194. package/dist/validators/references.d.ts +5 -0
  195. package/dist/validators/references.js +165 -0
  196. package/dist/validators/references.js.map +1 -0
  197. package/dist/validators/required-modules.d.ts +8 -0
  198. package/dist/validators/required-modules.js +59 -0
  199. package/dist/validators/required-modules.js.map +1 -0
  200. package/dist/validators/runner.d.ts +11 -0
  201. package/dist/validators/runner.js +73 -0
  202. package/dist/validators/runner.js.map +1 -0
  203. package/dist/workspace.d.ts +32 -0
  204. package/dist/workspace.js +37 -0
  205. package/dist/workspace.js.map +1 -0
  206. package/dist/yaml-indexer.d.ts +15 -0
  207. package/dist/yaml-indexer.js +112 -0
  208. package/dist/yaml-indexer.js.map +1 -0
  209. package/package.json +50 -0
@@ -0,0 +1,305 @@
1
+ /**
2
+ * Pure function:把两份 PRD yaml AST 对比成结构化 DiffResult。
3
+ * 不读不写,可独立单测。
4
+ *
5
+ * 18 个 diffable 单元 = 14 个普通模块 + data_and_api 的 4 子组(DC/API/PC/SEC)。
6
+ * Summary 的 unchanged_modules 用 15 模块(parent)计数。
7
+ */
8
+ // ---------- helpers ----------
9
+ function isEmpty(v) {
10
+ if (v === null || v === undefined)
11
+ return true;
12
+ if (typeof v === "string" && v === "")
13
+ return true;
14
+ if (Array.isArray(v) && v.length === 0)
15
+ return true;
16
+ return false;
17
+ }
18
+ function valueEqual(a, b) {
19
+ if (isEmpty(a) && isEmpty(b))
20
+ return true;
21
+ if (Array.isArray(a) && Array.isArray(b)) {
22
+ if (a.length !== b.length)
23
+ return false;
24
+ return a.every((v, i) => valueEqual(v, b[i]));
25
+ }
26
+ if (typeof a === "object" &&
27
+ a !== null &&
28
+ typeof b === "object" &&
29
+ b !== null) {
30
+ const ak = Object.keys(a).filter((k) => !isEmpty(a[k]));
31
+ const bk = Object.keys(b).filter((k) => !isEmpty(b[k]));
32
+ if (ak.length !== bk.length)
33
+ return false;
34
+ return ak.every((k) => valueEqual(a[k], b[k]));
35
+ }
36
+ return a === b;
37
+ }
38
+ function isMultiline(v) {
39
+ if (typeof v !== "string")
40
+ return false;
41
+ if (v.includes("\n"))
42
+ return true;
43
+ if (v.length > 80)
44
+ return true;
45
+ return false;
46
+ }
47
+ function objectFieldChanges(before, after, fieldList) {
48
+ const changes = [];
49
+ for (const f of fieldList) {
50
+ const bv = before?.[f];
51
+ const av = after?.[f];
52
+ if (!valueEqual(bv, av)) {
53
+ changes.push({
54
+ field: f,
55
+ before: bv ?? null,
56
+ after: av ?? null,
57
+ is_multiline: isMultiline(bv) || isMultiline(av),
58
+ });
59
+ }
60
+ }
61
+ return changes;
62
+ }
63
+ function diffList(leftArr, rightArr, opts) {
64
+ const left = Array.isArray(leftArr) ? leftArr : [];
65
+ const right = Array.isArray(rightArr) ? rightArr : [];
66
+ const leftMap = new Map();
67
+ for (const item of left) {
68
+ const k = opts.primaryKeyOf(item);
69
+ if (k)
70
+ leftMap.set(k, item);
71
+ }
72
+ const rightMap = new Map();
73
+ for (const item of right) {
74
+ const k = opts.primaryKeyOf(item);
75
+ if (k)
76
+ rightMap.set(k, item);
77
+ }
78
+ const added = [];
79
+ const modified = [];
80
+ const removed = [];
81
+ for (const [k, rItem] of rightMap) {
82
+ if (!leftMap.has(k)) {
83
+ added.push({
84
+ primary_key: k,
85
+ display_label: opts.displayLabelOf?.(rItem),
86
+ });
87
+ }
88
+ else {
89
+ const lItem = leftMap.get(k);
90
+ const fc = objectFieldChanges(lItem, rItem, opts.fieldList);
91
+ if (fc.length > 0) {
92
+ modified.push({
93
+ primary_key: k,
94
+ display_label: opts.displayLabelOf?.(rItem),
95
+ field_changes: fc,
96
+ });
97
+ }
98
+ }
99
+ }
100
+ for (const [k, lItem] of leftMap) {
101
+ if (!rightMap.has(k)) {
102
+ removed.push({
103
+ primary_key: k,
104
+ display_label: opts.displayLabelOf?.(lItem),
105
+ });
106
+ }
107
+ }
108
+ return {
109
+ module_key: opts.module_key,
110
+ module_label: opts.module_label,
111
+ added,
112
+ modified,
113
+ removed,
114
+ };
115
+ }
116
+ function diffObjectModule(left, right, module_key, module_label, fieldList) {
117
+ const fc = objectFieldChanges(left ?? {}, right ?? {}, fieldList);
118
+ const modified = fc.length > 0
119
+ ? [{ primary_key: module_key, field_changes: fc }]
120
+ : [];
121
+ return {
122
+ module_key,
123
+ module_label,
124
+ added: [],
125
+ modified,
126
+ removed: [],
127
+ };
128
+ }
129
+ // ---------- 模块字段定义表 ----------
130
+ const META_FIELDS = [
131
+ "project",
132
+ "feature",
133
+ "title",
134
+ "summary",
135
+ "owner",
136
+ "tags",
137
+ "created_at",
138
+ "source_materials",
139
+ "lifecycle",
140
+ ];
141
+ const BG_FIELDS = ["background", "goals"];
142
+ const ENTITY_FIELDS = ["name", "description", "fields", "relations", "lifecycle_states"];
143
+ const IN_SCOPE_FIELDS = ["name", "summary"];
144
+ const OOS_FIELDS = ["reason"];
145
+ const FLOW_FIELDS = ["actor", "trigger", "action", "outcome"];
146
+ const SP_FIELDS = ["allowed_actions", "notes"];
147
+ const RULE_FIELDS = ["rule", "rationale", "applies_to"];
148
+ const SCENARIO_FIELDS = ["condition", "expected_behavior", "input", "output", "refers_to"];
149
+ const EDGE_FIELDS = ["situation", "expected_behavior", "mitigation"];
150
+ const UI_FIELDS = [
151
+ "page",
152
+ "purpose",
153
+ "key_elements",
154
+ "user_actions",
155
+ "empty_state",
156
+ "loading_state",
157
+ "error_state",
158
+ ];
159
+ const CONSTRAINT_FIELDS = ["text", "applies_to"];
160
+ const AC_FIELDS = ["criterion", "priority", "verification_method", "refers_to"];
161
+ const Q_FIELDS = ["question", "severity", "deferred_to", "owner", "due_date"];
162
+ const ROLE_FIELDS = ["description", "typical_goals"];
163
+ // ---------- 主入口 ----------
164
+ export function diffPRDs(left, right) {
165
+ const perModule = {};
166
+ perModule.meta = diffObjectModule(left?.meta, right?.meta, "meta", "版本信息", META_FIELDS);
167
+ perModule.background_and_goals = diffObjectModule(left?.background_and_goals, right?.background_and_goals, "background_and_goals", "背景与目标", BG_FIELDS);
168
+ perModule.users_and_roles = diffList(left?.users_and_roles, right?.users_and_roles, {
169
+ module_key: "users_and_roles",
170
+ module_label: "用户与角色",
171
+ primaryKeyOf: (u) => (typeof u?.role === "string" ? u.role : ""),
172
+ fieldList: ROLE_FIELDS,
173
+ });
174
+ perModule.in_scope = diffList(left?.in_scope, right?.in_scope, {
175
+ module_key: "in_scope",
176
+ module_label: "本期范围",
177
+ primaryKeyOf: (s) => (typeof s?.id === "string" ? s.id : ""),
178
+ displayLabelOf: (s) => s?.name,
179
+ fieldList: IN_SCOPE_FIELDS,
180
+ });
181
+ perModule.out_of_scope = diffList(left?.out_of_scope, right?.out_of_scope, {
182
+ module_key: "out_of_scope",
183
+ module_label: "明确不做",
184
+ primaryKeyOf: (o) => (typeof o?.item === "string" ? o.item : ""),
185
+ fieldList: OOS_FIELDS,
186
+ });
187
+ perModule.entities = diffList(left?.entities, right?.entities, {
188
+ module_key: "entities",
189
+ module_label: "核心实体",
190
+ primaryKeyOf: (e) => (typeof e?.id === "string" ? e.id : ""),
191
+ displayLabelOf: (e) => e?.name,
192
+ fieldList: ENTITY_FIELDS,
193
+ });
194
+ perModule.main_flow = diffList(left?.main_flow, right?.main_flow, {
195
+ module_key: "main_flow",
196
+ module_label: "主流程",
197
+ primaryKeyOf: (s) => (typeof s?.step === "number" ? `step-${s.step}` : ""),
198
+ fieldList: FLOW_FIELDS,
199
+ });
200
+ perModule.state_permissions = diffList(left?.state_permissions, right?.state_permissions, {
201
+ module_key: "state_permissions",
202
+ module_label: "状态与操作权限",
203
+ primaryKeyOf: (sp) => typeof sp?.entity_id === "string" && typeof sp?.state === "string"
204
+ ? `${sp.entity_id} · ${sp.state}`
205
+ : "",
206
+ fieldList: SP_FIELDS,
207
+ });
208
+ perModule.business_rules = diffList(left?.business_rules, right?.business_rules, {
209
+ module_key: "business_rules",
210
+ module_label: "业务规则",
211
+ primaryKeyOf: (r) => (typeof r?.id === "string" ? r.id : ""),
212
+ fieldList: RULE_FIELDS,
213
+ });
214
+ perModule.scenarios = diffList(left?.scenarios, right?.scenarios, {
215
+ module_key: "scenarios",
216
+ module_label: "场景矩阵",
217
+ primaryKeyOf: (s) => (typeof s?.id === "string" ? s.id : ""),
218
+ fieldList: SCENARIO_FIELDS,
219
+ });
220
+ perModule.edge_cases = diffList(left?.edge_cases, right?.edge_cases, {
221
+ module_key: "edge_cases",
222
+ module_label: "异常与边界",
223
+ primaryKeyOf: (e) => (typeof e?.id === "string" ? e.id : ""),
224
+ displayLabelOf: (e) => e?.situation,
225
+ fieldList: EDGE_FIELDS,
226
+ });
227
+ perModule.ui_interaction = diffList(left?.ui_interaction, right?.ui_interaction, {
228
+ module_key: "ui_interaction",
229
+ module_label: "页面与交互",
230
+ primaryKeyOf: (u) => (typeof u?.id === "string" ? u.id : ""),
231
+ displayLabelOf: (u) => u?.page,
232
+ fieldList: UI_FIELDS,
233
+ });
234
+ // data_and_api: 4 subgroups merged into one ModuleDiff
235
+ const dArr = [
236
+ diffList(left?.data_and_api?.data_constraints, right?.data_and_api?.data_constraints, {
237
+ module_key: "data_and_api",
238
+ module_label: "数据与接口约束",
239
+ primaryKeyOf: (c) => (typeof c?.id === "string" ? c.id : ""),
240
+ fieldList: CONSTRAINT_FIELDS,
241
+ }),
242
+ diffList(left?.data_and_api?.api_constraints, right?.data_and_api?.api_constraints, {
243
+ module_key: "data_and_api",
244
+ module_label: "数据与接口约束",
245
+ primaryKeyOf: (c) => (typeof c?.id === "string" ? c.id : ""),
246
+ fieldList: CONSTRAINT_FIELDS,
247
+ }),
248
+ diffList(left?.data_and_api?.performance_constraints, right?.data_and_api?.performance_constraints, {
249
+ module_key: "data_and_api",
250
+ module_label: "数据与接口约束",
251
+ primaryKeyOf: (c) => (typeof c?.id === "string" ? c.id : ""),
252
+ fieldList: CONSTRAINT_FIELDS,
253
+ }),
254
+ diffList(left?.data_and_api?.security_constraints, right?.data_and_api?.security_constraints, {
255
+ module_key: "data_and_api",
256
+ module_label: "数据与接口约束",
257
+ primaryKeyOf: (c) => (typeof c?.id === "string" ? c.id : ""),
258
+ fieldList: CONSTRAINT_FIELDS,
259
+ }),
260
+ ];
261
+ perModule.data_and_api = {
262
+ module_key: "data_and_api",
263
+ module_label: "数据与接口约束",
264
+ added: dArr.flatMap((m) => m.added),
265
+ modified: dArr.flatMap((m) => m.modified),
266
+ removed: dArr.flatMap((m) => m.removed),
267
+ };
268
+ perModule.acceptance_criteria = diffList(left?.acceptance_criteria, right?.acceptance_criteria, {
269
+ module_key: "acceptance_criteria",
270
+ module_label: "验收标准",
271
+ primaryKeyOf: (a) => (typeof a?.id === "string" ? a.id : ""),
272
+ displayLabelOf: (a) => a?.criterion,
273
+ fieldList: AC_FIELDS,
274
+ });
275
+ perModule.open_questions = diffList(left?.open_questions, right?.open_questions, {
276
+ module_key: "open_questions",
277
+ module_label: "待确认问题",
278
+ primaryKeyOf: (q) => (typeof q?.id === "string" ? q.id : ""),
279
+ displayLabelOf: (q) => q?.question,
280
+ fieldList: Q_FIELDS,
281
+ });
282
+ // totals
283
+ let added = 0;
284
+ let modified = 0;
285
+ let removed = 0;
286
+ let changed_module_count = 0;
287
+ for (const md of Object.values(perModule)) {
288
+ added += md.added.length;
289
+ modified += md.modified.length;
290
+ removed += md.removed.length;
291
+ if (md.added.length + md.modified.length + md.removed.length > 0) {
292
+ changed_module_count++;
293
+ }
294
+ }
295
+ return {
296
+ perModule,
297
+ totals: {
298
+ added,
299
+ modified,
300
+ removed,
301
+ unchanged_modules: 15 - changed_module_count,
302
+ },
303
+ };
304
+ }
305
+ //# sourceMappingURL=engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.js","sourceRoot":"","sources":["../../src/diff/engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import type { DiffResult } from "./engine.js";
2
+ import { type Locale } from "../i18n/index.js";
3
+ export interface DiffMeta {
4
+ feature: string;
5
+ from: {
6
+ ref: string;
7
+ frozen_at?: string;
8
+ };
9
+ to: {
10
+ ref: string;
11
+ frozen_at?: string;
12
+ };
13
+ }
14
+ export interface RenderOptions {
15
+ color: boolean;
16
+ locale: Locale;
17
+ }
18
+ export declare function renderDiff(result: DiffResult, meta: DiffMeta, opts: RenderOptions): string;
@@ -0,0 +1,129 @@
1
+ /**
2
+ * Pure function:把 DiffResult 渲染成 plain text(可选 ANSI 上色)。
3
+ * 不读不写,可独立单测。
4
+ */
5
+ import { Chalk } from "chalk";
6
+ import { getMessages } from "../i18n/index.js";
7
+ const MODULE_ORDER = [
8
+ "meta",
9
+ "background_and_goals",
10
+ "users_and_roles",
11
+ "in_scope",
12
+ "out_of_scope",
13
+ "entities",
14
+ "main_flow",
15
+ "state_permissions",
16
+ "business_rules",
17
+ "scenarios",
18
+ "edge_cases",
19
+ "ui_interaction",
20
+ "data_and_api",
21
+ "acceptance_criteria",
22
+ "open_questions",
23
+ ];
24
+ // Forced-color chalk instance (level 3 = truecolor); used when color=true
25
+ const colorChalk = new Chalk({ level: 3 });
26
+ function refLabel(r) {
27
+ if (r.ref === "working")
28
+ return "working";
29
+ if (r.frozen_at)
30
+ return `${r.ref} (frozen ${r.frozen_at.slice(0, 10)})`;
31
+ return r.ref;
32
+ }
33
+ function colorize(s, fn, on) {
34
+ return on ? fn(s) : s;
35
+ }
36
+ function stringifyValue(v) {
37
+ if (v === null || v === undefined)
38
+ return "(空)";
39
+ if (Array.isArray(v))
40
+ return "[" + v.map((x) => String(x)).join(", ") + "]";
41
+ if (typeof v === "object")
42
+ return JSON.stringify(v);
43
+ return String(v);
44
+ }
45
+ function renderFieldChange(fc, beforeLabel, afterLabel, color) {
46
+ if (!fc.is_multiline) {
47
+ const before = colorize(stringifyValue(fc.before), colorChalk.red.bind(colorChalk), color);
48
+ const after = colorize(stringifyValue(fc.after), colorChalk.green.bind(colorChalk), color);
49
+ return ` - ${fc.field}: ${before} → ${after}`;
50
+ }
51
+ const before = stringifyValue(fc.before);
52
+ const after = stringifyValue(fc.after);
53
+ return [
54
+ ` - ${fc.field}:`,
55
+ ` ${beforeLabel}:${colorize(before, colorChalk.red.bind(colorChalk), color)}`,
56
+ ` ${afterLabel}:${colorize(after, colorChalk.green.bind(colorChalk), color)}`,
57
+ ].join("\n");
58
+ }
59
+ export function renderDiff(result, meta, opts) {
60
+ const m = getMessages(opts.locale);
61
+ const lines = [];
62
+ lines.push(m.diff_header({ from: refLabel(meta.from), to: refLabel(meta.to) }));
63
+ lines.push(m.diff_summary({
64
+ added: result.totals.added,
65
+ modified: result.totals.modified,
66
+ removed: result.totals.removed,
67
+ unchanged: result.totals.unchanged_modules,
68
+ }));
69
+ lines.push("");
70
+ if (result.totals.added === 0 &&
71
+ result.totals.modified === 0 &&
72
+ result.totals.removed === 0) {
73
+ lines.push(m.diff_no_changes);
74
+ return lines.join("\n") + "\n";
75
+ }
76
+ if (result.totals.added > 0) {
77
+ lines.push(colorize(m.diff_section_added({ count: result.totals.added }), colorChalk.green.bind(colorChalk), opts.color));
78
+ for (const key of MODULE_ORDER) {
79
+ const md = result.perModule[key];
80
+ if (!md)
81
+ continue;
82
+ const sorted = [...md.added].sort((a, b) => a.primary_key.localeCompare(b.primary_key));
83
+ for (const item of sorted) {
84
+ const head = `[+] ${md.module_label} · ${item.primary_key}`;
85
+ const labeled = item.display_label && item.display_label !== item.primary_key
86
+ ? `${head} — ${item.display_label}`
87
+ : head;
88
+ lines.push(colorize(labeled, colorChalk.green.bind(colorChalk), opts.color));
89
+ }
90
+ }
91
+ lines.push("");
92
+ }
93
+ if (result.totals.modified > 0) {
94
+ lines.push(colorize(m.diff_section_modified({ count: result.totals.modified }), colorChalk.yellow.bind(colorChalk), opts.color));
95
+ for (const key of MODULE_ORDER) {
96
+ const md = result.perModule[key];
97
+ if (!md)
98
+ continue;
99
+ const sorted = [...md.modified].sort((a, b) => a.primary_key.localeCompare(b.primary_key));
100
+ for (const item of sorted) {
101
+ const head = `[~] ${md.module_label}${item.primary_key !== md.module_key ? ` · ${item.primary_key}` : ""}`;
102
+ lines.push(colorize(head, colorChalk.yellow.bind(colorChalk), opts.color));
103
+ for (const fc of item.field_changes ?? []) {
104
+ lines.push(renderFieldChange(fc, m.diff_before_label, m.diff_after_label, opts.color));
105
+ }
106
+ lines.push("");
107
+ }
108
+ }
109
+ }
110
+ if (result.totals.removed > 0) {
111
+ lines.push(colorize(m.diff_section_removed({ count: result.totals.removed }), colorChalk.red.bind(colorChalk), opts.color));
112
+ for (const key of MODULE_ORDER) {
113
+ const md = result.perModule[key];
114
+ if (!md)
115
+ continue;
116
+ const sorted = [...md.removed].sort((a, b) => a.primary_key.localeCompare(b.primary_key));
117
+ for (const item of sorted) {
118
+ const head = `[-] ${md.module_label} · ${item.primary_key}`;
119
+ const labeled = item.display_label && item.display_label !== item.primary_key
120
+ ? `${head} — ${item.display_label}`
121
+ : head;
122
+ lines.push(colorize(labeled, colorChalk.red.bind(colorChalk), opts.color));
123
+ }
124
+ }
125
+ lines.push("");
126
+ }
127
+ return lines.join("\n").trimEnd() + "\n";
128
+ }
129
+ //# sourceMappingURL=render.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/diff/render.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * 是否启用颜色:
3
+ * - NO_COLOR=1 → 禁用
4
+ * - 非 TTY → 禁用
5
+ * - 否则启用
6
+ */
7
+ export declare function colorEnabled(): boolean;
8
+ export declare function pass(s: string): string;
9
+ export declare function fail(s: string): string;
10
+ export declare function skip(s: string): string;
11
+ /**
12
+ * Semantic alias for `skip` — yellow text used to flag warnings (e.g. sync
13
+ * drift, backend unreachable) that don't change exit code. Aliased rather
14
+ * than duplicated so the existing "[SKIP] = yellow" convention stays intact.
15
+ */
16
+ export declare function warn(s: string): string;
17
+ export declare function dim(s: string): string;
@@ -0,0 +1,35 @@
1
+ import chalk from "chalk";
2
+ /**
3
+ * 是否启用颜色:
4
+ * - NO_COLOR=1 → 禁用
5
+ * - 非 TTY → 禁用
6
+ * - 否则启用
7
+ */
8
+ export function colorEnabled() {
9
+ if (process.env.NO_COLOR)
10
+ return false;
11
+ if (!process.stdout.isTTY)
12
+ return false;
13
+ return true;
14
+ }
15
+ export function pass(s) {
16
+ return colorEnabled() ? chalk.green(s) : s;
17
+ }
18
+ export function fail(s) {
19
+ return colorEnabled() ? chalk.red(s) : s;
20
+ }
21
+ export function skip(s) {
22
+ return colorEnabled() ? chalk.yellow(s) : s;
23
+ }
24
+ /**
25
+ * Semantic alias for `skip` — yellow text used to flag warnings (e.g. sync
26
+ * drift, backend unreachable) that don't change exit code. Aliased rather
27
+ * than duplicated so the existing "[SKIP] = yellow" convention stays intact.
28
+ */
29
+ export function warn(s) {
30
+ return colorEnabled() ? chalk.yellow(s) : s;
31
+ }
32
+ export function dim(s) {
33
+ return colorEnabled() ? chalk.dim(s) : s;
34
+ }
35
+ //# sourceMappingURL=colors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"colors.js","sourceRoot":"","sources":["../../src/formatter/colors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B;;;;;GAKG;AACH,MAAM,UAAU,YAAY;IAC1B,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ;QAAE,OAAO,KAAK,CAAC;IACvC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IACxC,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,CAAS;IAC5B,OAAO,YAAY,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,CAAS;IAC5B,OAAO,YAAY,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,CAAS;IAC5B,OAAO,YAAY,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC9C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,IAAI,CAAC,CAAS;IAC5B,OAAO,YAAY,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC9C,CAAC;AAED,MAAM,UAAU,GAAG,CAAC,CAAS;IAC3B,OAAO,YAAY,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC3C,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { type Locale } from "../i18n/index.js";
2
+ import type { ValidationResult } from "../types.js";
3
+ interface FormatOptions {
4
+ pattern: string;
5
+ }
6
+ export declare function formatHuman(result: ValidationResult, locale: Locale, opts: FormatOptions): string;
7
+ export {};
@@ -0,0 +1,70 @@
1
+ import { getMessages } from "../i18n/index.js";
2
+ import * as c from "./colors.js";
3
+ export function formatHuman(result, locale, opts) {
4
+ const m = getMessages(locale);
5
+ const lines = [];
6
+ // header
7
+ lines.push(m.validating({ pattern: opts.pattern }));
8
+ lines.push("");
9
+ for (const r of result.results) {
10
+ lines.push(...renderFeature(r, m));
11
+ lines.push("");
12
+ }
13
+ lines.push(m.summary_line({
14
+ passed: result.summary.passed,
15
+ failed: result.summary.failed,
16
+ skipped: result.summary.skipped,
17
+ }));
18
+ lines.push(m.exit_code_line({ code: result.exitCode }));
19
+ return lines.join("\n");
20
+ }
21
+ function renderIssueText(issue, m) {
22
+ // Dynamic lookup by issue code — escape hatch for string-keyed dispatch
23
+ const renderer = m[issue.code];
24
+ if (typeof renderer === "function")
25
+ return renderer(issue.details);
26
+ if (typeof renderer === "string")
27
+ return renderer;
28
+ return `[${issue.code}] ${JSON.stringify(issue.details)}`;
29
+ }
30
+ function renderFeature(r, m) {
31
+ const lines = [];
32
+ const warnings = r.issues.filter((i) => i.severity === "warning");
33
+ if (r.status === "pass") {
34
+ lines.push(`${c.pass(m.status_pass)} ${r.feature}`);
35
+ lines.push(" " +
36
+ m.feature_pass_summary({
37
+ complete: r.modulesComplete,
38
+ total: r.modulesTotal,
39
+ schema_version: r.schemaVersion || "?",
40
+ }));
41
+ for (const w of warnings) {
42
+ lines.push(" ! " + renderIssueText(w, m));
43
+ }
44
+ return lines;
45
+ }
46
+ if (r.status === "skip") {
47
+ lines.push(`${c.skip(m.status_skip)} ${r.feature}`);
48
+ lines.push(" " + m.feature_skip_reason_no_yaml);
49
+ return lines;
50
+ }
51
+ // fail
52
+ const refs = r.issues.filter((i) => i.code === "reference_not_found" || i.code === "reference_wrong_type").length;
53
+ const blocks = r.issues.filter((i) => i.code === "blocking_question").length;
54
+ lines.push(`${c.fail(m.status_fail)} ${r.feature}`);
55
+ lines.push(" " +
56
+ m.feature_fail_summary({
57
+ complete: r.modulesComplete,
58
+ total: r.modulesTotal,
59
+ refs,
60
+ blocks,
61
+ }));
62
+ for (const issue of r.issues) {
63
+ if (issue.severity === "info")
64
+ continue;
65
+ const prefix = issue.severity === "warning" ? "! " : "- ";
66
+ lines.push(" " + prefix + renderIssueText(issue, m));
67
+ }
68
+ return lines;
69
+ }
70
+ //# sourceMappingURL=human.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"human.js","sourceRoot":"","sources":["../../src/formatter/human.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export interface AtomicWriteOptions {
2
+ /** Posix permission mode applied via chmod after write. Optional. */
3
+ mode?: number;
4
+ /** Text encoding. Defaults to utf8. */
5
+ encoding?: BufferEncoding;
6
+ }
7
+ export declare function writeFileAtomic(path: string, data: string, opts?: AtomicWriteOptions): void;