yg-team-cli 2.6.1 → 2.6.3

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.
package/dist/index.js CHANGED
@@ -460,6 +460,121 @@ var init_utils = __esm({
460
460
  }
461
461
  return milestones;
462
462
  }
463
+ /**
464
+ * 解析增强版里程碑信息(支持 [F]/[B]/[I] 前缀分类)
465
+ */
466
+ static parseMilestonesEnhanced(content) {
467
+ const milestones = [];
468
+ const lines = content.split("\n");
469
+ let currentMilestone = null;
470
+ let inMilestone = false;
471
+ for (const line of lines) {
472
+ if (line.match(/^###\s+Milestone\s+\d+:/)) {
473
+ if (currentMilestone) {
474
+ currentMilestone.totalCount = currentMilestone.todos.length;
475
+ milestones.push(currentMilestone);
476
+ }
477
+ const title = line.replace(/^###\s+/, "").trim();
478
+ currentMilestone = {
479
+ title,
480
+ todos: [],
481
+ frontendTodos: [],
482
+ backendTodos: [],
483
+ integrationTodos: [],
484
+ generalTodos: [],
485
+ completedCount: 0,
486
+ totalCount: 0
487
+ };
488
+ inMilestone = true;
489
+ continue;
490
+ }
491
+ if (inMilestone && currentMilestone) {
492
+ if (line.match(/^###\s+Milestone/)) {
493
+ currentMilestone.totalCount = currentMilestone.todos.length;
494
+ milestones.push(currentMilestone);
495
+ currentMilestone = null;
496
+ const title = line.replace(/^###\s+/, "").trim();
497
+ currentMilestone = {
498
+ title,
499
+ todos: [],
500
+ frontendTodos: [],
501
+ backendTodos: [],
502
+ integrationTodos: [],
503
+ generalTodos: [],
504
+ completedCount: 0,
505
+ totalCount: 0
506
+ };
507
+ continue;
508
+ }
509
+ const todoMatch = line.match(/^-\s+\[([ xX])\]\s*(\[[FBIN]\])?\s*(.+)/);
510
+ if (todoMatch) {
511
+ const isCompleted = todoMatch[1].toLowerCase() === "x";
512
+ const prefix = todoMatch[2]?.trim() || "";
513
+ const rawContent = todoMatch[3].trim();
514
+ let type = "general";
515
+ let apiAssociation;
516
+ let dependencies;
517
+ if (prefix === "[F]") {
518
+ type = "frontend";
519
+ } else if (prefix === "[B]") {
520
+ type = "backend";
521
+ const apiMatch = rawContent.match(/\(关联 API:\s*`([^`]+)`\)/);
522
+ if (apiMatch) {
523
+ apiAssociation = apiMatch[1];
524
+ }
525
+ } else if (prefix === "[I]") {
526
+ type = "integration";
527
+ const depMatch = rawContent.match(/\(依赖:\s*([^)]+)\)/);
528
+ if (depMatch) {
529
+ dependencies = depMatch[1].split(",").map((d) => d.trim()).filter((d) => d.length > 0);
530
+ }
531
+ }
532
+ const todoItem = {
533
+ raw: line.trim(),
534
+ content: rawContent.replace(/\s*\(关联 API:\s*`[^`]+`\)/, "").replace(/\s*\(依赖:\s*[^)]+\)/, "").trim(),
535
+ type,
536
+ apiAssociation,
537
+ dependencies,
538
+ isCompleted
539
+ };
540
+ currentMilestone.todos.push(todoItem);
541
+ if (isCompleted) {
542
+ currentMilestone.completedCount++;
543
+ }
544
+ switch (type) {
545
+ case "frontend":
546
+ currentMilestone.frontendTodos.push(todoItem);
547
+ break;
548
+ case "backend":
549
+ currentMilestone.backendTodos.push(todoItem);
550
+ break;
551
+ case "integration":
552
+ currentMilestone.integrationTodos.push(todoItem);
553
+ break;
554
+ default:
555
+ currentMilestone.generalTodos.push(todoItem);
556
+ }
557
+ }
558
+ }
559
+ }
560
+ if (currentMilestone) {
561
+ currentMilestone.totalCount = currentMilestone.todos.length;
562
+ milestones.push(currentMilestone);
563
+ }
564
+ return milestones;
565
+ }
566
+ /**
567
+ * 解析增强版里程碑(向后兼容版 - 优先尝试增强解析,失败回退到简单解析)
568
+ */
569
+ static parseMilestonesEnhancedWithFallback(content) {
570
+ const enhanced = this.parseMilestonesEnhanced(content);
571
+ const hasEnhancedFormat = enhanced.some(
572
+ (m) => m.todos.some(
573
+ (t) => t.type !== "general" || t.apiAssociation || t.dependencies
574
+ )
575
+ );
576
+ return { enhanced, isEnhanced: hasEnhancedFormat };
577
+ }
463
578
  /**
464
579
  * 解析 spec 状态(基于进度动态推导)
465
580
  */
@@ -886,22 +1001,22 @@ var init_gitlab_api = __esm({
886
1001
  * 从 Git URL 中提取项目路径
887
1002
  */
888
1003
  static parseProjectPath(repository) {
889
- let path20 = repository;
890
- if (path20.startsWith("git@")) {
891
- path20 = path20.replace(/^git@/, "");
892
- const colonIndex = path20.indexOf(":");
1004
+ let path21 = repository;
1005
+ if (path21.startsWith("git@")) {
1006
+ path21 = path21.replace(/^git@/, "");
1007
+ const colonIndex = path21.indexOf(":");
893
1008
  if (colonIndex !== -1) {
894
- path20 = path20.substring(colonIndex + 1);
1009
+ path21 = path21.substring(colonIndex + 1);
895
1010
  }
896
1011
  } else {
897
- path20 = path20.replace(/^https?:\/\//, "");
898
- const parts = path20.split("/");
1012
+ path21 = path21.replace(/^https?:\/\//, "");
1013
+ const parts = path21.split("/");
899
1014
  if (parts.length > 1) {
900
- path20 = parts.slice(1).join("/");
1015
+ path21 = parts.slice(1).join("/");
901
1016
  }
902
1017
  }
903
- path20 = path20.replace(/\.git$/, "");
904
- return path20;
1018
+ path21 = path21.replace(/\.git$/, "");
1019
+ return path21;
905
1020
  }
906
1021
  /**
907
1022
  * 编码项目路径用于 API 请求
@@ -955,10 +1070,10 @@ var init_gitlab_api = __esm({
955
1070
  // src/index.ts
956
1071
  init_esm_shims();
957
1072
  init_logger();
958
- import { Command as Command16 } from "commander";
1073
+ import { Command as Command17 } from "commander";
959
1074
  import chalk4 from "chalk";
960
1075
  import fs5 from "fs-extra";
961
- import path19 from "path";
1076
+ import path20 from "path";
962
1077
  import { fileURLToPath as fileURLToPath2 } from "url";
963
1078
 
964
1079
  // src/commands/init.ts
@@ -2768,7 +2883,7 @@ ${cleanedMilestones}`;
2768
2883
  function buildBreakdownPrompt(specContent) {
2769
2884
  return `Role: Senior Technical Lead and Agile Coach
2770
2885
 
2771
- Task: Break down the following feature spec into milestones and todo lists.
2886
+ Task: Break down the following feature spec into milestones with frontend, backend, and integration tasks.
2772
2887
 
2773
2888
  Context:
2774
2889
  - Read TECH_STACK.md for technology constraints
@@ -2784,13 +2899,18 @@ ${specContent}
2784
2899
  Output Requirements:
2785
2900
  1. Parse the existing spec content and identify technical requirements.
2786
2901
  2. Break it down into 2-5 milestones.
2787
- 3. Each milestone should have:
2788
- - Clear name and objective
2789
- - Estimated days (1-3 days per milestone)
2790
- - Todo list with 3-8 actionable items
2902
+ 3. Each milestone must have three sections:
2903
+ - **\u524D\u7AEF\u4EFB\u52A1**: Frontend tasks marked with [F] prefix
2904
+ - **\u540E\u7AEF\u4EFB\u52A1**: Backend tasks marked with [B] prefix, include API associations
2905
+ - **\u8054\u8C03\u4EFB\u52A1**: Integration tasks marked with [I] prefix, include dependencies
2791
2906
  4. Todo items should be:
2792
- - Concrete, specific, and testable.
2793
- - Independent as much as possible.
2907
+ - Concrete, specific, and testable
2908
+ - Independent as much as possible
2909
+
2910
+ Task Prefix Format:
2911
+ - Frontend: \`- [ ] [F] \u5177\u4F53\u7684\u524D\u7AEF\u4EFB\u52A1\u63CF\u8FF0\`
2912
+ - Backend: \`- [ ] [B] \u5177\u4F53\u7684\u540E\u7AEF\u4EFB\u52A1\u63CF\u8FF0 (\u5173\u8054 API: \`METHOD /api/path\`)\`
2913
+ - Integration: \`- [ ] [I] \u8054\u8C03\u4EFB\u52A1\u63CF\u8FF0 (\u4F9D\u8D56: F-x, B-y)\`
2794
2914
 
2795
2915
  IMPORTANT:
2796
2916
  - Output ONLY the "## \u91CC\u7A0B\u7891 (Milestones)" section.
@@ -2805,9 +2925,16 @@ IMPORTANT:
2805
2925
  **\u76EE\u6807**: [\u7B80\u77ED\u63CF\u8FF0\u8FD9\u4E2A\u91CC\u7A0B\u7891\u7684\u76EE\u6807]
2806
2926
  **\u9884\u4F30**: 2 \u5929
2807
2927
 
2808
- - [ ] Todo 1 - \u5177\u4F53\u53EF\u6267\u884C\u7684\u4EFB\u52A1
2809
- - [ ] Todo 2 - \u5177\u4F53\u53EF\u6267\u884C\u7684\u4EFB\u52A1
2810
- - [ ] Todo 3 - \u5177\u4F53\u53EF\u6267\u884C\u7684\u4EFB\u52A1
2928
+ **\u524D\u7AEF\u4EFB\u52A1**:
2929
+ - [ ] [F] \u524D\u7AEF\u4EFB\u52A1\u63CF\u8FF0 1
2930
+ - [ ] [F] \u524D\u7AEF\u4EFB\u52A1\u63CF\u8FF0 2
2931
+
2932
+ **\u540E\u7AEF\u4EFB\u52A1**:
2933
+ - [ ] [B] \u540E\u7AEF\u4EFB\u52A1\u63CF\u8FF0 1 (\u5173\u8054 API: \`POST /api/xxx\`)
2934
+ - [ ] [B] \u540E\u7AEF\u4EFB\u52A1\u63CF\u8FF0 2 (\u5173\u8054 API: \`GET /api/yyy\`)
2935
+
2936
+ **\u8054\u8C03\u4EFB\u52A1**:
2937
+ - [ ] [I] \u8054\u8C03\u4EFB\u52A1\u63CF\u8FF0 1 (\u4F9D\u8D56: F-1, B-1)
2811
2938
 
2812
2939
  ### Milestone 2: [\u91CC\u7A0B\u7891\u540D\u79F0]
2813
2940
  ...
@@ -2910,8 +3037,8 @@ async function selectMilestone(specFile) {
2910
3037
  logger.step("\u6B65\u9AA4 2/3: \u89E3\u6790 milestones...");
2911
3038
  logger.newLine();
2912
3039
  const specContent = await FileUtils.read(specFile);
2913
- const milestones = SpecUtils.parseMilestones(specContent);
2914
- if (milestones.length === 0) {
3040
+ const { enhanced, isEnhanced } = SpecUtils.parseMilestonesEnhancedWithFallback(specContent);
3041
+ if (enhanced.length === 0) {
2915
3042
  logger.info("\u8BE5 spec \u5C1A\u672A\u62C6\u5206 milestones");
2916
3043
  const { breakdownNow } = await inquirer3.prompt([
2917
3044
  {
@@ -2929,19 +3056,32 @@ async function selectMilestone(specFile) {
2929
3056
  return "\u6574\u4E2A spec";
2930
3057
  }
2931
3058
  }
2932
- const choices = milestones.map((m, idx) => {
2933
- const isDone = m.completedCount === m.todos.length && m.todos.length > 0;
3059
+ const choices = enhanced.map((m, idx) => {
3060
+ const isDone = m.completedCount === m.totalCount && m.totalCount > 0;
2934
3061
  const statusIcon = isDone ? "\u2713" : m.completedCount > 0 ? "\u27F3" : "\u25CB";
2935
- const progress = `[${m.completedCount}/${m.todos.length}]`;
3062
+ const progress = `[${m.completedCount}/${m.totalCount}]`;
2936
3063
  const label = isDone ? `\u2713 ${m.title}` : `${statusIcon} ${progress} ${m.title}`;
3064
+ let detailInfo = `(${m.totalCount} \u4E2A\u4EFB\u52A1)`;
3065
+ if (isEnhanced) {
3066
+ const fCount = m.frontendTodos.filter((t) => !t.isCompleted).length;
3067
+ const bCount = m.backendTodos.filter((t) => !t.isCompleted).length;
3068
+ const iCount = m.integrationTodos.filter((t) => !t.isCompleted).length;
3069
+ const details = [];
3070
+ if (fCount > 0) details.push(`\u524D\u7AEF:${fCount}`);
3071
+ if (bCount > 0) details.push(`\u540E\u7AEF:${bCount}`);
3072
+ if (iCount > 0) details.push(`\u8054\u8C03:${iCount}`);
3073
+ if (details.length > 0) {
3074
+ detailInfo = `(${details.join(", ")} \u672A\u5B8C\u6210)`;
3075
+ }
3076
+ }
2937
3077
  return {
2938
- name: `${idx + 1}. ${label} (${m.todos.length} \u4E2A\u4EFB\u52A1)`,
3078
+ name: `${idx + 1}. ${label} ${detailInfo}`,
2939
3079
  value: m.title,
2940
3080
  short: m.title
2941
3081
  };
2942
3082
  });
2943
3083
  choices.push({
2944
- name: `${milestones.length + 1}. \u6574\u4E2A spec (\u5168\u90E8 milestones)`,
3084
+ name: `${enhanced.length + 1}. \u6574\u4E2A spec (\u5168\u90E8 milestones)`,
2945
3085
  value: "\u6574\u4E2A spec",
2946
3086
  short: "\u6574\u4E2A spec"
2947
3087
  });
@@ -2962,6 +3102,79 @@ async function selectTodo(specFile, milestone) {
2962
3102
  logger.newLine();
2963
3103
  logger.step("\u6B65\u9AA4 3/3: \u9009\u62E9 todo \u4EFB\u52A1...");
2964
3104
  logger.newLine();
3105
+ const specContent = await FileUtils.read(specFile);
3106
+ const { enhanced, isEnhanced } = SpecUtils.parseMilestonesEnhancedWithFallback(specContent);
3107
+ const targetMilestone = enhanced.find((m) => m.title === milestone);
3108
+ if (!targetMilestone || !isEnhanced) {
3109
+ return await selectTodoSimple(specFile, milestone);
3110
+ }
3111
+ return await selectTodoEnhanced(targetMilestone);
3112
+ }
3113
+ async function selectTodoEnhanced(milestone) {
3114
+ const choices = [];
3115
+ if (milestone.frontendTodos.length > 0) {
3116
+ choices.push({ name: `\u2501\u2501 \u524D\u7AEF\u4EFB\u52A1 (${milestone.frontendTodos.length}) \u2501\u2501`, disabled: true });
3117
+ milestone.frontendTodos.forEach((todo2, idx) => {
3118
+ const icon = todo2.isCompleted ? "[x]" : "[ ]";
3119
+ choices.push({
3120
+ name: ` [F] ${icon} ${todo2.content}`,
3121
+ value: todo2.content,
3122
+ short: `[F] ${todo2.content}`
3123
+ });
3124
+ });
3125
+ }
3126
+ if (milestone.backendTodos.length > 0) {
3127
+ choices.push({ name: `\u2501\u2501 \u540E\u7AEF\u4EFB\u52A1 (${milestone.backendTodos.length}) \u2501\u2501`, disabled: true });
3128
+ milestone.backendTodos.forEach((todo2, idx) => {
3129
+ const icon = todo2.isCompleted ? "[x]" : "[ ]";
3130
+ const apiInfo = todo2.apiAssociation ? ` (${todo2.apiAssociation})` : "";
3131
+ choices.push({
3132
+ name: ` [B] ${icon} ${todo2.content}${apiInfo}`,
3133
+ value: todo2.content,
3134
+ short: `[B] ${todo2.content}`
3135
+ });
3136
+ });
3137
+ }
3138
+ if (milestone.integrationTodos.length > 0) {
3139
+ choices.push({ name: `\u2501\u2501 \u8054\u8C03\u4EFB\u52A1 (${milestone.integrationTodos.length}) \u2501\u2501`, disabled: true });
3140
+ milestone.integrationTodos.forEach((todo2, idx) => {
3141
+ const icon = todo2.isCompleted ? "[x]" : "[ ]";
3142
+ const depsInfo = todo2.dependencies ? ` (\u4F9D\u8D56: ${todo2.dependencies.join(", ")})` : "";
3143
+ choices.push({
3144
+ name: ` [I] ${icon} ${todo2.content}${depsInfo}`,
3145
+ value: todo2.content,
3146
+ short: `[I] ${todo2.content}`
3147
+ });
3148
+ });
3149
+ }
3150
+ if (milestone.generalTodos.length > 0) {
3151
+ choices.push({ name: `\u2501\u2501 \u901A\u7528\u4EFB\u52A1 (${milestone.generalTodos.length}) \u2501\u2501`, disabled: true });
3152
+ milestone.generalTodos.forEach((todo2, idx) => {
3153
+ const icon = todo2.isCompleted ? "[x]" : "[ ]";
3154
+ choices.push({
3155
+ name: ` ${icon} ${todo2.content}`,
3156
+ value: todo2.content,
3157
+ short: todo2.content
3158
+ });
3159
+ });
3160
+ }
3161
+ choices.push({ name: "\u2501\u2501 \u5176\u4ED6 \u2501\u2501", disabled: true });
3162
+ choices.push({
3163
+ name: `\u5168\u90E8\u4EFB\u52A1 (\u6574\u4E2A milestone)`,
3164
+ value: "\u5168\u90E8\u4EFB\u52A1",
3165
+ short: "\u5168\u90E8\u4EFB\u52A1"
3166
+ });
3167
+ const { todo } = await inquirer3.prompt([
3168
+ {
3169
+ type: "list",
3170
+ name: "todo",
3171
+ message: "\u9009\u62E9 todo \u4EFB\u52A1:",
3172
+ choices
3173
+ }
3174
+ ]);
3175
+ return todo;
3176
+ }
3177
+ async function selectTodoSimple(specFile, milestone) {
2965
3178
  const specContent = await FileUtils.read(specFile);
2966
3179
  const milestones = SpecUtils.parseMilestones(specContent);
2967
3180
  const targetMilestone = milestones.find((m) => m.title === milestone);
@@ -3189,10 +3402,14 @@ async function askAndUpdateSpecStatus(specFile, milestone, todo) {
3189
3402
  break;
3190
3403
  }
3191
3404
  if (todo !== "\u5168\u90E8\u529F\u80FD" && todo !== "\u5168\u90E8\u4EFB\u52A1") {
3192
- const todoMatch = line.match(/^-\s+\[[ x ]\]\s*(.+)/);
3193
- if (todoMatch && todoMatch[1].trim() === todo) {
3194
- targetTodoIndex = i;
3195
- break;
3405
+ const todoMatch = line.match(/^-\s+\[ \]\s*(\[[FBIN]\]\s*)?(.+)/);
3406
+ if (todoMatch) {
3407
+ const todoContent = todoMatch[2].trim();
3408
+ const cleanContent = todoContent.replace(/\s*\(关联 API:\s*`[^`]+`\)/, "").replace(/\s*\(依赖:\s*[^)]+\)/, "").trim();
3409
+ if (cleanContent === todo) {
3410
+ targetTodoIndex = i;
3411
+ break;
3412
+ }
3196
3413
  }
3197
3414
  }
3198
3415
  }
@@ -4419,13 +4636,596 @@ git checkout ${data.branch}
4419
4636
  `;
4420
4637
  }
4421
4638
 
4422
- // src/commands/lint.ts
4639
+ // src/commands/accept.ts
4423
4640
  init_esm_shims();
4424
4641
  init_utils();
4425
4642
  init_logger();
4426
4643
  import { Command as Command7 } from "commander";
4644
+ import inquirer6 from "inquirer";
4645
+ import path13 from "path";
4646
+ var acceptCommand = new Command7("accept").argument("[spec-file]", "Spec \u6587\u4EF6\u8DEF\u5F84").description("\u9A8C\u6536\u529F\u80FD - \u8D70\u67E5\u6240\u6709\u9700\u6C42\uFF0C\u9A8C\u8BC1\u8054\u8C03\u662F\u5426\u5B8C\u6210").action(async (specFile) => {
4647
+ try {
4648
+ logger.header("\u9A8C\u6536\u6A21\u5F0F");
4649
+ logger.newLine();
4650
+ const hasTechStack = await FileUtils.exists("TECH_STACK.md");
4651
+ if (!hasTechStack) {
4652
+ logger.error("\u5F53\u524D\u76EE\u5F55\u4E0D\u662F\u4E00\u4E2A\u6709\u6548\u7684 team-cli \u9879\u76EE");
4653
+ logger.info("\u8BF7\u5148\u8FD0\u884C 'team-cli init <project-name>' \u6216\u5207\u6362\u5230\u9879\u76EE\u76EE\u5F55");
4654
+ process.exit(1);
4655
+ }
4656
+ logger.success("\u68C0\u6D4B\u5230\u9879\u76EE\u4E0A\u4E0B\u6587");
4657
+ const selectedSpec = await selectSpec2(specFile);
4658
+ const selectedMilestone = await selectMilestone2(selectedSpec);
4659
+ const result = await runAcceptanceCheck(selectedSpec, selectedMilestone);
4660
+ await generateAcceptanceReport(result);
4661
+ if (result.issues.length > 0) {
4662
+ await handleIssues(result);
4663
+ }
4664
+ await syncSpecStatus(selectedSpec, result);
4665
+ logger.header("\u9A8C\u6536\u5B8C\u6210!");
4666
+ logger.newLine();
4667
+ } catch (error) {
4668
+ logger.error(`\u9A8C\u6536\u5931\u8D25: ${error.message}`);
4669
+ if (process.env.DEBUG) {
4670
+ console.error(error);
4671
+ }
4672
+ process.exit(1);
4673
+ }
4674
+ });
4675
+ async function selectSpec2(defaultSpec) {
4676
+ logger.step("\u6B65\u9AA4 1/4: \u9009\u62E9 spec \u6587\u4EF6...");
4677
+ logger.newLine();
4678
+ const specDir = "docs/specs";
4679
+ const exists = await FileUtils.exists(specDir);
4680
+ if (!exists) {
4681
+ throw new Error("docs/specs \u76EE\u5F55\u4E0D\u5B58\u5728");
4682
+ }
4683
+ const files = await FileUtils.findFiles("*.md", specDir);
4684
+ const specFiles = files.filter((f) => !f.includes("template"));
4685
+ if (specFiles.length === 0) {
4686
+ throw new Error("\u672A\u627E\u5230 spec \u6587\u4EF6");
4687
+ }
4688
+ if (defaultSpec) {
4689
+ const fullPath = defaultSpec.startsWith("docs/specs/") ? defaultSpec : path13.join(specDir, defaultSpec);
4690
+ const exists2 = await FileUtils.exists(fullPath);
4691
+ if (!exists2) {
4692
+ throw new Error(`Spec \u6587\u4EF6\u4E0D\u5B58\u5728: ${defaultSpec}`);
4693
+ }
4694
+ logger.success(`\u5DF2\u9009\u62E9: ${fullPath}`);
4695
+ return fullPath;
4696
+ }
4697
+ const specs = [];
4698
+ for (const file of specFiles) {
4699
+ const fullPath = path13.join(specDir, file);
4700
+ const content = await FileUtils.read(fullPath);
4701
+ const status = SpecUtils.parseSpecStatus(content);
4702
+ specs.push({ file: fullPath, name: file, status });
4703
+ }
4704
+ const activeSpecs = specs.filter(
4705
+ (s) => s.status === "\u5DF2\u62C6\u5206" || s.status === "\u8FDB\u884C\u4E2D" || s.status === "\u5DF2\u5B8C\u6210"
4706
+ );
4707
+ if (activeSpecs.length === 0) {
4708
+ logger.warn("\u6CA1\u6709\u53EF\u9A8C\u6536\u7684 spec \u6587\u4EF6");
4709
+ const { continueAnyway } = await inquirer6.prompt([
4710
+ {
4711
+ type: "confirm",
4712
+ name: "continueAnyway",
4713
+ message: "\u662F\u5426\u7EE7\u7EED\u67E5\u770B\u6240\u6709 spec?",
4714
+ default: true
4715
+ }
4716
+ ]);
4717
+ if (!continueAnyway) {
4718
+ process.exit(0);
4719
+ }
4720
+ }
4721
+ const targetSpecs = activeSpecs.length > 0 ? activeSpecs : specs;
4722
+ const choices = targetSpecs.map((spec) => ({
4723
+ name: `[${spec.status}] ${spec.name}`,
4724
+ value: spec.file,
4725
+ short: spec.name
4726
+ }));
4727
+ const { selectedFile } = await inquirer6.prompt([
4728
+ {
4729
+ type: "list",
4730
+ name: "selectedFile",
4731
+ message: "\u9009\u62E9\u8981\u9A8C\u6536\u7684 spec:",
4732
+ choices
4733
+ }
4734
+ ]);
4735
+ logger.success(`\u5DF2\u9009\u62E9: ${selectedFile}`);
4736
+ return selectedFile;
4737
+ }
4738
+ async function selectMilestone2(specFile) {
4739
+ logger.newLine();
4740
+ logger.step("\u6B65\u9AA4 2/4: \u89E3\u6790 milestones...");
4741
+ logger.newLine();
4742
+ const specContent = await FileUtils.read(specFile);
4743
+ const { enhanced } = SpecUtils.parseMilestonesEnhancedWithFallback(specContent);
4744
+ if (enhanced.length === 0) {
4745
+ throw new Error("\u8BE5 spec \u5C1A\u672A\u62C6\u5206 milestones\uFF0C\u65E0\u6CD5\u8FDB\u884C\u9A8C\u6536");
4746
+ }
4747
+ const choices = enhanced.map((m, idx) => {
4748
+ const isDone = m.completedCount === m.totalCount;
4749
+ const statusIcon = isDone ? "\u2713" : m.completedCount > 0 ? "\u27F3" : "\u25CB";
4750
+ const progress = `[${m.completedCount}/${m.totalCount}]`;
4751
+ return {
4752
+ name: `${idx + 1}. ${statusIcon} ${progress} ${m.title}`,
4753
+ value: m.title,
4754
+ short: m.title
4755
+ };
4756
+ });
4757
+ const { milestone } = await inquirer6.prompt([
4758
+ {
4759
+ type: "list",
4760
+ name: "milestone",
4761
+ message: "\u9009\u62E9\u8981\u9A8C\u6536\u7684 milestone:",
4762
+ choices
4763
+ }
4764
+ ]);
4765
+ return milestone;
4766
+ }
4767
+ async function runAcceptanceCheck(specFile, milestone) {
4768
+ logger.newLine();
4769
+ logger.step("\u6B65\u9AA4 3/4: \u6267\u884C\u9A8C\u6536\u68C0\u67E5...");
4770
+ logger.newLine();
4771
+ const specContent = await FileUtils.read(specFile);
4772
+ const { enhanced } = SpecUtils.parseMilestonesEnhancedWithFallback(specFile);
4773
+ const targetMilestone = enhanced.find((m) => m.title === milestone);
4774
+ if (!targetMilestone) {
4775
+ throw new Error(`\u672A\u627E\u5230 milestone: ${milestone}`);
4776
+ }
4777
+ const result = {
4778
+ specFile,
4779
+ milestone,
4780
+ checkTime: (/* @__PURE__ */ new Date()).toLocaleString("zh-CN"),
4781
+ frontendTasks: { total: 0, completed: 0, items: [] },
4782
+ backendTasks: { total: 0, completed: 0, items: [] },
4783
+ apiVerification: { total: 0, verified: 0, items: [] },
4784
+ integrationTasks: { total: 0, completed: 0, items: [] },
4785
+ issues: []
4786
+ };
4787
+ logger.info("\u68C0\u67E5\u524D\u7AEF\u4EFB\u52A1...");
4788
+ for (const todo of targetMilestone.frontendTodos) {
4789
+ const checkResult = await checkFrontendTask(todo);
4790
+ result.frontendTasks.items.push(checkResult);
4791
+ if (checkResult.status === "pass") {
4792
+ result.frontendTasks.completed++;
4793
+ }
4794
+ result.frontendTasks.total++;
4795
+ const icon = checkResult.status === "pass" ? "\u2713" : checkResult.status === "fail" ? "\u2717" : "\u25CB";
4796
+ logger.info(` ${icon} [F] ${todo.content}${checkResult.filePath ? ` - ${checkResult.filePath}` : ""}`);
4797
+ }
4798
+ logger.info("\u68C0\u67E5\u540E\u7AEF\u4EFB\u52A1...");
4799
+ for (const todo of targetMilestone.backendTodos) {
4800
+ const checkResult = await checkBackendTask(todo);
4801
+ result.backendTasks.items.push(checkResult);
4802
+ if (checkResult.status === "pass") {
4803
+ result.backendTasks.completed++;
4804
+ }
4805
+ result.backendTasks.total++;
4806
+ const icon = checkResult.status === "pass" ? "\u2713" : checkResult.status === "fail" ? "\u2717" : "\u25CB";
4807
+ logger.info(` ${icon} [B] ${todo.content}${checkResult.filePath ? ` - ${checkResult.filePath}` : ""}`);
4808
+ }
4809
+ logger.info("\u9A8C\u8BC1 API \u5B9E\u73B0...");
4810
+ for (const todo of targetMilestone.backendTodos) {
4811
+ if (todo.apiAssociation) {
4812
+ const checkResult = await verifyApiImplementation(todo);
4813
+ result.apiVerification.items.push(checkResult);
4814
+ if (checkResult.status === "pass") {
4815
+ result.apiVerification.verified++;
4816
+ }
4817
+ result.apiVerification.total++;
4818
+ const icon = checkResult.status === "pass" ? "\u2713" : checkResult.status === "fail" ? "\u2717" : "\u25CB";
4819
+ logger.info(` ${icon} ${todo.apiAssociation}${checkResult.filePath ? ` - ${checkResult.filePath}` : ""}`);
4820
+ }
4821
+ }
4822
+ logger.info("\u68C0\u67E5\u8054\u8C03\u4EFB\u52A1...");
4823
+ for (const todo of targetMilestone.integrationTodos) {
4824
+ const checkResult = await checkIntegrationTask(todo);
4825
+ result.integrationTasks.items.push(checkResult);
4826
+ if (checkResult.status === "pass") {
4827
+ result.integrationTasks.completed++;
4828
+ }
4829
+ result.integrationTasks.total++;
4830
+ const icon = checkResult.status === "pass" ? "\u2713" : checkResult.status === "fail" ? "\u2717" : "\u25CB";
4831
+ logger.info(` ${icon} [I] ${todo.content}`);
4832
+ }
4833
+ return result;
4834
+ }
4835
+ async function checkFrontendTask(todo) {
4836
+ const frontendPaths = [
4837
+ `frontend/src/pages/${todo.content}.tsx`,
4838
+ `frontend/src/components/${todo.content}.tsx`,
4839
+ `frontend/src/components/${todo.content.replace(/\s+/g, "")}.tsx`,
4840
+ `frontend/src/views/${todo.content}.vue`,
4841
+ `frontend/src/components/${todo.content}.vue`
4842
+ ];
4843
+ for (const fp of frontendPaths) {
4844
+ if (await FileUtils.exists(fp)) {
4845
+ return {
4846
+ description: `[F] ${todo.content}`,
4847
+ status: "pass",
4848
+ details: "\u524D\u7AEF\u4EE3\u7801\u5B58\u5728",
4849
+ filePath: fp
4850
+ };
4851
+ }
4852
+ }
4853
+ const pathMatch = todo.content.match(/\s*-\s*(.+?\.(tsx|vue|js|jsx))\s*/);
4854
+ if (pathMatch) {
4855
+ const filePath = pathMatch[1];
4856
+ if (await FileUtils.exists(filePath)) {
4857
+ return {
4858
+ description: `[F] ${todo.content}`,
4859
+ status: "pass",
4860
+ details: "\u524D\u7AEF\u4EE3\u7801\u5B58\u5728",
4861
+ filePath
4862
+ };
4863
+ }
4864
+ }
4865
+ return {
4866
+ description: `[F] ${todo.content}`,
4867
+ status: "fail",
4868
+ details: "\u524D\u7AEF\u4EE3\u7801\u4E0D\u5B58\u5728\u6216\u8DEF\u5F84\u65E0\u6CD5\u9A8C\u8BC1"
4869
+ };
4870
+ }
4871
+ async function checkBackendTask(todo) {
4872
+ const backendPaths = [
4873
+ `backend/src/main/java/${todo.content.replace(/\s+/g, "/")}.java`,
4874
+ `backend/src/${todo.content.toLowerCase().replace(/\s+/g, "/")}.java`
4875
+ ];
4876
+ for (const fp of backendPaths) {
4877
+ if (await FileUtils.exists(fp)) {
4878
+ return {
4879
+ description: `[B] ${todo.content}`,
4880
+ status: "pass",
4881
+ details: "\u540E\u7AEF\u4EE3\u7801\u5B58\u5728",
4882
+ filePath: fp
4883
+ };
4884
+ }
4885
+ }
4886
+ const pathMatch = todo.content.match(/\s*-\s*(.+?\.(java|kt|py|go))\s*/);
4887
+ if (pathMatch) {
4888
+ const filePath = pathMatch[1];
4889
+ if (await FileUtils.exists(filePath)) {
4890
+ return {
4891
+ description: `[B] ${todo.content}`,
4892
+ status: "pass",
4893
+ details: "\u540E\u7AEF\u4EE3\u7801\u5B58\u5728",
4894
+ filePath
4895
+ };
4896
+ }
4897
+ }
4898
+ return {
4899
+ description: `[B] ${todo.content}`,
4900
+ status: "fail",
4901
+ details: "\u540E\u7AEF\u4EE3\u7801\u4E0D\u5B58\u5728\u6216\u8DEF\u5F84\u65E0\u6CD5\u9A8C\u8BC1"
4902
+ };
4903
+ }
4904
+ async function verifyApiImplementation(todo) {
4905
+ if (!todo.apiAssociation) {
4906
+ return {
4907
+ description: todo.apiAssociation || "API \u9A8C\u8BC1",
4908
+ status: "pending",
4909
+ details: "\u65E0 API \u5173\u8054\u4FE1\u606F"
4910
+ };
4911
+ }
4912
+ const apiMatch = todo.apiAssociation.match(/^(GET|POST|PUT|DELETE|PATCH)\s+\/(.+)$/);
4913
+ if (!apiMatch) {
4914
+ return {
4915
+ description: todo.apiAssociation,
4916
+ status: "pending",
4917
+ details: "\u65E0\u6CD5\u89E3\u6790 API \u683C\u5F0F"
4918
+ };
4919
+ }
4920
+ const method = apiMatch[1];
4921
+ const apiPath = apiMatch[2];
4922
+ const controllerPaths = [
4923
+ `backend/src/main/java/**/*Controller.java`,
4924
+ `backend/src/**/*Controller.java`
4925
+ ];
4926
+ const controllerFiles = await FileUtils.findFiles("**/*Controller.java", "backend/src");
4927
+ for (const cf of controllerFiles) {
4928
+ const content = await FileUtils.read(cf);
4929
+ if (content.includes(apiPath) || content.includes(`"${apiPath}"`)) {
4930
+ const methodAnnotations = {
4931
+ GET: ["@GetMapping", "@RequestMapping(method = RequestMethod.GET)"],
4932
+ POST: ["@PostMapping", "@RequestMapping(method = RequestMethod.POST)"],
4933
+ PUT: ["@PutMapping", "@RequestMapping(method = RequestMethod.PUT)"],
4934
+ DELETE: ["@DeleteMapping", "@RequestMapping(method = RequestMethod.DELETE)"],
4935
+ PATCH: ["@PatchMapping", "@RequestMapping(method = RequestMethod.PATCH)"]
4936
+ };
4937
+ for (const annotation of methodAnnotations[method] || []) {
4938
+ if (content.includes(annotation)) {
4939
+ return {
4940
+ description: todo.apiAssociation,
4941
+ status: "pass",
4942
+ details: "API Controller \u5B9E\u73B0\u5B58\u5728",
4943
+ filePath: cf
4944
+ };
4945
+ }
4946
+ }
4947
+ }
4948
+ }
4949
+ return {
4950
+ description: todo.apiAssociation,
4951
+ status: "fail",
4952
+ details: "API Controller \u672A\u5B9E\u73B0"
4953
+ };
4954
+ }
4955
+ async function checkIntegrationTask(todo) {
4956
+ const integrationEvidence = [
4957
+ "**/*integration*.test.*",
4958
+ "**/*e2e*.test.*",
4959
+ "**/*IT.java",
4960
+ "docs/integration-test-results.md",
4961
+ "docs/session-logs/**"
4962
+ ];
4963
+ const sessionDir = "docs/sessions";
4964
+ if (await FileUtils.exists(sessionDir)) {
4965
+ const sessionFiles = await FileUtils.findFiles("*.md", sessionDir);
4966
+ const hasRecentSession = sessionFiles.some(
4967
+ (sf) => sf.includes("integration") || sf.includes("\u8054\u8C03")
4968
+ );
4969
+ if (hasRecentSession) {
4970
+ return {
4971
+ description: `[I] ${todo.content}`,
4972
+ status: "pass",
4973
+ details: "\u8054\u8C03\u8BC1\u636E\u5B58\u5728\uFF08session \u65E5\u5FD7\uFF09"
4974
+ };
4975
+ }
4976
+ }
4977
+ return {
4978
+ description: `[I] ${todo.content}`,
4979
+ status: "pending",
4980
+ details: "\u5EFA\u8BAE\u4EBA\u5DE5\u9A8C\u8BC1\u8054\u8C03\u7ED3\u679C"
4981
+ };
4982
+ }
4983
+ async function generateAcceptanceReport(result) {
4984
+ logger.newLine();
4985
+ logger.step("\u6B65\u9AA4 4/4: \u751F\u6210\u9A8C\u6536\u62A5\u544A...");
4986
+ logger.newLine();
4987
+ const reportDir = "docs/acceptance-reports";
4988
+ await FileUtils.ensureDir(reportDir);
4989
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
4990
+ const specName = path13.basename(result.specFile, ".md");
4991
+ const milestoneSafe = result.milestone.replace(/[^a-zA-Z0-9]/g, "-");
4992
+ const reportFile = path13.join(reportDir, `${timestamp}_${specName}_${milestoneSafe}.md`);
4993
+ const report = generateMarkdownReport(result);
4994
+ await FileUtils.write(reportFile, report);
4995
+ logger.success(`\u9A8C\u6536\u62A5\u544A\u5DF2\u751F\u6210: ${reportFile}`);
4996
+ logger.newLine();
4997
+ console.log(generateConsoleReport(result));
4998
+ }
4999
+ function generateMarkdownReport(result) {
5000
+ const lines = [];
5001
+ lines.push("# \u9A8C\u6536\u62A5\u544A");
5002
+ lines.push("");
5003
+ lines.push(`**Spec \u6587\u4EF6**: ${result.specFile}`);
5004
+ lines.push(`**Milestone**: ${result.milestone}`);
5005
+ lines.push(`**\u9A8C\u6536\u65F6\u95F4**: ${result.checkTime}`);
5006
+ lines.push("");
5007
+ lines.push("## \u68C0\u67E5\u7ED3\u679C\u6C47\u603B");
5008
+ lines.push("");
5009
+ lines.push("| \u68C0\u67E5\u9879 | \u72B6\u6001 |");
5010
+ lines.push("|--------|------|");
5011
+ lines.push(
5012
+ `| \u524D\u7AEF\u4EFB\u52A1 | ${result.frontendTasks.completed}/${result.frontendTasks.total} \u5B8C\u6210 |`
5013
+ );
5014
+ lines.push(
5015
+ `| \u540E\u7AEF\u4EFB\u52A1 | ${result.backendTasks.completed}/${result.backendTasks.total} \u5B8C\u6210 |`
5016
+ );
5017
+ lines.push(`| API \u9A8C\u8BC1 | ${result.apiVerification.verified}/${result.apiVerification.total} \u5B9E\u73B0 |`);
5018
+ lines.push(
5019
+ `| \u8054\u8C03\u4EFB\u52A1 | ${result.integrationTasks.completed}/${result.integrationTasks.total} \u5B8C\u6210 |`
5020
+ );
5021
+ lines.push("");
5022
+ lines.push("## \u8BE6\u7EC6\u8BB0\u5F55");
5023
+ lines.push("");
5024
+ lines.push("### \u524D\u7AEF\u4EFB\u52A1");
5025
+ lines.push("");
5026
+ for (const item of result.frontendTasks.items) {
5027
+ const icon = item.status === "pass" ? "\u2713" : item.status === "fail" ? "\u2717" : "\u25CB";
5028
+ lines.push(`- ${icon} ${item.description} - ${item.details || ""} ${item.filePath ? `(\`${item.filePath}\`)` : ""}`);
5029
+ }
5030
+ lines.push("");
5031
+ lines.push("### \u540E\u7AEF\u4EFB\u52A1");
5032
+ lines.push("");
5033
+ for (const item of result.backendTasks.items) {
5034
+ const icon = item.status === "pass" ? "\u2713" : item.status === "fail" ? "\u2717" : "\u25CB";
5035
+ lines.push(`- ${icon} ${item.description} - ${item.details || ""} ${item.filePath ? `(\`${item.filePath}\`)` : ""}`);
5036
+ }
5037
+ lines.push("");
5038
+ lines.push("### API \u9A8C\u8BC1");
5039
+ lines.push("");
5040
+ for (const item of result.apiVerification.items) {
5041
+ const icon = item.status === "pass" ? "\u2713" : item.status === "fail" ? "\u2717" : "\u25CB";
5042
+ lines.push(`- ${icon} ${item.description} - ${item.details || ""} ${item.filePath ? `(\`${item.filePath}\`)` : ""}`);
5043
+ }
5044
+ lines.push("");
5045
+ lines.push("### \u8054\u8C03\u4EFB\u52A1");
5046
+ lines.push("");
5047
+ for (const item of result.integrationTasks.items) {
5048
+ const icon = item.status === "pass" ? "\u2713" : item.status === "fail" ? "\u2717" : "\u26A0";
5049
+ lines.push(`- ${icon} ${item.description} - ${item.details || ""}`);
5050
+ }
5051
+ lines.push("");
5052
+ if (result.issues.length > 0) {
5053
+ lines.push("## \u53D1\u73B0\u7684\u95EE\u9898");
5054
+ lines.push("");
5055
+ lines.push("| \u95EE\u9898 | \u7C7B\u578B | \u4E25\u91CD\u7A0B\u5EA6 | \u72B6\u6001 |");
5056
+ lines.push("|------|------|---------|------|");
5057
+ for (const issue of result.issues) {
5058
+ lines.push(`| ${issue.title} | ${issue.type} | ${issue.severity} | ${issue.status} |`);
5059
+ }
5060
+ lines.push("");
5061
+ lines.push("**\u64CD\u4F5C**:");
5062
+ lines.push(`- \u8FD0\u884C \`team-cli bugfix ${result.specFile}\` \u67E5\u770B\u8BE6\u60C5`);
5063
+ lines.push("- \u6216\u8FD0\u884C `team-cli hotfix` \u7ACB\u5373\u4FEE\u590D");
5064
+ lines.push("");
5065
+ }
5066
+ lines.push("## \u4E0B\u4E00\u6B65\u5EFA\u8BAE");
5067
+ lines.push("");
5068
+ if (result.issues.length > 0) {
5069
+ lines.push("- [ ] \u4FEE\u590D\u53D1\u73B0\u7684\u95EE\u9898");
5070
+ }
5071
+ lines.push("- [ ] \u8FD0\u884C `team-cli dev` \u7EE7\u7EED\u5F00\u53D1");
5072
+ lines.push("- [ ] \u8FD0\u884C `team-cli accept` \u91CD\u65B0\u9A8C\u6536");
5073
+ lines.push("");
5074
+ return lines.join("\n");
5075
+ }
5076
+ function generateConsoleReport(result) {
5077
+ const lines = [];
5078
+ lines.push("\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510");
5079
+ lines.push("\u2502 \u9A8C \u6536 \u7ED3 \u679C \u6458 \u8981 \u2502");
5080
+ lines.push("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524");
5081
+ lines.push(`\u2502 Spec: ${result.specFile.padEnd(40)}\u2502`);
5082
+ lines.push(`\u2502 Milestone: ${result.milestone.padEnd(37)}\u2502`);
5083
+ lines.push("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524");
5084
+ lines.push(
5085
+ `\u2502 \u524D\u7AEF\u4EFB\u52A1: ${result.frontendTasks.completed}/${result.frontendTasks.total} \u5B8C\u6210`.padEnd(47) + "\u2502"
5086
+ );
5087
+ lines.push(
5088
+ `\u2502 \u540E\u7AEF\u4EFB\u52A1: ${result.backendTasks.completed}/${result.backendTasks.total} \u5B8C\u6210`.padEnd(47) + "\u2502"
5089
+ );
5090
+ lines.push(
5091
+ `\u2502 API \u9A8C\u8BC1: ${result.apiVerification.verified}/${result.apiVerification.total} \u5B9E\u73B0`.padEnd(47) + "\u2502"
5092
+ );
5093
+ lines.push(
5094
+ `\u2502 \u8054\u8C03\u4EFB\u52A1: ${result.integrationTasks.completed}/${result.integrationTasks.total} \u5B8C\u6210`.padEnd(47) + "\u2502"
5095
+ );
5096
+ lines.push("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524");
5097
+ const totalIssues = result.issues.length;
5098
+ if (totalIssues > 0) {
5099
+ lines.push(`\u2502 \u26A0 \u53D1\u73B0\u95EE\u9898: ${totalIssues} \u4E2A`.padEnd(47) + "\u2502");
5100
+ } else {
5101
+ lines.push(`\u2502 \u2713 \u9A8C\u6536\u901A\u8FC7`.padEnd(47) + "\u2502");
5102
+ }
5103
+ lines.push("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518");
5104
+ return lines.join("\n");
5105
+ }
5106
+ async function handleIssues(result) {
5107
+ logger.newLine();
5108
+ logger.warn(`\u53D1\u73B0 ${result.issues.length} \u4E2A\u95EE\u9898\u9700\u8981\u5904\u7406`);
5109
+ const bugfixDir = "docs/bugfixes";
5110
+ await FileUtils.ensureDir(bugfixDir);
5111
+ for (const issue of result.issues) {
5112
+ const bugfixFile = path13.join(
5113
+ bugfixDir,
5114
+ `${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}_${issue.id}.md`
5115
+ );
5116
+ const bugfixContent = generateBugfixContent(result, issue);
5117
+ await FileUtils.write(bugfixFile, bugfixContent);
5118
+ logger.info(` \u5DF2\u521B\u5EFA Bugfix \u8BB0\u5F55: ${bugfixFile}`);
5119
+ }
5120
+ logger.newLine();
5121
+ const { fixNow } = await inquirer6.prompt([
5122
+ {
5123
+ type: "confirm",
5124
+ name: "fixNow",
5125
+ message: "\u662F\u5426\u7ACB\u5373\u4FEE\u590D\u53D1\u73B0\u7684\u95EE\u9898?",
5126
+ default: false
5127
+ }
5128
+ ]);
5129
+ if (fixNow) {
5130
+ logger.info("\u8BF7\u8FD0\u884C `team-cli hotfix` \u7ACB\u5373\u4FEE\u590D\u95EE\u9898");
5131
+ } else {
5132
+ logger.info(`\u95EE\u9898\u8BB0\u5F55\u5DF2\u4FDD\u5B58\u5230 ${bugfixDir} \u76EE\u5F55`);
5133
+ logger.info("\u8FD0\u884C `team-cli bugfix` \u67E5\u770B\u6240\u6709\u95EE\u9898\u8BB0\u5F55");
5134
+ }
5135
+ }
5136
+ function generateBugfixContent(result, issue) {
5137
+ const lines = [];
5138
+ lines.push("# Bugfix \u8BB0\u5F55");
5139
+ lines.push("");
5140
+ lines.push(`**ID**: ${issue.id}`);
5141
+ lines.push(`**\u521B\u5EFA\u65F6\u95F4**: ${issue.createdAt}`);
5142
+ lines.push(`**\u72B6\u6001**: ${issue.status}`);
5143
+ lines.push("");
5144
+ lines.push("## \u95EE\u9898\u63CF\u8FF0");
5145
+ lines.push("");
5146
+ lines.push(issue.description);
5147
+ lines.push("");
5148
+ lines.push("## \u6240\u5C5E\u8303\u56F4");
5149
+ lines.push("");
5150
+ lines.push(`- Spec: ${result.specFile}`);
5151
+ lines.push(`- Milestone: ${result.milestone}`);
5152
+ if (issue.todo) {
5153
+ lines.push(`- Todo: ${issue.todo}`);
5154
+ }
5155
+ lines.push("");
5156
+ lines.push("## \u4E25\u91CD\u7A0B\u5EA6");
5157
+ lines.push("");
5158
+ lines.push(`- ${issue.severity.toUpperCase()}`);
5159
+ lines.push("");
5160
+ lines.push("## \u95EE\u9898\u7C7B\u578B");
5161
+ lines.push("");
5162
+ lines.push(`- ${issue.type}`);
5163
+ lines.push("");
5164
+ lines.push("## \u89E3\u51B3\u65B9\u6848");
5165
+ lines.push("");
5166
+ lines.push("<!-- TODO: \u586B\u5199\u89E3\u51B3\u65B9\u6848 -->");
5167
+ lines.push("");
5168
+ lines.push("## \u9A8C\u8BC1\u6B65\u9AA4");
5169
+ lines.push("");
5170
+ lines.push("1. ");
5171
+ lines.push("2. ");
5172
+ lines.push("3. ");
5173
+ lines.push("");
5174
+ return lines.join("\n");
5175
+ }
5176
+ async function syncSpecStatus(specFile, result) {
5177
+ const content = await FileUtils.read(specFile);
5178
+ const lines = content.split("\n");
5179
+ let inTargetMilestone = false;
5180
+ let milestoneIndex = -1;
5181
+ for (let i = 0; i < lines.length; i++) {
5182
+ const line = lines[i];
5183
+ if (line.includes(result.milestone)) {
5184
+ inTargetMilestone = true;
5185
+ milestoneIndex = i;
5186
+ continue;
5187
+ }
5188
+ if (inTargetMilestone && line.match(/^###\s+Milestone/)) {
5189
+ break;
5190
+ }
5191
+ }
5192
+ if (milestoneIndex !== -1) {
5193
+ let completedTasks = 0;
5194
+ let totalTasks = 0;
5195
+ for (let i = milestoneIndex + 1; i < lines.length; i++) {
5196
+ const line = lines[i];
5197
+ if (line.match(/^###\s+Milestone/)) {
5198
+ break;
5199
+ }
5200
+ if (line.match(/^-\s+\[/)) {
5201
+ totalTasks++;
5202
+ if (line.match(/^-\s+\[x\]/)) {
5203
+ completedTasks++;
5204
+ }
5205
+ }
5206
+ }
5207
+ const progressLine = `${result.milestone} [${completedTasks}/${totalTasks}]`;
5208
+ const linesBefore = lines.slice(0, milestoneIndex);
5209
+ const linesAfter = lines.slice(milestoneIndex + 1);
5210
+ if (!lines[milestoneIndex].includes(`[${completedTasks}/${totalTasks}]`)) {
5211
+ const updatedMilestoneLine = lines[milestoneIndex].replace(
5212
+ /(\s*\[\d+\/\d+\])?$/,
5213
+ ` [${completedTasks}/${totalTasks}]`
5214
+ );
5215
+ lines[milestoneIndex] = updatedMilestoneLine;
5216
+ await FileUtils.write(specFile, lines.join("\n"));
5217
+ logger.info(`\u5DF2\u540C\u6B65\u91CC\u7A0B\u7891\u8FDB\u5EA6: [${completedTasks}/${totalTasks}]`);
5218
+ }
5219
+ }
5220
+ }
5221
+
5222
+ // src/commands/lint.ts
5223
+ init_esm_shims();
5224
+ init_utils();
5225
+ init_logger();
5226
+ import { Command as Command8 } from "commander";
4427
5227
  import { execa as execa3 } from "execa";
4428
- var lintCommand = new Command7("lint").option("--fix", "\u81EA\u52A8\u4FEE\u590D\u95EE\u9898").description("\u4EE3\u7801\u8D28\u91CF\u68C0\u67E5 (\u524D\u7AEF + \u540E\u7AEF)").action(async (options) => {
5228
+ var lintCommand = new Command8("lint").option("--fix", "\u81EA\u52A8\u4FEE\u590D\u95EE\u9898").option("--no-type-check", "\u8DF3\u8FC7 TypeScript \u7C7B\u578B\u68C0\u67E5").description("\u4EE3\u7801\u8D28\u91CF\u68C0\u67E5 (\u524D\u7AEF + \u540E\u7AEF)").action(async (options) => {
4429
5229
  try {
4430
5230
  logger.header("\u4EE3\u7801\u8D28\u91CF\u68C0\u67E5");
4431
5231
  logger.newLine();
@@ -4455,15 +5255,26 @@ var lintCommand = new Command7("lint").option("--fix", "\u81EA\u52A8\u4FEE\u590D
4455
5255
  stdio: "inherit"
4456
5256
  });
4457
5257
  }
4458
- await execa3("npx", ["tsc", "--noEmit"], {
4459
- cwd: "frontend",
4460
- stdio: "pipe"
4461
- });
5258
+ if (options.typeCheck !== false) {
5259
+ try {
5260
+ logger.step("\u6B63\u5728\u8FDB\u884C TypeScript \u7C7B\u578B\u68C0\u67E5...");
5261
+ await execa3("npx", ["tsc", "--noEmit"], {
5262
+ cwd: "frontend",
5263
+ stdio: "pipe"
5264
+ });
5265
+ } catch (tscError) {
5266
+ logger.warn("TypeScript \u7C7B\u578B\u68C0\u67E5\u53D1\u73B0\u95EE\u9898\uFF0C\u8BF7\u68C0\u67E5\u4EE3\u7801\u7C7B\u578B\u5B89\u5168\u3002");
5267
+ if (process.env.DEBUG) {
5268
+ console.log(tscError.stdout);
5269
+ }
5270
+ results.frontend.errors.push("TypeScript \u7C7B\u578B\u68C0\u67E5\u5931\u8D25 (\u5DF2\u8DF3\u8FC7\u963B\u585E)");
5271
+ }
5272
+ }
4462
5273
  results.frontend.passed = true;
4463
5274
  logger.success("\u524D\u7AEF\u4EE3\u7801\u68C0\u67E5\u901A\u8FC7");
4464
5275
  } catch (error) {
4465
5276
  results.frontend.errors.push(error.message);
4466
- logger.error("\u524D\u7AEF\u4EE3\u7801\u68C0\u67E5\u5931\u8D25");
5277
+ logger.error(`\u524D\u7AEF\u4EE3\u7801\u68C0\u67E5\u5931\u8D25: ${error.message}`);
4467
5278
  }
4468
5279
  } else {
4469
5280
  logger.info("\u672A\u627E\u5230\u524D\u7AEF\u9879\u76EE (frontend/package.json)");
@@ -4549,9 +5360,9 @@ var lintCommand = new Command7("lint").option("--fix", "\u81EA\u52A8\u4FEE\u590D
4549
5360
  init_esm_shims();
4550
5361
  init_utils();
4551
5362
  init_logger();
4552
- import { Command as Command8 } from "commander";
4553
- import path13 from "path";
4554
- var statusCommand = new Command8("status").description("\u67E5\u770B\u9879\u76EE\u72B6\u6001").action(async () => {
5363
+ import { Command as Command9 } from "commander";
5364
+ import path14 from "path";
5365
+ var statusCommand = new Command9("status").description("\u67E5\u770B\u9879\u76EE\u72B6\u6001").action(async () => {
4555
5366
  try {
4556
5367
  logger.header("\u9879\u76EE\u72B6\u6001");
4557
5368
  logger.newLine();
@@ -4608,7 +5419,7 @@ async function displayFeatureInventory() {
4608
5419
  }
4609
5420
  const inventory = [];
4610
5421
  for (const file of specs) {
4611
- const filePath = path13.join(specDir, file);
5422
+ const filePath = path14.join(specDir, file);
4612
5423
  const content = await FileUtils.read(filePath);
4613
5424
  const status = SpecUtils.parseSpecStatus(content);
4614
5425
  const statusWithIcon = SpecUtils.getStatusWithIcon(status);
@@ -4668,7 +5479,7 @@ async function displayRecentActivity() {
4668
5479
  }
4669
5480
  const sorted = files.sort().reverse().slice(0, 5);
4670
5481
  for (const file of sorted) {
4671
- const filePath = path13.join(sessionDir, file);
5482
+ const filePath = path14.join(sessionDir, file);
4672
5483
  const stat = await FileUtils.read(filePath);
4673
5484
  const specMatch = stat.match(/\*\*Spec\*\*:\s*(.+)/);
4674
5485
  const spec = specMatch ? specMatch[1].trim() : "\u672A\u77E5";
@@ -4687,10 +5498,10 @@ async function displayRecentActivity() {
4687
5498
  init_esm_shims();
4688
5499
  init_utils();
4689
5500
  init_logger();
4690
- import { Command as Command9 } from "commander";
4691
- import path14 from "path";
4692
- import inquirer6 from "inquirer";
4693
- var detectDepsCommand = new Command9("detect-deps").argument("[spec-file]", "Spec \u6587\u4EF6\u8DEF\u5F84").description("\u68C0\u6D4B\u4F9D\u8D56\u5173\u7CFB").action(async (specFile) => {
5501
+ import { Command as Command10 } from "commander";
5502
+ import path15 from "path";
5503
+ import inquirer7 from "inquirer";
5504
+ var detectDepsCommand = new Command10("detect-deps").argument("[spec-file]", "Spec \u6587\u4EF6\u8DEF\u5F84").description("\u68C0\u6D4B\u4F9D\u8D56\u5173\u7CFB").action(async (specFile) => {
4694
5505
  try {
4695
5506
  logger.header("\u68C0\u6D4B\u4F9D\u8D56\u5173\u7CFB");
4696
5507
  logger.newLine();
@@ -4716,7 +5527,7 @@ var detectDepsCommand = new Command9("detect-deps").argument("[spec-file]", "Spe
4716
5527
  process.exit(1);
4717
5528
  }
4718
5529
  for (const spec of specs) {
4719
- const specPath = path14.join(specsDir, spec);
5530
+ const specPath = path15.join(specsDir, spec);
4720
5531
  logger.step(`\u5904\u7406: ${spec}`);
4721
5532
  await detectDependencies(specPath);
4722
5533
  logger.newLine();
@@ -4742,7 +5553,7 @@ async function detectDependencies(specFile) {
4742
5553
  logger.step("\u81EA\u52A8\u68C0\u6D4B\u4F9D\u8D56\u5173\u7CFB...");
4743
5554
  const projectDir = ".";
4744
5555
  const allDeps = /* @__PURE__ */ new Set();
4745
- const backendDir = path14.join(projectDir, "backend");
5556
+ const backendDir = path15.join(projectDir, "backend");
4746
5557
  const backendExists = await FileUtils.exists(backendDir);
4747
5558
  if (backendExists) {
4748
5559
  const apiDeps = await scanBackendApiCalls(backendDir);
@@ -4752,7 +5563,7 @@ async function detectDependencies(specFile) {
4752
5563
  const serviceDeps = await scanBackendServiceRefs(backendDir);
4753
5564
  serviceDeps.forEach((d) => allDeps.add(d));
4754
5565
  }
4755
- const frontendDir = path14.join(projectDir, "frontend");
5566
+ const frontendDir = path15.join(projectDir, "frontend");
4756
5567
  const frontendExists = await FileUtils.exists(frontendDir);
4757
5568
  if (frontendExists) {
4758
5569
  const frontendDeps = await scanFrontendApiCalls(frontendDir);
@@ -4778,7 +5589,7 @@ async function detectDependencies(specFile) {
4778
5589
  logger.step(`- ${spec}`);
4779
5590
  }
4780
5591
  logger.newLine();
4781
- const answers = await inquirer6.prompt([
5592
+ const answers = await inquirer7.prompt([
4782
5593
  {
4783
5594
  type: "confirm",
4784
5595
  name: "autoUpdate",
@@ -4793,11 +5604,11 @@ async function detectDependencies(specFile) {
4793
5604
  }
4794
5605
  async function scanBackendApiCalls(backendDir) {
4795
5606
  const deps = [];
4796
- const srcDir = path14.join(backendDir, "src");
5607
+ const srcDir = path15.join(backendDir, "src");
4797
5608
  try {
4798
5609
  const javaFiles = await FileUtils.findFiles("*.java", srcDir);
4799
5610
  for (const file of javaFiles) {
4800
- const filePath = path14.join(srcDir, file);
5611
+ const filePath = path15.join(srcDir, file);
4801
5612
  const content = await FileUtils.read(filePath);
4802
5613
  const pathRegex = /"(\/api\/[^"]+)"/g;
4803
5614
  let match;
@@ -4815,11 +5626,11 @@ async function scanBackendApiCalls(backendDir) {
4815
5626
  }
4816
5627
  async function scanBackendEntityRelations(backendDir) {
4817
5628
  const deps = [];
4818
- const srcDir = path14.join(backendDir, "src");
5629
+ const srcDir = path15.join(backendDir, "src");
4819
5630
  try {
4820
5631
  const javaFiles = await FileUtils.findFiles("*.java", srcDir);
4821
5632
  for (const file of javaFiles) {
4822
- const filePath = path14.join(srcDir, file);
5633
+ const filePath = path15.join(srcDir, file);
4823
5634
  const content = await FileUtils.read(filePath);
4824
5635
  if (content.includes("@JoinColumn") || content.includes("@ManyToOne") || content.includes("@OneToMany")) {
4825
5636
  const typeRegex = /type\s*=\s*(\w+)/g;
@@ -4835,11 +5646,11 @@ async function scanBackendEntityRelations(backendDir) {
4835
5646
  }
4836
5647
  async function scanBackendServiceRefs(backendDir) {
4837
5648
  const deps = [];
4838
- const srcDir = path14.join(backendDir, "src");
5649
+ const srcDir = path15.join(backendDir, "src");
4839
5650
  try {
4840
5651
  const javaFiles = await FileUtils.findFiles("*.java", srcDir);
4841
5652
  for (const file of javaFiles) {
4842
- const filePath = path14.join(srcDir, file);
5653
+ const filePath = path15.join(srcDir, file);
4843
5654
  const content = await FileUtils.read(filePath);
4844
5655
  const serviceRegex = /private\s+(\w+)Service/g;
4845
5656
  let match;
@@ -4855,11 +5666,11 @@ async function scanBackendServiceRefs(backendDir) {
4855
5666
  }
4856
5667
  async function scanFrontendApiCalls(frontendDir) {
4857
5668
  const deps = [];
4858
- const srcDir = path14.join(frontendDir, "src");
5669
+ const srcDir = path15.join(frontendDir, "src");
4859
5670
  try {
4860
5671
  const tsFiles = await FileUtils.findFiles("*.{ts,tsx,js,jsx}", srcDir);
4861
5672
  for (const file of tsFiles) {
4862
- const filePath = path14.join(srcDir, file);
5673
+ const filePath = path15.join(srcDir, file);
4863
5674
  const content = await FileUtils.read(filePath);
4864
5675
  const pathRegex = /"(\/api\/[^"]+)"/g;
4865
5676
  let match;
@@ -4948,9 +5759,9 @@ ${deps.map((d) => ` - [x] ${d}`).join("\n")}
4948
5759
  init_esm_shims();
4949
5760
  init_utils();
4950
5761
  init_logger();
4951
- import { Command as Command10 } from "commander";
4952
- import path15 from "path";
4953
- var syncMemoryCommand = new Command10("sync-memory").description("\u540C\u6B65 AI_MEMORY.md").action(async () => {
5762
+ import { Command as Command11 } from "commander";
5763
+ import path16 from "path";
5764
+ var syncMemoryCommand = new Command11("sync-memory").description("\u540C\u6B65 AI_MEMORY.md").action(async () => {
4954
5765
  try {
4955
5766
  logger.header("\u540C\u6B65 AI_MEMORY.md");
4956
5767
  logger.newLine();
@@ -4982,7 +5793,7 @@ var syncMemoryCommand = new Command10("sync-memory").description("\u540C\u6B65 A
4982
5793
  });
4983
5794
  async function syncFeatureInventory(aiMemoryFile, projectDir) {
4984
5795
  logger.step("\u540C\u6B65\u529F\u80FD\u6E05\u5355...");
4985
- const specsDir = path15.join(projectDir, "docs/specs");
5796
+ const specsDir = path16.join(projectDir, "docs/specs");
4986
5797
  const exists = await FileUtils.exists(specsDir);
4987
5798
  if (!exists) {
4988
5799
  return;
@@ -4997,7 +5808,7 @@ async function syncFeatureInventory(aiMemoryFile, projectDir) {
4997
5808
  for (const specFile of specs) {
4998
5809
  const name = specFile.replace(".md", "");
4999
5810
  const displayName = name.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
5000
- const specPath = path15.join(specsDir, specFile);
5811
+ const specPath = path16.join(specsDir, specFile);
5001
5812
  const content = await FileUtils.read(specPath);
5002
5813
  const status = SpecUtils.parseSpecStatus(content);
5003
5814
  const statusWithIcon = SpecUtils.getStatusWithIcon(status);
@@ -5016,7 +5827,7 @@ async function syncFeatureInventory(aiMemoryFile, projectDir) {
5016
5827
  }
5017
5828
  async function syncApiInventory(aiMemoryFile, projectDir) {
5018
5829
  logger.step("\u540C\u6B65 API \u5217\u8868...");
5019
- const backendDir = path15.join(projectDir, "backend");
5830
+ const backendDir = path16.join(projectDir, "backend");
5020
5831
  const exists = await FileUtils.exists(backendDir);
5021
5832
  if (!exists) {
5022
5833
  return;
@@ -5026,13 +5837,13 @@ async function syncApiInventory(aiMemoryFile, projectDir) {
5026
5837
  lines.push("");
5027
5838
  lines.push("> \u672C\u90E8\u5206\u7531 team-cli \u81EA\u52A8\u626B\u63CF\u540E\u7AEF Controller \u751F\u6210");
5028
5839
  lines.push("");
5029
- const srcDir = path15.join(backendDir, "src");
5840
+ const srcDir = path16.join(backendDir, "src");
5030
5841
  const controllers = await FileUtils.findFiles("*Controller.java", srcDir);
5031
5842
  if (controllers.length === 0) {
5032
5843
  lines.push("\u6682\u65E0 API");
5033
5844
  } else {
5034
5845
  for (const controllerFile of controllers) {
5035
- const controllerPath = path15.join(srcDir, controllerFile);
5846
+ const controllerPath = path16.join(srcDir, controllerFile);
5036
5847
  const controllerName = controllerFile.replace(".java", "");
5037
5848
  const module = controllerName.replace(/Controller$/, "").toLowerCase();
5038
5849
  lines.push(`### ${module} \u6A21\u5757`);
@@ -5109,7 +5920,7 @@ function extractMethodComment(content, methodName) {
5109
5920
  }
5110
5921
  async function syncDataModels(aiMemoryFile, projectDir) {
5111
5922
  logger.step("\u540C\u6B65\u6570\u636E\u6A21\u578B...");
5112
- const backendDir = path15.join(projectDir, "backend");
5923
+ const backendDir = path16.join(projectDir, "backend");
5113
5924
  const exists = await FileUtils.exists(backendDir);
5114
5925
  if (!exists) {
5115
5926
  return;
@@ -5119,7 +5930,7 @@ async function syncDataModels(aiMemoryFile, projectDir) {
5119
5930
  lines.push("");
5120
5931
  lines.push("> \u672C\u90E8\u5206\u7531 team-cli \u81EA\u52A8\u626B\u63CF\u540E\u7AEF Entity \u751F\u6210");
5121
5932
  lines.push("");
5122
- const srcDir = path15.join(backendDir, "src");
5933
+ const srcDir = path16.join(backendDir, "src");
5123
5934
  const entities = await FileUtils.findFiles("*Entity.java", srcDir);
5124
5935
  if (entities.length === 0) {
5125
5936
  lines.push("\u6682\u65E0\u6570\u636E\u6A21\u578B");
@@ -5127,7 +5938,7 @@ async function syncDataModels(aiMemoryFile, projectDir) {
5127
5938
  lines.push("| \u6A21\u578B | \u8BF4\u660E | \u5B57\u6BB5 | \u5173\u8054 |");
5128
5939
  lines.push("|------|------|------|------|");
5129
5940
  for (const entityFile of entities) {
5130
- const entityPath = path15.join(srcDir, entityFile);
5941
+ const entityPath = path16.join(srcDir, entityFile);
5131
5942
  const entityName = entityFile.replace(".java", "").replace(/Entity$/, "");
5132
5943
  const displayName = entityName.split(/(?=[A-Z])/).map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(" ");
5133
5944
  const content = await FileUtils.read(entityPath);
@@ -5229,26 +6040,26 @@ async function syncTemplateVersions(aiMemoryFile, projectDir) {
5229
6040
  await replaceOrInsertSection(aiMemoryFile, "## \u6A21\u677F\u7248\u672C\u4FE1\u606F", newContent);
5230
6041
  }
5231
6042
  function extractRepoName(repository) {
5232
- let path20 = repository;
5233
- path20 = path20.replace(/^https?:\/\//, "");
5234
- path20 = path20.replace(/^git@/, "");
5235
- const parts = path20.split("/");
6043
+ let path21 = repository;
6044
+ path21 = path21.replace(/^https?:\/\//, "");
6045
+ path21 = path21.replace(/^git@/, "");
6046
+ const parts = path21.split("/");
5236
6047
  if (parts.length > 1) {
5237
- path20 = parts.slice(1).join("/");
6048
+ path21 = parts.slice(1).join("/");
5238
6049
  }
5239
- path20 = path20.replace(/\.git$/, "");
5240
- return path20;
6050
+ path21 = path21.replace(/\.git$/, "");
6051
+ return path21;
5241
6052
  }
5242
6053
 
5243
6054
  // src/commands/check-api.ts
5244
6055
  init_esm_shims();
5245
6056
  init_utils();
5246
6057
  init_logger();
5247
- import { Command as Command11 } from "commander";
5248
- import path16 from "path";
5249
- import inquirer7 from "inquirer";
6058
+ import { Command as Command12 } from "commander";
6059
+ import path17 from "path";
6060
+ import inquirer8 from "inquirer";
5250
6061
  import { Listr as Listr6 } from "listr2";
5251
- var checkApiCommand = new Command11("check-api").description("API \u68C0\u67E5\uFF08\u51B2\u7A81/\u53D8\u66F4/Registry\uFF09").action(async () => {
6062
+ var checkApiCommand = new Command12("check-api").description("API \u68C0\u67E5\uFF08\u51B2\u7A81/\u53D8\u66F4/Registry\uFF09").action(async () => {
5252
6063
  try {
5253
6064
  logger.header("API \u68C0\u67E5");
5254
6065
  logger.newLine();
@@ -5258,7 +6069,7 @@ var checkApiCommand = new Command11("check-api").description("API \u68C0\u67E5\u
5258
6069
  logger.info("\u8BF7\u5148\u8FD0\u884C 'team-cli init <project-name>' \u6216\u5207\u6362\u5230\u9879\u76EE\u76EE\u5F55");
5259
6070
  process.exit(1);
5260
6071
  }
5261
- const answers = await inquirer7.prompt([
6072
+ const answers = await inquirer8.prompt([
5262
6073
  {
5263
6074
  type: "list",
5264
6075
  name: "checkType",
@@ -5309,7 +6120,7 @@ var checkApiCommand = new Command11("check-api").description("API \u68C0\u67E5\u
5309
6120
  }
5310
6121
  });
5311
6122
  async function checkApiConflicts(projectDir) {
5312
- const backendDir = path16.join(projectDir, "backend");
6123
+ const backendDir = path17.join(projectDir, "backend");
5313
6124
  const exists = await FileUtils.exists(backendDir);
5314
6125
  if (!exists) {
5315
6126
  logger.info("\u672A\u627E\u5230\u540E\u7AEF\u9879\u76EE");
@@ -5318,10 +6129,10 @@ async function checkApiConflicts(projectDir) {
5318
6129
  logger.step("\u626B\u63CF\u540E\u7AEF API...");
5319
6130
  logger.newLine();
5320
6131
  const apiMap = /* @__PURE__ */ new Map();
5321
- const srcDir = path16.join(backendDir, "src");
6132
+ const srcDir = path17.join(backendDir, "src");
5322
6133
  const controllers = await FileUtils.findFiles("*Controller.java", srcDir);
5323
6134
  for (const controllerFile of controllers) {
5324
- const controllerPath = path16.join(srcDir, controllerFile);
6135
+ const controllerPath = path17.join(srcDir, controllerFile);
5325
6136
  const apis = await extractApisFromController(controllerPath);
5326
6137
  for (const api of apis) {
5327
6138
  const key = `${api.method}:${api.path}`;
@@ -5352,8 +6163,8 @@ async function checkApiConflicts(projectDir) {
5352
6163
  }
5353
6164
  }
5354
6165
  async function detectApiChanges(projectDir) {
5355
- const backendDir = path16.join(projectDir, "backend");
5356
- const registryFile = path16.join(projectDir, "docs/api-registry.md");
6166
+ const backendDir = path17.join(projectDir, "backend");
6167
+ const registryFile = path17.join(projectDir, "docs/api-registry.md");
5357
6168
  const registryExists = await FileUtils.exists(registryFile);
5358
6169
  if (!registryExists) {
5359
6170
  logger.info("API Registry \u4E0D\u5B58\u5728\uFF0C\u8DF3\u8FC7\u53D8\u66F4\u68C0\u6D4B");
@@ -5365,10 +6176,10 @@ async function detectApiChanges(projectDir) {
5365
6176
  const registryContent = await FileUtils.read(registryFile);
5366
6177
  const existingApis = extractApisFromRegistry(registryContent);
5367
6178
  const currentApis = /* @__PURE__ */ new Map();
5368
- const srcDir = path16.join(backendDir, "src");
6179
+ const srcDir = path17.join(backendDir, "src");
5369
6180
  const controllers = await FileUtils.findFiles("*Controller.java", srcDir);
5370
6181
  for (const controllerFile of controllers) {
5371
- const controllerPath = path16.join(srcDir, controllerFile);
6182
+ const controllerPath = path17.join(srcDir, controllerFile);
5372
6183
  const apis = await extractApisFromController(controllerPath);
5373
6184
  for (const api of apis) {
5374
6185
  const key = `${api.method}:${api.path}`;
@@ -5430,9 +6241,9 @@ async function detectApiChanges(projectDir) {
5430
6241
  }
5431
6242
  }
5432
6243
  async function generateApiRegistry(projectDir) {
5433
- const registryFile = path16.join(projectDir, "docs/api-registry.md");
6244
+ const registryFile = path17.join(projectDir, "docs/api-registry.md");
5434
6245
  logger.step("\u626B\u63CF\u5E76\u751F\u6210 API Registry...");
5435
- await FileUtils.ensureDir(path16.dirname(registryFile));
6246
+ await FileUtils.ensureDir(path17.dirname(registryFile));
5436
6247
  const header = `# API Registry
5437
6248
 
5438
6249
  > \u672C\u6587\u4EF6\u8BB0\u5F55\u6240\u6709 API \u7684\u5B9A\u4E49\u3001\u7248\u672C\u548C\u53D8\u66F4\u5386\u53F2
@@ -5461,14 +6272,14 @@ async function generateApiRegistry(projectDir) {
5461
6272
  *\u6700\u540E\u66F4\u65B0: ${DateUtils.format(/* @__PURE__ */ new Date(), "YYYY-MM-DD HH:mm:ss")}*
5462
6273
  `;
5463
6274
  let content = header;
5464
- const backendDir = path16.join(projectDir, "backend");
6275
+ const backendDir = path17.join(projectDir, "backend");
5465
6276
  const exists = await FileUtils.exists(backendDir);
5466
6277
  if (exists) {
5467
- const srcDir = path16.join(backendDir, "src");
6278
+ const srcDir = path17.join(backendDir, "src");
5468
6279
  const controllers = await FileUtils.findFiles("*Controller.java", srcDir);
5469
6280
  const moduleMap = /* @__PURE__ */ new Map();
5470
6281
  for (const controllerFile of controllers) {
5471
- const controllerPath = path16.join(srcDir, controllerFile);
6282
+ const controllerPath = path17.join(srcDir, controllerFile);
5472
6283
  const controllerName = controllerFile.replace(".java", "");
5473
6284
  const module = controllerName.replace(/Controller$/, "").toLowerCase();
5474
6285
  if (!moduleMap.has(module)) {
@@ -5552,10 +6363,10 @@ function extractApisFromRegistry(registryContent) {
5552
6363
  let match;
5553
6364
  while ((match = apiRegex.exec(registryContent)) !== null) {
5554
6365
  const method = match[1];
5555
- const path20 = match[2].trim();
6366
+ const path21 = match[2].trim();
5556
6367
  const description = match[3].trim();
5557
- const key = `${method}:${path20}`;
5558
- apis.set(key, { method, path: path20, description });
6368
+ const key = `${method}:${path21}`;
6369
+ apis.set(key, { method, path: path21, description });
5559
6370
  }
5560
6371
  return apis;
5561
6372
  }
@@ -5576,10 +6387,10 @@ function extractMethodComment2(content, methodName) {
5576
6387
  init_esm_shims();
5577
6388
  init_utils();
5578
6389
  init_logger();
5579
- import { Command as Command12 } from "commander";
5580
- import path17 from "path";
5581
- import inquirer8 from "inquirer";
5582
- var logsCommand = new Command12("logs").argument("[filter]", "\u8FC7\u6EE4\u5668 (today, --all, \u6216\u65E5\u671F YYYY-MM-DD)").description("\u67E5\u770B\u4F1A\u8BDD\u65E5\u5FD7").action(async (filter = "today") => {
6390
+ import { Command as Command13 } from "commander";
6391
+ import path18 from "path";
6392
+ import inquirer9 from "inquirer";
6393
+ var logsCommand = new Command13("logs").argument("[filter]", "\u8FC7\u6EE4\u5668 (today, --all, \u6216\u65E5\u671F YYYY-MM-DD)").description("\u67E5\u770B\u4F1A\u8BDD\u65E5\u5FD7").action(async (filter = "today") => {
5583
6394
  try {
5584
6395
  logger.header("\u4F1A\u8BDD\u65E5\u5FD7");
5585
6396
  logger.newLine();
@@ -5602,7 +6413,7 @@ var logsCommand = new Command12("logs").argument("[filter]", "\u8FC7\u6EE4\u5668
5602
6413
  case "":
5603
6414
  case "today": {
5604
6415
  const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
5605
- targetDir = path17.join(sessionsDir, today);
6416
+ targetDir = path18.join(sessionsDir, today);
5606
6417
  const todayExists = await FileUtils.exists(targetDir);
5607
6418
  if (!todayExists) {
5608
6419
  logger.info("\u4ECA\u65E5\u6682\u65E0\u4F1A\u8BDD\u65E5\u5FD7");
@@ -5618,7 +6429,7 @@ var logsCommand = new Command12("logs").argument("[filter]", "\u8FC7\u6EE4\u5668
5618
6429
  break;
5619
6430
  }
5620
6431
  default: {
5621
- targetDir = path17.join(sessionsDir, filter);
6432
+ targetDir = path18.join(sessionsDir, filter);
5622
6433
  const dateExists = await FileUtils.exists(targetDir);
5623
6434
  if (!dateExists) {
5624
6435
  logger.error(`\u672A\u627E\u5230\u65E5\u671F '${filter}' \u7684\u65E5\u5FD7`);
@@ -5642,11 +6453,11 @@ var logsCommand = new Command12("logs").argument("[filter]", "\u8FC7\u6EE4\u5668
5642
6453
  process.exit(0);
5643
6454
  }
5644
6455
  for (let i = 0; i < logs.length; i++) {
5645
- const relPath = path17.relative(sessionsDir, logs[i]);
6456
+ const relPath = path18.relative(sessionsDir, logs[i]);
5646
6457
  logger.step(`${i + 1}) ${relPath}`);
5647
6458
  }
5648
6459
  logger.newLine();
5649
- const answers = await inquirer8.prompt([
6460
+ const answers = await inquirer9.prompt([
5650
6461
  {
5651
6462
  type: "input",
5652
6463
  name: "selection",
@@ -5683,7 +6494,7 @@ async function collectLogFiles(targetDir) {
5683
6494
  const allFiles = await FileUtils.findFiles("*.md", targetDir);
5684
6495
  const filtered = allFiles.filter((f) => f !== "index.md");
5685
6496
  for (const file of filtered) {
5686
- const filePath = path17.join(targetDir, file);
6497
+ const filePath = path18.join(targetDir, file);
5687
6498
  const stat = await FileUtils.exists(filePath);
5688
6499
  if (stat) {
5689
6500
  logs.push(filePath);
@@ -5696,14 +6507,14 @@ async function collectLogFiles(targetDir) {
5696
6507
 
5697
6508
  // src/commands/update.ts
5698
6509
  init_esm_shims();
5699
- import { Command as Command13 } from "commander";
5700
- import path18 from "path";
6510
+ import { Command as Command14 } from "commander";
6511
+ import path19 from "path";
5701
6512
  init_logger();
5702
6513
  init_utils();
5703
6514
  import { execa as execa4 } from "execa";
5704
- import inquirer9 from "inquirer";
6515
+ import inquirer10 from "inquirer";
5705
6516
  import fs4 from "fs-extra";
5706
- var updateCommand = new Command13("update").description("\u68C0\u67E5\u5E76\u66F4\u65B0\u6A21\u677F\u7248\u672C").option("-f, --frontend", "\u68C0\u67E5\u524D\u7AEF\u6A21\u677F\u66F4\u65B0").option("-b, --backend", "\u68C0\u67E5\u540E\u7AEF\u6A21\u677F\u66F4\u65B0").option("-a, --all", "\u68C0\u67E5\u6240\u6709\u6A21\u677F (\u9ED8\u8BA4)").option("-t, --tag <tag>", "\u66F4\u65B0\u5230\u6307\u5B9A\u6807\u7B7E").option("-B, --branch <branch>", "\u66F4\u65B0\u5230\u6307\u5B9A\u5206\u652F").option("--dry-run", "\u9884\u89C8\u66F4\u65B0\uFF0C\u4E0D\u5B9E\u9645\u6267\u884C").action(async (options) => {
6517
+ var updateCommand = new Command14("update").description("\u68C0\u67E5\u5E76\u66F4\u65B0\u6A21\u677F\u7248\u672C").option("-f, --frontend", "\u68C0\u67E5\u524D\u7AEF\u6A21\u677F\u66F4\u65B0").option("-b, --backend", "\u68C0\u67E5\u540E\u7AEF\u6A21\u677F\u66F4\u65B0").option("-a, --all", "\u68C0\u67E5\u6240\u6709\u6A21\u677F (\u9ED8\u8BA4)").option("-t, --tag <tag>", "\u66F4\u65B0\u5230\u6307\u5B9A\u6807\u7B7E").option("-B, --branch <branch>", "\u66F4\u65B0\u5230\u6307\u5B9A\u5206\u652F").option("--dry-run", "\u9884\u89C8\u66F4\u65B0\uFF0C\u4E0D\u5B9E\u9645\u6267\u884C").action(async (options) => {
5707
6518
  try {
5708
6519
  logger.header("\u6A21\u677F\u7248\u672C\u68C0\u67E5");
5709
6520
  logger.newLine();
@@ -5775,7 +6586,7 @@ var updateCommand = new Command13("update").description("\u68C0\u67E5\u5E76\u66F
5775
6586
  logger.info("Dry run \u6A21\u5F0F\uFF0C\u4E0D\u6267\u884C\u5B9E\u9645\u66F4\u65B0");
5776
6587
  return;
5777
6588
  }
5778
- const answers = await inquirer9.prompt([
6589
+ const answers = await inquirer10.prompt([
5779
6590
  {
5780
6591
  type: "confirm",
5781
6592
  name: "shouldUpdate",
@@ -5802,7 +6613,7 @@ async function performUpdate(projectPath, updates) {
5802
6613
  for (const update of updates) {
5803
6614
  const { type, info, updateOptions } = update;
5804
6615
  const targetDir = type === "frontend" ? "frontend" : "backend";
5805
- const targetPath = path18.join(projectPath, targetDir);
6616
+ const targetPath = path19.join(projectPath, targetDir);
5806
6617
  logger.newLine();
5807
6618
  logger.step(`\u66F4\u65B0 ${type === "frontend" ? "\u524D\u7AEF" : "\u540E\u7AEF"}\u6A21\u677F...`);
5808
6619
  if (updateOptions?.tag || updateOptions?.branch) {
@@ -5833,8 +6644,8 @@ async function performUpdate(projectPath, updates) {
5833
6644
  }
5834
6645
  }
5835
6646
  const ref = updateOptions?.tag || updateOptions?.branch || "HEAD";
5836
- const backupDir = path18.join(projectPath, `.backup-${Date.now()}`);
5837
- await fs4.copy(targetPath, path18.join(backupDir, targetDir));
6647
+ const backupDir = path19.join(projectPath, `.backup-${Date.now()}`);
6648
+ await fs4.copy(targetPath, path19.join(backupDir, targetDir));
5838
6649
  logger.info(`\u5DF2\u521B\u5EFA\u5907\u4EFD: ${backupDir}`);
5839
6650
  if (updateOptions?.dryRun) {
5840
6651
  logger.info("[Dry Run] \u5C06\u4F1A\u66F4\u65B0\u5230\u4EE5\u4E0B\u7248\u672C:");
@@ -5844,7 +6655,7 @@ async function performUpdate(projectPath, updates) {
5844
6655
  continue;
5845
6656
  }
5846
6657
  try {
5847
- const tempDir = path18.join(projectPath, `.template-update-${Date.now()}`);
6658
+ const tempDir = path19.join(projectPath, `.template-update-${Date.now()}`);
5848
6659
  await execa4("git", ["clone", "--depth=1", "--branch", ref, info.repository, tempDir], {
5849
6660
  stdio: "pipe"
5850
6661
  });
@@ -5861,7 +6672,7 @@ async function performUpdate(projectPath, updates) {
5861
6672
  const currentFiles = await FileUtils.findFiles("*", targetPath);
5862
6673
  for (const file of currentFiles) {
5863
6674
  if (!keepFiles.includes(file)) {
5864
- const filePath = path18.join(targetPath, file);
6675
+ const filePath = path19.join(targetPath, file);
5865
6676
  try {
5866
6677
  await fs4.remove(filePath);
5867
6678
  } catch {
@@ -5883,7 +6694,7 @@ async function performUpdate(projectPath, updates) {
5883
6694
  logger.error(`\u66F4\u65B0\u5931\u8D25: ${error.message}`);
5884
6695
  logger.info("\u6B63\u5728\u6062\u590D\u5907\u4EFD...");
5885
6696
  await fs4.remove(targetPath);
5886
- await fs4.copy(path18.join(backupDir, targetDir), targetPath);
6697
+ await fs4.copy(path19.join(backupDir, targetDir), targetPath);
5887
6698
  await fs4.remove(backupDir);
5888
6699
  logger.info("\u5DF2\u6062\u590D\u5230\u66F4\u65B0\u524D\u7684\u72B6\u6001");
5889
6700
  }
@@ -5904,16 +6715,16 @@ init_esm_shims();
5904
6715
  init_user_config();
5905
6716
  init_gitlab_api();
5906
6717
  init_logger();
5907
- import { Command as Command14 } from "commander";
5908
- import inquirer10 from "inquirer";
6718
+ import { Command as Command15 } from "commander";
6719
+ import inquirer11 from "inquirer";
5909
6720
  import chalk2 from "chalk";
5910
- var setTokenCommand = new Command14("set-token").description("\u8BBE\u7F6E GitLab Access Token").option("-t, --token <token>", "Access Token").option("-u, --url <url>", "GitLab Base URL", "https://gitlab.com").action(async (options) => {
6721
+ var setTokenCommand = new Command15("set-token").description("\u8BBE\u7F6E GitLab Access Token").option("-t, --token <token>", "Access Token").option("-u, --url <url>", "GitLab Base URL", "https://gitlab.com").action(async (options) => {
5911
6722
  try {
5912
6723
  logger.header("GitLab Access Token \u914D\u7F6E");
5913
6724
  logger.newLine();
5914
6725
  let { token, url } = options;
5915
6726
  if (!token) {
5916
- const answers = await inquirer10.prompt([
6727
+ const answers = await inquirer11.prompt([
5917
6728
  {
5918
6729
  type: "password",
5919
6730
  name: "token",
@@ -5975,7 +6786,7 @@ var setTokenCommand = new Command14("set-token").description("\u8BBE\u7F6E GitLa
5975
6786
  process.exit(1);
5976
6787
  }
5977
6788
  });
5978
- var showConfigCommand = new Command14("show").description("\u663E\u793A\u5F53\u524D\u914D\u7F6E").action(async () => {
6789
+ var showConfigCommand = new Command15("show").description("\u663E\u793A\u5F53\u524D\u914D\u7F6E").action(async () => {
5979
6790
  try {
5980
6791
  logger.header("GitLab \u914D\u7F6E");
5981
6792
  logger.newLine();
@@ -6014,14 +6825,14 @@ var showConfigCommand = new Command14("show").description("\u663E\u793A\u5F53\u5
6014
6825
  process.exit(1);
6015
6826
  }
6016
6827
  });
6017
- var removeConfigCommand = new Command14("remove").alias("rm").description("\u5220\u9664 GitLab \u914D\u7F6E").action(async () => {
6828
+ var removeConfigCommand = new Command15("remove").alias("rm").description("\u5220\u9664 GitLab \u914D\u7F6E").action(async () => {
6018
6829
  try {
6019
6830
  const hasConfig = await userConfigManager.hasConfig();
6020
6831
  if (!hasConfig) {
6021
6832
  logger.warn("\u672A\u914D\u7F6E GitLab Access Token");
6022
6833
  return;
6023
6834
  }
6024
- const answers = await inquirer10.prompt([
6835
+ const answers = await inquirer11.prompt([
6025
6836
  {
6026
6837
  type: "confirm",
6027
6838
  name: "confirm",
@@ -6043,7 +6854,7 @@ var removeConfigCommand = new Command14("remove").alias("rm").description("\u522
6043
6854
  process.exit(1);
6044
6855
  }
6045
6856
  });
6046
- var validateTokenCommand = new Command14("validate").alias("test").description("\u9A8C\u8BC1\u5F53\u524D Token \u662F\u5426\u6709\u6548").action(async () => {
6857
+ var validateTokenCommand = new Command15("validate").alias("test").description("\u9A8C\u8BC1\u5F53\u524D Token \u662F\u5426\u6709\u6548").action(async () => {
6047
6858
  try {
6048
6859
  logger.header("\u9A8C\u8BC1 GitLab Token");
6049
6860
  logger.newLine();
@@ -6073,17 +6884,17 @@ var validateTokenCommand = new Command14("validate").alias("test").description("
6073
6884
  process.exit(1);
6074
6885
  }
6075
6886
  });
6076
- var configCommand = new Command14("config").description("\u7BA1\u7406 GitLab \u914D\u7F6E").addCommand(setTokenCommand).addCommand(showConfigCommand).addCommand(removeConfigCommand).addCommand(validateTokenCommand);
6887
+ var configCommand = new Command15("config").description("\u7BA1\u7406 GitLab \u914D\u7F6E").addCommand(setTokenCommand).addCommand(showConfigCommand).addCommand(removeConfigCommand).addCommand(validateTokenCommand);
6077
6888
 
6078
6889
  // src/commands/diff.ts
6079
6890
  init_esm_shims();
6080
- import { Command as Command15 } from "commander";
6891
+ import { Command as Command16 } from "commander";
6081
6892
  import chalk3 from "chalk";
6082
6893
  init_logger();
6083
6894
  init_utils();
6084
6895
  init_user_config();
6085
6896
  init_gitlab_api();
6086
- var diffCommand = new Command15("diff").description("\u5BF9\u6BD4\u672C\u5730\u4E0E\u8FDC\u7A0B\u6A21\u677F\u5DEE\u5F02").option("-f, --frontend", "\u5BF9\u6BD4\u524D\u7AEF\u6A21\u677F").option("-b, --backend", "\u5BF9\u6BD4\u540E\u7AEF\u6A21\u677F").option("-t, --tag <tag>", "\u6307\u5B9A\u8FDC\u7A0B\u6807\u7B7E").option("-B, --branch <branch>", "\u6307\u5B9A\u8FDC\u7A0B\u5206\u652F").option("-o, --output <format>", "\u8F93\u51FA\u683C\u5F0F (table|json|diff)", "table").action(async (options) => {
6897
+ var diffCommand = new Command16("diff").description("\u5BF9\u6BD4\u672C\u5730\u4E0E\u8FDC\u7A0B\u6A21\u677F\u5DEE\u5F02").option("-f, --frontend", "\u5BF9\u6BD4\u524D\u7AEF\u6A21\u677F").option("-b, --backend", "\u5BF9\u6BD4\u540E\u7AEF\u6A21\u677F").option("-t, --tag <tag>", "\u6307\u5B9A\u8FDC\u7A0B\u6807\u7B7E").option("-B, --branch <branch>", "\u6307\u5B9A\u8FDC\u7A0B\u5206\u652F").option("-o, --output <format>", "\u8F93\u51FA\u683C\u5F0F (table|json|diff)", "table").action(async (options) => {
6087
6898
  try {
6088
6899
  logger.header("\u6A21\u677F\u7248\u672C\u5BF9\u6BD4");
6089
6900
  logger.newLine();
@@ -6369,9 +7180,9 @@ var Table = class {
6369
7180
  };
6370
7181
 
6371
7182
  // src/index.ts
6372
- var __dirname2 = path19.dirname(fileURLToPath2(import.meta.url));
6373
- var pkg = fs5.readJsonSync(path19.join(__dirname2, "../package.json"));
6374
- var program = new Command16();
7183
+ var __dirname2 = path20.dirname(fileURLToPath2(import.meta.url));
7184
+ var pkg = fs5.readJsonSync(path20.join(__dirname2, "../package.json"));
7185
+ var program = new Command17();
6375
7186
  program.name("team-cli").description("AI-Native \u56E2\u961F\u7814\u53D1\u811A\u624B\u67B6").version(pkg.version);
6376
7187
  program.option("-v, --verbose", "\u8BE6\u7EC6\u8F93\u51FA\u6A21\u5F0F").option("--debug", "\u8C03\u8BD5\u6A21\u5F0F");
6377
7188
  program.addCommand(initCommand);
@@ -6381,6 +7192,7 @@ program.addCommand(devCommand);
6381
7192
  program.addCommand(addFeatureCommand);
6382
7193
  program.addCommand(bugfixCommand);
6383
7194
  program.addCommand(hotfixCommand);
7195
+ program.addCommand(acceptCommand);
6384
7196
  program.addCommand(lintCommand);
6385
7197
  program.addCommand(statusCommand);
6386
7198
  program.addCommand(detectDepsCommand);
@@ -6402,7 +7214,8 @@ function showHelp() {
6402
7214
  console.log(" team-cli split-prd <prd-folder> \u5C06 PRD \u62C6\u5206\u6210\u591A\u4E2A specs");
6403
7215
  console.log(" team-cli breakdown [spec-file] \u5C06 spec \u62C6\u5206\u4E3A milestones \u548C todos");
6404
7216
  console.log(" team-cli dev \u5F00\u53D1\u6A21\u5F0F\uFF0C\u6267\u884C\u5177\u4F53\u4EFB\u52A1");
6405
- console.log(" team-cli add-feature <name> \u6DFB\u52A0\u65B0\u529F\u80FD");
7217
+ console.log(" team-cli accept [spec-file] \u9A8C\u6536\u529F\u80FD\uFF0C\u8D70\u67E5\u6240\u6709\u9700\u6C42");
7218
+ console.log(" team-cli add-feature <name> \u6DFB\u52A0\u65B0\u529F\u80FD");
6406
7219
  console.log(" team-cli bugfix \u521B\u5EFA Bugfix \u8BB0\u5F55");
6407
7220
  console.log(" team-cli hotfix \u521B\u5EFA Hotfix");
6408
7221
  console.log(" team-cli detect-deps [spec] \u68C0\u6D4B\u4F9D\u8D56\u5173\u7CFB");
@@ -6427,6 +7240,7 @@ function showHelp() {
6427
7240
  console.log(" 1. PRD \u2192 specs (split-prd)");
6428
7241
  console.log(" 2. spec \u2192 milestones + todos (breakdown)");
6429
7242
  console.log(" 3. \u9009\u62E9 milestone/todo \u2192 \u5B9E\u73B0 (dev)");
7243
+ console.log(" 4. \u9A8C\u6536 (accept) \u2192 \u9A8C\u8BC1\u8054\u8C03\u662F\u5426\u5B8C\u6210");
6430
7244
  console.log("");
6431
7245
  console.log(chalk4.bold("\u8FED\u4EE3\u6D41\u7A0B:"));
6432
7246
  console.log(" team-cli add-feature <name> # \u6DFB\u52A0\u65B0\u529F\u80FD");