chiefwiggum 1.3.41 → 1.3.43

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.
Files changed (2) hide show
  1. package/dist/cli.cjs +116 -9
  2. package/package.json +1 -1
package/dist/cli.cjs CHANGED
@@ -1078,16 +1078,32 @@ async function setupProjectConfig() {
1078
1078
  console.log("Make sure you're in a git repo with a GitHub remote.");
1079
1079
  }
1080
1080
  console.log();
1081
+ let exitHint = "Then run chiefwiggum new again";
1082
+ let exitCommand = "";
1083
+ if (ghCheck.reason === "not_installed") {
1084
+ exitHint = "brew install gh (macOS) or apt install gh (Linux)";
1085
+ exitCommand = "gh --version";
1086
+ } else if (ghCheck.reason === "not_authenticated") {
1087
+ exitHint = "gh auth login";
1088
+ exitCommand = "gh auth login";
1089
+ } else if (ghCheck.reason === "not_github_repo") {
1090
+ exitHint = "git remote add origin <url>";
1091
+ exitCommand = "git remote -v";
1092
+ }
1081
1093
  const fallback = await select2({
1082
1094
  message: "What would you like to do?",
1083
1095
  options: [
1084
1096
  { value: "todo", label: "Use TODO.md instead", hint: "Track tasks locally" },
1085
- { value: "exit", label: "Exit and set up gh first", hint: "Then run chiefwiggum new again" }
1097
+ { value: "exit", label: "Exit and set up gh first", hint: exitHint }
1086
1098
  ]
1087
1099
  });
1088
1100
  if (fallback === "exit") {
1089
1101
  console.log();
1090
- console.log(import_picocolors7.default.dim("Run 'chiefwiggum new' again after setting up gh."));
1102
+ if (exitCommand) {
1103
+ console.log(import_picocolors7.default.cyan(` ${exitCommand}`));
1104
+ console.log();
1105
+ }
1106
+ console.log(import_picocolors7.default.dim("Then run 'chiefwiggum new' again."));
1091
1107
  process.exit(0);
1092
1108
  }
1093
1109
  config2.projectTracker = "todo";
@@ -1402,12 +1418,42 @@ Create 5-15 issues.${projectName ? ` Add each to project "${projectName}".` : ""
1402
1418
  }
