@ghyper9023/pi-dev-workflow 0.2.0 → 0.3.1

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.
@@ -24,6 +24,7 @@
24
24
  */
25
25
 
26
26
  import type { ExtensionAPI, ExtensionCommandContext } from "@earendil-works/pi-coding-agent";
27
+ import { runGrillPhase, runPRDPhase, type AgentDef, type GrillOptions } from "./grill-me-agent";
27
28
 
28
29
  // ── Helpers ──────────────────────────────────────────────────
29
30
 
@@ -135,7 +136,7 @@ function assembleDocPrompt(f: DocFields): string {
135
136
  }
136
137
  lines.push("**任务**:");
137
138
  lines.push("1. 提取核心要点,按逻辑结构重组(概述 → 快速开始 → 详细说明 → 常见问题)。");
138
- lines.push(`2. 添加至少 2 个真实可运行的示例(使用 ${wrap(f.language)} 语法高亮)。`);
139
+ lines.push(`2. 添加至少 1 个真实可运行的示例(使用 ${wrap(f.language)} 语法高亮)。`);
139
140
  lines.push("3. 如存在争议点,列出不同观点并注明\"无共识\"。");
140
141
  if (!isEmpty(f.existingMaterial)) {
141
142
  lines.push(`**已有材料**:${f.existingMaterial!.trim()}`);
@@ -161,7 +162,7 @@ function assembleRefactorPrompt(f: RefactorFields): string {
161
162
  lines.push("");
162
163
  lines.push(`**背景**:当前代码存在 ${wrap(f.problems)}。`);
163
164
  lines.push("**任务**:");
164
- lines.push("1. 识别 3 个主要问题。");
165
+ lines.push("1. 识别主要问题。");
165
166
  lines.push("2. 提出重构方案,说明改动前后差异。");
166
167
  lines.push("3. 输出重构后的完整版本。");
167
168
  lines.push("**硬性约束**:");
@@ -350,8 +351,215 @@ function assembleComparePrompt(f: CompareFields): string {
350
351
  return lines.join("\n");
351
352
  }
352
353
 
354
+ // ── Specialized Agent Definitions for Grill ─────────────────
355
+
356
+ /** Bug fix root cause analysis & reproduction review. */
357
+ const FIX_GRILL_AGENT_DEF: AgentDef = {
358
+ name: "fix-grill-agent",
359
+ description: "Bug fix review agent — challenges the developer on understanding the bug root cause",
360
+ tools: ["read", "bash"],
361
+ systemPrompt: [
362
+ "You are an expert debugger reviewing a bug fix plan. Interview the developer relentlessly.",
363
+ "",
364
+ "## Rules",
365
+ "- For EACH question, provide recommended answer OPTIONS (a/b/c format)",
366
+ "- Focus on: reproduction steps, environment conditions, input variations, error messages, logs, attempted fixes",
367
+ "- Push for precise root cause identification — ask 'why' at least 3 levels deep",
368
+ "- Check if the developer has considered: edge cases in inputs, race conditions, state leakage, timeout, memory",
369
+ "- Verify the proposed fix addresses the root cause, not just the symptom",
370
+ "- If the codebase has logs/metrics available, suggest checking specific patterns",
371
+ "- Stress-test regression risk: could the fix break other parts of the system?",
372
+ "- Explore the codebase (use read/bash tools) when a question can be answered by looking at existing code",
373
+ "",
374
+ "## Output format",
375
+ "Output ALL questions in ONE JSON response. No preamble or explanation.",
376
+ 'Only output the JSON object: { "questions": [{ "id": 1, "question": "...", "options": ["..."] }] }',
377
+ "",
378
+ "## Quantity",
379
+ "Ask 5-15 questions — enough to thoroughly understand the root cause before committing to a fix.",
380
+ "",
381
+ "## Language",
382
+ "Questions and options should be in the same language as the bug report (default: Chinese).",
383
+ ].join("\n"),
384
+ timeoutMs: 300_000,
385
+ };
386
+
387
+ /** Document outline & structure review. */
388
+ const DOC_GRILL_AGENT_DEF: AgentDef = {
389
+ name: "doc-grill-agent",
390
+ description: "Documentation review agent — reviews document outline before writing",
391
+ tools: ["read", "bash"],
392
+ systemPrompt: [
393
+ "You are an expert technical writer reviewing a documentation plan. Interview the developer.",
394
+ "",
395
+ "## Rules",
396
+ "- For EACH question, provide recommended answer OPTIONS (a/b/c format)",
397
+ "- Focus on: target audience level, document structure, what examples to include, what NOT to cover",
398
+ "- Check if the proposed outline covers: overview → quick start → detailed usage → FAQ/troubleshooting",
399
+ "- Ask about existing documentation that should be linked or consolidated",
400
+ "- Clarify terminology preferences and API naming conventions",
401
+ "- Identify potential gaps: error handling, security considerations, performance notes, deprecation notices",
402
+ "- Explore the codebase (use read/bash tools) to see existing docs for consistency",
403
+ "",
404
+ "## Output format",
405
+ "Output ALL questions in ONE JSON response. No preamble or explanation.",
406
+ 'Only output the JSON object: { "questions": [{ "id": 1, "question": "...", "options": ["..."] }] }',
407
+ "",
408
+ "## Quantity",
409
+ "Ask 3-10 questions — enough to define the scope and structure.",
410
+ "",
411
+ "## Language",
412
+ "Questions and options should be in the same language as the documentation request (default: Chinese).",
413
+ ].join("\n"),
414
+ timeoutMs: 300_000,
415
+ };
416
+
417
+ /** Refactoring plan review. */
418
+ const REFACTOR_GRILL_AGENT_DEF: AgentDef = {
419
+ name: "refactor-grill-agent",
420
+ description: "Refactoring review agent — reviews refactoring plan before implementation",
421
+ tools: ["read", "bash"],
422
+ systemPrompt: [
423
+ "You are an expert software architect reviewing a refactoring plan. Interview the developer.",
424
+ "",
425
+ "## Rules",
426
+ "- For EACH question, provide recommended answer OPTIONS (a/b/c format)",
427
+ "- Focus on: module boundaries, API compatibility, dependency inversion, test strategy, migration steps",
428
+ "- Verify that behavior is preserved — no hidden logic changes disguised as refactoring",
429
+ "- Ask about: interface contracts, error handling behavior, logging behavior, side effects",
430
+ "- Check for risk: what's the rollback plan? Can we refactor incrementally?",
431
+ "- Ask about test coverage: are existing tests sufficient to catch regressions?",
432
+ "- Explore the codebase (use read/bash tools) to understand current module coupling",
433
+ "- Identify potential performance impact of the refactoring",
434
+ "- Check if there are circular dependency issues that should be addressed",
435
+ "",
436
+ "## Output format",
437
+ "Output ALL questions in ONE JSON response. No preamble or explanation.",
438
+ 'Only output the JSON object: { "questions": [{ "id": 1, "question": "...", "options": ["..."] }] }',
439
+ "",
440
+ "## Quantity",
441
+ "Ask 5-15 questions — thorough enough to catch hidden coupling issues.",
442
+ "",
443
+ "## Language",
444
+ "Questions and options should be in the same language as the refactoring request (default: Chinese).",
445
+ ].join("\n"),
446
+ timeoutMs: 300_000,
447
+ };
448
+
449
+ /** Test plan coverage review. */
450
+ const TEST_GRILL_AGENT_DEF: AgentDef = {
451
+ name: "test-grill-agent",
452
+ description: "Test plan review agent — reviews test coverage and approach before writing tests",
453
+ tools: ["read", "bash"],
454
+ systemPrompt: [
455
+ "You are an expert QA engineer reviewing a test plan. Interview the developer.",
456
+ "",
457
+ "## Rules",
458
+ "- For EACH question, provide recommended answer OPTIONS (a/b/c format)",
459
+ "- Focus on: coverage dimensions, edge cases not yet considered, mocking strategy, test isolation",
460
+ "- Ask about: null/empty inputs, timeouts, idempotency, retry logic, success/failure paths",
461
+ "- Check if the developer has considered: 4xx/5xx HTTP responses, concurrent access, partial failures",
462
+ "- Ask about testing infrastructure: how to run tests, CI integration, test data management",
463
+ "- Verify testability: are dependencies injected? Can we mock external services?",
464
+ "- Explore the codebase (use read/bash tools) to understand existing test patterns",
465
+ "- Ask about coverage thresholds and whether branch coverage is needed",
466
+ "",
467
+ "## Output format",
468
+ "Output ALL questions in ONE JSON response. No preamble or explanation.",
469
+ 'Only output the JSON object: { "questions": [{ "id": 1, "question": "...", "options": ["..."] }] }',
470
+ "",
471
+ "## Quantity",
472
+ "Ask 5-12 questions — enough to define a thorough test strategy.",
473
+ "",
474
+ "## Language",
475
+ "Questions and options should be in the same language as the test request (default: Chinese).",
476
+ ].join("\n"),
477
+ timeoutMs: 300_000,
478
+ };
479
+
480
+ /** Performance optimization plan review. */
481
+ const PERF_GRILL_AGENT_DEF: AgentDef = {
482
+ name: "perf-grill-agent",
483
+ description: "Performance review agent — reviews optimization approach and benchmarking strategy",
484
+ tools: ["read", "bash"],
485
+ systemPrompt: [
486
+ "You are an expert performance engineer reviewing an optimization plan. Interview the developer.",
487
+ "",
488
+ "## Rules",
489
+ "- For EACH question, provide recommended answer OPTIONS (a/b/c format)",
490
+ "- Focus on: benchmarking methodology, measurement tools, baseline metrics, optimization approaches",
491
+ "- Verify the bottleneck identification: is it really the bottleneck? What's the evidence?",
492
+ "- Ask about: existing profiling data, hot paths, memory vs CPU trade-offs",
493
+ "- Check if simpler solutions exist (e.g., caching before algorithm rewrite)",
494
+ "- Ask about regression risk: could the optimization introduce correctness issues?",
495
+ "- Explore the codebase (use read/bash tools) to understand current implementation",
496
+ "- Ask about monitoring: how will we measure the improvement in production?",
497
+ "- Challenge assumptions: is this optimization premature? What's the user-facing impact?",
498
+ "",
499
+ "## Output format",
500
+ "Output ALL questions in ONE JSON response. No preamble or explanation.",
501
+ 'Only output the JSON object: { "questions": [{ "id": 1, "question": "...", "options": ["..."] }] }',
502
+ "",
503
+ "## Quantity",
504
+ "Ask 5-12 questions — enough to validate the approach before implementation.",
505
+ "",
506
+ "## Language",
507
+ "Questions and options should be in the same language as the optimization request (default: Chinese).",
508
+ ].join("\n"),
509
+ timeoutMs: 300_000,
510
+ };
511
+
353
512
  // ── Command runner ───────────────────────────────────────────
354
513
 
514
+ /**
515
+ * Run a wizard with an optional Grill phase:
516
+ * Wizard → Assemble → (Grill?) → Send
517
+ */
518
+ async function runWizardWithGrill(
519
+ ctx: ExtensionCommandContext,
520
+ pi: ExtensionAPI,
521
+ type: string,
522
+ label: string,
523
+ questions: Array<{ label: string; placeholder: string; key: string }>,
524
+ assembler: (answers: Record<string, string>) => string,
525
+ grillOptions?: GrillOptions,
526
+ ): Promise<void> {
527
+ ctx.ui.notify(`📋 /dev-${type} — ${label},请逐项填写以下信息(留空跳过对应段落,Esc 取消)`, "info");
528
+
529
+ const answers: Record<string, string> = {};
530
+ for (const q of questions) {
531
+ const val = await ask(ctx, q.label, q.placeholder);
532
+ if (val === undefined) {
533
+ ctx.ui.notify("❌ 已取消", "warning");
534
+ return;
535
+ }
536
+ answers[q.key] = val;
537
+ }
538
+
539
+ const basePrompt = assembler(answers);
540
+
541
+ // ── Grill phase (if agentDef provided) ────────────────────
542
+ let finalPrompt = basePrompt;
543
+ if (grillOptions) {
544
+ const grillResult = await runGrillPhase(basePrompt, ctx, {
545
+ agentDef: grillOptions.agentDef,
546
+ title: grillOptions.title,
547
+ description: grillOptions.description,
548
+ questionTitle: grillOptions.questionTitle,
549
+ loaderLabel: grillOptions.loaderLabel,
550
+ });
551
+ if (grillResult.cancelled) {
552
+ ctx.ui.notify("❌ 操作已取消", "warning");
553
+ return;
554
+ }
555
+ finalPrompt = grillResult.enhancedPrompt;
556
+ }
557
+
558
+ ctx.ui.notify(`✅ 提示词已组装完成,正在发送给主代理...`, "success");
559
+ pi.sendUserMessage(finalPrompt);
560
+ ctx.ui.notify(`📝 /dev-${type} 提示词已投递,主代理正在处理`, "info");
561
+ }
562
+
355
563
  /**
356
564
  * Run a wizard: ask questions, assemble prompt, send to agent.
357
565
  * @param ctx Command context
@@ -414,7 +622,7 @@ const FIX_QUESTIONS = [
414
622
  ];
415
623
 
416
624
  const DOC_QUESTIONS = [
417
- { label: "模块/API 名称", placeholder: "如 AuthService, REST API v2...", key: "moduleName" },
625
+ { label: "模块/API/doc 名称", placeholder: "如 AuthService, REST API v2...", key: "moduleName" },
418
626
  { label: "目标受众", placeholder: "如 小白 / 前端开发者 / 架构师", key: "audience" },
419
627
  { label: "关键信息点", placeholder: "他们需要了解如何使用认证接口", key: "keyInfo" },
420
628
  { label: "示例语言", placeholder: "如 TypeScript, Python, curl...", key: "language" },
@@ -482,64 +690,150 @@ const COMPARE_QUESTIONS = [
482
690
  export default function (pi: ExtensionAPI) {
483
691
  // ── /dev-feat ──────────────────────────────────────────────
484
692
  pi.registerCommand("dev-feat", {
485
- description: "(prompt wizard) 新功能/创意生成 — 交互填写后发送优化提示词给主代理",
486
- handler: async (args, ctx) => {
487
- await runWizard(ctx, pi, "feat", "新功能/创意生成", FEAT_QUESTIONS, assembleFeatPrompt);
693
+ description: "(prompt wizard) 新功能/创意生成 — 支持设计评审 (Grill) + PRD 生成",
694
+ handler: async (_args, ctx) => {
695
+ // ── Phase 1: Wizard ──────────────────────────────────
696
+ ctx.ui.notify("📋 /dev-feat — 新功能/创意生成,请逐项填写以下信息(留空跳过对应段落,Esc 取消)", "info");
697
+
698
+ const answers: Record<string, string> = {};
699
+ for (const q of FEAT_QUESTIONS) {
700
+ const val = await ask(ctx, q.label, q.placeholder);
701
+ if (val === undefined) {
702
+ ctx.ui.notify("❌ 已取消", "warning");
703
+ return;
704
+ }
705
+ answers[q.key] = val;
706
+ }
707
+
708
+ // ── Phase 2: Assemble base prompt ───────────────────
709
+ const basePrompt = assembleFeatPrompt(answers as FeatFields);
710
+ ctx.ui.notify(`✅ 基本信息已收集,共 ${FEAT_QUESTIONS.length} 项`, "success");
711
+
712
+ // ── Phase 3: Grill (设计评审) ───────────────────────
713
+ const grillResult = await runGrillPhase(basePrompt, ctx);
714
+ if (grillResult.cancelled) {
715
+ ctx.ui.notify("❌ 操作已取消", "warning");
716
+ return;
717
+ }
718
+ const finalPrompt = grillResult.enhancedPrompt;
719
+
720
+ // ── Phase 4: Send to main agent ─────────────────────
721
+ ctx.ui.notify(`✅ 提示词已组装完成,正在发送给主代理...`, "success");
722
+ pi.sendUserMessage(finalPrompt);
723
+ ctx.ui.notify(`📝 /dev-feat 提示词已投递,主代理正在处理`, "info");
724
+
725
+ // ── Phase 5: Wait for agent to finish ───────────────
726
+ await ctx.waitForIdle();
727
+
728
+ // ── Phase 6: PRD generation ─────────────────────────
729
+ const moduleHint = (answers as FeatFields).module || "feature";
730
+ const grillContext = finalPrompt;
731
+ await runPRDPhase(grillContext, moduleHint, pi, ctx);
488
732
  },
489
733
  });
490
734
 
491
735
  // ── /dev-fix ───────────────────────────────────────────────
492
736
  pi.registerCommand("dev-fix", {
493
- description: "(prompt wizard) 问题排查/错误修正 — 交互填写后发送优化提示词给主代理",
494
- handler: async (args, ctx) => {
495
- await runWizard(ctx, pi, "fix", "问题排查/错误修正", FIX_QUESTIONS, assembleFixPrompt);
737
+ description: "(prompt wizard) 问题排查/错误修正 — 支持根因分析评审 (Grill)",
738
+ handler: async (_args, ctx) => {
739
+ await runWizardWithGrill(
740
+ ctx, pi, "fix", "问题排查/错误修正",
741
+ FIX_QUESTIONS, assembleFixPrompt,
742
+ {
743
+ agentDef: FIX_GRILL_AGENT_DEF,
744
+ title: "🐛 Bug 根因分析评审",
745
+ description: "是否进入 Bug 根因分析评审 (Grill) 模式?\nAI 会从复现条件、根因推理、修复方案、回归风险等维度挑战你的理解。",
746
+ questionTitle: "Bug 根因分析",
747
+ loaderLabel: "🧠 AI 正在分析代码并生成根因评审问题...",
748
+ },
749
+ );
496
750
  },
497
751
  });
498
752
 
499
753
  // ── /dev-doc ───────────────────────────────────────────────
500
754
  pi.registerCommand("dev-doc", {
501
- description: "(prompt wizard) 文档生成/总结 — 交互填写后发送优化提示词给主代理",
502
- handler: async (args, ctx) => {
503
- await runWizard(ctx, pi, "doc", "文档生成/总结", DOC_QUESTIONS, assembleDocPrompt);
755
+ description: "(prompt wizard) 文档生成/总结 — 支持大纲评审 (Grill)",
756
+ handler: async (_args, ctx) => {
757
+ await runWizardWithGrill(
758
+ ctx, pi, "doc", "文档生成/总结",
759
+ DOC_QUESTIONS, assembleDocPrompt,
760
+ {
761
+ agentDef: DOC_GRILL_AGENT_DEF,
762
+ title: "📄 文档大纲评审",
763
+ description: "是否进入文档大纲评审 (Grill) 模式?\nAI 会从受众定位、结构安排、示例选择等维度审视你的文档计划。",
764
+ questionTitle: "文档大纲评审",
765
+ loaderLabel: "🧠 AI 正在分析并生成文档大纲评审问题...",
766
+ },
767
+ );
504
768
  },
505
769
  });
506
770
 
507
771
  // ── /dev-refactor ──────────────────────────────────────────
508
772
  pi.registerCommand("dev-refactor", {
509
- description: "(prompt wizard) 重构/优化现有结构 — 交互填写后发送优化提示词给主代理",
510
- handler: async (args, ctx) => {
511
- await runWizard(ctx, pi, "refactor", "重构/优化", REFACTOR_QUESTIONS, assembleRefactorPrompt);
773
+ description: "(prompt wizard) 重构/优化现有结构 — 支持重构计划评审 (Grill)",
774
+ handler: async (_args, ctx) => {
775
+ await runWizardWithGrill(
776
+ ctx, pi, "refactor", "重构/优化",
777
+ REFACTOR_QUESTIONS, assembleRefactorPrompt,
778
+ {
779
+ agentDef: REFACTOR_GRILL_AGENT_DEF,
780
+ title: "🔧 重构方案评审",
781
+ description: "是否进入重构方案评审 (Grill) 模式?\nAI 会从模块边界、API 兼容性、测试策略、迁移风险等维度审视你的重构计划。",
782
+ questionTitle: "重构方案评审",
783
+ loaderLabel: "🧠 AI 正在分析代码并生成重构评审问题...",
784
+ },
785
+ );
512
786
  },
513
787
  });
514
788
 
515
789
  // ── /dev-test ──────────────────────────────────────────────
516
790
  pi.registerCommand("dev-test", {
517
- description: "(prompt wizard) 测试用例生成 — 交互填写后发送优化提示词给主代理",
518
- handler: async (args, ctx) => {
519
- await runWizard(ctx, pi, "test", "测试用例/评估", TEST_QUESTIONS, assembleTestPrompt);
791
+ description: "(prompt wizard) 测试用例生成 — 支持测试计划评审 (Grill)",
792
+ handler: async (_args, ctx) => {
793
+ await runWizardWithGrill(
794
+ ctx, pi, "test", "测试用例/评估",
795
+ TEST_QUESTIONS, assembleTestPrompt,
796
+ {
797
+ agentDef: TEST_GRILL_AGENT_DEF,
798
+ title: "🧪 测试计划评审",
799
+ description: "是否进入测试计划评审 (Grill) 模式?\nAI 会从覆盖维度、边界条件、模拟策略等角度审视你的测试方案。",
800
+ questionTitle: "测试计划评审",
801
+ loaderLabel: "🧠 AI 正在分析并生成测试评审问题...",
802
+ },
803
+ );
520
804
  },
521
805
  });
522
806
 
523
807
  // ── /dev-chore ─────────────────────────────────────────────
524
808
  pi.registerCommand("dev-chore", {
525
809
  description: "(prompt wizard) 日常维护/杂项自动化 — 交互填写后发送优化提示词给主代理",
526
- handler: async (args, ctx) => {
810
+ handler: async (_args, ctx) => {
527
811
  await runWizard(ctx, pi, "chore", "日常维护/自动化", CHORE_QUESTIONS, assembleChorePrompt);
528
812
  },
529
813
  });
530
814
 
531
815
  // ── /dev-perf ──────────────────────────────────────────────
532
816
  pi.registerCommand("dev-perf", {
533
- description: "(prompt wizard) 性能优化 — 交互填写后发送优化提示词给主代理",
534
- handler: async (args, ctx) => {
535
- await runWizard(ctx, pi, "perf", "性能优化", PERF_QUESTIONS, assemblePerfPrompt);
817
+ description: "(prompt wizard) 性能优化 — 支持优化方案评审 (Grill)",
818
+ handler: async (_args, ctx) => {
819
+ await runWizardWithGrill(
820
+ ctx, pi, "perf", "性能优化",
821
+ PERF_QUESTIONS, assemblePerfPrompt,
822
+ {
823
+ agentDef: PERF_GRILL_AGENT_DEF,
824
+ title: "⚡ 性能优化方案评审",
825
+ description: "是否进入性能优化方案评审 (Grill) 模式?\nAI 会从基准测试方法、优化方向、回归风险等维度审视你的方案。",
826
+ questionTitle: "性能优化方案评审",
827
+ loaderLabel: "🧠 AI 正在分析并生成性能优化评审问题...",
828
+ },
829
+ );
536
830
  },
537
831
  });
538
832
 
539
833
  // ── /dev-style ─────────────────────────────────────────────
540
834
  pi.registerCommand("dev-style", {
541
835
  description: "(prompt wizard) 风格/格式调整 — 交互填写后发送优化提示词给主代理",
542
- handler: async (args, ctx) => {
836
+ handler: async (_args, ctx) => {
543
837
  await runWizard(ctx, pi, "style", "风格/格式调整", STYLE_QUESTIONS, assembleStylePrompt);
544
838
  },
545
839
  });
@@ -547,7 +841,7 @@ export default function (pi: ExtensionAPI) {
547
841
  // ── /dev-security ──────────────────────────────────────────
548
842
  pi.registerCommand("dev-security", {
549
843
  description: "(prompt wizard) 安全审查 — 交互填写后发送优化提示词给主代理",
550
- handler: async (args, ctx) => {
844
+ handler: async (_args, ctx) => {
551
845
  await runWizard(ctx, pi, "security", "安全审查", SECURITY_QUESTIONS, assembleSecurityPrompt);
552
846
  },
553
847
  });
@@ -555,7 +849,7 @@ export default function (pi: ExtensionAPI) {
555
849
  // ── /dev-explain ───────────────────────────────────────────
556
850
  pi.registerCommand("dev-explain", {
557
851
  description: "(prompt wizard) 概念解释 — 交互填写后发送优化提示词给主代理",
558
- handler: async (args, ctx) => {
852
+ handler: async (_args, ctx) => {
559
853
  await runWizard(ctx, pi, "explain", "概念解释", EXPLAIN_QUESTIONS, assembleExplainPrompt);
560
854
  },
561
855
  });
@@ -563,7 +857,7 @@ export default function (pi: ExtensionAPI) {
563
857
  // ── /dev-compare ───────────────────────────────────────────
564
858
  pi.registerCommand("dev-compare", {
565
859
  description: "(prompt wizard) 对比评估 — 交互填写后发送优化提示词给主代理",
566
- handler: async (args, ctx) => {
860
+ handler: async (_args, ctx) => {
567
861
  await runWizard(ctx, pi, "compare", "对比评估", COMPARE_QUESTIONS, assembleComparePrompt);
568
862
  },
569
863
  });
@@ -47,11 +47,14 @@ function parseGitOutput(output: string): GitSummary {
47
47
  }
48
48
 
49
49
  // Parse <summary>...</summary>
50
- const summaryMatch = output.match(/<summary>([\s\S]*?)<\/summary>/);
50
+ // Anchor to start of line (^ with m flag) to avoid matching a nested
51
+ // <summary> tag inside <details> content before the real top-level summary.
52
+ const summaryMatch = output.match(/^<summary>([\s\S]*?)<\/summary>/m);
51
53
  if (summaryMatch) result.summary = summaryMatch[1].trim();
52
54
 
53
55
  // Parse <details>...</details> → extract each line
54
- const detailsMatch = output.match(/<details>([\s\S]*?)<\/details>/);
56
+ // Anchor to start of line to avoid matching nested <details> inside content.
57
+ const detailsMatch = output.match(/^<details>([\s\S]*?)<\/details>/m);
55
58
  if (detailsMatch) {
56
59
  const lines = detailsMatch[1]
57
60
  .split("\n")