chiefwiggum 1.3.21 → 1.3.23
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 +158 -20
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -626,14 +626,27 @@ async function cmdLoop() {
|
|
|
626
626
|
var __dirname = (0, import_node_path2.dirname)((0, import_node_url.fileURLToPath)(importMetaUrl));
|
|
627
627
|
var LOCAL_TEMPLATES_DIR = ".chiefwiggum/templates";
|
|
628
628
|
var CONFIG_FILE = ".chiefwiggum/CLAUDE.md";
|
|
629
|
+
function stripTrailingCommas(json) {
|
|
630
|
+
return json.replace(/,(\s*[}\]])/g, "$1");
|
|
631
|
+
}
|
|
629
632
|
function getConfig() {
|
|
630
633
|
if (!(0, import_node_fs3.existsSync)(CONFIG_FILE)) {
|
|
631
634
|
return { projectTracker: "todo" };
|
|
632
635
|
}
|
|
636
|
+
const raw = (0, import_node_fs3.readFileSync)(CONFIG_FILE, "utf-8");
|
|
633
637
|
try {
|
|
634
|
-
return JSON.parse(
|
|
638
|
+
return JSON.parse(raw);
|
|
635
639
|
} catch {
|
|
636
|
-
|
|
640
|
+
try {
|
|
641
|
+
const fixed = stripTrailingCommas(raw);
|
|
642
|
+
const config2 = JSON.parse(fixed);
|
|
643
|
+
console.log(import_picocolors7.default.yellow("Note: Fixed trailing comma in config file."));
|
|
644
|
+
saveConfig(config2);
|
|
645
|
+
return config2;
|
|
646
|
+
} catch {
|
|
647
|
+
console.log(import_picocolors7.default.yellow("Warning: Could not parse config file. Using defaults."));
|
|
648
|
+
return { projectTracker: "todo" };
|
|
649
|
+
}
|
|
637
650
|
}
|
|
638
651
|
}
|
|
639
652
|
function saveConfig(config2) {
|
|
@@ -818,7 +831,7 @@ function checkGitHubCLI() {
|
|
|
818
831
|
async function setupProjectConfig() {
|
|
819
832
|
const existingConfig = getConfig();
|
|
820
833
|
if ((0, import_node_fs3.existsSync)(CONFIG_FILE)) {
|
|
821
|
-
if (existingConfig.projectTracker === "github" && existingConfig.githubProject
|
|
834
|
+
if (existingConfig.projectTracker === "github" && !existingConfig.githubProject) {
|
|
822
835
|
const ghCheck = checkGitHubCLI();
|
|
823
836
|
if (ghCheck.ok) {
|
|
824
837
|
const projectName = await selectOrCreateProjectBoard(ghCheck.repo);
|
|
@@ -955,6 +968,22 @@ async function selectOrCreateProjectBoard(knownRepo) {
|
|
|
955
968
|
return null;
|
|
956
969
|
}
|
|
957
970
|
} else if (selectedProject !== "__none__") {
|
|
971
|
+
try {
|
|
972
|
+
const projectsOutput = (0, import_node_child_process6.execSync)(
|
|
973
|
+
`gh project list --owner ${repoName.split("/")[0]} --format json`,
|
|
974
|
+
{ encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
975
|
+
);
|
|
976
|
+
const projects = JSON.parse(projectsOutput);
|
|
977
|
+
const project = projects.projects?.find((p2) => p2.title === selectedProject);
|
|
978
|
+
if (project?.number) {
|
|
979
|
+
(0, import_node_child_process6.execSync)(
|
|
980
|
+
`gh project link ${project.number} --owner ${repoName.split("/")[0]} --repo ${repoName}`,
|
|
981
|
+
{ stdio: ["pipe", "pipe", "pipe"] }
|
|
982
|
+
);
|
|
983
|
+
console.log(import_picocolors7.default.green(`\u2713 Linked "${selectedProject}" to ${repoName}`));
|
|
984
|
+
}
|
|
985
|
+
} catch {
|
|
986
|
+
}
|
|
958
987
|
return selectedProject;
|
|
959
988
|
}
|
|
960
989
|
return null;
|
|
@@ -1120,9 +1149,8 @@ Write directly to CLAUDE.md.`;
|
|
|
1120
1149
|
if (projectName) {
|
|
1121
1150
|
console.log(import_picocolors7.default.dim(` Issues will be added to board: ${projectName}`));
|
|
1122
1151
|
}
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
const issuesPrompt = `You are creating GitHub Issues based on specs.
|
|
1152
|
+
console.log(import_picocolors7.default.dim(" Planning issues..."));
|
|
1153
|
+
const issuesPrompt = `You are planning GitHub Issues based on specs.
|
|
1126
1154
|
|
|
1127
1155
|
Here is the PRD:
|
|
1128
1156
|
<prd>
|
|
@@ -1134,21 +1162,102 @@ Here is the Technical Specification:
|
|
|
1134
1162
|
${techGenerated}
|
|
1135
1163
|
</technical>
|
|
1136
1164
|
|
|
1137
|
-
|
|
1165
|
+
Generate a JSON array of issues to create. Each issue should have:
|
|
1166
|
+
- title: Clear, actionable title
|
|
1167
|
+
- body: Description of the task (markdown supported)
|
|
1168
|
+
- labels: Array of labels (e.g., ["phase-1", "enhancement"])
|
|
1169
|
+
|
|
1138
1170
|
Break down the work into granular issues (1-2 hours each).
|
|
1139
1171
|
Group related issues with labels like "phase-1", "phase-2", etc.
|
|
1140
|
-
|
|
1141
|
-
For each issue, run a command like:
|
|
1142
|
-
gh issue create --title "Issue title" --body "Description of the task" --label "phase-1"
|
|
1143
|
-
|
|
1144
|
-
${projectInstruction}
|
|
1145
|
-
|
|
1146
1172
|
Create 5-15 issues covering the full implementation.
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1173
|
+
|
|
1174
|
+
Output ONLY valid JSON, no other text:
|
|
1175
|
+
[
|
|
1176
|
+
{"title": "...", "body": "...", "labels": ["phase-1", "enhancement"]},
|
|
1177
|
+
...
|
|
1178
|
+
]`;
|
|
1179
|
+
const result = await runClaude({ prompt: issuesPrompt });
|
|
1180
|
+
let issues = [];
|
|
1181
|
+
let usedFallback = false;
|
|
1182
|
+
try {
|
|
1183
|
+
const jsonMatch = result.output.match(/\[[\s\S]*\]/);
|
|
1184
|
+
if (jsonMatch) {
|
|
1185
|
+
issues = JSON.parse(jsonMatch[0]);
|
|
1186
|
+
}
|
|
1187
|
+
} catch {
|
|
1188
|
+
}
|
|
1189
|
+
if (issues.length === 0) {
|
|
1190
|
+
console.log(import_picocolors7.default.dim(" Generating issues directly..."));
|
|
1191
|
+
const fallbackPrompt = `Create GitHub Issues using gh CLI for this project.
|
|
1192
|
+
PRD: ${prdGenerated.slice(0, 2e3)}
|
|
1193
|
+
Tech: ${techGenerated.slice(0, 2e3)}
|
|
1194
|
+
Run: gh issue create --title "..." --body "..." --label "phase-1"
|
|
1195
|
+
Create 5-15 issues.${projectName ? ` Add each to project "${projectName}".` : ""}`;
|
|
1196
|
+
await runClaude({ prompt: fallbackPrompt });
|
|
1197
|
+
usedFallback = true;
|
|
1198
|
+
}
|
|
1199
|
+
if (!usedFallback) {
|
|
1200
|
+
const total = issues.length;
|
|
1201
|
+
console.log(import_picocolors7.default.dim(` Creating ${total} issues...`));
|
|
1202
|
+
let projectNumber = null;
|
|
1203
|
+
if (projectName) {
|
|
1204
|
+
try {
|
|
1205
|
+
const projectsOutput = (0, import_node_child_process6.execSync)(
|
|
1206
|
+
`gh project list --owner ${repoName.split("/")[0]} --format json`,
|
|
1207
|
+
{ encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
1208
|
+
);
|
|
1209
|
+
const projects = JSON.parse(projectsOutput);
|
|
1210
|
+
const project = projects.projects?.find((p2) => p2.title === projectName);
|
|
1211
|
+
projectNumber = project?.number?.toString() || null;
|
|
1212
|
+
} catch {
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
let created = 0;
|
|
1216
|
+
let failed = 0;
|
|
1217
|
+
for (let i = 0; i < issues.length; i++) {
|
|
1218
|
+
const issue = issues[i];
|
|
1219
|
+
const progress = Math.round((i + 1) / total * 100);
|
|
1220
|
+
const barWidth = 20;
|
|
1221
|
+
const filled = Math.round(progress / 100 * barWidth);
|
|
1222
|
+
const empty = barWidth - filled;
|
|
1223
|
+
const bar = import_picocolors7.default.green("\u2588".repeat(filled)) + import_picocolors7.default.dim("\u2591".repeat(empty));
|
|
1224
|
+
process.stdout.write(`\r ${bar} ${progress}% (${i + 1}/${total}) Creating: ${issue.title.slice(0, 40)}...`.padEnd(100));
|
|
1225
|
+
try {
|
|
1226
|
+
const labelsArg = issue.labels.length > 0 ? `--label "${issue.labels.join(",")}"` : "";
|
|
1227
|
+
const body = issue.body.replace(/"/g, '\\"').replace(/`/g, "\\`");
|
|
1228
|
+
const title = issue.title.replace(/"/g, '\\"');
|
|
1229
|
+
const createCmd = `gh issue create --title "${title}" --body "${body}" ${labelsArg}`;
|
|
1230
|
+
const issueUrl = (0, import_node_child_process6.execSync)(createCmd, {
|
|
1231
|
+
encoding: "utf-8",
|
|
1232
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
1233
|
+
}).trim();
|
|
1234
|
+
if (projectNumber && issueUrl) {
|
|
1235
|
+
try {
|
|
1236
|
+
(0, import_node_child_process6.execSync)(
|
|
1237
|
+
`gh project item-add ${projectNumber} --owner ${repoName.split("/")[0]} --url "${issueUrl}"`,
|
|
1238
|
+
{ stdio: ["pipe", "pipe", "pipe"] }
|
|
1239
|
+
);
|
|
1240
|
+
} catch {
|
|
1241
|
+
}
|
|
1242
|
+
}
|
|
1243
|
+
created++;
|
|
1244
|
+
} catch {
|
|
1245
|
+
failed++;
|
|
1246
|
+
}
|
|
1247
|
+
}
|
|
1248
|
+
process.stdout.write("\r" + " ".repeat(100) + "\r");
|
|
1249
|
+
console.log(import_picocolors7.default.green(` \u2713 Created ${created} GitHub Issues`));
|
|
1250
|
+
if (failed > 0) {
|
|
1251
|
+
console.log(import_picocolors7.default.yellow(` \u26A0 ${failed} issues failed to create`));
|
|
1252
|
+
}
|
|
1253
|
+
if (projectName && projectNumber) {
|
|
1254
|
+
console.log(import_picocolors7.default.green(` \u2713 Added to board "${projectName}"`));
|
|
1255
|
+
}
|
|
1256
|
+
} else {
|
|
1257
|
+
console.log(import_picocolors7.default.green(" \u2713 GitHub Issues created"));
|
|
1258
|
+
if (projectName) {
|
|
1259
|
+
console.log(import_picocolors7.default.green(` \u2713 Added to board "${projectName}"`));
|
|
1260
|
+
}
|
|
1152
1261
|
}
|
|
1153
1262
|
} else {
|
|
1154
1263
|
console.log();
|
|
@@ -1246,14 +1355,27 @@ var import_node_fs5 = require("fs");
|
|
|
1246
1355
|
var import_node_child_process7 = require("child_process");
|
|
1247
1356
|
var import_picocolors9 = __toESM(require("picocolors"), 1);
|
|
1248
1357
|
var CONFIG_FILE2 = ".chiefwiggum/CLAUDE.md";
|
|
1358
|
+
function stripTrailingCommas2(json) {
|
|
1359
|
+
return json.replace(/,(\s*[}\]])/g, "$1");
|
|
1360
|
+
}
|
|
1249
1361
|
function getConfig2() {
|
|
1250
1362
|
if (!(0, import_node_fs5.existsSync)(CONFIG_FILE2)) {
|
|
1251
1363
|
return { projectTracker: "todo" };
|
|
1252
1364
|
}
|
|
1365
|
+
const raw = (0, import_node_fs5.readFileSync)(CONFIG_FILE2, "utf-8");
|
|
1253
1366
|
try {
|
|
1254
|
-
return JSON.parse(
|
|
1367
|
+
return JSON.parse(raw);
|
|
1255
1368
|
} catch {
|
|
1256
|
-
|
|
1369
|
+
try {
|
|
1370
|
+
const fixed = stripTrailingCommas2(raw);
|
|
1371
|
+
const config2 = JSON.parse(fixed);
|
|
1372
|
+
console.log(import_picocolors9.default.yellow("Note: Fixed trailing comma in config file."));
|
|
1373
|
+
saveConfig2(config2);
|
|
1374
|
+
return config2;
|
|
1375
|
+
} catch {
|
|
1376
|
+
console.log(import_picocolors9.default.yellow("Warning: Could not parse config file. Using defaults."));
|
|
1377
|
+
return { projectTracker: "todo" };
|
|
1378
|
+
}
|
|
1257
1379
|
}
|
|
1258
1380
|
}
|
|
1259
1381
|
function saveConfig2(config2) {
|
|
@@ -1424,6 +1546,22 @@ async function selectOrCreateProjectBoard2(knownRepo) {
|
|
|
1424
1546
|
return null;
|
|
1425
1547
|
}
|
|
1426
1548
|
} else if (selectedProject !== "__none__") {
|
|
1549
|
+
try {
|
|
1550
|
+
const projectsOutput = (0, import_node_child_process7.execSync)(
|
|
1551
|
+
`gh project list --owner ${repoName.split("/")[0]} --format json`,
|
|
1552
|
+
{ encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
1553
|
+
);
|
|
1554
|
+
const projects = JSON.parse(projectsOutput);
|
|
1555
|
+
const project = projects.projects?.find((p2) => p2.title === selectedProject);
|
|
1556
|
+
if (project?.number) {
|
|
1557
|
+
(0, import_node_child_process7.execSync)(
|
|
1558
|
+
`gh project link ${project.number} --owner ${repoName.split("/")[0]} --repo ${repoName}`,
|
|
1559
|
+
{ stdio: ["pipe", "pipe", "pipe"] }
|
|
1560
|
+
);
|
|
1561
|
+
console.log(import_picocolors9.default.green(`\u2713 Linked "${selectedProject}" to ${repoName}`));
|
|
1562
|
+
}
|
|
1563
|
+
} catch {
|
|
1564
|
+
}
|
|
1427
1565
|
return selectedProject;
|
|
1428
1566
|
}
|
|
1429
1567
|
return null;
|