chiefwiggum 1.3.48 → 1.3.51
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/cli.cjs +59 -12
- package/package.json +1 -1
- package/templates/prd-template.md +26 -3
package/dist/cli.cjs
CHANGED
|
@@ -865,6 +865,22 @@ function countOpenGitHubIssues() {
|
|
|
865
865
|
return 0;
|
|
866
866
|
}
|
|
867
867
|
}
|
|
868
|
+
function parsePRDFrontmatter(content) {
|
|
869
|
+
const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
|
|
870
|
+
if (!frontmatterMatch) return null;
|
|
871
|
+
const frontmatter = {};
|
|
872
|
+
const lines = frontmatterMatch[1].split("\n");
|
|
873
|
+
for (const line of lines) {
|
|
874
|
+
const match = line.match(/^(\w+):\s*"?([^"]+)"?$/);
|
|
875
|
+
if (match) {
|
|
876
|
+
const [, key, value] = match;
|
|
877
|
+
if (key === "project" || key === "branch" || key === "priority" || key === "source_plan") {
|
|
878
|
+
frontmatter[key] = value.trim();
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
return Object.keys(frontmatter).length > 0 ? frontmatter : null;
|
|
883
|
+
}
|
|
868
884
|
function findMarkdownFiles(dir, basePath = "") {
|
|
869
885
|
const results = [];
|
|
870
886
|
try {
|
|
@@ -1285,6 +1301,7 @@ async function generateFromPlan(planFile) {
|
|
|
1285
1301
|
const claudeTemplate = (0, import_node_fs3.readFileSync)(`${LOCAL_TEMPLATES_DIR}/CLAUDE-template.md`, "utf-8");
|
|
1286
1302
|
console.log();
|
|
1287
1303
|
console.log(import_picocolors7.default.yellow(`[1/4] Generating ${prdPath}...`));
|
|
1304
|
+
const planFilename = planFile.split("/").pop() || planFile;
|
|
1288
1305
|
const prdPrompt = `You are filling in a PRD template based on a project plan.
|
|
1289
1306
|
|
|
1290
1307
|
Here is the plan:
|
|
@@ -1299,6 +1316,18 @@ ${prdTemplate}
|
|
|
1299
1316
|
|
|
1300
1317
|
Fill in the template with specific details from the plan.
|
|
1301
1318
|
Replace all placeholder text in [brackets] with real content.
|
|
1319
|
+
|
|
1320
|
+
IMPORTANT for YAML frontmatter at the top:
|
|
1321
|
+
- project: Use a short, descriptive project name (e.g., "User Authentication System")
|
|
1322
|
+
- branch: Suggest a git branch name (e.g., "feat/user-auth")
|
|
1323
|
+
- priority: Set to "high", "medium", or "low" based on the plan
|
|
1324
|
+
- source_plan: Set to "${planFilename}"
|
|
1325
|
+
|
|
1326
|
+
For User Stories section:
|
|
1327
|
+
- Each "### Story:" becomes a GitHub Issue
|
|
1328
|
+
- Use P0 for critical, P1 for important, P2 for nice-to-have
|
|
1329
|
+
- Include specific acceptance criteria as checkboxes
|
|
1330
|
+
|
|
1302
1331
|
Write the completed PRD directly to ${prdPath}.
|
|
1303
1332
|
Do NOT ask questions \u2014 infer everything from the plan.`;
|
|
1304
1333
|
await runClaude({ prompt: prdPrompt });
|
|
@@ -1435,8 +1464,14 @@ Create 5-15 issues.${projectName ? ` Add each to project "${projectName}".` : ""
|
|
|
1435
1464
|
} catch {
|
|
1436
1465
|
}
|
|
1437
1466
|
console.log(import_picocolors7.default.dim(" Creating epic from PRD..."));
|
|
1438
|
-
const
|
|
1439
|
-
|
|
1467
|
+
const prdFrontmatter = parsePRDFrontmatter(prdGenerated);
|
|
1468
|
+
let epicTitle;
|
|
1469
|
+
if (prdFrontmatter?.project) {
|
|
1470
|
+
epicTitle = `Epic: ${prdFrontmatter.project}`;
|
|
1471
|
+
} else {
|
|
1472
|
+
const planTitleMatch = planContent.match(/^#\s+(.+)$/m);
|
|
1473
|
+
epicTitle = planTitleMatch ? `Epic: ${planTitleMatch[1]}` : "Epic: Project Implementation";
|
|
1474
|
+
}
|
|
1440
1475
|
const epicBodyInitial = `${prdGenerated}
|
|
1441
1476
|
|
|
1442
1477
|
---
|
|
@@ -1549,14 +1584,23 @@ _Creating issues..._
|
|
|
1549
1584
|
let failed = 0;
|
|
1550
1585
|
const failedIssues = [];
|
|
1551
1586
|
const createdIssueNumbers = [];
|
|
1587
|
+
const supportsInPlace = process.stdout.isTTY && !process.env.SSH_TTY && !process.env.CI;
|
|
1552
1588
|
const loggedMilestones = /* @__PURE__ */ new Set();
|
|
1553
1589
|
for (let i = 0; i < issues.length; i++) {
|
|
1554
1590
|
const issue = issues[i];
|
|
1555
1591
|
const progress = Math.round((i + 1) / total * 100);
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1592
|
+
if (supportsInPlace) {
|
|
1593
|
+
const barWidth = 20;
|
|
1594
|
+
const filled = Math.round(progress / 100 * barWidth);
|
|
1595
|
+
const empty = barWidth - filled;
|
|
1596
|
+
const bar = import_picocolors7.default.green("\u2588".repeat(filled)) + import_picocolors7.default.dim("\u2591".repeat(empty));
|
|
1597
|
+
process.stdout.write(`\r ${bar} ${progress}% (${i + 1}/${total}) Creating: ${issue.title.slice(0, 40)}...`);
|
|
1598
|
+
} else {
|
|
1599
|
+
const milestone = Math.floor(progress / 25) * 25;
|
|
1600
|
+
if (milestone > 0 && !loggedMilestones.has(milestone) && milestone < 100) {
|
|
1601
|
+
console.log(import_picocolors7.default.dim(` ${milestone}% complete (${i + 1}/${total})...`));
|
|
1602
|
+
loggedMilestones.add(milestone);
|
|
1603
|
+
}
|
|
1560
1604
|
}
|
|
1561
1605
|
try {
|
|
1562
1606
|
const validLabels = issue.labels.filter((label) => availableLabels.size === 0 || availableLabels.has(label));
|
|
@@ -1593,20 +1637,20 @@ ${issue.body}`;
|
|
|
1593
1637
|
if (projectNumber && issueUrl) {
|
|
1594
1638
|
try {
|
|
1595
1639
|
const addOutput = (0, import_node_child_process6.execSync)(
|
|
1596
|
-
`gh project item-add ${projectNumber} --owner ${owner} --url "${issueUrl}"`,
|
|
1640
|
+
`gh project item-add ${projectNumber} --owner ${owner} --url "${issueUrl}" --format json`,
|
|
1597
1641
|
{ encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
1598
1642
|
);
|
|
1599
1643
|
if (projectId && statusFieldId && todoOptionId) {
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1644
|
+
try {
|
|
1645
|
+
const addResult = JSON.parse(addOutput);
|
|
1646
|
+
const itemId = addResult.id;
|
|
1647
|
+
if (itemId) {
|
|
1604
1648
|
(0, import_node_child_process6.execSync)(
|
|
1605
1649
|
`gh project item-edit --project-id ${projectId} --id ${itemId} --field-id ${statusFieldId} --single-select-option-id ${todoOptionId}`,
|
|
1606
1650
|
{ stdio: ["pipe", "pipe", "pipe"] }
|
|
1607
1651
|
);
|
|
1608
|
-
} catch {
|
|
1609
1652
|
}
|
|
1653
|
+
} catch {
|
|
1610
1654
|
}
|
|
1611
1655
|
}
|
|
1612
1656
|
} catch {
|
|
@@ -1619,6 +1663,9 @@ ${issue.body}`;
|
|
|
1619
1663
|
failedIssues.push({ title: issue.title, error: errorMsg });
|
|
1620
1664
|
}
|
|
1621
1665
|
}
|
|
1666
|
+
if (supportsInPlace) {
|
|
1667
|
+
process.stdout.write("\r" + " ".repeat(80) + "\r");
|
|
1668
|
+
}
|
|
1622
1669
|
console.log(import_picocolors7.default.green(` \u2713 Created ${created} GitHub Issues`));
|
|
1623
1670
|
if (failed > 0) {
|
|
1624
1671
|
console.log(import_picocolors7.default.yellow(` \u26A0 ${failed} issues failed to create:`));
|
package/package.json
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
project: "[Project Name - short, descriptive title]"
|
|
3
|
+
branch: "[feat/feature-name or fix/bug-name]"
|
|
4
|
+
priority: "[high|medium|low]"
|
|
5
|
+
source_plan: "[filename of the input plan]"
|
|
6
|
+
---
|
|
7
|
+
|
|
1
8
|
# Product Requirements Document
|
|
2
9
|
|
|
3
10
|
## Overview
|
|
@@ -15,9 +22,25 @@
|
|
|
15
22
|
|
|
16
23
|
## User Stories
|
|
17
24
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
25
|
+
<!-- Each story becomes a GitHub Issue. Use this exact format: -->
|
|
26
|
+
|
|
27
|
+
### Story: [Short descriptive title]
|
|
28
|
+
- **Priority**: P0
|
|
29
|
+
- **As a**: [user type]
|
|
30
|
+
- **I want**: [action]
|
|
31
|
+
- **So that**: [benefit]
|
|
32
|
+
- **Acceptance Criteria**:
|
|
33
|
+
- [ ] Criterion 1
|
|
34
|
+
- [ ] Criterion 2
|
|
35
|
+
|
|
36
|
+
### Story: [Another story title]
|
|
37
|
+
- **Priority**: P1
|
|
38
|
+
- **As a**: [user type]
|
|
39
|
+
- **I want**: [action]
|
|
40
|
+
- **So that**: [benefit]
|
|
41
|
+
- **Acceptance Criteria**:
|
|
42
|
+
- [ ] Criterion 1
|
|
43
|
+
- [ ] Criterion 2
|
|
21
44
|
|
|
22
45
|
## Functional Requirements
|
|
23
46
|
|