hypercore-cli 1.1.1 → 1.3.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 (158) hide show
  1. package/LICENSE +92 -21
  2. package/README.md +8 -1
  3. package/dist/App-YMX7FSXR.js +1 -0
  4. package/dist/api-Q2TX5JJL.js +1 -0
  5. package/dist/auth-X6CUT3DW.js +1 -0
  6. package/dist/background-ACODXSUG.js +1 -0
  7. package/dist/backlog-JD2IM336.js +1 -0
  8. package/dist/chunk-2QI2IU2V.js +1 -0
  9. package/dist/chunk-3KFRDIPQ.js +1 -0
  10. package/dist/chunk-42C5J7PN.js +1 -0
  11. package/dist/chunk-4D7XVJ7Q.js +1 -0
  12. package/dist/chunk-545IGTXV.js +1 -0
  13. package/dist/chunk-5KUSGQP2.js +1 -0
  14. package/dist/chunk-AUQ64BK2.js +1 -0
  15. package/dist/chunk-AV244H5C.js +1 -0
  16. package/dist/chunk-BQVBEFS4.js +1 -0
  17. package/dist/chunk-BYWQLFP2.js +1 -0
  18. package/dist/chunk-COITWWZJ.js +1 -0
  19. package/dist/chunk-CR7UUJVX.js +1 -0
  20. package/dist/chunk-E3MULLBX.js +1 -0
  21. package/dist/chunk-EWBV7YPP.js +1 -0
  22. package/dist/chunk-EZHYVJGQ.js +1 -0
  23. package/dist/chunk-FAKXBY7Q.js +1 -0
  24. package/dist/chunk-FHGATV5B.js +1 -0
  25. package/dist/chunk-I2G27Y5P.js +1 -0
  26. package/dist/chunk-IKF43TX2.js +1 -0
  27. package/dist/chunk-INSPHCBN.js +1 -0
  28. package/dist/chunk-LQMDUKIE.js +1 -0
  29. package/dist/chunk-M3MTKGA5.js +1 -0
  30. package/dist/chunk-MPO54FU3.js +1 -0
  31. package/dist/chunk-PVKCZI6A.js +1 -0
  32. package/dist/chunk-Q7KEPCYL.js +1 -0
  33. package/dist/chunk-R5XD3NT2.js +1 -0
  34. package/dist/chunk-ROBZ6PAL.js +1 -0
  35. package/dist/chunk-RXB5BS2N.js +1 -0
  36. package/dist/chunk-RZ3HNYMT.js +1 -0
  37. package/dist/chunk-UCGLRMTG.js +1 -0
  38. package/dist/chunk-UEHJVRKB.js +1 -0
  39. package/dist/chunk-UZYX5GGF.js +1 -0
  40. package/dist/chunk-XQJBB725.js +1 -0
  41. package/dist/chunk-ZB5ZQSXH.js +1 -0
  42. package/dist/claude-US2QPRBA.js +1 -0
  43. package/dist/commands-5TFN74MD.js +1 -0
  44. package/dist/commands-EKPWCB3T.js +1 -0
  45. package/dist/commands-QHJLREPM.js +1 -0
  46. package/dist/config-2OUL5FLS.js +1 -0
  47. package/dist/config-loader-N7IBWN2P.js +1 -0
  48. package/dist/diagnose-NLHN4SAJ.js +1 -0
  49. package/dist/display-TB5YACJV.js +1 -0
  50. package/dist/extractor-3KTM2IUL.js +1 -0
  51. package/dist/feature-flag-VVIF5FJG.js +1 -0
  52. package/dist/history-GVNDPXXQ.js +1 -0
  53. package/dist/index.js +1 -402
  54. package/dist/instance-registry-I5AIVJE2.js +1 -0
  55. package/dist/keybindings-RN3A7CRW.js +1 -0
  56. package/dist/loader-3IKPXP4R.js +1 -0
  57. package/dist/network-GI2F3IDE.js +1 -0
  58. package/dist/notify-O6FNVHC4.js +1 -0
  59. package/dist/openai-compat-IPCMINVF.js +1 -0
  60. package/dist/permissions-5O7KVAXU.js +1 -0
  61. package/dist/prompt-VWFPFM4N.js +1 -0
  62. package/dist/quality-GPQD25UL.js +1 -0
  63. package/dist/repl-YNXCDVU4.js +1 -0
  64. package/dist/roadmap-QRZODSNJ.js +1 -0
  65. package/dist/server-USQP4GC4.js +1 -0
  66. package/dist/session-5HDDQQP6.js +1 -0
  67. package/dist/skills-DXWSVJSU.js +1 -0
  68. package/dist/store-WXXTKTTL.js +1 -0
  69. package/dist/team-VTPJ3WRT.js +1 -0
  70. package/dist/telemetry-NT4UZLBS.js +1 -0
  71. package/dist/test-runner-F6B6RH3S.js +1 -0
  72. package/dist/theme-JJJ6ABR2.js +1 -0
  73. package/dist/upgrade-RUG3R7R5.js +1 -0
  74. package/dist/verify-6OGRY2PR.js +1 -0
  75. package/dist/version-DLROA5JN.js +1 -0
  76. package/dist/web/static/app.js +1 -562
  77. package/dist/web/static/index.html +114 -126
  78. package/dist/web/static/mirror.css +1 -1001
  79. package/dist/web/static/mirror.html +155 -178
  80. package/dist/web/static/mirror.js +1 -1125
  81. package/dist/web/static/onboard.css +1 -302
  82. package/dist/web/static/onboard.html +121 -145
  83. package/dist/web/static/onboard.js +1 -300
  84. package/dist/web/static/style.css +1 -602
  85. package/dist/web/static/utils.js +1 -0
  86. package/dist/web/static/workspace.css +1 -1568
  87. package/dist/web/static/workspace.html +369 -402
  88. package/dist/web/static/workspace.js +1 -1683
  89. package/dist/web-P5YUKEAU.js +1 -0
  90. package/package.json +25 -4
  91. package/dist/api-D4PUN5BN.js +0 -162
  92. package/dist/auth-UTR4I6QY.js +0 -21
  93. package/dist/background-2EGCAAQH.js +0 -14
  94. package/dist/backlog-Q2NZCLNY.js +0 -24
  95. package/dist/chunk-2CMSCWQW.js +0 -162
  96. package/dist/chunk-4DVYJAJL.js +0 -57
  97. package/dist/chunk-77FRUHTU.js +0 -271
  98. package/dist/chunk-7ZYMJFCA.js +0 -251
  99. package/dist/chunk-BE46C7JW.js +0 -46
  100. package/dist/chunk-CM423E2U.js +0 -133
  101. package/dist/chunk-E4NKO2KI.js +0 -263
  102. package/dist/chunk-GH7E2OJE.js +0 -223
  103. package/dist/chunk-GMLQ7GZ5.js +0 -134
  104. package/dist/chunk-GU2FZQ6A.js +0 -69
  105. package/dist/chunk-IOPKN5GD.js +0 -190
  106. package/dist/chunk-LWDNLX6B.js +0 -2025
  107. package/dist/chunk-MGLJ53QN.js +0 -219
  108. package/dist/chunk-NHPDLYEW.js +0 -139
  109. package/dist/chunk-OGQGKMDX.js +0 -173
  110. package/dist/chunk-OPZYEVYR.js +0 -150
  111. package/dist/chunk-OWAOKDIN.js +0 -1505
  112. package/dist/chunk-R3GPQC7I.js +0 -393
  113. package/dist/chunk-RKB2JOV2.js +0 -43
  114. package/dist/chunk-RNG3K465.js +0 -80
  115. package/dist/chunk-SHJQMIJL.js +0 -288
  116. package/dist/chunk-SVF2VWOZ.js +0 -145
  117. package/dist/chunk-TGTYKBGC.js +0 -86
  118. package/dist/chunk-V2EBSFPU.js +0 -575
  119. package/dist/chunk-VJDQNNSO.js +0 -681
  120. package/dist/chunk-VQ35XX7B.js +0 -167
  121. package/dist/chunk-WHLVZCQY.js +0 -245
  122. package/dist/chunk-XMGHVNH2.js +0 -66
  123. package/dist/chunk-YWOSOTUO.js +0 -58
  124. package/dist/chunk-ZQRNV2US.js +0 -166
  125. package/dist/chunk-ZSBHUGWR.js +0 -262
  126. package/dist/claude-O5FSOXZC.js +0 -12
  127. package/dist/commands-43PLOWRU.js +0 -128
  128. package/dist/commands-5YVUSUMP.js +0 -232
  129. package/dist/commands-VZMZJFZF.js +0 -1044
  130. package/dist/config-WXXEEEVW.js +0 -8
  131. package/dist/config-loader-SXO674TF.js +0 -24
  132. package/dist/diagnose-BX45APUZ.js +0 -12
  133. package/dist/display-IIUBEYWN.js +0 -58
  134. package/dist/extractor-R5ABXNTJ.js +0 -129
  135. package/dist/history-JPXZEOT3.js +0 -180
  136. package/dist/index.d.ts +0 -1
  137. package/dist/instance-registry-6NJTCAE4.js +0 -15
  138. package/dist/keybindings-ADWNOX5M.js +0 -15
  139. package/dist/loader-AXDDCB2G.js +0 -58
  140. package/dist/network-V3O4UZYZ.js +0 -279
  141. package/dist/notify-HPTALZDC.js +0 -14
  142. package/dist/openai-compat-UFDV2SCK.js +0 -12
  143. package/dist/permissions-JUKXMNDH.js +0 -10
  144. package/dist/prompt-5CZ34WGA.js +0 -166
  145. package/dist/quality-ST7PPNFR.js +0 -16
  146. package/dist/repl-EOWP6AAB.js +0 -3374
  147. package/dist/roadmap-5OBEKROY.js +0 -17
  148. package/dist/server-BB5AENWU.js +0 -57
  149. package/dist/session-5NDKKFLN.js +0 -21
  150. package/dist/skills-JVLIQVJN.js +0 -175
  151. package/dist/store-G7KRD4PN.js +0 -25
  152. package/dist/team-FVNNVDBY.js +0 -385
  153. package/dist/telemetry-6R4EIE6O.js +0 -30
  154. package/dist/test-runner-REKSVPPY.js +0 -619
  155. package/dist/theme-3SYJ3UQA.js +0 -14
  156. package/dist/upgrade-YSXCO63I.js +0 -83
  157. package/dist/verify-JUDKTPKZ.js +0 -14
  158. package/dist/web-H2BJXUBZ.js +0 -39
