@rotorsoft/gent 1.12.1 → 1.13.0

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/index.js CHANGED
@@ -14,7 +14,6 @@ import {
14
14
  createIssue,
15
15
  createPullRequest,
16
16
  createSpinner,
17
- extractPriorityFromLabels,
18
17
  extractTypeFromLabels,
19
18
  generateDefaultConfig,
20
19
  getConfigPath,
@@ -26,6 +25,7 @@ import {
26
25
  getWorkflowLabels,
27
26
  isValidIssueNumber,
28
27
  listIssues,
28
+ listOpenPrs,
29
29
  loadAgentInstructions,
30
30
  loadConfig,
31
31
  logger,
@@ -35,7 +35,7 @@ import {
35
35
  sortByPriority,
36
36
  updateIssueLabels,
37
37
  withSpinner
38
- } from "./chunk-UWYWIOYZ.js";
38
+ } from "./chunk-KLHUMY5L.js";
39
39
 
40
40
  // src/index.ts
41
41
  import { Command } from "commander";
@@ -196,7 +196,7 @@ async function initCommand(options) {
196
196
  }
197
197
  ]);
198
198
  if (setupLabels) {
199
- const { setupLabelsCommand: setupLabelsCommand2 } = await import("./setup-labels-5EHRPUPF.js");
199
+ const { setupLabelsCommand: setupLabelsCommand2 } = await import("./setup-labels-3ANC76NF.js");
200
200
  await setupLabelsCommand2();
201
201
  }
202
202
  }
@@ -808,105 +808,6 @@ Next steps:
808
808
 
809
809
  // src/commands/list.ts
810
810
  import chalk2 from "chalk";
811
- async function listCommand(options) {
812
- const isAuthed = await checkGhAuth();
813
- if (!isAuthed) {
814
- logger.error("Not authenticated with GitHub. Run 'gh auth login' first.");
815
- process.exit(1);
816
- }
817
- const config = loadConfig();
818
- const workflowLabels = getWorkflowLabels(config);
819
- const labels = [];
820
- if (options.label) {
821
- labels.push(options.label);
822
- }
823
- if (options.status && options.status !== "all") {
824
- switch (options.status) {
825
- case "ready":
826
- labels.push(workflowLabels.ready);
827
- break;
828
- case "in-progress":
829
- labels.push(workflowLabels.inProgress);
830
- break;
831
- case "completed":
832
- labels.push(workflowLabels.completed);
833
- break;
834
- case "blocked":
835
- labels.push(workflowLabels.blocked);
836
- break;
837
- }
838
- } else if (!options.status) {
839
- labels.push(workflowLabels.ready);
840
- }
841
- let issues;
842
- try {
843
- issues = await listIssues({
844
- labels: labels.length > 0 ? labels : void 0,
845
- state: "open",
846
- limit: options.limit || 20
847
- });
848
- } catch (error) {
849
- logger.error(`Failed to fetch issues: ${error}`);
850
- return;
851
- }
852
- if (issues.length === 0) {
853
- logger.info("No issues found matching the criteria.");
854
- return;
855
- }
856
- sortByPriority(issues);
857
- logger.bold(`Found ${issues.length} issue(s):`);
858
- logger.newline();
859
- for (const issue of issues) {
860
- const type = extractTypeFromLabels(issue.labels);
861
- const priority = extractPriorityFromLabels(issue.labels);
862
- const status = getIssueStatus(issue.labels, workflowLabels);
863
- const priorityColor = getPriorityColor(priority);
864
- const statusColor = getStatusColor(status);
865
- console.log(
866
- ` ${colors.issue(`#${issue.number.toString().padStart(4)}`)} ${priorityColor(`[${priority}]`.padEnd(10))} ${statusColor(`[${status}]`.padEnd(14))} ${colors.label(`[${type}]`.padEnd(10))} ` + issue.title.slice(0, 50) + (issue.title.length > 50 ? "..." : "")
867
- );
868
- }
869
- logger.newline();
870
- logger.dim(`Run ${colors.command("gent run <issue-number>")} to implement an issue`);
871
- logger.dim(`Run ${colors.command("gent run --auto")} to auto-select highest priority`);
872
- }
873
- function getIssueStatus(labels, workflowLabels) {
874
- if (labels.includes(workflowLabels.ready)) return "ready";
875
- if (labels.includes(workflowLabels.inProgress)) return "in-progress";
876
- if (labels.includes(workflowLabels.completed)) return "completed";
877
- if (labels.includes(workflowLabels.blocked)) return "blocked";
878
- return "unknown";
879
- }
880
- function getPriorityColor(priority) {
881
- switch (priority) {
882
- case "critical":
883
- return chalk2.red;
884
- case "high":
885
- return chalk2.yellow;
886
- case "medium":
887
- return chalk2.blue;
888
- case "low":
889
- return chalk2.green;
890
- default:
891
- return chalk2.gray;
892
- }
893
- }
894
- function getStatusColor(status) {
895
- switch (status) {
896
- case "ready":
897
- return chalk2.green;
898
- case "in-progress":
899
- return chalk2.yellow;
900
- case "completed":
901
- return chalk2.blue;
902
- case "blocked":
903
- return chalk2.red;
904
- default:
905
- return chalk2.gray;
906
- }
907
- }
908
-
909
- // src/commands/run.ts
910
811
  import inquirer3 from "inquirer";
