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 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 planTitleMatch = planContent.match(/^#\s+(.+)$/m);
1439
- const epicTitle = planTitleMatch ? `Epic: ${planTitleMatch[1]}` : "Epic: Project Implementation";
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
- const milestone = Math.floor(progress / 25) * 25;
1557
- if (milestone > 0 && !loggedMilestones.has(milestone) && milestone < 100) {
1558
- console.log(import_picocolors7.default.dim(` ${milestone}% complete (${i + 1}/${total})...`));
1559
- loggedMilestones.add(milestone);
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
- const itemIdMatch = addOutput.match(/Added item\s+(\S+)/i);
1601
- const itemId = itemIdMatch?.[1];
1602
- if (itemId) {
1603
- try {
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,6 +1,6 @@
1
1
  {
2
2
  "name": "chiefwiggum",
3
- "version": "1.3.48",
3
+ "version": "1.3.51",
4
4
  "description": "Autonomous coding agent CLI. Point it at a plan, watch it build.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -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
- ### As a [user type]
19
- - I want to [action]
20
- - So that [benefit]
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