chiefwiggum 1.3.28 → 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 +111 -15
  2. package/package.json +1 -1
package/dist/cli.cjs CHANGED
@@ -489,8 +489,8 @@ async function runClaude(options) {
489
489
  });
490
490
  });
491
491
  }
492
- async function runTaskIteration(iteration) {
493
- 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.
494
494
 
495
495
  ## Before Starting
496
496
  Read these files to understand the project:
@@ -516,6 +516,38 @@ Read these files to understand the project:
516
516
  ## When Done
517
517
  Output: RALPH_COMPLETE
518
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();
519
551
  let lastResult = {
520
552
  success: false,
521
553
  output: "",
@@ -569,6 +601,28 @@ function hasUncheckedTasks() {
569
601
  const content = (0, import_node_fs2.readFileSync)(config.todoFile, "utf-8");
570
602
  return /^\s*-\s*\[\s\]/m.test(content);
571
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
+ }
572
626
  function getCurrentCommit() {
573
627
  try {
574
628
  return (0, import_node_child_process5.execSync)("git rev-parse HEAD", { encoding: "utf-8" }).trim();
@@ -584,19 +638,36 @@ function pushToOrigin() {
584
638
  }
585
639
  }
586
640
  async function cmdLoop() {
587
- if (!(0, import_node_fs2.existsSync)(config.todoFile)) {
588
- console.log(import_picocolors6.default.red(`Missing ${config.todoFile}`));
589
- process.exit(1);
590
- }
591
- const maxIterations = countUncheckedTasks();
592
- if (maxIterations === 0) {
593
- console.log(import_picocolors6.default.green(`No unchecked tasks in ${config.todoFile}. All done!`));
594
- 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
+ }
595
666
  }
596
667
  console.log();
597
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"));
598
669
  console.log(import_picocolors6.default.green(" Starting Build Loop"));
599
- console.log(import_picocolors6.default.green(` Tasks remaining: ${maxIterations}`));
670
+ console.log(import_picocolors6.default.green(` ${trackerLabel} remaining: ${maxIterations}`));
600
671
  console.log(import_picocolors6.default.green(` Timeout: ${config.iterationTimeoutMinutes}m per task`));
601
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"));
602
673
  let consecutiveFailures = 0;
@@ -607,7 +678,7 @@ async function cmdLoop() {
607
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`));
608
679
  cleanupStaleProcesses();
609
680
  const startTime = Date.now();
610
- const result = await runTaskIteration(i);
681
+ const result = await runTaskIteration(i, isGitHub);
611
682
  const duration = Math.round((Date.now() - startTime) / 1e3);
612
683
  console.log();
613
684
  console.log(`Completed in ${duration}s (exit: ${result.success ? 0 : 1})`);
@@ -638,10 +709,10 @@ async function cmdLoop() {
638
709
  console.log(import_picocolors6.default.red(`Stopping: No commits for ${config.maxNoCommitCycles} cycles`));
639
710
  process.exit(1);
640
711
  }
641
- if (!hasUncheckedTasks()) {
712
+ if (!hasRemainingTasks()) {
642
713
  console.log();
643
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"));
644
- console.log(import_picocolors6.default.green(" All tasks completed!"));
715
+ console.log(import_picocolors6.default.green(` All ${trackerLabel.toLowerCase()} completed!`));
645
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"));
646
717
  pushToOrigin();
647
718
  process.exit(0);
@@ -689,6 +760,22 @@ function getProjectTracker() {
689
760
  function getGithubProject() {
690
761
  return getConfig().githubProject;
691
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
+ }
692
779
  var BUNDLED_TEMPLATES_DIR = (0, import_node_path2.join)(__dirname, "..", "templates");
693
780
  var SKIP_DIRS = /* @__PURE__ */ new Set([
694
781
  "node_modules",
@@ -777,8 +864,17 @@ async function cmdNew(planFile) {
777
864
  break;
778
865
  }
779
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
+ }
780
876
  const startChoice = await select2({
781
- message: "Ready to start. What would you like to do?",
877
+ message: `Ready to start (${taskInfo}). What would you like to do?`,
782
878
  options: [
783
879
  { value: "start", label: "Start the build loop now" },
784
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.28",
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": {