911
812
 
912
813
  // src/lib/git.ts
@@ -1028,6 +929,22 @@ async function getLastCommitTimestamp() {
1028
929
  const { stdout } = await execa2("git", ["log", "-1", "--format=%cI"]);
1029
930
  return stdout.trim();
1030
931
  }
932
+ async function listLocalBranches() {
933
+ const { stdout } = await execa2("git", ["branch", "--format=%(refname:short)"]);
934
+ return stdout.trim().split("\n").filter(Boolean);
935
+ }
936
+ async function remoteBranchExists(name) {
937
+ try {
938
+ await execa2("git", ["ls-remote", "--exit-code", "--heads", "origin", name]);
939
+ return true;
940
+ } catch {
941
+ return false;
942
+ }
943
+ }
944
+ async function fetchAndCheckout(name) {
945
+ await execa2("git", ["fetch", "origin", `${name}:${name}`]);
946
+ await execa2("git", ["checkout", name]);
947
+ }
1031
948
 
1032
949
  // src/lib/branch.ts
1033
950
  async function generateBranchName(config, issueNumber, issueTitle, type) {
@@ -1100,7 +1017,308 @@ function extractIssueNumber(branchName) {
1100
1017
  return info?.issueNumber ?? null;
1101
1018
  }
1102
1019
 
1020
+ // src/commands/list.ts
1021
+ function findBranchForIssue(issueNumber, branches) {
1022
+ for (const branch of branches) {
1023
+ const info = parseBranchName(branch);
1024
+ if (info && info.issueNumber === issueNumber) {
1025
+ return branch;
1026
+ }
1027
+ }
1028
+ return null;
1029
+ }
1030
+ function buildTicketChoices(inProgressIssues, readyIssues, openPrs, localBranches) {
1031
+ const choices = [];
1032
+ const seen = /* @__PURE__ */ new Set();
1033
+ const prByIssue = /* @__PURE__ */ new Map();
1034
+ for (const pr of openPrs) {
1035
+ const info = parseBranchName(pr.headRefName);
1036
+ if (info) {
1037
+ prByIssue.set(info.issueNumber, pr);
1038
+ }
1039
+ }
1040
+ for (const issue of inProgressIssues) {
1041
+ if (seen.has(issue.number)) continue;
1042
+ seen.add(issue.number);
1043
+ const branch = findBranchForIssue(issue.number, localBranches);
1044
+ const pr = prByIssue.get(issue.number);
1045
+ choices.push({
1046
+ issueNumber: issue.number,
1047
+ title: issue.title,
1048
+ branch: branch || pr?.headRefName || null,
1049
+ category: pr ? "open-pr" : "in-progress"
1050
+ });
1051
+ }
1052
+ for (const [issueNumber, pr] of prByIssue) {
1053
+ if (seen.has(issueNumber)) continue;
1054
+ seen.add(issueNumber);
1055
+ const issue = [...inProgressIssues, ...readyIssues].find(
1056
+ (i) => i.number === issueNumber
1057
+ );
1058
+ choices.push({
1059
+ issueNumber,
1060
+ title: issue?.title || pr.title,
1061
+ branch: pr.headRefName,
1062
+ category: "open-pr"
1063
+ });
1064
+ }
1065
+ for (const issue of readyIssues) {
1066
+ if (seen.has(issue.number)) continue;
1067
+ seen.add(issue.number);
1068
+ const branch = findBranchForIssue(issue.number, localBranches);
1069
+ choices.push({
1070
+ issueNumber: issue.number,
1071
+ title: issue.title,
1072
+ branch,
1073
+ category: "ready"
1074
+ });
1075
+ }
1076
+ return choices;
1077
+ }
1078
+ function categoryLabel(category) {
1079
+ switch (category) {
1080
+ case "in-progress":
1081
+ return chalk2.yellow("[in progress]");
1082
+ case "open-pr":
1083
+ return chalk2.blue("[open PR]");
1084
+ case "ready":
1085
+ return chalk2.green("[ready]");
1086
+ }
1087
+ }
1088
+ function formatChoice(choice) {
1089
+ const num = colors.issue(`#${choice.issueNumber}`);
1090
+ const cat = categoryLabel(choice.category);
1091
+ const title = choice.title.length > 50 ? choice.title.slice(0, 50) + "..." : choice.title;
1092
+ return `${num} ${cat} ${title}`;
1093
+ }
1094
+ async function listCommand(options) {
1095
+ const isAuthed = await checkGhAuth();
1096
+ if (!isAuthed) {
1097
+ logger.error("Not authenticated with GitHub. Run 'gh auth login' first.");
1098
+ return;
1099
+ }
1100
+ const config = loadConfig();
1101
+ const workflowLabels = getWorkflowLabels(config);
1102
+ const currentBranch = await getCurrentBranch();
1103
+ const defaultBranch = await getDefaultBranch();
1104
+ const statusFilter = options.status;
1105
+ const limit = options.limit || 20;
1106
+ let inProgressIssues = [];
1107
+ let readyIssues = [];
1108
+ if (statusFilter && statusFilter !== "all") {
1109
+ const labels = [];
1110
+ if (options.label) labels.push(options.label);
1111
+ switch (statusFilter) {
1112
+ case "ready":
1113
+ labels.push(workflowLabels.ready);
1114
+ break;
1115
+ case "in-progress":
1116
+ labels.push(workflowLabels.inProgress);
1117
+ break;
1118
+ case "completed":
1119
+ labels.push(workflowLabels.completed);
1120
+ break;
1121
+ case "blocked":
1122
+ labels.push(workflowLabels.blocked);
1123
+ break;
1124
+ }
1125
+ const [issues, localBranches2] = await withSpinner(
1126
+ "Fetching tickets...",
1127
+ () => Promise.all([
1128
+ listIssues({ labels, state: "open", limit }),
1129
+ listLocalBranches()
1130
+ ])
1131
+ );
1132
+ sortByPriority(issues);
1133
+ if (statusFilter === "in-progress") {
1134
+ inProgressIssues = issues;
1135
+ } else {
1136
+ readyIssues = issues;
1137
+ }
1138
+ const choices2 = buildTicketChoices(
1139
+ inProgressIssues,
1140
+ readyIssues,
1141
+ [],
1142
+ localBranches2
1143
+ );
1144
+ if (choices2.length === 0) {
1145
+ logger.info("No issues found matching the criteria.");
1146
+ return;
1147
+ }
1148
+ await presentSelector(
1149
+ choices2,
1150
+ currentBranch,
1151
+ defaultBranch,
1152
+ config
1153
+ );
1154
+ return;
1155
+ }
1156
+ const labelFilter = options.label ? [options.label] : [];
1157
+ const [inProgress, ready, prs, localBranches] = await withSpinner(
1158
+ "Fetching tickets...",
1159
+ () => Promise.all([
1160
+ listIssues({
1161
+ labels: [workflowLabels.inProgress, ...labelFilter],
1162
+ state: "open",
1163
+ limit
1164
+ }),
1165
+ listIssues({
1166
+ labels: [workflowLabels.ready, ...labelFilter],
1167
+ state: "open",
1168
+ limit
1169
+ }),
1170
+ listOpenPrs(30),
1171
+ listLocalBranches()
1172
+ ])
1173
+ );
1174
+ sortByPriority(inProgress);
1175
+ sortByPriority(ready);
1176
+ const choices = buildTicketChoices(inProgress, ready, prs, localBranches);
1177
+ if (choices.length === 0) {
1178
+ logger.info("No tickets found.");
1179
+ logger.dim(
1180
+ `Create a ticket with ${colors.command("gent create")} or add the '${workflowLabels.ready}' label to an issue.`
1181
+ );
1182
+ return;
1183
+ }
1184
+ await presentSelector(choices, currentBranch, defaultBranch, config);
1185
+ }
1186
+ async function presentSelector(choices, currentBranch, defaultBranch, config) {
1187
+ const dirty = await hasUncommittedChanges();
1188
+ const inquirerChoices = [];
1189
+ inquirerChoices.push({
1190
+ name: `${chalk2.magenta(defaultBranch)}${currentBranch === defaultBranch ? chalk2.dim(" (current)") : ""}`,
1191
+ value: "__main__"
1192
+ });
1193
+ inquirerChoices.push(new inquirer3.Separator("\u2500"));
1194
+ const inProgress = choices.filter((c) => c.category === "in-progress");
1195
+ const openPrChoices = choices.filter((c) => c.category === "open-pr");
1196
+ const ready = choices.filter((c) => c.category === "ready");
1197
+ if (inProgress.length > 0) {
1198
+ inquirerChoices.push(new inquirer3.Separator(chalk2.yellow(" In Progress")));
1199
+ for (const c of inProgress) {
1200
+ inquirerChoices.push({
1201
+ name: formatChoice(c),
1202
+ value: String(c.issueNumber)
1203
+ });
1204
+ }
1205
+ }
1206
+ if (openPrChoices.length > 0) {
1207
+ inquirerChoices.push(new inquirer3.Separator(chalk2.blue(" Open PRs")));
1208
+ for (const c of openPrChoices) {
1209
+ inquirerChoices.push({
1210
+ name: formatChoice(c),
1211
+ value: String(c.issueNumber)
1212
+ });
1213
+ }
1214
+ }
1215
+ if (ready.length > 0) {
1216
+ inquirerChoices.push(new inquirer3.Separator(chalk2.green(" Ready")));
1217
+ for (const c of ready) {
1218
+ inquirerChoices.push({
1219
+ name: formatChoice(c),
1220
+ value: String(c.issueNumber)
1221
+ });
1222
+ }
1223
+ }
1224
+ const { selected } = await inquirer3.prompt([
1225
+ {
1226
+ type: "list",
1227
+ name: "selected",
1228
+ message: "Select a ticket to switch to:",
1229
+ choices: inquirerChoices,
1230
+ pageSize: 20
1231
+ }
1232
+ ]);
1233
+ if (selected === "__main__") {
1234
+ if (currentBranch === defaultBranch) {
1235
+ logger.info(`Already on ${colors.branch(defaultBranch)}`);
1236
+ return;
1237
+ }
1238
+ if (dirty) {
1239
+ const ok = await confirmDirty();
1240
+ if (!ok) return;
1241
+ }
1242
+ await withSpinner(`Switching to ${defaultBranch}...`, async () => {
1243
+ await checkoutBranch(defaultBranch);
1244
+ });
1245
+ logger.success(`Switched to ${colors.branch(defaultBranch)}`);
1246
+ return;
1247
+ }
1248
+ const issueNumber = parseInt(selected, 10);
1249
+ const ticket = choices.find((c) => c.issueNumber === issueNumber);
1250
+ if (!ticket) return;
1251
+ if (dirty) {
1252
+ const ok = await confirmDirty();
1253
+ if (!ok) return;
1254
+ }
1255
+ const targetBranch = ticket.branch;
1256
+ if (targetBranch) {
1257
+ if (await branchExists(targetBranch)) {
1258
+ await withSpinner(`Switching to ${targetBranch}...`, async () => {
1259
+ await checkoutBranch(targetBranch);
1260
+ });
1261
+ logger.success(`Switched to ${colors.branch(targetBranch)}`);
1262
+ } else if (await remoteBranchExists(targetBranch)) {
1263
+ await withSpinner(
1264
+ `Fetching ${targetBranch} from remote...`,
1265
+ async () => {
1266
+ await fetchAndCheckout(targetBranch);
1267
+ }
1268
+ );
1269
+ logger.success(
1270
+ `Fetched and switched to ${colors.branch(targetBranch)}`
1271
+ );
1272
+ } else {
1273
+ logger.warning(
1274
+ `Branch ${colors.branch(targetBranch)} not found locally or on remote.`
1275
+ );
1276
+ await offerCreateBranch(config, issueNumber, ticket.title);
1277
+ }
1278
+ } else {
1279
+ await offerCreateBranch(config, issueNumber, ticket.title);
1280
+ }
1281
+ }
1282
+ async function confirmDirty() {
1283
+ logger.warning("You have uncommitted changes.");
1284
+ const { proceed } = await inquirer3.prompt([
1285
+ {
1286
+ type: "confirm",
1287
+ name: "proceed",
1288
+ message: "Continue anyway? (changes will carry over to the new branch)",
1289
+ default: false
1290
+ }
1291
+ ]);
1292
+ if (!proceed) {
1293
+ logger.info("Aborting. Please commit or stash your changes first.");
1294
+ }
1295
+ return proceed;
1296
+ }
1297
+ async function offerCreateBranch(config, issueNumber, title) {
1298
+ const branchName = await generateBranchName(
1299
+ config,
1300
+ issueNumber,
1301
+ title,
1302
+ "feature"
1303
+ );
1304
+ const { create } = await inquirer3.prompt([
1305
+ {
1306
+ type: "confirm",
1307
+ name: "create",
1308
+ message: `No branch exists. Create ${colors.branch(branchName)}?`,
1309
+ default: true
1310
+ }
1311
+ ]);
1312
+ if (!create) return;
1313
+ const defaultBranch = await getDefaultBranch();
1314
+ await withSpinner(`Creating branch ${branchName}...`, async () => {
1315
+ await createBranch(branchName, defaultBranch);
1316
+ });
1317
+ logger.success(`Created and switched to ${colors.branch(branchName)}`);
1318
+ }
1319
+
1103
1320
  // src/commands/run.ts
1321
+ import inquirer4 from "inquirer";
1104
1322
  async function runCommand(issueNumberArg, options) {
1105
1323
  logger.bold("Running AI implementation workflow...");
1106
1324
  logger.newline();
@@ -1122,7 +1340,7 @@ async function runCommand(issueNumberArg, options) {
1122
1340
  const hasChanges = await hasUncommittedChanges();
1123
1341
  if (hasChanges) {
1124
1342
  logger.warning("You have uncommitted changes.");
1125
- const { proceed } = await inquirer3.prompt([
1343
+ const { proceed } = await inquirer4.prompt([
1126
1344
  {
1127
1345
  type: "confirm",
1128
1346
  name: "proceed",
@@ -1137,22 +1355,14 @@ async function runCommand(issueNumberArg, options) {
1137
1355
  }
1138
1356
  const workflowLabels = getWorkflowLabels(config);
1139
1357
  let issueNumber;
1140
- if (options.auto) {
1141
- const autoIssue = await autoSelectIssue(workflowLabels.ready);
1142
- if (!autoIssue) {
1143
- logger.error("No ai-ready issues found.");
1144
- return;
1145
- }
1146
- issueNumber = autoIssue.number;
1147
- logger.info(`Auto-selected: ${colors.issue(`#${issueNumber}`)} - ${autoIssue.title}`);
1148
- } else if (issueNumberArg) {
1358
+ if (issueNumberArg) {
1149
1359
  if (!isValidIssueNumber(issueNumberArg)) {
1150
1360
  logger.error("Invalid issue number.");
1151
1361
  return;
1152
1362
  }
1153
1363
  issueNumber = parseInt(issueNumberArg, 10);
1154
1364
  } else {
1155
- logger.error("Please provide an issue number or use --auto");
1365
+ logger.error("Please provide an issue number. Use 'gent switch' to browse tickets.");
1156
1366
  return;
1157
1367
  }
1158
1368
  let issue;
@@ -1166,7 +1376,7 @@ async function runCommand(issueNumberArg, options) {
1166
1376
  }
1167
1377
  if (!issue.labels.includes(workflowLabels.ready)) {
1168
1378
  logger.warning(`Issue #${issueNumber} does not have the '${workflowLabels.ready}' label.`);
1169
- const { proceed } = await inquirer3.prompt([
1379
+ const { proceed } = await inquirer4.prompt([
1170
1380
  {
1171
1381
  type: "confirm",
1172
1382
  name: "proceed",
@@ -1188,7 +1398,7 @@ Labels: ${issue.labels.join(", ")}`);
1188
1398
  const onMain = await isOnMainBranch();
1189
1399
  if (await branchExists(branchName)) {
1190
1400
  logger.info(`Branch ${colors.branch(branchName)} already exists.`);
1191
- const { action } = await inquirer3.prompt([
1401
+ const { action } = await inquirer4.prompt([
1192
1402
  {
1193
1403
  type: "list",
1194
1404
  name: "action",
@@ -1210,7 +1420,7 @@ Labels: ${issue.labels.join(", ")}`);
1210
1420
  } else {
1211
1421
  if (!onMain) {
1212
1422
  logger.warning(`Not on main branch (currently on ${colors.branch(currentBranch)}).`);
1213
- const { fromMain } = await inquirer3.prompt([
1423
+ const { fromMain } = await inquirer4.prompt([
1214
1424
  {
1215
1425
  type: "confirm",
1216
1426
  name: "fromMain",
@@ -1331,31 +1541,9 @@ No commits were created. Please retry later.`
1331
1541
  3. Push branch: ${colors.command("git push -u origin " + branchName)}
1332
1542
  4. Create PR: ${colors.command("gent pr")}`);
1333
1543
  }
1334
- async function autoSelectIssue(readyLabel) {
1335
- let issues = await listIssues({
1336
- labels: [readyLabel, "priority:critical"],
1337
- state: "open",
1338
- limit: 1
1339
- });
1340
- if (issues.length > 0) return issues[0];
1341
- issues = await listIssues({
1342
- labels: [readyLabel, "priority:high"],
1343
- state: "open",
1344
- limit: 1
1345
- });
1346
- if (issues.length > 0) return issues[0];
1347
- issues = await listIssues({
1348
- labels: [readyLabel],
1349
- state: "open",
1350
- limit: 10
1351
- });
1352
- if (issues.length === 0) return null;
1353
- sortByPriority(issues);
1354
- return issues[0];
1355
- }
1356
1544
 
1357
1545
  // src/commands/pr.ts
1358
- import inquirer4 from "inquirer";
1546
+ import inquirer5 from "inquirer";
1359
1547
 
1360
1548
  // src/lib/playwright.ts
1361
1549
  import { execa as execa3 } from "execa";
@@ -1436,7 +1624,7 @@ async function prCommand(options) {
1436
1624
  const hasUnpushed = await getUnpushedCommits();
1437
1625
  if (hasUnpushed) {
1438
1626
  logger.warning("Branch has unpushed commits.");
1439
- const { push } = await inquirer4.prompt([
1627
+ const { push } = await inquirer5.prompt([
1440
1628
  {
1441
1629
  type: "confirm",
1442
1630
  name: "push",
@@ -1573,7 +1761,7 @@ function generateFallbackBody(issue, commits) {
1573
1761
  }
1574
1762
 
1575
1763
  // src/commands/fix.ts
1576
- import inquirer5 from "inquirer";
1764
+ import inquirer6 from "inquirer";
1577
1765
 
1578
1766
  // src/lib/review-feedback.ts
1579
1767
  var ACTIONABLE_KEYWORDS = [
@@ -1764,7 +1952,7 @@ async function fixCommand(options) {
1764
1952
  const hasChanges = await hasUncommittedChanges();
1765
1953
  if (hasChanges) {
1766
1954
  logger.warning("You have uncommitted changes.");
1767
- const { proceed } = await inquirer5.prompt([
1955
+ const { proceed } = await inquirer6.prompt([
1768
1956
  {
1769
1957
  type: "confirm",
1770
1958
  name: "proceed",
@@ -1893,7 +2081,7 @@ import { homedir } from "os";
1893
2081
  // package.json
1894
2082
  var package_default = {
1895
2083
  name: "@rotorsoft/gent",
1896
- version: "1.12.1",
2084
+ version: "1.13.0",
1897
2085
  description: "AI-powered GitHub workflow CLI - leverage AI (Claude, Gemini, or Codex) to create tickets, implement features, and manage PRs",
1898
2086
  keywords: [
1899
2087
  "cli",
@@ -2303,7 +2491,7 @@ async function statusCommand() {
2303
2491
  }
2304
2492
 
2305
2493
  // src/commands/tui.ts
2306
- import inquirer6 from "inquirer";
2494
+ import inquirer7 from "inquirer";
2307
2495
  import { execa as execa4 } from "execa";
2308
2496
 
2309
2497
  // src/tui/state.ts
@@ -2432,7 +2620,6 @@ function getAvailableActions(state) {
2432
2620
  }
2433
2621
  if (state.isOnMain) {
2434
2622
  actions.push({ id: "create", label: "new", shortcut: "n" });
2435
- actions.push({ id: "run-auto", label: "run next", shortcut: "r" });
2436
2623
  actions.push({ id: "list", label: "list", shortcut: "l" });
2437
2624
  actions.push({ id: "switch-provider", label: "switch", shortcut: "s" });
2438
2625
  actions.push({ id: "quit", label: "quit", shortcut: "q" });
@@ -2458,6 +2645,7 @@ function getAvailableActions(state) {
2458
2645
  if (state.pr && (state.pr.state === "merged" || state.pr.state === "closed")) {
2459
2646
  actions.push({ id: "checkout-main", label: "main", shortcut: "m" });
2460
2647
  }
2648
+ actions.push({ id: "list", label: "list", shortcut: "l" });
2461
2649
  actions.push({ id: "switch-provider", label: "switch", shortcut: "s" });
2462
2650
  actions.push({ id: "quit", label: "quit", shortcut: "q" });
2463
2651
  return actions;
@@ -2739,7 +2927,7 @@ function clearScreen() {
2739
2927
  // src/commands/tui.ts
2740
2928
  var CANCEL = /* @__PURE__ */ Symbol("cancel");
2741
2929
  async function confirm(message) {
2742
- const { ok } = await inquirer6.prompt([
2930
+ const { ok } = await inquirer7.prompt([
2743
2931
  {
2744
2932
  type: "confirm",
2745
2933
  name: "ok",
@@ -2784,25 +2972,19 @@ async function executeAction(actionId, state, providerSetter) {
2784
2972
  switch (actionId) {
2785
2973
  case "quit":
2786
2974
  return false;
2787
- case "list":
2788
- clearScreen();
2789
- await listCommand({ status: "ready", limit: 20 });
2790
- await promptContinue();
2791
- return true;
2792
- case "run-auto": {
2975
+ case "list": {
2793
2976
  clearScreen();
2794
- if (!await confirm("Start AI agent to implement next ticket?")) return true;
2795
2977
  try {
2796
- await runCommand(void 0, { auto: true });
2978
+ await listCommand({});
2797
2979
  } catch (error) {
2798
- logger.error(`Run failed: ${error}`);
2799
- await promptContinue();
2980
+ logger.error(`List failed: ${error}`);
2800
2981
  }
2801
- return false;
2982
+ await promptContinue();
2983
+ return true;
2802
2984
  }
2803
2985
  case "create": {
2804
2986
  clearScreen();
2805
- const { description } = await inquirer6.prompt([
2987
+ const { description } = await inquirer7.prompt([
2806
2988
  {
2807
2989
  type: "input",
2808
2990
  name: "description",
@@ -2936,7 +3118,7 @@ async function generateCommitMessage(diffContent, issueNumber, issueTitle, state
2936
3118
  } catch {
2937
3119
  logger.warning("AI commit message generation failed");
2938
3120
  console.log();
2939
- const { message } = await inquirer6.prompt([
3121
+ const { message } = await inquirer7.prompt([
2940
3122
  {
2941
3123
  type: "input",
2942
3124
  name: "message",
@@ -3005,7 +3187,7 @@ async function handlePush() {
3005
3187
  var PROVIDERS = ["claude", "gemini", "codex"];
3006
3188
  async function handleSwitchProvider(state, setProvider) {
3007
3189
  const current = state.config.ai.provider;
3008
- const { provider } = await inquirer6.prompt([
3190
+ const { provider } = await inquirer7.prompt([
3009
3191
  {
3010
3192
  type: "list",
3011
3193
  name: "provider",
@@ -3060,7 +3242,7 @@ async function handleVideoCapture(state) {
3060
3242
  }
3061
3243
  async function promptContinue() {
3062
3244
  console.log();
3063
- await inquirer6.prompt([
3245
+ await inquirer7.prompt([
3064
3246
  {
3065
3247
  type: "input",
3066
3248
  name: "continue",
@@ -3126,15 +3308,15 @@ program.command("setup-labels").description("Setup GitHub labels for AI workflow
3126
3308
  program.command("create <description>").description("Create an AI-enhanced GitHub issue").option("-y, --yes", "Skip confirmation and create issue immediately").option("-p, --provider <provider>", "AI provider to use (claude, gemini, or codex)").option("-t, --title <title>", "Override the generated issue title").action(async (description, options) => {
3127
3309
  await createCommand(description, { yes: options.yes, provider: options.provider, title: options.title });
3128
3310
  });
3129
- program.command("list").description("List GitHub issues by label/status").option("-l, --label <label>", "Filter by label").option("-s, --status <status>", "Filter by workflow status (ready, in-progress, completed, blocked, all)").option("-n, --limit <number>", "Maximum number of issues to show", "20").action(async (options) => {
3311
+ program.command("list").description("List and switch to GitHub issues").option("-l, --label <label>", "Filter by label").option("-s, --status <status>", "Filter by workflow status (ready, in-progress, completed, blocked, all)").option("-n, --limit <number>", "Maximum number of issues to show", "20").action(async (options) => {
3130
3312
  await listCommand({
3131
3313
  label: options.label,
3132
3314
  status: options.status,
3133
3315
  limit: parseInt(options.limit, 10)
3134
3316
  });
3135
3317
  });
3136
- program.command("run [issue-number]").description("Run AI to implement a GitHub issue").option("-a, --auto", "Auto-select highest priority ai-ready issue").option("-p, --provider <provider>", "AI provider to use (claude, gemini, or codex)").action(async (issueNumber, options) => {
3137
- await runCommand(issueNumber, { auto: options.auto, provider: options.provider });
3318
+ program.command("run [issue-number]").description("Run AI to implement a GitHub issue").option("-p, --provider <provider>", "AI provider to use (claude, gemini, or codex)").action(async (issueNumber, options) => {
3319
+ await runCommand(issueNumber, { provider: options.provider });
3138
3320
  });
3139
3321
  program.command("pr").description("Create an AI-enhanced pull request").option("-d, --draft", "Create as draft PR").option("-p, --provider <provider>", "AI provider to use (claude, gemini, or codex)").option("--no-video", "Disable video capture for UI changes").action(async (options) => {
3140
3322
  await prCommand({