@@ -1,1044 +0,0 @@
1
- import {
2
- activateMilestone,
3
- addMilestone,
4
- doneMilestone,
5
- getRoadmap,
6
- listMilestones
7
- } from "./chunk-OPZYEVYR.js";
8
- import {
9
- checkBuild,
10
- checkDeps,
11
- checkPackageSize,
12
- checkTests,
13
- checkTodos,
14
- runQualityReport
15
- } from "./chunk-ZSBHUGWR.js";
16
- import {
17
- findingsToBacklog,
18
- runAIDiagnosis,
19
- runRuleDiagnosis
20
- } from "./chunk-SHJQMIJL.js";
21
- import {
22
- recordBaseline,
23
- verifyCompletedItems
24
- } from "./chunk-IOPKN5GD.js";
25
- import {
26
- getEventsSummary
27
- } from "./chunk-2CMSCWQW.js";
28
- import {
29
- addItem,
30
- archiveItem,
31
- doneItem,
32
- getItem,
33
- getStats,
34
- listItems,
35
- pickItem,
36
- reopenItem,
37
- updateItem
38
- } from "./chunk-MGLJ53QN.js";
39
-
40
- // src/admin/commands.ts
41
- import chalk from "chalk";
42
-
43
- // src/admin/version.ts
44
- import { execSync } from "child_process";
45
- import { join } from "path";
46
- import { readFile } from "fs/promises";
47
- import { existsSync } from "fs";
48
- function git(cmd, cwd) {
49
- try {
50
- return execSync(`git ${cmd}`, {
51
- cwd: cwd || process.cwd(),
52
- encoding: "utf-8",
53
- timeout: 1e4,
54
- stdio: ["pipe", "pipe", "pipe"]
55
- }).trim();
56
- } catch {
57
- return "";
58
- }
59
- }
60
- function isGitRepo(cwd) {
61
- return git("rev-parse --is-inside-work-tree", cwd) === "true";
62
- }
63
- async function getVersionInfo(projectRoot) {
64
- const pkgPath = join(projectRoot, "package.json");
65
- let currentVersion = "unknown";
66
- if (existsSync(pkgPath)) {
67
- try {
68
- const pkg = JSON.parse(await readFile(pkgPath, "utf-8"));
69
- currentVersion = pkg.version || "unknown";
70
- } catch {
71
- }
72
- }
73
- if (!isGitRepo(projectRoot)) {
74
- return {
75
- currentVersion,
76
- lastTag: "",
77
- lastTagDate: "",
78
- daysSinceTag: 0,
79
- pendingCommits: 0,
80
- filesChanged: 0,
81
- insertions: 0,
82
- deletions: 0,
83
- commitsByType: {},
84
- recentCommits: []
85
- };
86
- }
87
- const lastTag = git("describe --tags --abbrev=0 2>/dev/null", projectRoot) || "";
88
- let lastTagDate = "";
89
- let daysSinceTag = 0;
90
- if (lastTag) {
91
- lastTagDate = git(`log -1 --format=%ai ${lastTag}`, projectRoot).slice(0, 10);
92
- const tagTime = new Date(lastTagDate).getTime();
93
- daysSinceTag = Math.floor((Date.now() - tagTime) / 864e5);
94
- }
95
- const range = lastTag ? `${lastTag}..HEAD` : "HEAD";
96
- const logRaw = git(`log ${range} --oneline`, projectRoot);
97
- const pendingCommits = logRaw ? logRaw.split("\n").filter((l) => l.trim()).length : 0;
98
- let filesChanged = 0;
99
- let insertions = 0;
100
- let deletions = 0;
101
- if (lastTag) {
102
- const diffStat = git(`diff --stat ${lastTag}..HEAD`, projectRoot);
103
- const summaryLine = diffStat.split("\n").pop() || "";
104
- const filesMatch = summaryLine.match(/(\d+) files? changed/);
105
- const insMatch = summaryLine.match(/(\d+) insertions?/);
106
- const delMatch = summaryLine.match(/(\d+) deletions?/);
107
- filesChanged = filesMatch ? parseInt(filesMatch[1]) : 0;
108
- insertions = insMatch ? parseInt(insMatch[1]) : 0;
109
- deletions = delMatch ? parseInt(delMatch[1]) : 0;
110
- }
111
- const commitsByType = {};
112
- const recentCommits = [];
113
- if (pendingCommits > 0) {
114
- const detailedLog = git(`log ${range} --format=%h|%s|%ai`, projectRoot);
115
- for (const line of detailedLog.split("\n")) {
116
- if (!line.trim()) continue;
117
- const [hash, message, date] = line.split("|");
118
- const typeMatch = message?.match(/^(\w+)[\(:]/);
119
- const type = typeMatch ? typeMatch[1] : "other";
120
- commitsByType[type] = (commitsByType[type] || 0) + 1;
121
- if (recentCommits.length < 20) {
122
- recentCommits.push({ hash, type, message: message || "", date: (date || "").slice(0, 10) });
123
- }
124
- }
125
- }
126
- return {
127
- currentVersion,
128
- lastTag,
129
- lastTagDate,
130
- daysSinceTag,
131
- pendingCommits,
132
- filesChanged,
133
- insertions,
134
- deletions,
135
- commitsByType,
136
- recentCommits
137
- };
138
- }
139
- async function runReleaseChecks(projectRoot) {
140
- const checks = [];
141
- try {
142
- execSync("npm run build", { cwd: projectRoot, stdio: "pipe", timeout: 6e4 });
143
- checks.push({ name: "Build", ok: true, detail: "\u901A\u8FC7" });
144
- } catch {
145
- checks.push({ name: "Build", ok: false, detail: "\u6784\u5EFA\u5931\u8D25" });
146
- }
147
- try {
148
- const testOutput = execSync("npm test", { cwd: projectRoot, encoding: "utf-8", stdio: "pipe", timeout: 6e4 });
149
- const passMatch = testOutput.match(/(\d+) passed/);
150
- const passCount = passMatch ? passMatch[1] : "?";
151
- checks.push({ name: "Test", ok: true, detail: `${passCount} \u901A\u8FC7` });
152
- } catch {
153
- checks.push({ name: "Test", ok: false, detail: "\u6D4B\u8BD5\u5931\u8D25" });
154
- }
155
- const status = git("status --porcelain", projectRoot);
156
- const uncommitted = status ? status.split("\n").filter((l) => l.trim()).length : 0;
157
- if (uncommitted === 0) {
158
- checks.push({ name: "Git Status", ok: true, detail: "\u5DE5\u4F5C\u533A\u5E72\u51C0" });
159
- } else {
160
- checks.push({ name: "Git Status", ok: false, detail: `${uncommitted} \u4E2A\u672A\u63D0\u4EA4\u53D8\u66F4` });
161
- }
162
- const changelogExists = existsSync(join(projectRoot, "CHANGELOG.md"));
163
- checks.push({ name: "CHANGELOG", ok: changelogExists, detail: changelogExists ? "\u5B58\u5728" : "\u672A\u521B\u5EFA" });
164
- try {
165
- const packOutput = execSync("npm pack --dry-run 2>&1", { cwd: projectRoot, encoding: "utf-8", timeout: 3e4 });
166
- const sizeMatch = packOutput.match(/total files:\s*(\d+)/i) || packOutput.match(/(\d+)\s*files/i);
167
- const bytesMatch = packOutput.match(/(\d+\.?\d*\s*[kKmM]?B)/);
168
- const detail = `${bytesMatch ? bytesMatch[1] : "?"}, ${sizeMatch ? sizeMatch[1] : "?"} files`;
169
- checks.push({ name: "Package", ok: true, detail });
170
- } catch {
171
- checks.push({ name: "Package", ok: false, detail: "pack \u5931\u8D25" });
172
- }
173
- const pkgPath = join(projectRoot, "package.json");
174
- if (existsSync(pkgPath)) {
175
- try {
176
- const pkg = JSON.parse(await readFile(pkgPath, "utf-8"));
177
- const tagName = `v${pkg.version}`;
178
- const existingTag = git(`tag -l ${tagName}`, projectRoot);
179
- if (existingTag) {
180
- checks.push({ name: "Version", ok: false, detail: `tag ${tagName} \u5DF2\u5B58\u5728` });
181
- } else {
182
- checks.push({ name: "Version", ok: true, detail: `${tagName} \u53EF\u7528` });
183
- }
184
- } catch {
185
- }
186
- }
187
- return checks;
188
- }
189
- function getReleaseHistory(projectRoot) {
190
- if (!isGitRepo(projectRoot)) return [];
191
- const raw = git("tag -l --sort=-version:refname --format=%(refname:short)|%(creatordate:short)|%(subject)", projectRoot);
192
- if (!raw) return [];
193
- return raw.split("\n").filter((l) => l.trim()).map((line) => {
194
- const [tag, date, ...msgParts] = line.split("|");
195
- return { tag, date: date || "", message: msgParts.join("|") || "" };
196
- });
197
- }
198
-
199
- // src/admin/commands.ts
200
- var WUXING_EMOJI = {
201
- "\u6728": "\u{1F333}",
202
- "\u706B": "\u{1F525}",
203
- "\u6C34": "\u{1F30A}",
204
- "\u91D1": "\u2699\uFE0F",
205
- "\u571F": "\u{1F3D4}\uFE0F"
206
- };
207
- var STATUS_EMOJI = {
208
- idea: "\u{1F4A1}",
209
- planned: "\u2B1A",
210
- developing: "\u{1F504}",
211
- done: "\u2705",
212
- archived: "\u{1F4E6}"
213
- };
214
- var TYPE_LABEL = {
215
- feature: "\u529F\u80FD",
216
- improvement: "\u6539\u8FDB",
217
- idea: "\u60F3\u6CD5",
218
- bugfix: "\u4FEE\u590D"
219
- };
220
- function parseOpts(args) {
221
- const positional = [];
222
- const opts = {};
223
- for (let i = 0; i < args.length; i++) {
224
- if (args[i].startsWith("--") && i + 1 < args.length) {
225
- const key = args[i].slice(2);
226
- opts[key] = args[++i];
227
- } else if (args[i].startsWith("-") && args[i].length === 2 && i + 1 < args.length) {
228
- const shortMap = { t: "type", w: "wuxing", p: "priority", v: "version", d: "desc" };
229
- const key = shortMap[args[i][1]] || args[i][1];
230
- opts[key] = args[++i];
231
- } else {
232
- positional.push(args[i]);
233
- }
234
- }
235
- return { positional, opts };
236
- }
237
- async function handleAdd(args, _ctx) {
238
- const { positional, opts } = parseOpts(args);
239
- const title = positional.join(" ").trim();
240
- if (!title) {
241
- console.log(chalk.red("\n \u7528\u6CD5: /admin add <\u6807\u9898> [--type feature] [--wuxing \u6728] [--priority B] [--version v1.2] [--desc \u63CF\u8FF0]\n"));
242
- return;
243
- }
244
- const type = opts.type || "feature";
245
- if (!["feature", "improvement", "idea", "bugfix"].includes(type)) {
246
- console.log(chalk.red(`
247
- type \u65E0\u6548: ${type}\uFF08\u53EF\u9009: feature/improvement/idea/bugfix\uFF09
248
- `));
249
- return;
250
- }
251
- const wuxing = opts.wuxing || "\u6728";
252
- if (!["\u6728", "\u706B", "\u6C34", "\u91D1", "\u571F"].includes(wuxing)) {
253
- console.log(chalk.red(`
254
- wuxing \u65E0\u6548: ${wuxing}\uFF08\u53EF\u9009: \u6728/\u706B/\u6C34/\u91D1/\u571F\uFF09
255
- `));
256
- return;
257
- }
258
- const priority = opts.priority || "B";
259
- if (!["S", "A", "B", "C"].includes(priority)) {
260
- console.log(chalk.red(`
261
- priority \u65E0\u6548: ${priority}\uFF08\u53EF\u9009: S/A/B/C\uFF09
262
- `));
263
- return;
264
- }
265
- const item = await addItem({
266
- title,
267
- description: opts.desc || "",
268
- type,
269
- wuxing,
270
- priority,
271
- targetVersion: opts.version || "",
272
- tags: opts.tag ? opts.tag.split(",") : []
273
- });
274
- const wx = WUXING_EMOJI[item.wuxing] || "";
275
- console.log(chalk.green(`
276
- \u2705 #${item.id} \u5DF2\u521B\u5EFA`));
277
- console.log(chalk.dim(` ${wx} [${item.priority}\u7EA7] [${TYPE_LABEL[item.type] || item.type}] ${item.title}`));
278
- if (item.targetVersion) console.log(chalk.dim(` \u76EE\u6807\u7248\u672C: ${item.targetVersion}`));
279
- console.log();
280
- }
281
- async function handleLs(args) {
282
- const { opts } = parseOpts(args);
283
- const items = await listItems({
284
- status: opts.status,
285
- wuxing: opts.wuxing,
286
- priority: opts.priority,
287
- version: opts.version,
288
- type: opts.type
289
- });
290
- const stats = await getStats();
291
- console.log();
292
- console.log(chalk.bold(` \u{1F4CB} \u9700\u6C42\u6C60`) + chalk.dim(` (${stats.total} \u6761` + (stats.byStatus["developing"] ? `, ${stats.byStatus["developing"]} developing` : "") + (stats.byStatus["planned"] ? `, ${stats.byStatus["planned"]} planned` : "") + (stats.byStatus["idea"] ? `, ${stats.byStatus["idea"]} idea` : "") + ")"));
293
- console.log();
294
- if (items.length === 0) {
295
- console.log(chalk.dim(" \u6682\u65E0\u9700\u6C42\u3002\u4F7F\u7528 /admin add <\u6807\u9898> \u6DFB\u52A0"));
296
- console.log();
297
- return;
298
- }
299
- let currentPriority = "";
300
- for (const item of items) {
301
- if (item.priority !== currentPriority) {
302
- currentPriority = item.priority;
303
- console.log(chalk.dim(` \u2500\u2500 ${currentPriority}\u7EA7 \u2500\u2500`));
304
- }
305
- const wx = WUXING_EMOJI[item.wuxing] || "";
306
- const st = STATUS_EMOJI[item.status] || "";
307
- const ver = item.targetVersion ? chalk.dim(` ${item.targetVersion}`) : "";
308
- console.log(` ${chalk.dim("#" + item.id)} ${wx} ${st} ${item.title}${ver}`);
309
- }
310
- console.log();
311
- }
312
- async function handleShow(args) {
313
- const id = parseInt(args[0]);
314
- if (!id) {
315
- console.log(chalk.red("\n \u7528\u6CD5: /admin show <id>\n"));
316
- return;
317
- }
318
- const item = await getItem(id);
319
- if (!item) {
320
- console.log(chalk.red(`
321
- \u672A\u627E\u5230 #${id}
322
- `));
323
- return;
324
- }
325
- const wx = WUXING_EMOJI[item.wuxing] || "";
326
- console.log();
327
- console.log(chalk.bold(` #${item.id} ${item.title}`));
328
- console.log();
329
- console.log(` ${chalk.dim("\u7C7B\u578B:")} ${TYPE_LABEL[item.type] || item.type} ${chalk.dim("\u4E94\u884C:")} ${wx}${item.wuxing} ${chalk.dim("\u4F18\u5148\u7EA7:")} ${item.priority} ${chalk.dim("\u72B6\u6001:")} ${item.status}`);
330
- if (item.targetVersion) console.log(` ${chalk.dim("\u7248\u672C:")} ${item.targetVersion}`);
331
- if (item.tags.length) console.log(` ${chalk.dim("\u6807\u7B7E:")} ${item.tags.join(", ")}`);
332
- if (item.description) console.log(` ${chalk.dim("\u63CF\u8FF0:")} ${item.description}`);
333
- if (item.evidence) console.log(` ${chalk.dim("\u8BC1\u636E:")} ${item.evidence}`);
334
- console.log(` ${chalk.dim("\u6765\u6E90:")} ${item.source} ${chalk.dim("\u521B\u5EFA:")} ${item.createdAt.slice(0, 10)}`);
335
- if (item.startedAt) console.log(` ${chalk.dim("\u5F00\u59CB:")} ${item.startedAt.slice(0, 10)}`);
336
- if (item.resolvedAt) console.log(` ${chalk.dim("\u5B8C\u6210:")} ${item.resolvedAt.slice(0, 10)}`);
337
- console.log();
338
- }
339
- async function handleEdit(args) {
340
- const { positional, opts } = parseOpts(args);
341
- const id = parseInt(positional[0]);
342
- if (!id) {
343
- console.log(chalk.red("\n \u7528\u6CD5: /admin edit <id> [--priority S] [--wuxing \u706B] [--version v1.3] [--type bugfix]\n"));
344
- return;
345
- }
346
- const updates = {};
347
- if (opts.priority) {
348
- if (!["S", "A", "B", "C"].includes(opts.priority)) {
349
- console.log(chalk.red(`
350
- priority \u65E0\u6548: ${opts.priority}\uFF08\u53EF\u9009: S/A/B/C\uFF09
351
- `));
352
- return;
353
- }
354
- updates.priority = opts.priority;
355
- }
356
- if (opts.wuxing) {
357
- if (!["\u6728", "\u706B", "\u6C34", "\u91D1", "\u571F"].includes(opts.wuxing)) {
358
- console.log(chalk.red(`
359
- wuxing \u65E0\u6548: ${opts.wuxing}\uFF08\u53EF\u9009: \u6728/\u706B/\u6C34/\u91D1/\u571F\uFF09
360
- `));
361
- return;
362
- }
363
- updates.wuxing = opts.wuxing;
364
- }
365
- if (opts.type) {
366
- if (!["feature", "improvement", "idea", "bugfix"].includes(opts.type)) {
367
- console.log(chalk.red(`
368
- type \u65E0\u6548: ${opts.type}\uFF08\u53EF\u9009: feature/improvement/idea/bugfix\uFF09
369
- `));
370
- return;
371
- }
372
- updates.type = opts.type;
373
- }
374
- if (opts.status) {
375
- if (!["idea", "planned", "developing", "done", "archived"].includes(opts.status)) {
376
- console.log(chalk.red(`
377
- status \u65E0\u6548: ${opts.status}\uFF08\u53EF\u9009: idea/planned/developing/done/archived\uFF09
378
- `));
379
- return;
380
- }
381
- updates.status = opts.status;
382
- }
383
- if (opts.version) updates.targetVersion = opts.version;
384
- if (opts.title) updates.title = opts.title;
385
- if (Object.keys(updates).length === 0) {
386
- console.log(chalk.dim("\n \u65E0\u4FEE\u6539\u9879\n"));
387
- return;
388
- }
389
- const item = await updateItem(id, updates);
390
- if (!item) {
391
- console.log(chalk.red(`
392
- \u672A\u627E\u5230 #${id}
393
- `));
394
- return;
395
- }
396
- console.log(chalk.green(`
397
- \u2705 #${id} \u5DF2\u66F4\u65B0
398
- `));
399
- }
400
- async function handlePick(args, _ctx) {
401
- const id = parseInt(args[0]);
402
- if (!id) {
403
- console.log(chalk.red("\n \u7528\u6CD5: /admin pick <id>\n"));
404
- return;
405
- }
406
- const item = await pickItem(id);
407
- if (!item) {
408
- console.log(chalk.red(`
409
- \u672A\u627E\u5230 #${id}
410
- `));
411
- return;
412
- }
413
- const wx = WUXING_EMOJI[item.wuxing] || "";
414
- console.log();
415
- console.log(chalk.cyan(` \u{1F504} #${item.id} ${item.title} \u2192 developing`));
416
- console.log();
417
- console.log(` ${chalk.dim("\u7C7B\u578B:")} ${TYPE_LABEL[item.type] || item.type} ${chalk.dim("\u4E94\u884C:")} ${wx}${item.wuxing} ${chalk.dim("\u4F18\u5148\u7EA7:")} ${item.priority}`);
418
- if (item.description) console.log(` ${chalk.dim("\u63CF\u8FF0:")} ${item.description}`);
419
- if (item.targetVersion) console.log(` ${chalk.dim("\u7248\u672C:")} ${item.targetVersion}`);
420
- console.log();
421
- console.log(chalk.dim(" \u9700\u6C42\u5DF2\u52A0\u8F7D\u3002\u544A\u8BC9\u6211\u600E\u4E48\u505A\u3002"));
422
- console.log();
423
- }
424
- async function handleDone(args) {
425
- const id = parseInt(args[0]);
426
- if (!id) {
427
- console.log(chalk.red("\n \u7528\u6CD5: /admin done <id>\n"));
428
- return;
429
- }
430
- const item = await doneItem(id);
431
- if (!item) {
432
- console.log(chalk.red(`
433
- \u672A\u627E\u5230 #${id}
434
- `));
435
- return;
436
- }
437
- console.log(chalk.green(`
438
- \u2705 #${item.id} ${item.title} \u2192 done`));
439
- console.log(chalk.dim(` \u5B8C\u6210\u4E8E: ${item.resolvedAt?.slice(0, 10)}`));
440
- try {
441
- const baseline = await recordBaseline(id);
442
- if (baseline) {
443
- console.log(chalk.dim(` \u{1F4CF} \u57FA\u7EBF: ${baseline.key} = ${baseline.value}`));
444
- console.log(chalk.dim(` \u4E0B\u6B21 /admin verify \u65F6\u5C06\u81EA\u52A8\u68C0\u6D4B\u6539\u5584\u6548\u679C`));
445
- }
446
- } catch {
447
- }
448
- console.log();
449
- }
450
- async function handleArchive(args) {
451
- const id = parseInt(args[0]);
452
- if (!id) {
453
- console.log(chalk.red("\n \u7528\u6CD5: /admin archive <id>\n"));
454
- return;
455
- }
456
- const item = await archiveItem(id);
457
- if (!item) {
458
- console.log(chalk.red(`
459
- \u672A\u627E\u5230 #${id}
460
- `));
461
- return;
462
- }
463
- console.log(chalk.dim(`
464
- \u{1F4E6} #${item.id} ${item.title} \u2192 archived
465
- `));
466
- }
467
- async function handleReopen(args) {
468
- const id = parseInt(args[0]);
469
- if (!id) {
470
- console.log(chalk.red("\n \u7528\u6CD5: /admin reopen <id>\n"));
471
- return;
472
- }
473
- const item = await reopenItem(id);
474
- if (!item) {
475
- console.log(chalk.red(`
476
- \u672A\u627E\u5230 #${id}
477
- `));
478
- return;
479
- }
480
- console.log(chalk.green(`
481
- \u{1F504} #${item.id} ${item.title} \u2192 planned
482
- `));
483
- }
484
- async function handleVersion() {
485
- const info = await getVersionInfo(process.cwd());
486
- console.log();
487
- console.log(chalk.bold(` \u{1F3D7}\uFE0F \u7248\u672C\u4E2D\u5FC3`));
488
- console.log();
489
- console.log(` ${chalk.dim("\u5F53\u524D:")} v${info.currentVersion}`);
490
- if (info.lastTag) {
491
- console.log(` ${chalk.dim("\u4E0A\u6B21\u53D1\u5E03:")} ${info.lastTag} (${info.lastTagDate}, ${info.daysSinceTag}\u5929\u524D)`);
492
- } else {
493
- console.log(chalk.dim(" \u5C1A\u65E0\u53D1\u5E03 tag"));
494
- }
495
- console.log(` ${chalk.dim("\u5F85\u53D1\u5E03:")} ${info.pendingCommits} commits, ${info.filesChanged} files (+${info.insertions}/-${info.deletions})`);
496
- if (Object.keys(info.commitsByType).length > 0) {
497
- console.log();
498
- console.log(chalk.dim(" \u53D8\u66F4\u5206\u7C7B:"));
499
- const typeEmoji = {
500
- feat: "\u{1F333}",
501
- fix: "\u{1F333}",
502
- docs: "\u{1F525}",
503
- style: "\u{1F525}",
504
- refactor: "\u2699\uFE0F",
505
- perf: "\u{1F30A}",
506
- test: "\u2699\uFE0F",
507
- chore: "\u{1F3D4}\uFE0F"
508
- };
509
- for (const [type, count] of Object.entries(info.commitsByType)) {
510
- console.log(` ${typeEmoji[type] || "\xB7"} ${type}: ${count} commits`);
511
- }
512
- }
513
- if (info.recentCommits.length > 0) {
514
- console.log();
515
- console.log(chalk.dim(" \u6700\u8FD1\u63D0\u4EA4:"));
516
- for (const c of info.recentCommits.slice(0, 8)) {
517
- console.log(chalk.dim(` ${c.hash} ${c.message}`));
518
- }
519
- if (info.recentCommits.length > 8) {
520
- console.log(chalk.dim(` ... \u8FD8\u6709 ${info.recentCommits.length - 8} \u6761`));
521
- }
522
- }
523
- console.log();
524
- }
525
- async function handleReleaseCheck() {
526
- console.log(chalk.dim("\n \u{1F680} \u53D1\u5E03\u68C0\u67E5\u4E2D...\n"));
527
- const checks = await runReleaseChecks(process.cwd());
528
- let allPassed = true;
529
- for (const c of checks) {
530
- const icon = c.ok ? chalk.green("\u2705") : chalk.red("\u274C");
531
- console.log(` ${icon} ${chalk.bold(c.name)} ${chalk.dim(c.detail)}`);
532
- if (!c.ok) allPassed = false;
533
- }
534
- console.log();
535
- if (allPassed) {
536
- console.log(chalk.green(" \u7ED3\u8BBA: \u{1F7E2} \u53EF\u4EE5\u53D1\u5E03"));
537
- } else {
538
- const failCount = checks.filter((c) => !c.ok).length;
539
- console.log(chalk.yellow(` \u7ED3\u8BBA: \u{1F7E1} \u6682\u4E0D\u53EF\u53D1\u5E03 (${failCount} \u9879\u672A\u901A\u8FC7)`));
540
- }
541
- console.log();
542
- }
543
- async function handleReleaseHistory() {
544
- const history = getReleaseHistory(process.cwd());
545
- console.log();
546
- if (history.length === 0) {
547
- console.log(chalk.dim(" \u5C1A\u65E0\u53D1\u5E03\u5386\u53F2 (\u65E0 git tag)"));
548
- } else {
549
- console.log(chalk.bold(" \u{1F4DC} \u53D1\u5E03\u5386\u53F2"));
550
- console.log();
551
- for (const h of history) {
552
- console.log(` ${chalk.cyan(h.tag)} ${chalk.dim(h.date)} ${h.message || ""}`);
553
- }
554
- }
555
- console.log();
556
- }
557
- var SEVERITY_EMOJI = {
558
- high: "\u{1F534}",
559
- warning: "\u{1F7E1}",
560
- opportunity: "\u{1F7E2}"
561
- };
562
- async function handleDiagnose(args, ctx) {
563
- const { opts } = parseOpts(args);
564
- const days = parseInt(opts.days || "7") || 7;
565
- const useAI = args.includes("--ai");
566
- console.log(chalk.dim(`
567
- \u{1F50D} \u8BCA\u65AD\u4E2D (\u8FD1 ${days} \u5929)${useAI ? " [AI \u589E\u5F3A]" : " [\u89C4\u5219\u5F15\u64CE]"}...
568
- `));
569
- if (useAI) {
570
- const { ruleFindings, aiFindings, aiRawText } = await runAIDiagnosis(ctx, days);
571
- console.log("\n");
572
- if (ruleFindings.length > 0) {
573
- console.log(chalk.dim(" \u2500\u2500 \u89C4\u5219\u5F15\u64CE\u53D1\u73B0 \u2500\u2500"));
574
- for (const f of ruleFindings) {
575
- console.log(` ${SEVERITY_EMOJI[f.severity] || "\xB7"} ${chalk.bold(f.title)}`);
576
- console.log(chalk.dim(` ${f.detail}`));
577
- console.log(chalk.dim(` \u2192 ${f.suggestion}`));
578
- }
579
- console.log();
580
- }
581
- if (aiFindings.length > 0) {
582
- console.log(chalk.dim(" \u2500\u2500 AI \u8865\u5145\u53D1\u73B0 \u2500\u2500"));
583
- for (const f of aiFindings) {
584
- console.log(` ${SEVERITY_EMOJI[f.severity] || "\xB7"} ${chalk.bold(f.title)}`);
585
- console.log(chalk.dim(` ${f.detail}`));
586
- console.log(chalk.dim(` \u2192 ${f.suggestion}`));
587
- }
588
- console.log();
589
- }
590
- const total = ruleFindings.length + aiFindings.length;
591
- if (total === 0) {
592
- console.log(chalk.green(" \u2705 \u672A\u53D1\u73B0\u95EE\u9898\n"));
593
- } else {
594
- console.log(chalk.dim(` \u5171 ${total} \u6761\u53D1\u73B0 (\u89C4\u5219 ${ruleFindings.length} + AI ${aiFindings.length})`));
595
- console.log(chalk.dim(` \u4F7F\u7528 /admin diagnose-to-backlog \u5C06\u53D1\u73B0\u8F6C\u4E3A\u9700\u6C42
596
- `));
597
- }
598
- } else {
599
- const findings = await runRuleDiagnosis(days);
600
- if (findings.length === 0) {
601
- console.log(chalk.green(" \u2705 \u672A\u53D1\u73B0\u95EE\u9898\n"));
602
- return;
603
- }
604
- for (const f of findings) {
605
- console.log(` ${SEVERITY_EMOJI[f.severity] || "\xB7"} ${chalk.bold(f.title)}`);
606
- console.log(chalk.dim(` ${f.detail}`));
607
- console.log(chalk.dim(` \u2192 ${f.suggestion}`));
608
- }
609
- console.log();
610
- console.log(chalk.dim(` \u5171 ${findings.length} \u6761\u53D1\u73B0`));
611
- console.log(chalk.dim(` \u4F7F\u7528 /admin diagnose --ai \u542F\u7528 AI \u589E\u5F3A\u8BCA\u65AD`));
612
- console.log(chalk.dim(` \u4F7F\u7528 /admin diagnose-to-backlog \u5C06\u53D1\u73B0\u8F6C\u4E3A\u9700\u6C42
613
- `));
614
- }
615
- }
616
- async function handleDiagnoseToBacklog(args) {
617
- const { opts } = parseOpts(args);
618
- const days = parseInt(opts.days || "7") || 7;
619
- const version = opts.version || "";
620
- console.log(chalk.dim(`
621
- \u{1F504} \u6B63\u5728\u5C06\u8BCA\u65AD\u53D1\u73B0\u8F6C\u4E3A\u9700\u6C42 (\u8FD1 ${days} \u5929)...
622
- `));
623
- const findings = await runRuleDiagnosis(days);
624
- if (findings.length === 0) {
625
- console.log(chalk.dim(" \u65E0\u53D1\u73B0\u53EF\u8F6C\u5316\n"));
626
- return;
627
- }
628
- const createdIds = await findingsToBacklog(findings, version);
629
- if (createdIds.length === 0) {
630
- console.log(chalk.dim(" \u6240\u6709\u53D1\u73B0\u5DF2\u5B58\u5728\u4E8E\u9700\u6C42\u6C60\u4E2D\uFF08\u5DF2\u53BB\u91CD\uFF09\n"));
631
- } else {
632
- console.log(chalk.green(` \u2705 \u5DF2\u521B\u5EFA ${createdIds.length} \u6761\u9700\u6C42: ${createdIds.map((id) => "#" + id).join(", ")}`));
633
- if (findings.length > createdIds.length) {
634
- console.log(chalk.dim(` \u8DF3\u8FC7 ${findings.length - createdIds.length} \u6761\u91CD\u590D`));
635
- }
636
- console.log(chalk.dim(` \u4F7F\u7528 /admin ls \u67E5\u770B\u9700\u6C42\u6C60
637
- `));
638
- }
639
- }
640
- async function handleQuality(args) {
641
- const subCmd = args[0];
642
- if (subCmd === "test" || subCmd === "tests") {
643
- return handleQualitySingle("test");
644
- }
645
- if (subCmd === "todos" || subCmd === "todo") {
646
- return handleQualitySingle("todos");
647
- }
648
- if (subCmd === "deps" || subCmd === "dep") {
649
- return handleQualitySingle("deps");
650
- }
651
- if (subCmd === "size") {
652
- return handleQualitySingle("size");
653
- }
654
- if (subCmd === "build") {
655
- return handleQualitySingle("build");
656
- }
657
- const skipTests = args.includes("--skip-tests");
658
- const skipBuild = args.includes("--skip-build");
659
- console.log(chalk.dim("\n \u{1F3E5} \u8D28\u91CF\u770B\u677F \xB7 \u68C0\u67E5\u4E2D...\n"));
660
- const report = await runQualityReport(process.cwd(), { skipTests, skipBuild });
661
- for (const c of report.checks) {
662
- const icon = c.ok ? chalk.green("\u2705") : chalk.red("\u274C");
663
- const valueStr = c.value !== void 0 && c.unit ? chalk.dim(` (${c.value}${c.unit})`) : "";
664
- console.log(` ${icon} ${chalk.bold(c.name)} ${c.detail}${valueStr}`);
665
- }
666
- console.log();
667
- const scoreColor = report.score >= 80 ? chalk.green : report.score >= 60 ? chalk.yellow : chalk.red;
668
- console.log(` \u7EFC\u5408\u5065\u5EB7\u5EA6: ${scoreColor(report.score + "/100")}`);
669
- console.log();
670
- }
671
- async function handleQualitySingle(which) {
672
- const projectRoot = process.cwd();
673
- console.log(chalk.dim(`
674
- \u68C0\u67E5\u4E2D...
675
- `));
676
- let result;
677
- switch (which) {
678
- case "test":
679
- result = await checkTests(projectRoot);
680
- break;
681
- case "todos":
682
- result = await checkTodos(projectRoot);
683
- break;
684
- case "deps":
685
- result = await checkDeps(projectRoot);
686
- break;
687
- case "size":
688
- result = await checkPackageSize(projectRoot);
689
- break;
690
- case "build":
691
- result = await checkBuild(projectRoot);
692
- break;
693
- default:
694
- console.log(chalk.red(` \u672A\u77E5\u68C0\u67E5\u9879: ${which}
695
- `));
696
- return;
697
- }
698
- const icon = result.ok ? chalk.green("\u2705") : chalk.red("\u274C");
699
- console.log(` ${icon} ${chalk.bold(result.name)} ${result.detail}`);
700
- if (result.value !== void 0 && result.unit) {
701
- console.log(chalk.dim(` \u503C: ${result.value} ${result.unit}`));
702
- }
703
- console.log();
704
- }
705
- var VERDICT_EMOJI = {
706
- effective: "\u2705",
707
- ineffective: "\u274C",
708
- pending: "\u23F3",
709
- "no-data": "\u2753"
710
- };
711
- var VERDICT_LABEL = {
712
- effective: "\u6709\u6548",
713
- ineffective: "\u65E0\u6548",
714
- pending: "\u5F85\u89C2\u5BDF",
715
- "no-data": "\u65E0\u6570\u636E"
716
- };
717
- async function handleVerify() {
718
- console.log(chalk.dim("\n \u{1F52C} \u6548\u679C\u9A8C\u8BC1\u4E2D...\n"));
719
- const report = await verifyCompletedItems();
720
- if (report.results.length === 0) {
721
- console.log(chalk.dim(" \u6682\u65E0\u53EF\u9A8C\u8BC1\u7684\u9700\u6C42"));
722
- console.log(chalk.dim(" \u63D0\u793A: \u4F7F\u7528 /admin done <id> \u5B8C\u6210\u9700\u6C42\u540E\uFF0C\u7CFB\u7EDF\u4F1A\u81EA\u52A8\u8BB0\u5F55\u57FA\u7EBF"));
723
- console.log();
724
- return;
725
- }
726
- for (const r of report.results) {
727
- const icon = VERDICT_EMOJI[r.verdict] || "\xB7";
728
- const label = VERDICT_LABEL[r.verdict] || r.verdict;
729
- console.log(` ${icon} ${chalk.bold(`#${r.itemId} ${r.title}`)} \u2192 ${label}`);
730
- console.log(chalk.dim(` \u6307\u6807: ${r.baselineKey} \u57FA\u7EBF: ${r.baselineValue}${r.afterValue !== null ? ` \u5F53\u524D: ${r.afterValue}` : ""}`));
731
- if (r.changePercent !== null) {
732
- const changeColor = r.verdict === "effective" ? chalk.green : r.verdict === "ineffective" ? chalk.red : chalk.yellow;
733
- console.log(chalk.dim(" ") + changeColor(r.detail));
734
- } else {
735
- console.log(chalk.dim(` ${r.detail}`));
736
- }
737
- }
738
- console.log();
739
- console.log(chalk.dim(` \u603B\u8BA1: ${report.summary.total} \u9879 | \u2705 ${report.summary.effective} \u6709\u6548 \u274C ${report.summary.ineffective} \u65E0\u6548 \u23F3 ${report.summary.pending} \u5F85\u89C2\u5BDF \u2753 ${report.summary.noData} \u65E0\u6570\u636E`));
740
- console.log();
741
- }
742
- async function handleRoadmap(args) {
743
- const { positional, opts } = parseOpts(args);
744
- if (opts.set) {
745
- const id = parseInt(opts.set);
746
- const ver = positional[0] || opts.version || "";
747
- if (!id || !ver) {
748
- console.log(chalk.red("\n \u7528\u6CD5: /admin roadmap --set <id> <version>\n"));
749
- return;
750
- }
751
- const item = await updateItem(id, { targetVersion: ver });
752
- if (!item) {
753
- console.log(chalk.red(`
754
- \u672A\u627E\u5230 #${id}
755
- `));
756
- return;
757
- }
758
- console.log(chalk.green(`
759
- \u2705 #${id} \u2192 ${ver}
760
- `));
761
- return;
762
- }
763
- const roadmap = await getRoadmap();
764
- if (roadmap.length === 0) {
765
- console.log(chalk.dim("\n \u6682\u65E0\u7248\u672C\u89C4\u5212"));
766
- console.log(chalk.dim(" \u4F7F\u7528 /admin add <\u6807\u9898> --version v1.2 \u6DFB\u52A0\u7248\u672C\u9700\u6C42"));
767
- console.log(chalk.dim(" \u4F7F\u7528 /admin milestone add <\u7248\u672C> <\u540D\u79F0> \u5B9A\u4E49\u91CC\u7A0B\u7891\n"));
768
- return;
769
- }
770
- console.log();
771
- console.log(chalk.bold(" \u{1F5FA}\uFE0F \u8DEF\u7EBF\u56FE"));
772
- console.log();
773
- for (const ver of roadmap) {
774
- const msLabel = ver.milestone ? ver.milestone.status === "done" ? chalk.green(" \u2713") : ver.milestone.status === "active" ? chalk.cyan(" \u2B24") : "" : "";
775
- const msName = ver.milestone ? chalk.dim(` \u2014 ${ver.milestone.name}`) : "";
776
- const barWidth = 20;
777
- const filled = Math.round(ver.stats.progress / 100 * barWidth);
778
- const bar = "\u2588".repeat(filled) + "\u2591".repeat(barWidth - filled);
779
- const progressColor = ver.stats.progress === 100 ? chalk.green : ver.stats.progress >= 50 ? chalk.cyan : chalk.yellow;
780
- console.log(` ${chalk.bold(ver.version)}${msLabel}${msName} ${progressColor(bar)} ${ver.stats.progress}%`);
781
- console.log(chalk.dim(` ${ver.stats.total} \u9700\u6C42: ${ver.stats.done} done, ${ver.stats.developing} dev, ${ver.stats.planned} planned, ${ver.stats.idea} idea`));
782
- const activeItems = ver.items.filter((i) => i.status === "developing" || i.status === "planned").slice(0, 5);
783
- for (const item of activeItems) {
784
- const wx = WUXING_EMOJI[item.wuxing] || "";
785
- const st = STATUS_EMOJI[item.status] || "";
786
- console.log(chalk.dim(` ${st} #${item.id} ${wx} ${item.title}`));
787
- }
788
- const remaining = ver.items.filter((i) => i.status === "developing" || i.status === "planned").length - activeItems.length;
789
- if (remaining > 0) {
790
- console.log(chalk.dim(` ... \u8FD8\u6709 ${remaining} \u6761`));
791
- }
792
- console.log();
793
- }
794
- }
795
- async function handleMilestone(args) {
796
- const subCmd = args[0];
797
- const subArgs = args.slice(1);
798
- if (subCmd === "add") {
799
- const ver = subArgs[0];
800
- const name = subArgs.slice(1).join(" ");
801
- if (!ver || !name) {
802
- console.log(chalk.red("\n \u7528\u6CD5: /admin milestone add <\u7248\u672C\u53F7> <\u540D\u79F0>\n"));
803
- return;
804
- }
805
- try {
806
- const ms = await addMilestone(ver, name);
807
- console.log(chalk.green(`
808
- \u2705 \u91CC\u7A0B\u7891 ${ms.version} "${ms.name}" \u5DF2\u521B\u5EFA
809
- `));
810
- } catch (err) {
811
- console.log(chalk.red(`
812
- ${err instanceof Error ? err.message : String(err)}
813
- `));
814
- }
815
- return;
816
- }
817
- if (subCmd === "done") {
818
- const ver = subArgs[0];
819
- if (!ver) {
820
- console.log(chalk.red("\n \u7528\u6CD5: /admin milestone done <\u7248\u672C\u53F7>\n"));
821
- return;
822
- }
823
- const ms = await doneMilestone(ver);
824
- if (!ms) {
825
- console.log(chalk.red(`
826
- \u672A\u627E\u5230\u91CC\u7A0B\u7891 ${ver}
827
- `));
828
- return;
829
- }
830
- console.log(chalk.green(`
831
- \u2705 \u91CC\u7A0B\u7891 ${ms.version} "${ms.name}" \u2192 done
832
- `));
833
- return;
834
- }
835
- if (subCmd === "activate") {
836
- const ver = subArgs[0];
837
- if (!ver) {
838
- console.log(chalk.red("\n \u7528\u6CD5: /admin milestone activate <\u7248\u672C\u53F7>\n"));
839
- return;
840
- }
841
- const ms = await activateMilestone(ver);
842
- if (!ms) {
843
- console.log(chalk.red(`
844
- \u672A\u627E\u5230\u91CC\u7A0B\u7891 ${ver}
845
- `));
846
- return;
847
- }
848
- console.log(chalk.cyan(`
849
- \u2B24 \u91CC\u7A0B\u7891 ${ms.version} "${ms.name}" \u2192 active
850
- `));
851
- return;
852
- }
853
- const milestones = await listMilestones();
854
- if (milestones.length === 0) {
855
- console.log(chalk.dim("\n \u6682\u65E0\u91CC\u7A0B\u7891"));
856
- console.log(chalk.dim(" \u4F7F\u7528 /admin milestone add <\u7248\u672C\u53F7> <\u540D\u79F0> \u521B\u5EFA\n"));
857
- return;
858
- }
859
- console.log();
860
- console.log(chalk.bold(" \u{1F3C1} \u91CC\u7A0B\u7891"));
861
- console.log();
862
- const msStatusIcon = {
863
- planning: "\u{1F4DD}",
864
- active: "\u2B24",
865
- done: "\u2705",
866
- cancelled: "\u26D4"
867
- };
868
- for (const ms of milestones) {
869
- const icon = msStatusIcon[ms.status] || "\xB7";
870
- const doneInfo = ms.doneAt ? chalk.dim(` (${ms.doneAt.slice(0, 10)})`) : "";
871
- console.log(` ${icon} ${chalk.bold(ms.version)} ${ms.name}${doneInfo}`);
872
- if (ms.description) console.log(chalk.dim(` ${ms.description}`));
873
- }
874
- console.log();
875
- }
876
- async function handleStatus() {
877
- const stats = await getStats();
878
- const summary = await getEventsSummary(7);
879
- console.log();
880
- console.log(chalk.bold(" \u{1FA9E} \u5185\u89C2 \xB7 HyperMirror \u72B6\u6001"));
881
- console.log();
882
- console.log(chalk.dim(" \u2500\u2500 \u9700\u6C42\u6C60 \u2500\u2500"));
883
- console.log(` \u603B\u8BA1: ${stats.total} \u6761 | ${STATUS_EMOJI["developing"]} developing: ${stats.byStatus["developing"] || 0} ${STATUS_EMOJI["planned"]} planned: ${stats.byStatus["planned"] || 0} ${STATUS_EMOJI["idea"]} idea: ${stats.byStatus["idea"] || 0} ${STATUS_EMOJI["done"]} done: ${stats.byStatus["done"] || 0}`);
884
- console.log();
885
- console.log(chalk.dim(" \u2500\u2500 \u4E8B\u4EF6\u91C7\u96C6 (\u8FD17\u5929) \u2500\u2500"));
886
- console.log(` \u4E8B\u4EF6\u603B\u6570: ${summary.totalEvents} | \u4F1A\u8BDD: ${summary.totalSessions} | \u5E73\u5747\u8F6E\u6B21: ${summary.avgSessionRounds}`);
887
- if (Object.keys(summary.cmdCounts).length > 0) {
888
- const topCmds = Object.entries(summary.cmdCounts).sort((a, b) => b[1].total - a[1].total).slice(0, 5);
889
- console.log(chalk.dim(" \u70ED\u95E8\u547D\u4EE4:"));
890
- for (const [cmd, c] of topCmds) {
891
- const failPart = c.fail > 0 ? chalk.red(` (${c.fail} \u5931\u8D25)`) : "";
892
- console.log(chalk.dim(` ${cmd}: ${c.total}\u6B21${failPart}`));
893
- }
894
- }
895
- if (summary.errors.length > 0) {
896
- console.log(chalk.dim(" \u8FD1\u671F\u9519\u8BEF:"));
897
- for (const e of summary.errors.slice(0, 3)) {
898
- console.log(chalk.dim(` ${e.type}: ${e.count}\u6B21`));
899
- }
900
- }
901
- console.log();
902
- }
903
- function showHelp() {
904
- console.log(`
905
- ${chalk.bold("\u{1FA9E} /admin \u2014 \u5185\u89C2\u5F15\u64CE \xB7 HyperMirror")}
906
-
907
- ${chalk.dim("\u9700\u6C42\u6C60:")}
908
- /admin add <\u6807\u9898> [opts] \u65B0\u589E\u9700\u6C42
909
- /admin ls [filters] \u5217\u8868\u7B5B\u9009
910
- /admin show <id> \u67E5\u770B\u8BE6\u60C5
911
- /admin edit <id> [opts] \u4FEE\u6539\u5B57\u6BB5
912
- /admin pick <id> \u5F00\u59CB\u5F00\u53D1
913
- /admin done <id> \u6807\u8BB0\u5B8C\u6210
914
- /admin archive <id> \u5F52\u6863
915
- /admin reopen <id> \u91CD\u65B0\u6253\u5F00
916
-
917
- ${chalk.dim("\u7248\u672C\u4E2D\u5FC3:")}
918
- /admin version \u7248\u672C\u6982\u89C8
919
- /admin release-check \u53D1\u5E03\u524D\u68C0\u67E5
920
- /admin release-history \u5386\u53F2\u7248\u672C
921
-
922
- ${chalk.dim("\u8BCA\u65AD\u5F15\u64CE (Phase 1):")}
923
- /admin diagnose [--days 7] \u89C4\u5219\u8BCA\u65AD
924
- /admin diagnose --ai AI \u589E\u5F3A\u8BCA\u65AD
925
- /admin diagnose-to-backlog \u53D1\u73B0\u2192\u9700\u6C42\u8F6C\u5316
926
-
927
- ${chalk.dim("\u8D28\u91CF\u770B\u677F (Phase 1):")}
928
- /admin quality \u5B8C\u6574\u8D28\u91CF\u62A5\u544A
929
- /admin quality test \u6D4B\u8BD5\u901A\u8FC7\u7387
930
- /admin quality todos TODO/FIXME \u626B\u63CF
931
- /admin quality deps \u4F9D\u8D56\u5B89\u5168\u68C0\u67E5
932
- /admin quality size \u5305\u4F53\u79EF
933
- /admin quality build \u7F16\u8BD1\u68C0\u67E5
934
-
935
- ${chalk.dim("\u6548\u679C\u9A8C\u8BC1 (Phase 2):")}
936
- /admin verify \u68C0\u6D4B\u5DF2\u5B8C\u6210\u9700\u6C42\u7684\u6539\u5584\u6548\u679C
937
-
938
- ${chalk.dim("\u8DEF\u7EBF\u56FE (Phase 2):")}
939
- /admin roadmap \u6309\u7248\u672C\u5206\u7EC4\u5C55\u793A\u9700\u6C42+\u8FDB\u5EA6
940
- /admin roadmap --set <id> <ver> \u5206\u914D\u9700\u6C42\u5230\u7248\u672C
941
- /admin milestone \u91CC\u7A0B\u7891\u5217\u8868
942
- /admin milestone add <ver> <name> \u65B0\u589E\u91CC\u7A0B\u7891
943
- /admin milestone done <ver> \u6807\u8BB0\u91CC\u7A0B\u7891\u5B8C\u6210
944
- /admin milestone activate <ver> \u6FC0\u6D3B\u91CC\u7A0B\u7891
945
-
946
- ${chalk.dim("\u603B\u89C8:")}
947
- /admin status \u5185\u89C2\u72B6\u6001\u6982\u89C8
948
- /admin help \u663E\u793A\u5E2E\u52A9
949
-
950
- ${chalk.dim("\u9009\u9879 (\u7528\u4E8E add/edit/ls):")}
951
- --type, -t feature|improvement|idea|bugfix
952
- --wuxing, -w \u6728|\u706B|\u6C34|\u91D1|\u571F
953
- --priority, -p S|A|B|C
954
- --version, -v \u76EE\u6807\u7248\u672C\u53F7
955
- --desc, -d \u63CF\u8FF0\u6587\u672C
956
- --status idea|planned|developing|done
957
- `);
958
- }
959
- function createAdminSlashCommands() {
960
- return [
961
- {
962
- name: "admin",
963
- aliases: ["mirror"],
964
- description: "\u5185\u89C2\u5F15\u64CE \xB7 \u9879\u76EE\u81EA\u7BA1\u7406 (/admin help \u67E5\u770B\u5B50\u547D\u4EE4)",
965
- category: "admin",
966
- handler: async (args, ctx) => {
967
- const subCmd = args[0]?.toLowerCase();
968
- const subArgs = args.slice(1);
969
- switch (subCmd) {
970
- // 需求池
971
- case "add":
972
- return handleAdd(subArgs, ctx);
973
- case "ls":
974
- case "list":
975
- return handleLs(subArgs);
976
- case "show":
977
- return handleShow(subArgs);
978
- case "edit":
979
- return handleEdit(subArgs);
980
- case "pick":
981
- return handlePick(subArgs, ctx);
982
- case "done":
983
- return handleDone(subArgs);
984
- case "archive":
985
- return handleArchive(subArgs);
986
- case "reopen":
987
- return handleReopen(subArgs);
988
- // 版本中心
989
- case "version":
990
- case "ver":
991
- return handleVersion();
992
- case "release-check":
993
- case "rc":
994
- return handleReleaseCheck();
995
- case "release-history":
996
- case "rh":
997
- return handleReleaseHistory();
998
- // 诊断 (Phase 1)
999
- case "diagnose":
1000
- case "diag":
1001
- return handleDiagnose(subArgs, ctx);
1002
- case "diagnose-to-backlog":
1003
- case "dtb":
1004
- return handleDiagnoseToBacklog(subArgs);
1005
- // 质量看板 (Phase 1)
1006
- case "quality":
1007
- case "q":
1008
- return handleQuality(subArgs);
1009
- // 效果验证 (Phase 2)
1010
- case "verify":
1011
- case "v":
1012
- return handleVerify();
1013
- // 路线图 (Phase 2)
1014
- case "roadmap":
1015
- case "rm":
1016
- return handleRoadmap(subArgs);
1017
- case "milestone":
1018
- case "ms":
1019
- return handleMilestone(subArgs);
1020
- // changelog (Phase 2)
1021
- case "changelog":
1022
- console.log(chalk.dim("\n /admin changelog \u2014 AI \u751F\u6210 CHANGELOG\uFF0C\u5C1A\u672A\u5B9E\u73B0\n"));
1023
- return;
1024
- // 总览
1025
- case "status":
1026
- case "st":
1027
- return handleStatus();
1028
- // 帮助
1029
- case "help":
1030
- case void 0:
1031
- showHelp();
1032
- return;
1033
- default:
1034
- console.log(chalk.red(`
1035
- \u672A\u77E5\u5B50\u547D\u4EE4: ${subCmd}`));
1036
- showHelp();
1037
- }
1038
- }
1039
- }
1040
- ];
1041
- }
1042
- export {
1043
- createAdminSlashCommands
1044
- };