chiefwiggum 1.3.27 → 1.3.29

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 +112 -22
  2. package/package.json +1 -1
package/dist/cli.cjs CHANGED
@@ -227,16 +227,10 @@ var TEXT_BANNER = `
227
227
  ${import_picocolors2.default.yellow("\u2591\u2588\u2580\u2580\u2591\u2588\u2591\u2588\u2591\u2580\u2588\u2580\u2591\u2588\u2580\u2580\u2591\u2588\u2580\u2580\u2591\u2591\u2591\u2588\u2591\u2588\u2591\u2580\u2588\u2580\u2591\u2588\u2580\u2580\u2591\u2588\u2580\u2580\u2591\u2588\u2591\u2588\u2591\u2588\u2584\u2588")}
228
228
  ${import_picocolors2.default.yellow("\u2591\u2588\u2591\u2591\u2591\u2588\u2580\u2588\u2591\u2591\u2588\u2591\u2591\u2588\u2580\u2580\u2591\u2588\u2580\u2580\u2591\u2591\u2591\u2588\u2584\u2588\u2591\u2591\u2588\u2591\u2591\u2588\u2591\u2588\u2591\u2588\u2591\u2588\u2591\u2588\u2591\u2588\u2591\u2588\u2591\u2588")}
229
229
  ${import_picocolors2.default.yellow("\u2591\u2580\u2580\u2580\u2591\u2580\u2591\u2580\u2591\u2580\u2580\u2580\u2591\u2580\u2580\u2580\u2591\u2580\u2591\u2591\u2591\u2591\u2591\u2580\u2591\u2580\u2591\u2580\u2580\u2580\u2591\u2580\u2580\u2580\u2591\u2580\u2580\u2580\u2591\u2580\u2580\u2580\u2591\u2580\u2591\u2580")}`;
230
- function centerText(text3, width) {
231
- const padding = Math.max(0, Math.floor((width - text3.length) / 2));
232
- return " ".repeat(padding) + text3;
233
- }
234
230
  function createBanner() {
235
231
  const artLines = WIGGUM_ART.split("\n").filter((line) => line.length > 0);
236
232
  const textLines = TEXT_BANNER.split("\n").filter((line) => line.length > 0);
237
- const artWidth = 75;
238
- const centeredText = textLines.map((line) => centerText(line, artWidth)).join("\n");
239
- return import_picocolors2.default.yellow(artLines.join("\n")) + "\n" + centeredText;
233
+ return import_picocolors2.default.yellow(artLines.join("\n")) + "\n\n" + textLines.join("\n");
240
234
  }
241
235
  var BANNER = createBanner();
242
236
  async function checkForUpdates(currentVersion) {
@@ -495,8 +489,8 @@ async function runClaude(options) {
495
489
  });
496
490
  });
497
491
  }
