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.
- package/dist/cli.cjs +112 -22
- 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
|
-
|
|
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
|
-
|
|
499
|
-
|
|
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
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
if (
|
|
599
|
-
|
|
600
|
-
|
|
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(`
|
|
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 (!
|
|
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(
|
|
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:
|
|
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'" },
|