yg-team-cli 2.5.1 → 2.5.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/README.md +7 -0
- package/dist/cli.js +67 -24
- package/dist/cli.js.map +1 -1
- package/dist/index.js +67 -24
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -43,6 +43,13 @@
|
|
|
43
43
|
**v2.5.1** - 修复目录创建 bug
|
|
44
44
|
- **修复**: `FileUtils.write` 现在自动创建父目录,解决 `docs/prd-docs/` 不存在时的写入失败问题
|
|
45
45
|
|
|
46
|
+
**v2.5.2** - init 命令新增 prd-docs 目录
|
|
47
|
+
- **新增**: `team-cli init` 现在默认创建 `docs/prd-docs/` 目录供存放 PRD 需求文档
|
|
48
|
+
|
|
49
|
+
**v2.5.3** - 优化 breakdown 命令合并逻辑
|
|
50
|
+
- **改进**: `breakdown` 现在仅请求生成里程碑部分,并精确合并到原 Spec 文件
|
|
51
|
+
- **修复**: 解决了 `breakdown` 命令可能会覆盖原文件技术设计内容的问题 (防止 Claude 的内容截断)
|
|
52
|
+
|
|
46
53
|
**v2.4.10** - 修复 Claude 返回权限确认而非实际内容问题
|
|
47
54
|
- **修复**: 添加 `--dangerously-skip-permissions` 参数跳过权限确认
|
|
48
55
|
- **问题**: v2.4.9 中 Claude CLI 在新目录首次运行时返回权限确认提示而非 spec 内容
|
package/dist/cli.js
CHANGED
|
@@ -1702,6 +1702,7 @@ frontend/
|
|
|
1702
1702
|
\u2514\u2500\u2500 public/ # \u9759\u6001\u8D44\u6E90
|
|
1703
1703
|
|
|
1704
1704
|
docs/
|
|
1705
|
+
\u251C\u2500\u2500 prd-docs/ # PRD \u9700\u6C42\u6587\u6863
|
|
1705
1706
|
\u251C\u2500\u2500 specs/ # \u529F\u80FD\u89C4\u683C\u6587\u6863
|
|
1706
1707
|
\u251C\u2500\u2500 api/ # API \u6587\u6863
|
|
1707
1708
|
\u2514\u2500\u2500 sessions/ # \u5F00\u53D1\u4F1A\u8BDD\u8BB0\u5F55
|
|
@@ -2367,6 +2368,7 @@ var init_init = __esm({
|
|
|
2367
2368
|
task: async () => {
|
|
2368
2369
|
await FileUtils.ensureDir(projectPath);
|
|
2369
2370
|
await FileUtils.ensureDir(path7.join(projectPath, "docs/specs"));
|
|
2371
|
+
await FileUtils.ensureDir(path7.join(projectPath, "docs/prd-docs"));
|
|
2370
2372
|
await FileUtils.ensureDir(path7.join(projectPath, "docs/api"));
|
|
2371
2373
|
await FileUtils.ensureDir(path7.join(projectPath, "docs/sessions"));
|
|
2372
2374
|
}
|
|
@@ -2515,6 +2517,58 @@ import { Command as Command2 } from "commander";
|
|
|
2515
2517
|
import inquirer2 from "inquirer";
|
|
2516
2518
|
import path8 from "path";
|
|
2517
2519
|
import { Listr as Listr2 } from "listr2";
|
|
2520
|
+
function mergeMilestones(original, milestones) {
|
|
2521
|
+
const milestoneHeader = "## \u91CC\u7A0B\u7891 (Milestones)";
|
|
2522
|
+
const lines = original.split("\n");
|
|
2523
|
+
const headerIndex = lines.findIndex((l) => l.trim().startsWith(milestoneHeader));
|
|
2524
|
+
let cleanedMilestones = milestones.trim();
|
|
2525
|
+
if (!cleanedMilestones.startsWith("## ")) {
|
|
2526
|
+
const firstHeaderIndex = cleanedMilestones.indexOf("## ");
|
|
2527
|
+
if (firstHeaderIndex !== -1) {
|
|
2528
|
+
cleanedMilestones = cleanedMilestones.substring(firstHeaderIndex);
|
|
2529
|
+
} else {
|
|
2530
|
+
cleanedMilestones = `${milestoneHeader}
|
|
2531
|
+
|
|
2532
|
+
${cleanedMilestones}`;
|
|
2533
|
+
}
|
|
2534
|
+
}
|
|
2535
|
+
if (headerIndex !== -1) {
|
|
2536
|
+
const beforePart = lines.slice(0, headerIndex).join("\n");
|
|
2537
|
+
const afterPart = lines.slice(headerIndex + 1);
|
|
2538
|
+
const nextHeaderIndex = afterPart.findIndex((l) => l.trim().startsWith("## "));
|
|
2539
|
+
if (nextHeaderIndex !== -1) {
|
|
2540
|
+
const remaining = afterPart.slice(nextHeaderIndex).join("\n");
|
|
2541
|
+
return `${beforePart.trim()}
|
|
2542
|
+
|
|
2543
|
+
${cleanedMilestones}
|
|
2544
|
+
|
|
2545
|
+
${remaining.trim()}`;
|
|
2546
|
+
} else {
|
|
2547
|
+
return `${beforePart.trim()}
|
|
2548
|
+
|
|
2549
|
+
${cleanedMilestones}`;
|
|
2550
|
+
}
|
|
2551
|
+
}
|
|
2552
|
+
const techDesignHeader = "## \u6280\u672F\u8BBE\u8BA1";
|
|
2553
|
+
const techIndex = lines.findIndex((l) => l.trim().startsWith(techDesignHeader));
|
|
2554
|
+
if (techIndex !== -1) {
|
|
2555
|
+
const afterTech = lines.slice(techIndex + 1);
|
|
2556
|
+
const nextHeaderIndex = afterTech.findIndex((l) => l.trim().startsWith("## "));
|
|
2557
|
+
if (nextHeaderIndex !== -1) {
|
|
2558
|
+
const splitPoint = techIndex + 1 + nextHeaderIndex;
|
|
2559
|
+
const before = lines.slice(0, splitPoint).join("\n");
|
|
2560
|
+
const after = lines.slice(splitPoint).join("\n");
|
|
2561
|
+
return `${before.trim()}
|
|
2562
|
+
|
|
2563
|
+
${cleanedMilestones}
|
|
2564
|
+
|
|
2565
|
+
${after.trim()}`;
|
|
2566
|
+
}
|
|
2567
|
+
}
|
|
2568
|
+
return `${original.trim()}
|
|
2569
|
+
|
|
2570
|
+
${cleanedMilestones}`;
|
|
2571
|
+
}
|
|
2518
2572
|
function buildBreakdownPrompt(specContent) {
|
|
2519
2573
|
return `Role: Senior Technical Lead and Agile Coach
|
|
2520
2574
|
|
|
@@ -2532,18 +2586,21 @@ ${specContent}
|
|
|
2532
2586
|
\`\`\`
|
|
2533
2587
|
|
|
2534
2588
|
Output Requirements:
|
|
2535
|
-
1. Parse the existing spec content
|
|
2536
|
-
2. Break it down into 2-5 milestones
|
|
2589
|
+
1. Parse the existing spec content and identify technical requirements.
|
|
2590
|
+
2. Break it down into 2-5 milestones.
|
|
2537
2591
|
3. Each milestone should have:
|
|
2538
2592
|
- Clear name and objective
|
|
2539
2593
|
- Estimated days (1-3 days per milestone)
|
|
2540
2594
|
- Todo list with 3-8 actionable items
|
|
2541
2595
|
4. Todo items should be:
|
|
2542
|
-
- Concrete and
|
|
2543
|
-
-
|
|
2544
|
-
- Independent as much as possible
|
|
2596
|
+
- Concrete, specific, and testable.
|
|
2597
|
+
- Independent as much as possible.
|
|
2545
2598
|
|
|
2546
|
-
|
|
2599
|
+
IMPORTANT:
|
|
2600
|
+
- Output ONLY the "## \u91CC\u7A0B\u7891 (Milestones)" section.
|
|
2601
|
+
- Do NOT output the entire spec file.
|
|
2602
|
+
- Do NOT output any preamble or postamble text.
|
|
2603
|
+
- Follow this exact format:
|
|
2547
2604
|
|
|
2548
2605
|
\`\`\`markdown
|
|
2549
2606
|
## \u91CC\u7A0B\u7891 (Milestones)
|
|
@@ -2557,24 +2614,9 @@ Format the milestones section as:
|
|
|
2557
2614
|
- [ ] Todo 3 - \u5177\u4F53\u53EF\u6267\u884C\u7684\u4EFB\u52A1
|
|
2558
2615
|
|
|
2559
2616
|
### Milestone 2: [\u91CC\u7A0B\u7891\u540D\u79F0]
|
|
2560
|
-
|
|
2561
|
-
**\u9884\u4F30**: 3 \u5929
|
|
2562
|
-
|
|
2563
|
-
- [ ] Todo 1
|
|
2564
|
-
- [ ] Todo 2
|
|
2565
|
-
- [ ] Todo 3
|
|
2566
|
-
- [ ] Todo 4
|
|
2617
|
+
...
|
|
2567
2618
|
\`\`\`
|
|
2568
|
-
|
|
2569
|
-
Important Instructions:
|
|
2570
|
-
1. Update the spec file directly with the milestone breakdown
|
|
2571
|
-
2. Keep all existing content, just add/update the milestones section
|
|
2572
|
-
3. If milestones section exists, replace it with new breakdown
|
|
2573
|
-
4. If milestones section doesn't exist, add it after "\u6280\u672F\u8BBE\u8BA1" section
|
|
2574
|
-
5. After updating the file, exit immediately
|
|
2575
|
-
6. Do not ask any questions
|
|
2576
|
-
7. Make sure todos are actionable and can be completed independently
|
|
2577
|
-
8. Consider dependencies when ordering todos within a milestone`;
|
|
2619
|
+
`;
|
|
2578
2620
|
}
|
|
2579
2621
|
var breakdownCommand;
|
|
2580
2622
|
var init_breakdown = __esm({
|
|
@@ -2667,7 +2709,8 @@ var init_breakdown = __esm({
|
|
|
2667
2709
|
{
|
|
2668
2710
|
title: "\u66F4\u65B0 spec \u6587\u4EF6",
|
|
2669
2711
|
task: async (ctx) => {
|
|
2670
|
-
|
|
2712
|
+
const mergedContent = mergeMilestones(ctx.specContent, ctx.breakdownResult);
|
|
2713
|
+
await FileUtils.write(ctx.selectedFile, mergedContent);
|
|
2671
2714
|
}
|
|
2672
2715
|
}
|
|
2673
2716
|
]);
|