498
- async function runTaskIteration(iteration) {
499
- const taskPrompt = `You are an autonomous coding agent. Complete ONE task from TODO.md.
492
+ function getTodoTaskPrompt() {
493
+ return `You are an autonomous coding agent. Complete ONE task from TODO.md.
500
494
 
501
495
  ## Before Starting
502
496
  Read these files to understand the project:
@@ -522,6 +516,38 @@ Read these files to understand the project:
522
516
  ## When Done
523
517
  Output: RALPH_COMPLETE
524
518
  If no tasks remain: RALPH_ALL_DONE`;
519
+ }
520
+ function getGitHubTaskPrompt() {
521
+ return `You are an autonomous coding agent. Complete ONE GitHub Issue.
522
+
523
+ ## Before Starting
524
+ Read these files to understand the project:
525
+ - CLAUDE.md \u2014 Project context and conventions
526
+ - specs/prd.md \u2014 What we are building
527
+ - specs/technical.md \u2014 How we are building it
528
+
529
+ Then list open issues: gh issue list --state open
530
+
531
+ ## Workflow
532
+ 1. Pick the FIRST open issue (lowest number)
533
+ 2. Read the issue: gh issue view <number>
534
+ 3. Implement the code
535
+ 4. Close the issue: gh issue close <number> --comment "Completed"
536
+ 5. Commit: git commit -m "type(scope): description (closes #<number>)"
537
+
538
+ ## Rules
539
+ - ONE issue per iteration
540
+ - Follow existing code patterns
541
+ - Use conventional commits (feat, fix, docs, refactor, test, chore)
542
+ - Include "closes #N" in commit message to link the commit
543
+ - If blocked after 3 attempts, output RALPH_BLOCKED: <reason>
544
+
545
+ ## When Done
546
+ Output: RALPH_COMPLETE
547
+ If no issues remain: RALPH_ALL_DONE`;
548
+ }
549
+ async function runTaskIteration(iteration, useGitHub = false) {
550
+ const taskPrompt = useGitHub ? getGitHubTaskPrompt() : getTodoTaskPrompt();
525
551
  let lastResult = {
526
552
  success: false,
527
553
  output: "",
@@ -575,6 +601,28 @@ function hasUncheckedTasks() {
575
601
  const content = (0, import_node_fs2.readFileSync)(config.todoFile, "utf-8");
576
602
  return /^\s*-\s*\[\s\]/m.test(content);
577
603
  }
604
+ function countOpenIssues() {
605
+ try {
606
+ const output = (0, import_node_child_process5.execSync)(
607
+ "gh issue list --state open --json number --jq 'length'",
608
+ { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"], timeout: 3e4 }
609
+ );
610
+ return parseInt(output.trim(), 10) || 0;
611
+ } catch {
612
+ return 0;
613
+ }
614
+ }
615
+ function hasOpenIssues() {
616
+ try {
617
+ const output = (0, import_node_child_process5.execSync)(
618
+ "gh issue list --state open --limit 1 --json number --jq 'length'",
619
+ { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"], timeout: 3e4 }
620
+ );
621
+ return parseInt(output.trim(), 10) > 0;
622
+ } catch {
623
+ return false;
624
+ }
625
+ }
578
626
  function getCurrentCommit() {
579
627
  try {
580
628
  return (0, import_node_child_process5.execSync)("git rev-parse HEAD", { encoding: "utf-8" }).trim();
@@ -590,19 +638,36 @@ function pushToOrigin() {
590
638
  }
591
639
  }
592
640
  async function cmdLoop() {
593
- if (!(0, import_node_fs2.existsSync)(config.todoFile)) {
594
- console.log(import_picocolors6.default.red(`Missing ${config.todoFile}`));
595
- process.exit(1);
596
- }
597
- const maxIterations = countUncheckedTasks();
598
- if (maxIterations === 0) {
599
- console.log(import_picocolors6.default.green(`No unchecked tasks in ${config.todoFile}. All done!`));
600
- process.exit(0);
641
+ const tracker = getProjectTracker();
642
+ const isGitHub = tracker === "github";
643
+ let maxIterations;
644
+ let hasRemainingTasks;
645
+ let trackerLabel;
646
+ if (isGitHub) {
647
+ maxIterations = countOpenIssues();
648
+ hasRemainingTasks = hasOpenIssues;
649
+ trackerLabel = "Issues";
650
+ if (maxIterations === 0) {
651
+ console.log(import_picocolors6.default.green("No open GitHub Issues. All done!"));
652
+ process.exit(0);
653
+ }
654
+ } else {
655
+ if (!(0, import_node_fs2.existsSync)(config.todoFile)) {
656
+ console.log(import_picocolors6.default.red(`Missing ${config.todoFile}`));
657
+ process.exit(1);
658
+ }
659
+ maxIterations = countUncheckedTasks();
660
+ hasRemainingTasks = hasUncheckedTasks;
661
+ trackerLabel = "Tasks";
662
+ if (maxIterations === 0) {
663
+ console.log(import_picocolors6.default.green(`No unchecked tasks in ${config.todoFile}. All done!`));
664
+ process.exit(0);
665
+ }
601
666
  }
602
667
  console.log();
603
668
  console.log(import_picocolors6.default.green("\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"));
604
669
  console.log(import_picocolors6.default.green(" Starting Build Loop"));
605
- console.log(import_picocolors6.default.green(` Tasks remaining: ${maxIterations}`));
670
+ console.log(import_picocolors6.default.green(` ${trackerLabel} remaining: ${maxIterations}`));
606
671
  console.log(import_picocolors6.default.green(` Timeout: ${config.iterationTimeoutMinutes}m per task`));
607
672
  console.log(import_picocolors6.default.green("\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"));
608
673
  let consecutiveFailures = 0;
@@ -613,7 +678,7 @@ async function cmdLoop() {
613
678
  console.log(import_picocolors6.default.yellow(`\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 Task ${i} of ${maxIterations} \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550`));
614
679
  cleanupStaleProcesses();
615
680
  const startTime = Date.now();
616
- const result = await runTaskIteration(i);
681
+ const result = await runTaskIteration(i, isGitHub);
617
682
  const duration = Math.round((Date.now() - startTime) / 1e3);
618
683
  console.log();
619
684
  console.log(`Completed in ${duration}s (exit: ${result.success ? 0 : 1})`);
@@ -644,10 +709,10 @@ async function cmdLoop() {
644
709
  console.log(import_picocolors6.default.red(`Stopping: No commits for ${config.maxNoCommitCycles} cycles`));
645
710
  process.exit(1);
646
711
  }
647
- if (!hasUncheckedTasks()) {
712
+ if (!hasRemainingTasks()) {
648
713
  console.log();
649
714
  console.log(import_picocolors6.default.green("\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"));
650
- console.log(import_picocolors6.default.green(" All tasks completed!"));
715
+ console.log(import_picocolors6.default.green(` All ${trackerLabel.toLowerCase()} completed!`));
651
716
  console.log(import_picocolors6.default.green("\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"));
652
717
  pushToOrigin();
653
718
  process.exit(0);
@@ -695,6 +760,22 @@ function getProjectTracker() {
695
760
  function getGithubProject() {
696
761
  return getConfig().githubProject;
697
762
  }
763
+ function countTodoTasks() {
764
+ if (!(0, import_node_fs3.existsSync)(config.todoFile)) return 0;
765
+ const content = (0, import_node_fs3.readFileSync)(config.todoFile, "utf-8");
766
+ return (content.match(/^\s*-\s*\[\s\]/gm) || []).length;
767
+ }
768
+ function countOpenGitHubIssues() {
769
+ try {
770
+ const output = (0, import_node_child_process6.execSync)(
771
+ "gh issue list --state open --json number --jq 'length'",
772
+ { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"], timeout: 3e4 }
773
+ );
774
+ return parseInt(output.trim(), 10) || 0;
775
+ } catch {
776
+ return 0;
777
+ }
778
+ }
698
779
  var BUNDLED_TEMPLATES_DIR = (0, import_node_path2.join)(__dirname, "..", "templates");
699
780
  var SKIP_DIRS = /* @__PURE__ */ new Set([
700
781
  "node_modules",
@@ -783,8 +864,17 @@ async function cmdNew(planFile) {
783
864
  break;
784
865
  }
785
866
  console.log();
867
+ const tracker = getProjectTracker();
868
+ let taskInfo;
869
+ if (tracker === "github") {
870
+ const count = countOpenGitHubIssues();
871
+ const projectName = getGithubProject();
872
+ taskInfo = projectName ? `${count} issues, ${projectName}` : `${count} issues, GitHub`;
873
+ } else {
874
+ taskInfo = `${countTodoTasks()} tasks, TODO.md`;
875
+ }
786
876
  const startChoice = await select2({
787
- message: "Ready to start. What would you like to do?",
877
+ message: `Ready to start (${taskInfo}). What would you like to do?`,
788
878
  options: [
789
879
  { value: "start", label: "Start the build loop now" },
790
880
  { value: "review", label: "Review files first, then start manually with 'chiefwiggum loop'" },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chiefwiggum",
3
- "version": "1.3.27",
3
+ "version": "1.3.29",
4
4
  "description": "Autonomous coding agent CLI. Point it at a plan, watch it build.",
5
5
  "type": "module",
6
6
  "bin": {