1403
1419
  if (!usedFallback) {
1404
1420
  const total = issues.length;
1405
- console.log(import_picocolors7.default.dim(` Creating ${total} issues...`));
1421
+ const owner = repoName.split("/")[0];
1422
+ console.log(import_picocolors7.default.dim(" Creating epic from PRD..."));
1423
+ const prdTitleMatch = prdGenerated.match(/^#\s+(.+)$/m);
1424
+ const epicTitle = prdTitleMatch ? `Epic: ${prdTitleMatch[1]}` : "Epic: Project Implementation";
1425
+ const epicBodyInitial = `${prdGenerated}
1426
+
1427
+ ---
1428
+
1429
+ ## Tasks
1430
+
1431
+ _Creating issues..._
1432
+ `;
1433
+ let epicNumber = null;
1434
+ let epicUrl = null;
1435
+ try {
1436
+ const escapeForShell = (str) => {
1437
+ return str.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/`/g, "\\`").replace(/\$/g, "\\$").replace(/!/g, "\\!").replace(/\n/g, "\\n");
1438
+ };
1439
+ const epicCmd = `gh issue create --title "${escapeForShell(epicTitle)}" --body "${escapeForShell(epicBodyInitial)}" --label "epic,chiefwiggum"`;
1440
+ epicUrl = (0, import_node_child_process6.execSync)(epicCmd, {
1441
+ encoding: "utf-8",
1442
+ stdio: ["pipe", "pipe", "pipe"]
1443
+ }).trim();
1444
+ const epicNumMatch = epicUrl.match(/\/issues\/(\d+)$/);
1445
+ epicNumber = epicNumMatch ? parseInt(epicNumMatch[1], 10) : null;
1446
+ if (epicNumber) {
1447
+ console.log(import_picocolors7.default.green(` \u2713 Created epic #${epicNumber}`));
1448
+ }
1449
+ } catch {
1450
+ console.log(import_picocolors7.default.yellow(" Could not create epic issue. Continuing without parent tracking..."));
1451
+ }
1452
+ console.log(import_picocolors7.default.dim(` Creating ${total} child issues...`));
1406
1453
  let projectNumber = null;
1407
1454
  let projectId = null;
1408
1455
  let statusFieldId = null;
1409
1456
  let todoOptionId = null;
1410
- const owner = repoName.split("/")[0];
1411
1457
  if (projectName) {
1412
1458
  try {
1413
1459
  const projectsOutput = (0, import_node_child_process6.execSync)(
@@ -1453,6 +1499,15 @@ Create 5-15 issues.${projectName ? ` Add each to project "${projectName}".` : ""
1453
1499
  } catch {
1454
1500
  }
1455
1501
  }
1502
+ if (epicUrl && projectNumber) {
1503
+ try {
1504
+ (0, import_node_child_process6.execSync)(
1505
+ `gh project item-add ${projectNumber} --owner ${owner} --url "${epicUrl}"`,
1506
+ { stdio: ["pipe", "pipe", "pipe"] }
1507
+ );
1508
+ } catch {
1509
+ }
1510
+ }
1456
1511
  let availableLabels = /* @__PURE__ */ new Set();
1457
1512
  try {
1458
1513
  const labelsOutput = (0, import_node_child_process6.execSync)("gh label list --json name --jq '.[].name'", {
@@ -1467,11 +1522,16 @@ Create 5-15 issues.${projectName ? ` Add each to project "${projectName}".` : ""
1467
1522
  `gh label create chiefwiggum --description "Created by Chief Wiggum CLI" --color "FFA500" 2>/dev/null || true`,
1468
1523
  { stdio: ["pipe", "pipe", "pipe"] }
1469
1524
  );
1525
+ (0, import_node_child_process6.execSync)(
1526
+ `gh label create epic --description "Parent tracking issue" --color "6366F1" 2>/dev/null || true`,
1527
+ { stdio: ["pipe", "pipe", "pipe"] }
1528
+ );
1470
1529
  } catch {
1471
1530
  }
1472
1531
  let created = 0;
1473
1532
  let failed = 0;
1474
1533
  const failedIssues = [];
1534
+ const createdIssueNumbers = [];
1475
1535
  for (let i = 0; i < issues.length; i++) {
1476
1536
  const issue = issues[i];
1477
1537
  const progress = Math.round((i + 1) / total * 100);
@@ -1487,13 +1547,25 @@ Create 5-15 issues.${projectName ? ` Add each to project "${projectName}".` : ""
1487
1547
  const escapeForShell = (str) => {
1488
1548
  return str.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/`/g, "\\`").replace(/\$/g, "\\$").replace(/!/g, "\\!").replace(/\n/g, "\\n");
1489
1549
  };
1490
- const body = escapeForShell(issue.body);
1550
+ let bodyWithEpic = issue.body;
1551
+ if (epicNumber) {
1552
+ bodyWithEpic = `Part of #${epicNumber}
1553
+
1554
+ ---
1555
+
1556
+ ${issue.body}`;
1557
+ }
1558
+ const body = escapeForShell(bodyWithEpic);
1491
1559
  const title = escapeForShell(issue.title);
1492
1560
  const createCmd = `gh issue create --title "${title}" --body "${body}" ${labelsArg}`;
1493
1561
  const issueUrl = (0, import_node_child_process6.execSync)(createCmd, {
1494
1562
  encoding: "utf-8",
1495
1563
  stdio: ["pipe", "pipe", "pipe"]
1496
1564
  }).trim();
1565
+ const issueNumMatch = issueUrl.match(/\/issues\/(\d+)$/);
1566
+ if (issueNumMatch) {
1567
+ createdIssueNumbers.push(parseInt(issueNumMatch[1], 10));
1568
+ }
1497
1569
  if (projectNumber && issueUrl) {
1498
1570
  try {
1499
1571
  const addOutput = (0, import_node_child_process6.execSync)(
@@ -1542,6 +1614,28 @@ Create 5-15 issues.${projectName ? ` Add each to project "${projectName}".` : ""
1542
1614
  console.log(import_picocolors7.default.green(` \u2713 Added to board "${projectName}"`));
1543
1615
  }
1544
1616
  }
1617
+ if (epicNumber && createdIssueNumbers.length > 0) {
1618
+ const escapeForShell = (str) => {
1619
+ return str.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/`/g, "\\`").replace(/\$/g, "\\$").replace(/!/g, "\\!").replace(/\n/g, "\\n");
1620
+ };
1621
+ const tasklist = createdIssueNumbers.map((num) => `- [ ] #${num}`).join("\n");
1622
+ const updatedEpicBody = `${prdGenerated}
1623
+
1624
+ ---
1625
+
1626
+ ## Tasks
1627
+
1628
+ ${tasklist}`;
1629
+ try {
1630
+ (0, import_node_child_process6.execSync)(
1631
+ `gh issue edit ${epicNumber} --body "${escapeForShell(updatedEpicBody)}"`,
1632
+ { stdio: ["pipe", "pipe", "pipe"] }
1633
+ );
1634
+ console.log(import_picocolors7.default.green(` \u2713 Updated epic #${epicNumber} with tasklist`));
1635
+ } catch {
1636
+ console.log(import_picocolors7.default.yellow(` Could not update epic with tasklist`));
1637
+ }
1638
+ }
1545
1639
  } else {
1546
1640
  console.log(import_picocolors7.default.green(" \u2713 GitHub Issues created"));
1547
1641
  if (projectName) {
@@ -1801,7 +1895,7 @@ async function cleanGitHubIssues() {
1801
1895
  let issues = [];
1802
1896
  try {
1803
1897
  const output = (0, import_node_child_process7.execSync)(
1804
- `gh issue list --label chiefwiggum --state open --json number,title,createdAt --limit 100`,
1898
+ `gh issue list --label chiefwiggum --state open --json number,title,createdAt,labels --limit 100`,
1805
1899
  { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
1806
1900
  );
1807
1901
  issues = JSON.parse(output);
@@ -1813,10 +1907,22 @@ async function cleanGitHubIssues() {
1813
1907
  console.log(import_picocolors8.default.dim("No open issues with 'chiefwiggum' label found."));
1814
1908
  return;
1815
1909
  }
1910
+ const isEpic = (i) => i.labels.some((l) => l.name === "epic");
1911
+ const epics = issues.filter(isEpic);
1912
+ const childIssues = issues.filter((i) => !isEpic(i));
1816
1913
  console.log();
1817
1914
  console.log(`Found ${issues.length} issues with 'chiefwiggum' label:`);
1818
- for (const issue of issues) {
1819
- console.log(` ${import_picocolors8.default.cyan(`#${issue.number}`)} - ${issue.title}`);
1915
+ if (epics.length > 0) {
1916
+ console.log(import_picocolors8.default.dim(" Epics:"));
1917
+ for (const issue of epics) {
1918
+ console.log(` ${import_picocolors8.default.magenta(`#${issue.number}`)} ${import_picocolors8.default.bold("\u{1F4CB}")} ${issue.title}`);
1919
+ }
1920
+ }
1921
+ if (childIssues.length > 0) {
1922
+ console.log(import_picocolors8.default.dim(" Tasks:"));
1923
+ for (const issue of childIssues) {
1924
+ console.log(` ${import_picocolors8.default.cyan(`#${issue.number}`)} - ${issue.title}`);
1925
+ }
1820
1926
  }
1821
1927
  console.log();
1822
1928
  const action = await select2({
@@ -1836,7 +1942,8 @@ async function cleanGitHubIssues() {
1836
1942
  message: "Select issues to remove (space to toggle, enter to confirm)",
1837
1943
  options: issues.map((i) => ({
1838
1944
  value: String(i.number),
1839
- label: `#${i.number} - ${i.title}`
1945
+ label: isEpic(i) ? `\u{1F4CB} #${i.number} - ${i.title}` : `#${i.number} - ${i.title}`,
1946
+ hint: isEpic(i) ? "epic" : void 0
1840
1947
  }))
1841
1948
  });
1842
1949
  if (selected.length === 0) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chiefwiggum",
3
- "version": "1.3.41",
3
+ "version": "1.3.43",
4
4
  "description": "Autonomous coding agent CLI. Point it at a plan, watch it build.",
5
5
  "type": "module",
6
6
  "bin": {