@rotorsoft/gent 1.3.2 → 1.4.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/README.md CHANGED
@@ -6,8 +6,8 @@ AI-powered GitHub workflow CLI - leverage AI (Claude or Gemini) to create ticket
6
6
 
7
7
  `gent` is a command-line tool that integrates AI with GitHub to automate your development workflow:
8
8
 
9
- - **Create AI-enhanced tickets** - Describe what you need, Claude generates detailed GitHub issues with proper labels
10
- - **Implement with AI** - Pick a ticket and let Claude implement it with automatic branch management
9
+ - **Create AI-enhanced tickets** - Describe what you need, the AI generates detailed GitHub issues with proper labels
10
+ - **Implement with AI** - Pick a ticket and let the AI implement it with automatic branch management
11
11
  - **Track progress** - Maintain a progress log for context across AI sessions
12
12
  - **Create smart PRs** - Generate AI-enhanced pull requests with proper descriptions
13
13
 
@@ -60,7 +60,7 @@ Creates workflow labels (`ai-ready`, `ai-in-progress`, etc.) and category labels
60
60
  gent create "Add user authentication with JWT tokens"
61
61
  ```
62
62
 
63
- Claude will:
63
+ The AI will:
64
64
  - Generate a detailed issue with technical context
65
65
  - Infer appropriate labels (type, priority, risk, area)
66
66
  - Create the issue on GitHub with `ai-ready` label
@@ -75,7 +75,7 @@ gent run 123
75
75
  gent run --auto
76
76
  ```
77
77
 
78
- Claude will:
78
+ The AI will:
79
79
  - Create a feature branch
80
80
  - Update labels to `ai-in-progress`
81
81
  - Implement the feature following your `AGENT.md` instructions
@@ -89,7 +89,7 @@ Claude will:
89
89
  gent pr
90
90
  ```
91
91
 
92
- Claude will:
92
+ The AI will:
93
93
  - Generate a PR description from commits and linked issue
94
94
  - Include "Closes #" reference
95
95
  - Create the PR on GitHub
@@ -244,7 +244,7 @@ validation:
244
244
 
245
245
  ### AGENT.md
246
246
 
247
- Project-specific instructions for Claude. This file tells Claude how to work with your codebase:
247
+ Project-specific instructions for the AI. This file tells the AI how to work with your codebase:
248
248
 
249
249
  - Project overview and architecture
250
250
  - Code patterns and conventions
@@ -288,7 +288,7 @@ This provides context for future AI sessions and human reviewers.
288
288
  │ created │
289
289
  └────┬─────┘
290
290
 
291
- Claude implements
291
+ AI implements
292
292
 
293
293
  v
294
294
  ┌──────────┐
@@ -401,8 +401,8 @@ gent create "Fix auth"
401
401
 
402
402
  ### Handling AI Blocks
403
403
 
404
- If Claude gets stuck (`ai-blocked` label):
405
- 1. Check the issue comments for Claude's notes
404
+ If the AI gets stuck (`ai-blocked` label):
405
+ 1. Check the issue comments for notes
406
406
  2. Add clarifying information to the issue
407
407
  3. Reset to `ai-ready` to retry
408
408
  4. Or implement manually
package/dist/index.js CHANGED
@@ -33,6 +33,9 @@ import {
33
33
  } from "./chunk-2LGYNV6S.js";
34
34
 
35
35
  // src/index.ts
36
+ import { readFileSync as readFileSync2 } from "fs";
37
+ import { join as join3, dirname as dirname2 } from "path";
38
+ import { fileURLToPath } from "url";
36
39
  import { Command } from "commander";
37
40
 
38
41
  // src/commands/init.ts
@@ -78,7 +81,7 @@ Each entry documents: date, feature, decisions, files changed, tests, and concer
78
81
  // src/commands/init.ts
79
82
  var DEFAULT_AGENT_MD = `# AI Agent Instructions
80
83
 
81
- This file contains instructions for Claude when working on this repository.
84
+ This file contains instructions for the AI when working on this repository.
82
85
 
83
86
  ## Project Overview
84
87
 
@@ -115,10 +118,7 @@ Follow conventional commits format:
115
118
  - \`chore:\` Maintenance/dependencies
116
119
  - \`docs:\` Documentation
117
120
 
118
- All AI commits should include:
119
- \`\`\`
120
- Co-Authored-By: Claude <noreply@anthropic.com>
121
- \`\`\`
121
+ All AI commits should include the Co-Authored-By trailer as specified in the task prompt.
122
122
 
123
123
  ## Important Files
124
124
 
@@ -194,8 +194,147 @@ async function initCommand(options) {
194
194
  import inquirer2 from "inquirer";
195
195
  import chalk from "chalk";
196
196
 
197
- // src/lib/claude.ts
197
+ // src/lib/ai-provider.ts
198
+ import { spawn } from "child_process";
198
199
  import { execa } from "execa";
200
+ async function invokeAI(options, config, providerOverride) {
201
+ const provider = providerOverride ?? config.ai.provider;
202
+ try {
203
+ const output = provider === "claude" ? await invokeClaudeInternal(options) : await invokeGeminiInternal(options);
204
+ return { output, provider };
205
+ } catch (error) {
206
+ if (isRateLimitError(error, provider)) {
207
+ if (config.ai.auto_fallback && config.ai.fallback_provider && !providerOverride) {
208
+ const fallback = config.ai.fallback_provider;
209
+ logger.warning(`Rate limit reached on ${getProviderDisplayName(provider)}, switching to ${getProviderDisplayName(fallback)}...`);
210
+ const output = fallback === "claude" ? await invokeClaudeInternal(options) : await invokeGeminiInternal(options);
211
+ return { output, provider: fallback };
212
+ }
213
+ const err = error;
214
+ err.message = `Rate limited on ${getProviderDisplayName(provider)}`;
215
+ err.rateLimited = true;
216
+ throw err;
217
+ }
218
+ throw error;
219
+ }
220
+ }
221
+ async function invokeAIInteractive(prompt, config, providerOverride) {
222
+ const provider = providerOverride ?? config.ai.provider;
223
+ if (provider === "claude") {
224
+ const args = ["--permission-mode", config.claude.permission_mode, prompt];
225
+ return {
226
+ result: execa("claude", args, { stdio: "inherit" }),
227
+ provider
228
+ };
229
+ } else {
230
+ return {
231
+ result: execa("gemini", ["-i", prompt], { stdio: "inherit" }),
232
+ provider
233
+ };
234
+ }
235
+ }
236
+ function getProviderDisplayName(provider) {
237
+ return provider === "claude" ? "Claude" : "Gemini";
238
+ }
239
+ function getProviderEmail(provider) {
240
+ return provider === "claude" ? "noreply@anthropic.com" : "noreply@google.com";
241
+ }
242
+ function isRateLimitError(error, provider) {
243
+ if (!error || typeof error !== "object") return false;
244
+ if (provider === "claude" && "exitCode" in error && error.exitCode === 2) {
245
+ return true;
246
+ }
247
+ if ("message" in error && typeof error.message === "string") {
248
+ const msg = error.message.toLowerCase();
249
+ if (msg.includes("rate limit") || msg.includes("quota exceeded") || msg.includes("too many requests")) {
250
+ return true;
251
+ }
252
+ }
253
+ return false;
254
+ }
255
+ async function invokeClaudeInternal(options) {
256
+ const args = ["--print"];
257
+ if (options.permissionMode) {
258
+ args.push("--permission-mode", options.permissionMode);
259
+ }
260
+ args.push(options.prompt);
261
+ if (options.printOutput) {
262
+ const subprocess = execa("claude", args, {
263
+ stdio: "inherit"
264
+ });
265
+ await subprocess;
266
+ return "";
267
+ } else if (options.streamOutput) {
268
+ return new Promise((resolve, reject) => {
269
+ const child = spawn("claude", args, {
270
+ stdio: ["inherit", "pipe", "pipe"]
271
+ });
272
+ let output = "";
273
+ child.stdout.on("data", (chunk) => {
274
+ const text = chunk.toString();
275
+ output += text;
276
+ process.stdout.write(text);
277
+ });
278
+ child.stderr.on("data", (chunk) => {
279
+ process.stderr.write(chunk);
280
+ });
281
+ child.on("close", (code) => {
282
+ if (code === 0) {
283
+ resolve(output);
284
+ } else {
285
+ const error = new Error(`Claude exited with code ${code}`);
286
+ error.exitCode = code ?? 1;
287
+ reject(error);
288
+ }
289
+ });
290
+ child.on("error", reject);
291
+ });
292
+ } else {
293
+ const { stdout } = await execa("claude", args);
294
+ return stdout;
295
+ }
296
+ }
297
+ async function invokeGeminiInternal(options) {
298
+ const args = [];
299
+ args.push(options.prompt);
300
+ if (options.printOutput) {
301
+ const subprocess = execa("gemini", args, {
302
+ stdio: "inherit"
303
+ });
304
+ await subprocess;
305
+ return "";
306
+ } else if (options.streamOutput) {
307
+ return new Promise((resolve, reject) => {
308
+ const child = spawn("gemini", args, {
309
+ stdio: ["inherit", "pipe", "pipe"]
310
+ });
311
+ let output = "";
312
+ child.stdout.on("data", (chunk) => {
313
+ const text = chunk.toString();
314
+ output += text;
315
+ process.stdout.write(text);
316
+ });
317
+ child.stderr.on("data", (chunk) => {
318
+ process.stderr.write(chunk);
319
+ });
320
+ child.on("close", (code) => {
321
+ if (code === 0) {
322
+ resolve(output);
323
+ } else {
324
+ const error = new Error(`Gemini exited with code ${code}`);
325
+ error.exitCode = code ?? 1;
326
+ reject(error);
327
+ }
328
+ });
329
+ child.on("error", reject);
330
+ });
331
+ } else {
332
+ const { stdout } = await execa("gemini", args);
333
+ return stdout;
334
+ }
335
+ }
336
+
337
+ // src/lib/prompts.ts
199
338
  function buildTicketPrompt(description, agentInstructions, additionalHints = null) {
200
339
  const basePrompt = `You are creating a GitHub issue for a software project following an AI-assisted development workflow.
201
340
 
@@ -249,6 +388,8 @@ Example: META:type=feature,priority=high,risk=low,area=ui`;
249
388
  return basePrompt;
250
389
  }
251
390
  function buildImplementationPrompt(issue, agentInstructions, progressContent, config) {
391
+ const providerName = getProviderDisplayName(config.ai.provider);
392
+ const providerEmail = getProviderEmail(config.ai.provider);
252
393
  return `GitHub Issue #${issue.number}: ${issue.title}
253
394
 
254
395
  ${issue.body}
@@ -271,16 +412,14 @@ ${config.validation.map((cmd) => ` - ${cmd}`).join("\n")}
271
412
  4. **Make an atomic commit** with a clear message following conventional commits format:
272
413
  - Use format: <type>: <description>
273
414
  - Include "Completed GitHub issue #${issue.number}" in body
274
- - End with: Co-Authored-By: Claude <noreply@anthropic.com>
415
+ - End with: Co-Authored-By: ${providerName} <${providerEmail}>
275
416
  5. **Update ${config.progress.file}** - append a compact entry documenting your work:
276
- \`\`\`
277
- [YYYY-MM-DD] #${issue.number} <type>: <brief description>
417
+ [YYYY-MM-DD] #${issue.number} <type>: <brief description>
278
418
  - Files: <comma-separated list of changed files>
279
419
  - Changes: <1-2 sentence summary of what was implemented>
280
420
  - Decisions: <key technical decisions made, if any>
281
421
  - Issues: <concerns or follow-ups for reviewers, if any>
282
- \`\`\`
283
- Keep entries minimal (4-6 lines max). Skip sections if not applicable.
422
+ Keep entries minimal (4-6 lines max). Skip sections if not applicable.
284
423
  6. **Do NOT push** - the user will review and push manually
285
424
 
286
425
  Focus on clean, minimal implementation. Don't over-engineer.`;
@@ -336,143 +475,6 @@ function extractIssueBody(output) {
336
475
  return body;
337
476
  }
338
477
 
339
- // src/lib/ai-provider.ts
340
- import { spawn } from "child_process";
341
- import { execa as execa2 } from "execa";
342
- async function invokeAI(options, config, providerOverride) {
343
- const provider = providerOverride ?? config.ai.provider;
344
- try {
345
- const output = provider === "claude" ? await invokeClaudeInternal(options) : await invokeGeminiInternal(options);
346
- return { output, provider };
347
- } catch (error) {
348
- if (isRateLimitError(error, provider)) {
349
- if (config.ai.auto_fallback && config.ai.fallback_provider && !providerOverride) {
350
- const fallback = config.ai.fallback_provider;
351
- logger.warning(`Rate limit reached on ${getProviderDisplayName(provider)}, switching to ${getProviderDisplayName(fallback)}...`);
352
- const output = fallback === "claude" ? await invokeClaudeInternal(options) : await invokeGeminiInternal(options);
353
- return { output, provider: fallback };
354
- }
355
- const err = error;
356
- err.message = `Rate limited on ${getProviderDisplayName(provider)}`;
357
- err.rateLimited = true;
358
- throw err;
359
- }
360
- throw error;
361
- }
362
- }
363
- async function invokeAIInteractive(prompt, config, providerOverride) {
364
- const provider = providerOverride ?? config.ai.provider;
365
- if (provider === "claude") {
366
- const args = ["--permission-mode", config.claude.permission_mode, prompt];
367
- return {
368
- result: execa2("claude", args, { stdio: "inherit" }),
369
- provider
370
- };
371
- } else {
372
- return {
373
- result: execa2("gemini", ["-i", prompt], { stdio: "inherit" }),
374
- provider
375
- };
376
- }
377
- }
378
- function getProviderDisplayName(provider) {
379
- return provider === "claude" ? "Claude" : "Gemini";
380
- }
381
- function isRateLimitError(error, provider) {
382
- if (!error || typeof error !== "object") return false;
383
- if (provider === "claude" && "exitCode" in error && error.exitCode === 2) {
384
- return true;
385
- }
386
- if ("message" in error && typeof error.message === "string") {
387
- const msg = error.message.toLowerCase();
388
- if (msg.includes("rate limit") || msg.includes("quota exceeded") || msg.includes("too many requests")) {
389
- return true;
390
- }
391
- }
392
- return false;
393
- }
394
- async function invokeClaudeInternal(options) {
395
- const args = ["--print"];
396
- if (options.permissionMode) {
397
- args.push("--permission-mode", options.permissionMode);
398
- }
399
- args.push(options.prompt);
400
- if (options.printOutput) {
401
- const subprocess = execa2("claude", args, {
402
- stdio: "inherit"
403
- });
404
- await subprocess;
405
- return "";
406
- } else if (options.streamOutput) {
407
- return new Promise((resolve, reject) => {
408
- const child = spawn("claude", args, {
409
- stdio: ["inherit", "pipe", "pipe"]
410
- });
411
- let output = "";
412
- child.stdout.on("data", (chunk) => {
413
- const text = chunk.toString();
414
- output += text;
415
- process.stdout.write(text);
416
- });
417
- child.stderr.on("data", (chunk) => {
418
- process.stderr.write(chunk);
419
- });
420
- child.on("close", (code) => {
421
- if (code === 0) {
422
- resolve(output);
423
- } else {
424
- const error = new Error(`Claude exited with code ${code}`);
425
- error.exitCode = code ?? 1;
426
- reject(error);
427
- }
428
- });
429
- child.on("error", reject);
430
- });
431
- } else {
432
- const { stdout } = await execa2("claude", args);
433
- return stdout;
434
- }
435
- }
436
- async function invokeGeminiInternal(options) {
437
- const args = [];
438
- args.push(options.prompt);
439
- if (options.printOutput) {
440
- const subprocess = execa2("gemini", args, {
441
- stdio: "inherit"
442
- });
443
- await subprocess;
444
- return "";
445
- } else if (options.streamOutput) {
446
- return new Promise((resolve, reject) => {
447
- const child = spawn("gemini", args, {
448
- stdio: ["inherit", "pipe", "pipe"]
449
- });
450
- let output = "";
451
- child.stdout.on("data", (chunk) => {
452
- const text = chunk.toString();
453
- output += text;
454
- process.stdout.write(text);
455
- });
456
- child.stderr.on("data", (chunk) => {
457
- process.stderr.write(chunk);
458
- });
459
- child.on("close", (code) => {
460
- if (code === 0) {
461
- resolve(output);
462
- } else {
463
- const error = new Error(`Gemini exited with code ${code}`);
464
- error.exitCode = code ?? 1;
465
- reject(error);
466
- }
467
- });
468
- child.on("error", reject);
469
- });
470
- } else {
471
- const { stdout } = await execa2("gemini", args);
472
- return stdout;
473
- }
474
- }
475
-
476
478
  // src/commands/create.ts
477
479
  async function createCommand(description, options) {
478
480
  logger.bold("Creating AI-enhanced ticket...");
@@ -511,7 +513,7 @@ async function createCommand(description, options) {
511
513
  }
512
514
  const meta = parseTicketMeta(aiOutput);
513
515
  if (!meta) {
514
- logger.warning("Could not parse metadata from Claude output. Using defaults.");
516
+ logger.warning("Could not parse metadata from AI output. Using defaults.");
515
517
  }
516
518
  const finalMeta = meta || {
517
519
  type: "feature",
@@ -554,7 +556,7 @@ async function createCommand(description, options) {
554
556
  {
555
557
  type: "input",
556
558
  name: "hints",
557
- message: "Enter additional hints or context for Claude:"
559
+ message: "Enter additional hints or context for the AI:"
558
560
  }
559
561
  ]);
560
562
  if (hints.trim()) {
@@ -723,9 +725,9 @@ function getStatusColor(status) {
723
725
  import inquirer3 from "inquirer";
724
726
 
725
727
  // src/lib/git.ts
726
- import { execa as execa3 } from "execa";
728
+ import { execa as execa2 } from "execa";
727
729
  async function getCurrentBranch() {
728
- const { stdout } = await execa3("git", ["branch", "--show-current"]);
730
+ const { stdout } = await execa2("git", ["branch", "--show-current"]);
729
731
  return stdout.trim();
730
732
  }
731
733
  async function isOnMainBranch() {
@@ -734,14 +736,14 @@ async function isOnMainBranch() {
734
736
  }
735
737
  async function getDefaultBranch() {
736
738
  try {
737
- const { stdout } = await execa3("git", [
739
+ const { stdout } = await execa2("git", [
738
740
  "symbolic-ref",
739
741
  "refs/remotes/origin/HEAD"
740
742
  ]);
741
743
  return stdout.trim().replace("refs/remotes/origin/", "");
742
744
  } catch {
743
745
  try {
744
- await execa3("git", ["rev-parse", "--verify", "main"]);
746
+ await execa2("git", ["rev-parse", "--verify", "main"]);
745
747
  return "main";
746
748
  } catch {
747
749
  return "master";
@@ -750,7 +752,7 @@ async function getDefaultBranch() {
750
752
  }
751
753
  async function branchExists(name) {
752
754
  try {
753
- await execa3("git", ["rev-parse", "--verify", name]);
755
+ await execa2("git", ["rev-parse", "--verify", name]);
754
756
  return true;
755
757
  } catch {
756
758
  return false;
@@ -758,21 +760,21 @@ async function branchExists(name) {
758
760
  }
759
761
  async function createBranch(name, from) {
760
762
  if (from) {
761
- await execa3("git", ["checkout", "-b", name, from]);
763
+ await execa2("git", ["checkout", "-b", name, from]);
762
764
  } else {
763
- await execa3("git", ["checkout", "-b", name]);
765
+ await execa2("git", ["checkout", "-b", name]);
764
766
  }
765
767
  }
766
768
  async function checkoutBranch(name) {
767
- await execa3("git", ["checkout", name]);
769
+ await execa2("git", ["checkout", name]);
768
770
  }
769
771
  async function hasUncommittedChanges() {
770
- const { stdout } = await execa3("git", ["status", "--porcelain"]);
772
+ const { stdout } = await execa2("git", ["status", "--porcelain"]);
771
773
  return stdout.trim().length > 0;
772
774
  }
773
775
  async function getUnpushedCommits() {
774
776
  try {
775
- const { stdout } = await execa3("git", [
777
+ const { stdout } = await execa2("git", [
776
778
  "log",
777
779
  "@{u}..HEAD",
778
780
  "--oneline"
@@ -784,18 +786,18 @@ async function getUnpushedCommits() {
784
786
  }
785
787
  async function pushBranch(branch) {
786
788
  const branchName = branch || await getCurrentBranch();
787
- await execa3("git", ["push", "-u", "origin", branchName]);
789
+ await execa2("git", ["push", "-u", "origin", branchName]);
788
790
  }
789
791
  async function getAuthorInitials() {
790
792
  try {
791
- const { stdout } = await execa3("git", ["config", "user.initials"]);
793
+ const { stdout } = await execa2("git", ["config", "user.initials"]);
792
794
  if (stdout.trim()) {
793
795
  return stdout.trim();
794
796
  }
795
797
  } catch {
796
798
  }
797
799
  try {
798
- const { stdout } = await execa3("git", ["config", "user.name"]);
800
+ const { stdout } = await execa2("git", ["config", "user.name"]);
799
801
  const name = stdout.trim();
800
802
  if (name) {
801
803
  const parts = name.split(/\s+/);
@@ -807,7 +809,7 @@ async function getAuthorInitials() {
807
809
  }
808
810
  async function getCommitsSinceBase(base = "main") {
809
811
  try {
810
- const { stdout } = await execa3("git", [
812
+ const { stdout } = await execa2("git", [
811
813
  "log",
812
814
  `${base}..HEAD`,
813
815
  "--pretty=format:%s"
@@ -819,7 +821,7 @@ async function getCommitsSinceBase(base = "main") {
819
821
  }
820
822
  async function getDiffSummary(base = "main") {
821
823
  try {
822
- const { stdout } = await execa3("git", [
824
+ const { stdout } = await execa2("git", [
823
825
  "diff",
824
826
  `${base}...HEAD`,
825
827
  "--stat"
@@ -830,7 +832,7 @@ async function getDiffSummary(base = "main") {
830
832
  }
831
833
  }
832
834
  async function getCurrentCommitSha() {
833
- const { stdout } = await execa3("git", ["rev-parse", "HEAD"]);
835
+ const { stdout } = await execa2("git", ["rev-parse", "HEAD"]);
834
836
  return stdout.trim();
835
837
  }
836
838
  async function hasNewCommits(beforeSha) {
@@ -1455,8 +1457,13 @@ async function statusCommand() {
1455
1457
  }
1456
1458
 
1457
1459
  // src/index.ts
1460
+ var __dirname = dirname2(fileURLToPath(import.meta.url));
1461
+ var packageJson = JSON.parse(
1462
+ readFileSync2(join3(__dirname, "../package.json"), "utf8")
1463
+ );
1464
+ var { version } = packageJson;
1458
1465
  var program = new Command();
1459
- program.name("gent").description("AI-powered GitHub workflow CLI - leverage Claude AI to create tickets, implement features, and manage PRs").version("0.1.0");
1466
+ program.name("gent").description("AI-powered GitHub workflow CLI - leverage AI (Claude or Gemini) to create tickets, implement features, and manage PRs").version(version);
1460
1467
  program.command("init").description("Initialize gent workflow in current repository").option("-f, --force", "Overwrite existing configuration").action(async (options) => {
1461
1468
  await initCommand(options);
1462
1469
  });
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/commands/init.ts","../src/lib/progress.ts","../src/commands/create.ts","../src/lib/claude.ts","../src/lib/ai-provider.ts","../src/commands/list.ts","../src/commands/run.ts","../src/lib/git.ts","../src/lib/branch.ts","../src/commands/pr.ts","../src/commands/status.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { initCommand } from \"./commands/init.js\";\nimport { setupLabelsCommand } from \"./commands/setup-labels.js\";\nimport { createCommand } from \"./commands/create.js\";\nimport { listCommand } from \"./commands/list.js\";\nimport { runCommand } from \"./commands/run.js\";\nimport { prCommand } from \"./commands/pr.js\";\nimport { statusCommand } from \"./commands/status.js\";\n\nconst program = new Command();\n\nprogram\n .name(\"gent\")\n .description(\"AI-powered GitHub workflow CLI - leverage Claude AI to create tickets, implement features, and manage PRs\")\n .version(\"0.1.0\");\n\nprogram\n .command(\"init\")\n .description(\"Initialize gent workflow in current repository\")\n .option(\"-f, --force\", \"Overwrite existing configuration\")\n .action(async (options) => {\n await initCommand(options);\n });\n\nprogram\n .command(\"setup-labels\")\n .description(\"Setup GitHub labels for AI workflow\")\n .action(async () => {\n await setupLabelsCommand();\n });\n\nprogram\n .command(\"create <description>\")\n .description(\"Create an AI-enhanced GitHub issue\")\n .option(\"-y, --yes\", \"Skip confirmation and create issue immediately\")\n .option(\"-p, --provider <provider>\", \"AI provider to use (claude or gemini)\")\n .action(async (description, options) => {\n await createCommand(description, { yes: options.yes, provider: options.provider });\n });\n\nprogram\n .command(\"list\")\n .description(\"List GitHub issues by label/status\")\n .option(\"-l, --label <label>\", \"Filter by label\")\n .option(\"-s, --status <status>\", \"Filter by workflow status (ready, in-progress, completed, blocked, all)\")\n .option(\"-n, --limit <number>\", \"Maximum number of issues to show\", \"20\")\n .action(async (options) => {\n await listCommand({\n label: options.label,\n status: options.status,\n limit: parseInt(options.limit, 10),\n });\n });\n\nprogram\n .command(\"run [issue-number]\")\n .description(\"Run AI to implement a GitHub issue\")\n .option(\"-a, --auto\", \"Auto-select highest priority ai-ready issue\")\n .option(\"-p, --provider <provider>\", \"AI provider to use (claude or gemini)\")\n .action(async (issueNumber, options) => {\n await runCommand(issueNumber, { auto: options.auto, provider: options.provider });\n });\n\nprogram\n .command(\"pr\")\n .description(\"Create an AI-enhanced pull request\")\n .option(\"-d, --draft\", \"Create as draft PR\")\n .option(\"-p, --provider <provider>\", \"AI provider to use (claude or gemini)\")\n .action(async (options) => {\n await prCommand({ draft: options.draft, provider: options.provider });\n });\n\nprogram\n .command(\"status\")\n .description(\"Show current workflow status\")\n .action(async () => {\n await statusCommand();\n });\n\nprogram.parse();\n","import { writeFileSync, existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport inquirer from \"inquirer\";\nimport { logger, colors } from \"../utils/logger.js\";\nimport { checkGitRepo } from \"../utils/validators.js\";\nimport { configExists, generateDefaultConfig, getConfigPath } from \"../lib/config.js\";\nimport { initializeProgress } from \"../lib/progress.js\";\nimport { loadConfig } from \"../lib/config.js\";\n\nconst DEFAULT_AGENT_MD = `# AI Agent Instructions\n\nThis file contains instructions for Claude when working on this repository.\n\n## Project Overview\n\n[Describe your project, its purpose, and key technologies used]\n\n## Code Patterns\n\n### Architecture\n[Document your architecture - e.g., MVC, Clean Architecture, etc.]\n\n### Naming Conventions\n[Document naming conventions for files, functions, variables, etc.]\n\n### Component Structure\n[If applicable, describe component/module structure]\n\n## Testing Requirements\n\n### Unit Tests\n- All new functions should have corresponding unit tests\n- Use [your testing framework] for unit tests\n- Aim for [X]% coverage on new code\n\n### Integration Tests\n[Document when and how to write integration tests]\n\n## Commit Conventions\n\nFollow conventional commits format:\n- \\`feat:\\` New feature\n- \\`fix:\\` Bug fix\n- \\`refactor:\\` Code improvement without behavior change\n- \\`test:\\` Testing additions\n- \\`chore:\\` Maintenance/dependencies\n- \\`docs:\\` Documentation\n\nAll AI commits should include:\n\\`\\`\\`\nCo-Authored-By: Claude <noreply@anthropic.com>\n\\`\\`\\`\n\n## Important Files\n\n[List key files the AI should understand before making changes]\n\n- \\`src/index.ts\\` - Main entry point\n- \\`src/config/\\` - Configuration files\n- [Add more key files]\n\n## Constraints\n\n- [List any constraints or limitations]\n- [E.g., \"Do not modify files in /vendor\"]\n- [E.g., \"Always use async/await over callbacks\"]\n`;\n\nexport async function initCommand(options: { force?: boolean }): Promise<void> {\n logger.bold(\"Initializing gent workflow...\");\n logger.newline();\n\n // Check if we're in a git repo\n const isGitRepo = await checkGitRepo();\n if (!isGitRepo) {\n logger.error(\"Not a git repository. Please run 'git init' first.\");\n process.exit(1);\n }\n\n const cwd = process.cwd();\n\n // Check if already initialized\n if (configExists(cwd) && !options.force) {\n const { overwrite } = await inquirer.prompt([\n {\n type: \"confirm\",\n name: \"overwrite\",\n message: \"gent is already initialized. Overwrite existing config?\",\n default: false,\n },\n ]);\n\n if (!overwrite) {\n logger.info(\"Initialization cancelled.\");\n return;\n }\n }\n\n // Create .gent.yml\n const configPath = getConfigPath(cwd);\n writeFileSync(configPath, generateDefaultConfig(), \"utf-8\");\n logger.success(`Created ${colors.file(\".gent.yml\")}`);\n\n // Create AGENT.md\n const agentPath = join(cwd, \"AGENT.md\");\n if (!existsSync(agentPath) || options.force) {\n writeFileSync(agentPath, DEFAULT_AGENT_MD, \"utf-8\");\n logger.success(`Created ${colors.file(\"AGENT.md\")}`);\n } else {\n logger.info(`${colors.file(\"AGENT.md\")} already exists, skipping`);\n }\n\n // Create progress.txt\n const config = loadConfig(cwd);\n initializeProgress(config, cwd);\n logger.success(`Created ${colors.file(config.progress.file)}`);\n\n logger.newline();\n logger.box(\"Setup Complete\", `Next steps:\n1. Edit ${colors.file(\"AGENT.md\")} with your project-specific instructions\n2. Edit ${colors.file(\".gent.yml\")} to customize settings\n3. Run ${colors.command(\"gent setup-labels\")} to create GitHub labels\n4. Run ${colors.command(\"gent create <description>\")} to create your first ticket`);\n\n // Ask about setting up labels\n const { setupLabels } = await inquirer.prompt([\n {\n type: \"confirm\",\n name: \"setupLabels\",\n message: \"Would you like to setup GitHub labels now?\",\n default: true,\n },\n ]);\n\n if (setupLabels) {\n const { setupLabelsCommand } = await import(\"./setup-labels.js\");\n await setupLabelsCommand();\n }\n}\n","import { existsSync, readFileSync, writeFileSync, mkdirSync } from \"node:fs\";\nimport { join, dirname } from \"node:path\";\nimport type { GentConfig, ProgressEntry } from \"../types/index.js\";\n\nexport function getProgressPath(\n config: GentConfig,\n cwd: string = process.cwd()\n): string {\n return join(cwd, config.progress.file);\n}\n\nexport function progressExists(\n config: GentConfig,\n cwd: string = process.cwd()\n): boolean {\n return existsSync(getProgressPath(config, cwd));\n}\n\nexport function readProgress(\n config: GentConfig,\n cwd: string = process.cwd()\n): string {\n const path = getProgressPath(config, cwd);\n if (!existsSync(path)) {\n return \"\";\n }\n return readFileSync(path, \"utf-8\");\n}\n\nexport function appendProgress(\n config: GentConfig,\n entry: ProgressEntry,\n cwd: string = process.cwd()\n): void {\n const path = getProgressPath(config, cwd);\n const content = formatProgressEntry(entry);\n\n // Ensure directory exists\n const dir = dirname(path);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n\n // Read existing content\n let existing = \"\";\n if (existsSync(path)) {\n existing = readFileSync(path, \"utf-8\");\n }\n\n // Check if we need to archive\n const lines = existing.split(\"\\n\").length;\n if (lines > config.progress.archive_threshold) {\n archiveProgress(config, existing, cwd);\n existing = `# Progress Log (archived previous entries)\\n\\n`;\n }\n\n // Append new entry\n writeFileSync(path, existing + content, \"utf-8\");\n}\n\nexport function formatProgressEntry(entry: ProgressEntry): string {\n let content = `\\n[${entry.date}] ${entry.type}: ${entry.description}\\n`;\n\n if (entry.issue) {\n content += `- Completed GitHub issue #${entry.issue}\\n`;\n }\n\n if (entry.decisions.length > 0) {\n content += `- Key implementation decisions:\\n`;\n for (const decision of entry.decisions) {\n content += ` * ${decision}\\n`;\n }\n }\n\n if (entry.files.length > 0) {\n content += `- Files changed:\\n`;\n for (const file of entry.files) {\n content += ` * ${file}\\n`;\n }\n }\n\n if (entry.tests.length > 0) {\n content += `- Tests: ${entry.tests.join(\", \")}\\n`;\n }\n\n if (entry.concerns.length > 0) {\n content += `- Concerns for reviewers:\\n`;\n for (const concern of entry.concerns) {\n content += ` * ${concern}\\n`;\n }\n }\n\n if (entry.followUp.length > 0) {\n content += `- Follow-up tasks:\\n`;\n for (const task of entry.followUp) {\n content += ` * ${task}\\n`;\n }\n }\n\n if (entry.commit) {\n content += `- Commit: ${entry.commit}\\n`;\n }\n\n return content;\n}\n\nfunction archiveProgress(\n config: GentConfig,\n content: string,\n cwd: string\n): void {\n const archiveDir = join(cwd, config.progress.archive_dir);\n\n if (!existsSync(archiveDir)) {\n mkdirSync(archiveDir, { recursive: true });\n }\n\n const date = new Date().toISOString().split(\"T\")[0];\n const archivePath = join(archiveDir, `progress-${date}.txt`);\n\n writeFileSync(archivePath, content, \"utf-8\");\n}\n\nexport function initializeProgress(\n config: GentConfig,\n cwd: string = process.cwd()\n): void {\n const path = getProgressPath(config, cwd);\n\n if (existsSync(path)) {\n return;\n }\n\n const initialContent = `# Progress Log\n\nThis file tracks AI-assisted development progress.\nEach entry documents: date, feature, decisions, files changed, tests, and concerns.\n\n---\n`;\n\n const dir = dirname(path);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n\n writeFileSync(path, initialContent, \"utf-8\");\n}\n\nexport function getRecentProgress(\n config: GentConfig,\n cwd: string = process.cwd(),\n maxLines: number = 100\n): string {\n const content = readProgress(config, cwd);\n const lines = content.split(\"\\n\");\n\n if (lines.length <= maxLines) {\n return content;\n }\n\n return lines.slice(-maxLines).join(\"\\n\");\n}\n","import inquirer from \"inquirer\";\nimport chalk from \"chalk\";\nimport { logger, colors } from \"../utils/logger.js\";\nimport { withSpinner } from \"../utils/spinner.js\";\nimport { loadConfig, loadAgentInstructions } from \"../lib/config.js\";\nimport {\n buildTicketPrompt,\n parseTicketMeta,\n extractIssueBody,\n} from \"../lib/claude.js\";\nimport { invokeAI, getProviderDisplayName } from \"../lib/ai-provider.js\";\nimport { createIssue } from \"../lib/github.js\";\nimport { buildIssueLabels } from \"../lib/labels.js\";\nimport { checkGhAuth, checkAIProvider } from \"../utils/validators.js\";\nimport type { AIProvider } from \"../types/index.js\";\n\nexport interface CreateOptions {\n yes?: boolean;\n provider?: AIProvider;\n}\n\ninterface TicketMeta {\n type: string;\n priority: string;\n risk: string;\n area: string;\n}\n\nexport async function createCommand(\n description: string,\n options: CreateOptions\n): Promise<void> {\n logger.bold(\"Creating AI-enhanced ticket...\");\n logger.newline();\n\n const config = loadConfig();\n\n // Determine which provider to use\n const provider = options.provider ?? config.ai.provider;\n const providerName = getProviderDisplayName(provider);\n\n // Validate prerequisites\n const [ghAuth, aiOk] = await Promise.all([\n checkGhAuth(),\n checkAIProvider(provider),\n ]);\n\n if (!ghAuth) {\n logger.error(\"Not authenticated with GitHub. Run 'gh auth login' first.\");\n process.exit(1);\n }\n\n if (!aiOk) {\n logger.error(`${providerName} CLI not found. Please install ${provider} CLI first.`);\n process.exit(1);\n }\n\n const agentInstructions = loadAgentInstructions();\n\n // Generate ticket with AI (may loop if user wants to regenerate)\n let aiOutput: string;\n let additionalHints: string | null = null;\n\n while (true) {\n // Build prompt and invoke AI\n const prompt = buildTicketPrompt(description, agentInstructions, additionalHints);\n\n try {\n // Show visual indicator before AI output\n console.log(chalk.dim(`┌─ Generating ticket with ${providerName}... ──────────────────────────┐`));\n logger.newline();\n const result = await invokeAI({ prompt, streamOutput: true }, config, options.provider);\n aiOutput = result.output;\n logger.newline();\n console.log(chalk.dim(\"└────────────────────────────────────────────────────────────┘\"));\n logger.newline();\n } catch (error) {\n logger.error(`${providerName} invocation failed: ${error}`);\n return;\n }\n\n // Parse metadata\n const meta = parseTicketMeta(aiOutput);\n if (!meta) {\n logger.warning(\"Could not parse metadata from Claude output. Using defaults.\");\n }\n\n const finalMeta: TicketMeta = meta || {\n type: \"feature\",\n priority: \"medium\",\n risk: \"low\",\n area: \"shared\",\n };\n\n // Extract issue body (without META line) and append signature\n const issueBody = extractIssueBody(aiOutput) + `\\n\\n---\\n*Created with ${providerName} by [gent](https://github.com/Rotorsoft/gent)*`;\n\n // Generate title from description\n const title =\n description.length > 60 ? description.slice(0, 57) + \"...\" : description;\n\n // Build labels\n const labels = buildIssueLabels(finalMeta);\n\n // Show ticket preview\n displayTicketPreview(title, finalMeta, issueBody);\n\n // Skip confirmation if --yes flag is passed\n if (options.yes) {\n await createAndDisplayIssue(title, issueBody, labels, finalMeta);\n return;\n }\n\n // Ask for confirmation\n const { action } = await inquirer.prompt([\n {\n type: \"list\",\n name: \"action\",\n message: \"What would you like to do?\",\n choices: [\n { name: \"Create issue\", value: \"create\" },\n { name: \"Edit description and regenerate\", value: \"edit\" },\n { name: \"Cancel\", value: \"cancel\" },\n ],\n },\n ]);\n\n if (action === \"cancel\") {\n logger.info(\"Issue creation cancelled.\");\n return;\n }\n\n if (action === \"create\") {\n await createAndDisplayIssue(title, issueBody, labels, finalMeta);\n return;\n }\n\n // action === \"edit\" - prompt for additional hints\n const { hints } = await inquirer.prompt([\n {\n type: \"input\",\n name: \"hints\",\n message: \"Enter additional hints or context for Claude:\",\n },\n ]);\n\n if (hints.trim()) {\n additionalHints = additionalHints\n ? `${additionalHints}\\n${hints.trim()}`\n : hints.trim();\n }\n\n logger.newline();\n logger.info(\"Regenerating ticket with additional context...\");\n logger.newline();\n }\n}\n\nfunction displayTicketPreview(\n title: string,\n meta: TicketMeta,\n body: string\n): void {\n // Count lines for summary\n const lineCount = body.split(\"\\n\").length;\n\n // Section header helper\n const sectionHeader = (label: string) =>\n console.log(chalk.bold.cyan(`${label}`));\n\n // Display preview with clean sections\n console.log(chalk.bold.white(\"━━━ Ticket Preview ━━━\"));\n logger.newline();\n\n sectionHeader(\"Title\");\n console.log(` ${title}`);\n logger.newline();\n\n sectionHeader(\"Labels\");\n console.log(\n ` ${colors.label(`type:${meta.type}`)} ${colors.label(`priority:${meta.priority}`)} ${colors.label(`risk:${meta.risk}`)} ${colors.label(`area:${meta.area}`)}`\n );\n logger.newline();\n\n sectionHeader(`Body (${lineCount} lines)`);\n // Indent each line of the body for visual hierarchy\n const bodyLines = body.split(\"\\n\");\n for (const line of bodyLines) {\n console.log(` ${line}`);\n }\n\n logger.newline();\n console.log(chalk.bold.white(\"━━━━━━━━━━━━━━━━━━━━━━\"));\n logger.newline();\n}\n\nasync function createAndDisplayIssue(\n title: string,\n body: string,\n labels: string[],\n meta: TicketMeta\n): Promise<void> {\n let issueNumber: number;\n try {\n issueNumber = await withSpinner(\"Creating GitHub issue...\", async () => {\n return createIssue({\n title,\n body,\n labels,\n });\n });\n } catch (error) {\n logger.error(`Failed to create issue: ${error}`);\n return;\n }\n\n logger.newline();\n logger.success(`Created issue ${colors.issue(`#${issueNumber}`)}`);\n logger.newline();\n\n logger.box(\n \"Issue Created\",\n `Issue: ${colors.issue(`#${issueNumber}`)}\nType: ${colors.label(`type:${meta.type}`)}\nPriority: ${colors.label(`priority:${meta.priority}`)}\nRisk: ${colors.label(`risk:${meta.risk}`)}\nArea: ${colors.label(`area:${meta.area}`)}\n\nNext steps:\n1. Review the issue on GitHub\n2. Run ${colors.command(`gent run ${issueNumber}`)} to implement`\n );\n}\n","import { spawn } from \"child_process\";\nimport { execa, type ResultPromise } from \"execa\";\nimport type { GentConfig } from \"../types/index.js\";\n\nexport interface ClaudeOptions {\n prompt: string;\n permissionMode?: string;\n printOutput?: boolean;\n streamOutput?: boolean;\n}\n\nexport async function invokeClaude(options: ClaudeOptions): Promise<string> {\n const args = [\"--print\"];\n\n if (options.permissionMode) {\n args.push(\"--permission-mode\", options.permissionMode);\n }\n\n args.push(options.prompt);\n\n if (options.printOutput) {\n // Stream output to console without capturing\n const subprocess = execa(\"claude\", args, {\n stdio: \"inherit\",\n });\n await subprocess;\n return \"\";\n } else if (options.streamOutput) {\n // Use native spawn for better streaming control\n return new Promise((resolve, reject) => {\n const child = spawn(\"claude\", args, {\n stdio: [\"inherit\", \"pipe\", \"pipe\"],\n });\n\n let output = \"\";\n\n child.stdout.on(\"data\", (chunk: Buffer) => {\n const text = chunk.toString();\n output += text;\n process.stdout.write(text);\n });\n\n child.stderr.on(\"data\", (chunk: Buffer) => {\n process.stderr.write(chunk);\n });\n\n child.on(\"close\", (code) => {\n if (code === 0) {\n resolve(output);\n } else {\n reject(new Error(`Claude exited with code ${code}`));\n }\n });\n\n child.on(\"error\", reject);\n });\n } else {\n const { stdout } = await execa(\"claude\", args);\n return stdout;\n }\n}\n\nexport async function invokeClaudeInteractive(\n prompt: string,\n config: GentConfig\n): Promise<ResultPromise> {\n const args = [\"--permission-mode\", config.claude.permission_mode, prompt];\n\n return execa(\"claude\", args, {\n stdio: \"inherit\",\n });\n}\n\nexport function buildTicketPrompt(\n description: string,\n agentInstructions: string | null,\n additionalHints: string | null = null\n): string {\n const basePrompt = `You are creating a GitHub issue for a software project following an AI-assisted development workflow.\n\nUser Request: ${description}\n\n${agentInstructions ? `Project-Specific Instructions:\\n${agentInstructions}\\n\\n` : \"\"}${additionalHints ? `Additional Context/Hints:\\n${additionalHints}\\n\\n` : \"\"}\n\nCreate a detailed GitHub issue following this exact template.\n\nIMPORTANT: Start your output IMMEDIATELY with \"## Description\" - do not include any preamble, commentary, or introduction before the template.\n\n## Description\n[Clear user-facing description of what needs to be done]\n\n## Technical Context\n**Type:** feature | fix | refactor | chore | docs | test\n**Category:** ui | api | database | workers | shared | testing | infra\n**Priority:** critical | high | medium | low\n**Risk:** low | medium | high\n\n### Architecture Notes\n- [Relevant patterns to follow]\n- [Related systems affected]\n- [Constraints or invariants]\n\n## Implementation Steps\n- [ ] Step 1: Specific technical task\n- [ ] Step 2: Specific technical task\n- [ ] Step 3: Specific technical task\n\n## Testing Requirements\n- **Unit tests:** [What to test]\n- **Integration tests:** [What to test if applicable]\n- **Manual verification:** [What to check]\n\n## Acceptance Criteria\n- [ ] Criterion 1\n- [ ] Criterion 2\n\n---\nIMPORTANT: After the issue content, on a new line, output ONLY the following metadata in this exact format:\nMETA:type=<type>,priority=<priority>,risk=<risk>,area=<area>\n\nExample: META:type=feature,priority=high,risk=low,area=ui`;\n\n return basePrompt;\n}\n\nexport function buildImplementationPrompt(\n issue: { number: number; title: string; body: string },\n agentInstructions: string | null,\n progressContent: string | null,\n config: GentConfig\n): string {\n return `GitHub Issue #${issue.number}: ${issue.title}\n\n${issue.body}\n\n${agentInstructions ? `## Project-Specific Instructions\\n${agentInstructions}\\n\\n` : \"\"}\n${progressContent ? `## Previous Progress\\n${progressContent}\\n\\n` : \"\"}\n\n## Your Task\n\n1. **Implement the feature/fix** following patterns from the project's AGENT.md or codebase conventions\n2. **Add unit tests** for any new functionality\n3. **Run validation** before committing:\n${config.validation.map((cmd) => ` - ${cmd}`).join(\"\\n\")}\n4. **Make an atomic commit** with a clear message following conventional commits format:\n - Use format: <type>: <description>\n - Include \"Completed GitHub issue #${issue.number}\" in body\n - End with: Co-Authored-By: Claude <noreply@anthropic.com>\n5. **Update ${config.progress.file}** - append a compact entry documenting your work:\n \\`\\`\\`\n [YYYY-MM-DD] #${issue.number} <type>: <brief description>\n - Files: <comma-separated list of changed files>\n - Changes: <1-2 sentence summary of what was implemented>\n - Decisions: <key technical decisions made, if any>\n - Issues: <concerns or follow-ups for reviewers, if any>\n \\`\\`\\`\n Keep entries minimal (4-6 lines max). Skip sections if not applicable.\n6. **Do NOT push** - the user will review and push manually\n\nFocus on clean, minimal implementation. Don't over-engineer.`;\n}\n\nexport function buildPrPrompt(\n issue: { number: number; title: string; body: string } | null,\n commits: string[],\n diffSummary: string\n): string {\n return `Generate a pull request description for the following changes.\n\n${issue ? `## Related Issue\\n#${issue.number}: ${issue.title}\\n\\n${issue.body}\\n\\n` : \"\"}\n\n## Commits\n${commits.map((c) => `- ${c}`).join(\"\\n\")}\n\n## Changed Files\n${diffSummary}\n\nGenerate a PR description in this format:\n\n## Summary\n- [1-3 bullet points summarizing the changes]\n\n## Test Plan\n- [ ] [Testing steps]\n\n${issue ? `Closes #${issue.number}` : \"\"}\n\nOnly output the PR description, nothing else.`;\n}\n\nexport function parseTicketMeta(\n output: string\n): { type: string; priority: string; risk: string; area: string } | null {\n const metaMatch = output.match(\n /META:type=(\\w+),priority=(\\w+),risk=(\\w+),area=(\\w+)/\n );\n\n if (!metaMatch) {\n return null;\n }\n\n return {\n type: metaMatch[1],\n priority: metaMatch[2],\n risk: metaMatch[3],\n area: metaMatch[4],\n };\n}\n\nexport function extractIssueBody(output: string): string {\n // Remove the META line from the output\n let body = output.replace(/\\n?META:type=\\w+,priority=\\w+,risk=\\w+,area=\\w+\\s*$/, \"\").trim();\n\n // Strip any preamble text before \"## Description\"\n const descriptionIndex = body.indexOf(\"## Description\");\n if (descriptionIndex > 0) {\n body = body.substring(descriptionIndex);\n }\n\n return body;\n}\n","import { spawn } from \"child_process\";\nimport { execa, type ResultPromise } from \"execa\";\nimport type { GentConfig, AIProvider } from \"../types/index.js\";\nimport { logger, colors } from \"../utils/logger.js\";\n\nexport interface AIProviderOptions {\n prompt: string;\n permissionMode?: string;\n printOutput?: boolean;\n streamOutput?: boolean;\n}\n\nexport interface AIProviderResult {\n output: string;\n provider: AIProvider;\n rateLimited?: boolean;\n}\n\n/**\n * Invoke AI provider (non-interactive mode)\n * Returns output from the provider\n */\nexport async function invokeAI(\n options: AIProviderOptions,\n config: GentConfig,\n providerOverride?: AIProvider\n): Promise<AIProviderResult> {\n const provider = providerOverride ?? config.ai.provider;\n\n try {\n const output = provider === \"claude\"\n ? await invokeClaudeInternal(options)\n : await invokeGeminiInternal(options);\n\n return { output, provider };\n } catch (error) {\n // Check for rate limiting\n if (isRateLimitError(error, provider)) {\n // Try fallback if configured\n if (config.ai.auto_fallback && config.ai.fallback_provider && !providerOverride) {\n const fallback = config.ai.fallback_provider;\n logger.warning(`Rate limit reached on ${getProviderDisplayName(provider)}, switching to ${getProviderDisplayName(fallback)}...`);\n\n const output = fallback === \"claude\"\n ? await invokeClaudeInternal(options)\n : await invokeGeminiInternal(options);\n\n return { output, provider: fallback };\n }\n\n // Return rate limited error\n const err = error as Error;\n err.message = `Rate limited on ${getProviderDisplayName(provider)}`;\n (err as Error & { rateLimited: boolean }).rateLimited = true;\n throw err;\n }\n\n throw error;\n }\n}\n\n/**\n * Invoke AI provider in interactive mode (stdio inherited)\n * Used for implementation sessions\n */\nexport async function invokeAIInteractive(\n prompt: string,\n config: GentConfig,\n providerOverride?: AIProvider\n): Promise<{ result: ResultPromise; provider: AIProvider }> {\n const provider = providerOverride ?? config.ai.provider;\n\n if (provider === \"claude\") {\n const args = [\"--permission-mode\", config.claude.permission_mode, prompt];\n return {\n result: execa(\"claude\", args, { stdio: \"inherit\" }),\n provider,\n };\n } else {\n // Gemini CLI uses -i/--prompt-interactive for interactive mode with initial prompt\n // Without -i, the positional prompt runs in one-shot mode and exits\n return {\n result: execa(\"gemini\", [\"-i\", prompt], { stdio: \"inherit\" }),\n provider,\n };\n }\n}\n\n/**\n * Get display name for provider\n */\nexport function getProviderDisplayName(provider: AIProvider): string {\n return provider === \"claude\" ? \"Claude\" : \"Gemini\";\n}\n\n/**\n * Get colored provider name for display\n */\nexport function getProviderDisplay(provider: AIProvider): string {\n const name = getProviderDisplayName(provider);\n return provider === \"claude\"\n ? colors.command(name)\n : colors.label(name);\n}\n\n/**\n * Check if error is a rate limit error\n */\nfunction isRateLimitError(error: unknown, provider: AIProvider): boolean {\n if (!error || typeof error !== \"object\") return false;\n\n // Claude CLI uses exit code 2 for rate limiting\n if (provider === \"claude\" && \"exitCode\" in error && error.exitCode === 2) {\n return true;\n }\n\n // Gemini CLI may use different exit codes or error messages\n // Check for common rate limit patterns in error messages\n if (\"message\" in error && typeof error.message === \"string\") {\n const msg = error.message.toLowerCase();\n if (msg.includes(\"rate limit\") || msg.includes(\"quota exceeded\") || msg.includes(\"too many requests\")) {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * Internal Claude invocation\n */\nasync function invokeClaudeInternal(options: AIProviderOptions): Promise<string> {\n const args = [\"--print\"];\n\n if (options.permissionMode) {\n args.push(\"--permission-mode\", options.permissionMode);\n }\n\n args.push(options.prompt);\n\n if (options.printOutput) {\n // Stream output to console without capturing\n const subprocess = execa(\"claude\", args, {\n stdio: \"inherit\",\n });\n await subprocess;\n return \"\";\n } else if (options.streamOutput) {\n // Use native spawn for better streaming control\n return new Promise((resolve, reject) => {\n const child = spawn(\"claude\", args, {\n stdio: [\"inherit\", \"pipe\", \"pipe\"],\n });\n\n let output = \"\";\n\n child.stdout.on(\"data\", (chunk: Buffer) => {\n const text = chunk.toString();\n output += text;\n process.stdout.write(text);\n });\n\n child.stderr.on(\"data\", (chunk: Buffer) => {\n process.stderr.write(chunk);\n });\n\n child.on(\"close\", (code) => {\n if (code === 0) {\n resolve(output);\n } else {\n const error = new Error(`Claude exited with code ${code}`);\n (error as Error & { exitCode: number }).exitCode = code ?? 1;\n reject(error);\n }\n });\n\n child.on(\"error\", reject);\n });\n } else {\n const { stdout } = await execa(\"claude\", args);\n return stdout;\n }\n}\n\n/**\n * Internal Gemini invocation\n */\nasync function invokeGeminiInternal(options: AIProviderOptions): Promise<string> {\n // Gemini CLI uses different argument structure\n const args: string[] = [];\n\n // Add prompt\n args.push(options.prompt);\n\n if (options.printOutput) {\n const subprocess = execa(\"gemini\", args, {\n stdio: \"inherit\",\n });\n await subprocess;\n return \"\";\n } else if (options.streamOutput) {\n return new Promise((resolve, reject) => {\n const child = spawn(\"gemini\", args, {\n stdio: [\"inherit\", \"pipe\", \"pipe\"],\n });\n\n let output = \"\";\n\n child.stdout.on(\"data\", (chunk: Buffer) => {\n const text = chunk.toString();\n output += text;\n process.stdout.write(text);\n });\n\n child.stderr.on(\"data\", (chunk: Buffer) => {\n process.stderr.write(chunk);\n });\n\n child.on(\"close\", (code) => {\n if (code === 0) {\n resolve(output);\n } else {\n const error = new Error(`Gemini exited with code ${code}`);\n (error as Error & { exitCode: number }).exitCode = code ?? 1;\n reject(error);\n }\n });\n\n child.on(\"error\", reject);\n });\n } else {\n const { stdout } = await execa(\"gemini\", args);\n return stdout;\n }\n}\n","import chalk from \"chalk\";\nimport { logger, colors } from \"../utils/logger.js\";\nimport { loadConfig } from \"../lib/config.js\";\nimport { listIssues } from \"../lib/github.js\";\nimport { getWorkflowLabels, sortByPriority, extractPriorityFromLabels, extractTypeFromLabels } from \"../lib/labels.js\";\nimport { checkGhAuth } from \"../utils/validators.js\";\nimport type { GitHubIssue } from \"../types/index.js\";\n\nexport interface ListOptions {\n label?: string;\n status?: \"ready\" | \"in-progress\" | \"completed\" | \"blocked\" | \"all\";\n limit?: number;\n}\n\nexport async function listCommand(options: ListOptions): Promise<void> {\n // Check gh auth\n const isAuthed = await checkGhAuth();\n if (!isAuthed) {\n logger.error(\"Not authenticated with GitHub. Run 'gh auth login' first.\");\n process.exit(1);\n }\n\n const config = loadConfig();\n const workflowLabels = getWorkflowLabels(config);\n\n // Build label filter\n const labels: string[] = [];\n\n if (options.label) {\n labels.push(options.label);\n }\n\n if (options.status && options.status !== \"all\") {\n switch (options.status) {\n case \"ready\":\n labels.push(workflowLabels.ready);\n break;\n case \"in-progress\":\n labels.push(workflowLabels.inProgress);\n break;\n case \"completed\":\n labels.push(workflowLabels.completed);\n break;\n case \"blocked\":\n labels.push(workflowLabels.blocked);\n break;\n }\n } else if (!options.status) {\n // Default to showing ai-ready issues\n labels.push(workflowLabels.ready);\n }\n\n let issues: GitHubIssue[];\n try {\n issues = await listIssues({\n labels: labels.length > 0 ? labels : undefined,\n state: \"open\",\n limit: options.limit || 20,\n });\n } catch (error) {\n logger.error(`Failed to fetch issues: ${error}`);\n return;\n }\n\n if (issues.length === 0) {\n logger.info(\"No issues found matching the criteria.\");\n return;\n }\n\n // Sort by priority\n sortByPriority(issues);\n\n logger.bold(`Found ${issues.length} issue(s):`);\n logger.newline();\n\n for (const issue of issues) {\n const type = extractTypeFromLabels(issue.labels);\n const priority = extractPriorityFromLabels(issue.labels);\n const status = getIssueStatus(issue.labels, workflowLabels);\n\n const priorityColor = getPriorityColor(priority);\n const statusColor = getStatusColor(status);\n\n console.log(\n ` ${colors.issue(`#${issue.number.toString().padStart(4)}`)} ` +\n `${priorityColor(`[${priority}]`.padEnd(10))} ` +\n `${statusColor(`[${status}]`.padEnd(14))} ` +\n `${colors.label(`[${type}]`.padEnd(10))} ` +\n issue.title.slice(0, 50) +\n (issue.title.length > 50 ? \"...\" : \"\")\n );\n }\n\n logger.newline();\n logger.dim(`Run ${colors.command(\"gent run <issue-number>\")} to implement an issue`);\n logger.dim(`Run ${colors.command(\"gent run --auto\")} to auto-select highest priority`);\n}\n\nfunction getIssueStatus(\n labels: string[],\n workflowLabels: ReturnType<typeof getWorkflowLabels>\n): string {\n if (labels.includes(workflowLabels.ready)) return \"ready\";\n if (labels.includes(workflowLabels.inProgress)) return \"in-progress\";\n if (labels.includes(workflowLabels.completed)) return \"completed\";\n if (labels.includes(workflowLabels.blocked)) return \"blocked\";\n return \"unknown\";\n}\n\nfunction getPriorityColor(priority: string): (text: string) => string {\n switch (priority) {\n case \"critical\":\n return chalk.red;\n case \"high\":\n return chalk.yellow;\n case \"medium\":\n return chalk.blue;\n case \"low\":\n return chalk.green;\n default:\n return chalk.gray;\n }\n}\n\nfunction getStatusColor(status: string): (text: string) => string {\n switch (status) {\n case \"ready\":\n return chalk.green;\n case \"in-progress\":\n return chalk.yellow;\n case \"completed\":\n return chalk.blue;\n case \"blocked\":\n return chalk.red;\n default:\n return chalk.gray;\n }\n}\n","import inquirer from \"inquirer\";\nimport { logger, colors } from \"../utils/logger.js\";\nimport { withSpinner } from \"../utils/spinner.js\";\nimport { loadConfig, loadAgentInstructions } from \"../lib/config.js\";\nimport { getIssue, listIssues, updateIssueLabels, addIssueComment } from \"../lib/github.js\";\nimport { buildImplementationPrompt } from \"../lib/claude.js\";\nimport { invokeAIInteractive, getProviderDisplayName } from \"../lib/ai-provider.js\";\nimport { getCurrentBranch, isOnMainBranch, createBranch, branchExists, checkoutBranch, hasUncommittedChanges, getCurrentCommitSha, hasNewCommits } from \"../lib/git.js\";\nimport { generateBranchName } from \"../lib/branch.js\";\nimport { getWorkflowLabels, extractTypeFromLabels, sortByPriority } from \"../lib/labels.js\";\nimport { readProgress } from \"../lib/progress.js\";\nimport { checkGhAuth, checkAIProvider, isValidIssueNumber } from \"../utils/validators.js\";\nimport type { GitHubIssue, AIProvider } from \"../types/index.js\";\n\nexport interface RunOptions {\n auto?: boolean;\n provider?: AIProvider;\n}\n\nexport async function runCommand(\n issueNumberArg: string | undefined,\n options: RunOptions\n): Promise<void> {\n logger.bold(\"Running AI implementation workflow...\");\n logger.newline();\n\n const config = loadConfig();\n\n // Determine which provider to use\n const provider = options.provider ?? config.ai.provider;\n const providerName = getProviderDisplayName(provider);\n\n // Validate prerequisites\n const [ghAuth, aiOk] = await Promise.all([\n checkGhAuth(),\n checkAIProvider(provider),\n ]);\n\n if (!ghAuth) {\n logger.error(\"Not authenticated with GitHub. Run 'gh auth login' first.\");\n process.exit(1);\n }\n\n if (!aiOk) {\n logger.error(`${providerName} CLI not found. Please install ${provider} CLI first.`);\n process.exit(1);\n }\n\n // Check for uncommitted changes\n const hasChanges = await hasUncommittedChanges();\n if (hasChanges) {\n logger.warning(\"You have uncommitted changes.\");\n const { proceed } = await inquirer.prompt([\n {\n type: \"confirm\",\n name: \"proceed\",\n message: \"Continue anyway?\",\n default: false,\n },\n ]);\n if (!proceed) {\n logger.info(\"Aborting. Please commit or stash your changes first.\");\n process.exit(0);\n }\n }\n\n const workflowLabels = getWorkflowLabels(config);\n\n // Get issue number\n let issueNumber: number;\n\n if (options.auto) {\n // Auto-select highest priority ai-ready issue\n const autoIssue = await autoSelectIssue(workflowLabels.ready);\n if (!autoIssue) {\n logger.error(\"No ai-ready issues found.\");\n process.exit(1);\n }\n issueNumber = autoIssue.number;\n logger.info(`Auto-selected: ${colors.issue(`#${issueNumber}`)} - ${autoIssue.title}`);\n } else if (issueNumberArg) {\n if (!isValidIssueNumber(issueNumberArg)) {\n logger.error(\"Invalid issue number.\");\n process.exit(1);\n }\n issueNumber = parseInt(issueNumberArg, 10);\n } else {\n logger.error(\"Please provide an issue number or use --auto\");\n process.exit(1);\n }\n\n // Fetch issue details\n let issue: GitHubIssue;\n try {\n issue = await withSpinner(\"Fetching issue...\", async () => {\n return getIssue(issueNumber);\n });\n } catch (error) {\n logger.error(`Failed to fetch issue #${issueNumber}: ${error}`);\n return;\n }\n\n // Verify issue has ai-ready label\n if (!issue.labels.includes(workflowLabels.ready)) {\n logger.warning(`Issue #${issueNumber} does not have the '${workflowLabels.ready}' label.`);\n const { proceed } = await inquirer.prompt([\n {\n type: \"confirm\",\n name: \"proceed\",\n message: \"Continue anyway?\",\n default: false,\n },\n ]);\n if (!proceed) {\n return;\n }\n }\n\n logger.newline();\n logger.box(\"Issue Details\", `#${issue.number}: ${issue.title}\nLabels: ${issue.labels.join(\", \")}`);\n logger.newline();\n\n // Generate branch name\n const type = extractTypeFromLabels(issue.labels);\n const branchName = await generateBranchName(config, issueNumber, issue.title, type);\n\n // Handle branch\n const currentBranch = await getCurrentBranch();\n const onMain = await isOnMainBranch();\n\n if (await branchExists(branchName)) {\n logger.info(`Branch ${colors.branch(branchName)} already exists.`);\n const { action } = await inquirer.prompt([\n {\n type: \"list\",\n name: \"action\",\n message: \"What would you like to do?\",\n choices: [\n { name: \"Continue on existing branch\", value: \"continue\" },\n { name: \"Delete and recreate branch\", value: \"recreate\" },\n { name: \"Cancel\", value: \"cancel\" },\n ],\n },\n ]);\n\n if (action === \"cancel\") {\n return;\n } else if (action === \"continue\") {\n await checkoutBranch(branchName);\n } else {\n // Recreate would require deleting first - for safety, just checkout\n await checkoutBranch(branchName);\n }\n } else {\n if (!onMain) {\n logger.warning(`Not on main branch (currently on ${colors.branch(currentBranch)}).`);\n const { fromMain } = await inquirer.prompt([\n {\n type: \"confirm\",\n name: \"fromMain\",\n message: \"Create branch from main instead?\",\n default: true,\n },\n ]);\n\n if (fromMain) {\n await createBranch(branchName, \"main\");\n } else {\n await createBranch(branchName);\n }\n } else {\n await createBranch(branchName);\n }\n logger.success(`Created branch ${colors.branch(branchName)}`);\n }\n\n // Update issue labels\n try {\n await updateIssueLabels(issueNumber, {\n add: [workflowLabels.inProgress],\n remove: [workflowLabels.ready],\n });\n logger.success(`Updated issue labels: ${colors.label(workflowLabels.ready)} → ${colors.label(workflowLabels.inProgress)}`);\n } catch (error) {\n logger.warning(`Failed to update labels: ${error}`);\n }\n\n // Build implementation prompt\n const agentInstructions = loadAgentInstructions();\n const progressContent = readProgress(config);\n const prompt = buildImplementationPrompt(issue, agentInstructions, progressContent, config);\n\n logger.newline();\n logger.info(`Starting ${colors.provider(providerName)} implementation session...`);\n logger.dim(`${providerName} will implement the feature and create a commit.`);\n logger.dim(\"Review the changes before pushing.\");\n logger.newline();\n\n // Capture commit SHA before AI runs\n const beforeSha = await getCurrentCommitSha();\n\n // Track if operation was cancelled\n let wasCancelled = false;\n const handleSignal = () => {\n wasCancelled = true;\n };\n process.on(\"SIGINT\", handleSignal);\n process.on(\"SIGTERM\", handleSignal);\n\n // Invoke AI interactively\n let aiExitCode: number | undefined;\n let usedProvider = provider;\n try {\n const { result, provider: actualProvider } = await invokeAIInteractive(prompt, config, options.provider);\n usedProvider = actualProvider;\n aiExitCode = result.exitCode ?? undefined;\n } catch (error) {\n if (error && typeof error === \"object\" && \"exitCode\" in error) {\n aiExitCode = error.exitCode as number;\n }\n logger.error(`${getProviderDisplayName(usedProvider)} session failed: ${error}`);\n // Don't exit - allow user to see what happened\n } finally {\n // Clean up signal handlers\n process.off(\"SIGINT\", handleSignal);\n process.off(\"SIGTERM\", handleSignal);\n }\n\n // Post-completion\n logger.newline();\n\n // Check if any new commits were created\n const commitsCreated = await hasNewCommits(beforeSha);\n\n // Handle cancellation - don't change labels\n if (wasCancelled) {\n logger.warning(\"Operation was cancelled. Labels unchanged.\");\n return;\n }\n\n // Determine appropriate label based on whether work was done\n const usedProviderName = getProviderDisplayName(usedProvider);\n if (commitsCreated) {\n logger.success(`${usedProviderName} session completed with new commits.`);\n\n // Update labels to completed\n try {\n await updateIssueLabels(issueNumber, {\n add: [workflowLabels.completed],\n remove: [workflowLabels.inProgress],\n });\n logger.success(`Updated labels: ${colors.label(workflowLabels.inProgress)} → ${colors.label(workflowLabels.completed)}`);\n } catch (error) {\n logger.warning(`Failed to update labels: ${error}`);\n }\n\n // Post comment to issue\n try {\n await addIssueComment(\n issueNumber,\n `AI implementation completed on branch \\`${branchName}\\` using ${usedProviderName}.\\n\\nPlease review the changes and create a PR when ready.`\n );\n logger.success(\"Posted completion comment to issue\");\n } catch (error) {\n logger.warning(`Failed to post comment: ${error}`);\n }\n } else {\n // No commits created - check if it was a rate limit or other issue\n // Exit code 2 typically indicates rate limiting for Claude CLI\n // Gemini may use different patterns\n const isRateLimited = aiExitCode === 2;\n\n if (isRateLimited) {\n logger.warning(`${usedProviderName} session ended due to rate limits. No commits were created.`);\n\n // Set ai-blocked label\n try {\n await updateIssueLabels(issueNumber, {\n add: [workflowLabels.blocked],\n remove: [workflowLabels.inProgress],\n });\n logger.info(`Updated labels: ${colors.label(workflowLabels.inProgress)} → ${colors.label(workflowLabels.blocked)}`);\n } catch (error) {\n logger.warning(`Failed to update labels: ${error}`);\n }\n\n // Post comment about rate limiting\n try {\n await addIssueComment(\n issueNumber,\n `AI implementation was blocked due to API rate limits on branch \\`${branchName}\\` (${usedProviderName}).\\n\\nNo commits were created. Please retry later.`\n );\n logger.info(\"Posted rate-limit comment to issue\");\n } catch (error) {\n logger.warning(`Failed to post comment: ${error}`);\n }\n } else {\n logger.warning(`${usedProviderName} session completed but no commits were created. Labels unchanged.`);\n // Leave as ai-in-progress so it can be retried\n }\n\n return;\n }\n\n logger.newline();\n logger.box(\"Next Steps\", `1. Review changes: ${colors.command(\"git diff HEAD~1\")}\n2. Run tests: ${colors.command(\"npm test\")}\n3. Push branch: ${colors.command(\"git push -u origin \" + branchName)}\n4. Create PR: ${colors.command(\"gent pr\")}`);\n}\n\nasync function autoSelectIssue(readyLabel: string): Promise<GitHubIssue | null> {\n // Try critical first\n let issues = await listIssues({\n labels: [readyLabel, \"priority:critical\"],\n state: \"open\",\n limit: 1,\n });\n if (issues.length > 0) return issues[0];\n\n // Try high\n issues = await listIssues({\n labels: [readyLabel, \"priority:high\"],\n state: \"open\",\n limit: 1,\n });\n if (issues.length > 0) return issues[0];\n\n // Get any ai-ready and sort\n issues = await listIssues({\n labels: [readyLabel],\n state: \"open\",\n limit: 10,\n });\n\n if (issues.length === 0) return null;\n\n sortByPriority(issues);\n return issues[0];\n}\n","import { execa } from \"execa\";\n\nexport async function getCurrentBranch(): Promise<string> {\n const { stdout } = await execa(\"git\", [\"branch\", \"--show-current\"]);\n return stdout.trim();\n}\n\nexport async function isOnMainBranch(): Promise<boolean> {\n const branch = await getCurrentBranch();\n return branch === \"main\" || branch === \"master\";\n}\n\nexport async function getDefaultBranch(): Promise<string> {\n try {\n const { stdout } = await execa(\"git\", [\n \"symbolic-ref\",\n \"refs/remotes/origin/HEAD\",\n ]);\n return stdout.trim().replace(\"refs/remotes/origin/\", \"\");\n } catch {\n // Fallback to checking if main or master exists\n try {\n await execa(\"git\", [\"rev-parse\", \"--verify\", \"main\"]);\n return \"main\";\n } catch {\n return \"master\";\n }\n }\n}\n\nexport async function branchExists(name: string): Promise<boolean> {\n try {\n await execa(\"git\", [\"rev-parse\", \"--verify\", name]);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function createBranch(name: string, from?: string): Promise<void> {\n if (from) {\n await execa(\"git\", [\"checkout\", \"-b\", name, from]);\n } else {\n await execa(\"git\", [\"checkout\", \"-b\", name]);\n }\n}\n\nexport async function checkoutBranch(name: string): Promise<void> {\n await execa(\"git\", [\"checkout\", name]);\n}\n\nexport async function hasUncommittedChanges(): Promise<boolean> {\n const { stdout } = await execa(\"git\", [\"status\", \"--porcelain\"]);\n return stdout.trim().length > 0;\n}\n\nexport async function getUnpushedCommits(): Promise<boolean> {\n try {\n const { stdout } = await execa(\"git\", [\n \"log\",\n \"@{u}..HEAD\",\n \"--oneline\",\n ]);\n return stdout.trim().length > 0;\n } catch {\n // No upstream set\n return true;\n }\n}\n\nexport async function pushBranch(branch?: string): Promise<void> {\n const branchName = branch || (await getCurrentBranch());\n await execa(\"git\", [\"push\", \"-u\", \"origin\", branchName]);\n}\n\nexport async function getAuthorInitials(): Promise<string> {\n // Try git config user.initials first\n try {\n const { stdout } = await execa(\"git\", [\"config\", \"user.initials\"]);\n if (stdout.trim()) {\n return stdout.trim();\n }\n } catch {\n // Not set, continue\n }\n\n // Fall back to deriving from user.name\n try {\n const { stdout } = await execa(\"git\", [\"config\", \"user.name\"]);\n const name = stdout.trim();\n if (name) {\n // Extract initials from name (e.g., \"John Doe\" -> \"jd\")\n const parts = name.split(/\\s+/);\n return parts.map((p) => p[0]?.toLowerCase() || \"\").join(\"\");\n }\n } catch {\n // Not set\n }\n\n return \"dev\";\n}\n\nexport async function getRepoInfo(): Promise<{\n owner: string;\n repo: string;\n} | null> {\n try {\n const { stdout } = await execa(\"git\", [\n \"config\",\n \"--get\",\n \"remote.origin.url\",\n ]);\n const url = stdout.trim();\n\n // Handle SSH format: git@github.com:owner/repo.git\n const sshMatch = url.match(/git@github\\.com:([^/]+)\\/([^.]+)/);\n if (sshMatch) {\n return { owner: sshMatch[1], repo: sshMatch[2] };\n }\n\n // Handle HTTPS format: https://github.com/owner/repo.git\n const httpsMatch = url.match(/github\\.com\\/([^/]+)\\/([^.]+)/);\n if (httpsMatch) {\n return { owner: httpsMatch[1], repo: httpsMatch[2] };\n }\n\n return null;\n } catch {\n return null;\n }\n}\n\nexport async function getCommitsSinceBase(\n base: string = \"main\"\n): Promise<string[]> {\n try {\n const { stdout } = await execa(\"git\", [\n \"log\",\n `${base}..HEAD`,\n \"--pretty=format:%s\",\n ]);\n return stdout.trim().split(\"\\n\").filter(Boolean);\n } catch {\n return [];\n }\n}\n\nexport async function getDiffSummary(base: string = \"main\"): Promise<string> {\n try {\n const { stdout } = await execa(\"git\", [\n \"diff\",\n `${base}...HEAD`,\n \"--stat\",\n ]);\n return stdout.trim();\n } catch {\n return \"\";\n }\n}\n\nexport async function getCurrentCommitSha(): Promise<string> {\n const { stdout } = await execa(\"git\", [\"rev-parse\", \"HEAD\"]);\n return stdout.trim();\n}\n\nexport async function hasNewCommits(beforeSha: string): Promise<boolean> {\n const currentSha = await getCurrentCommitSha();\n return currentSha !== beforeSha;\n}\n","import type { GentConfig, BranchInfo } from \"../types/index.js\";\nimport { getAuthorInitials } from \"./git.js\";\nimport { sanitizeSlug } from \"../utils/validators.js\";\n\nexport async function generateBranchName(\n config: GentConfig,\n issueNumber: number,\n issueTitle: string,\n type: string\n): Promise<string> {\n const author = await resolveAuthor(config);\n const slug = sanitizeSlug(issueTitle);\n\n return config.branch.pattern\n .replace(\"{author}\", author)\n .replace(\"{type}\", type)\n .replace(\"{issue}\", String(issueNumber))\n .replace(\"{slug}\", slug);\n}\n\nasync function resolveAuthor(config: GentConfig): Promise<string> {\n switch (config.branch.author_source) {\n case \"env\": {\n const envValue = process.env[config.branch.author_env_var];\n if (envValue) {\n return envValue;\n }\n // Fall through to git\n return getAuthorInitials();\n }\n case \"git\":\n default:\n return getAuthorInitials();\n }\n}\n\nexport function parseBranchName(branchName: string): BranchInfo | null {\n // Pattern 1: author/type-issue-slug (e.g., ro/feature-123-add-login)\n const pattern1 = /^([^/]+)\\/(feature|fix|refactor|chore|docs|test)-(\\d+)-(.+)$/;\n const match1 = branchName.match(pattern1);\n if (match1) {\n return {\n name: branchName,\n author: match1[1],\n type: match1[2],\n issueNumber: parseInt(match1[3], 10),\n slug: match1[4],\n };\n }\n\n // Pattern 2: type/issue-slug (e.g., feature/123-add-login)\n const pattern2 = /^(feature|fix|refactor|chore|docs|test)\\/(\\d+)-(.+)$/;\n const match2 = branchName.match(pattern2);\n if (match2) {\n return {\n name: branchName,\n author: \"\",\n type: match2[1],\n issueNumber: parseInt(match2[2], 10),\n slug: match2[3],\n };\n }\n\n // Pattern 3: issue-slug (e.g., 123-add-login)\n const pattern3 = /^(\\d+)-(.+)$/;\n const match3 = branchName.match(pattern3);\n if (match3) {\n return {\n name: branchName,\n author: \"\",\n type: \"feature\",\n issueNumber: parseInt(match3[1], 10),\n slug: match3[2],\n };\n }\n\n // Pattern 4: Just look for issue number anywhere\n const issueMatch = branchName.match(/(\\d+)/);\n if (issueMatch) {\n return {\n name: branchName,\n author: \"\",\n type: \"feature\",\n issueNumber: parseInt(issueMatch[1], 10),\n slug: branchName,\n };\n }\n\n return null;\n}\n\nexport function extractIssueNumber(branchName: string): number | null {\n const info = parseBranchName(branchName);\n return info?.issueNumber ?? null;\n}\n","import inquirer from \"inquirer\";\nimport { logger, colors } from \"../utils/logger.js\";\nimport { withSpinner } from \"../utils/spinner.js\";\nimport { loadConfig } from \"../lib/config.js\";\nimport { getIssue, createPullRequest, getPrForBranch, assignIssue, getCurrentUser, updateIssueLabels } from \"../lib/github.js\";\nimport { buildPrPrompt } from \"../lib/claude.js\";\nimport { invokeAI, getProviderDisplayName } from \"../lib/ai-provider.js\";\nimport { getCurrentBranch, isOnMainBranch, getDefaultBranch, getCommitsSinceBase, getDiffSummary, getUnpushedCommits, pushBranch } from \"../lib/git.js\";\nimport { extractIssueNumber } from \"../lib/branch.js\";\nimport { getWorkflowLabels } from \"../lib/labels.js\";\nimport { checkGhAuth, checkAIProvider } from \"../utils/validators.js\";\nimport type { GitHubIssue, AIProvider } from \"../types/index.js\";\n\nexport interface PrOptions {\n draft?: boolean;\n provider?: AIProvider;\n}\n\nexport async function prCommand(options: PrOptions): Promise<void> {\n logger.bold(\"Creating AI-enhanced pull request...\");\n logger.newline();\n\n const config = loadConfig();\n\n // Determine which provider to use\n const provider = options.provider ?? config.ai.provider;\n const providerName = getProviderDisplayName(provider);\n\n // Validate prerequisites\n const [ghAuth, aiOk] = await Promise.all([\n checkGhAuth(),\n checkAIProvider(provider),\n ]);\n\n if (!ghAuth) {\n logger.error(\"Not authenticated with GitHub. Run 'gh auth login' first.\");\n process.exit(1);\n }\n\n if (!aiOk) {\n logger.error(`${providerName} CLI not found. Please install ${provider} CLI first.`);\n process.exit(1);\n }\n\n // Check we're not on main\n if (await isOnMainBranch()) {\n logger.error(\"Cannot create PR from main/master branch.\");\n process.exit(1);\n }\n\n // Check for existing PR\n const existingPr = await getPrForBranch();\n if (existingPr) {\n logger.warning(`A PR already exists for this branch: ${colors.url(existingPr.url)}`);\n return;\n }\n\n const currentBranch = await getCurrentBranch();\n const baseBranch = await getDefaultBranch();\n\n logger.info(`Branch: ${colors.branch(currentBranch)}`);\n logger.info(`Base: ${colors.branch(baseBranch)}`);\n\n // Check if we need to push\n const hasUnpushed = await getUnpushedCommits();\n if (hasUnpushed) {\n logger.warning(\"Branch has unpushed commits.\");\n const { push } = await inquirer.prompt([\n {\n type: \"confirm\",\n name: \"push\",\n message: \"Push to remote before creating PR?\",\n default: true,\n },\n ]);\n\n if (push) {\n await withSpinner(\"Pushing branch...\", async () => {\n await pushBranch();\n });\n logger.success(\"Branch pushed\");\n }\n }\n\n // Extract issue number from branch\n const issueNumber = extractIssueNumber(currentBranch);\n let issue: GitHubIssue | null = null;\n\n if (issueNumber) {\n try {\n issue = await getIssue(issueNumber);\n logger.info(`Linked issue: ${colors.issue(`#${issueNumber}`)} - ${issue.title}`);\n } catch {\n logger.warning(`Could not fetch issue #${issueNumber}`);\n }\n } else {\n logger.warning(\"Could not extract issue number from branch name.\");\n }\n\n // Get commits and diff\n const commits = await getCommitsSinceBase(baseBranch);\n const diffSummary = await getDiffSummary(baseBranch);\n\n if (commits.length === 0) {\n logger.error(\"No commits found since base branch.\");\n return;\n }\n\n logger.info(`Commits: ${commits.length}`);\n logger.newline();\n\n // Generate PR description with AI\n const prompt = buildPrPrompt(issue, commits, diffSummary);\n\n let prBody: string;\n try {\n logger.info(`Generating PR description with ${colors.provider(providerName)}...`);\n logger.newline();\n const result = await invokeAI({ prompt, streamOutput: true }, config, options.provider);\n prBody = result.output;\n logger.newline();\n } catch (error) {\n logger.warning(`${providerName} invocation failed: ${error}`);\n // Fall back to basic description\n prBody = generateFallbackBody(issue, commits);\n }\n\n // Append signature footer\n prBody += `\\n\\n---\\n*Created with ${providerName} by [gent](https://github.com/Rotorsoft/gent)*`;\n\n // Generate title\n const prTitle = issue?.title || commits[0] || currentBranch;\n\n // Create PR\n let prUrl: string;\n try {\n prUrl = await withSpinner(\"Creating pull request...\", async () => {\n return createPullRequest({\n title: prTitle,\n body: prBody,\n base: baseBranch,\n draft: options.draft,\n });\n });\n } catch (error) {\n logger.error(`Failed to create PR: ${error}`);\n return;\n }\n\n // Assign issue to current user if linked\n if (issueNumber) {\n try {\n const user = await getCurrentUser();\n await assignIssue(issueNumber, user);\n logger.success(`Assigned issue #${issueNumber} to ${user}`);\n } catch {\n // Non-critical, ignore\n }\n\n // Update issue labels to ai-completed\n const workflowLabels = getWorkflowLabels(config);\n try {\n await updateIssueLabels(issueNumber, {\n add: [workflowLabels.completed],\n remove: [workflowLabels.inProgress],\n });\n logger.success(`Updated labels: ${colors.label(workflowLabels.inProgress)} → ${colors.label(workflowLabels.completed)}`);\n } catch {\n // Non-critical, ignore\n }\n }\n\n logger.newline();\n logger.success(`Pull request created!`);\n logger.newline();\n logger.highlight(prUrl);\n logger.newline();\n\n if (options.draft) {\n logger.dim(\"Created as draft. Mark as ready for review when done.\");\n }\n}\n\nfunction generateFallbackBody(\n issue: GitHubIssue | null,\n commits: string[]\n): string {\n let body = \"## Summary\\n\\n\";\n\n if (issue) {\n body += `Implements #${issue.number}: ${issue.title}\\n\\n`;\n }\n\n body += \"## Changes\\n\\n\";\n for (const commit of commits.slice(0, 10)) {\n body += `- ${commit}\\n`;\n }\n\n body += \"\\n## Test Plan\\n\\n- [ ] Tests pass\\n- [ ] Manual verification\\n\\n\";\n\n if (issue) {\n body += `Closes #${issue.number}\\n`;\n }\n\n return body;\n}\n","import { logger, colors } from \"../utils/logger.js\";\nimport { loadConfig } from \"../lib/config.js\";\nimport { getIssue, getPrForBranch } from \"../lib/github.js\";\nimport { getCurrentBranch, isOnMainBranch, hasUncommittedChanges, getUnpushedCommits, getCommitsSinceBase, getDefaultBranch } from \"../lib/git.js\";\nimport { extractIssueNumber, parseBranchName } from \"../lib/branch.js\";\nimport { getWorkflowLabels } from \"../lib/labels.js\";\nimport { progressExists, readProgress } from \"../lib/progress.js\";\nimport { configExists } from \"../lib/config.js\";\nimport { checkGhAuth, checkClaudeCli, checkGeminiCli, checkGitRepo } from \"../utils/validators.js\";\nimport { getProviderDisplayName } from \"../lib/ai-provider.js\";\n\nexport async function statusCommand(): Promise<void> {\n logger.bold(\"Gent Workflow Status\");\n logger.newline();\n\n // Check prerequisites\n const gitRepo = await checkGitRepo();\n if (!gitRepo) {\n logger.error(\"Not a git repository.\");\n process.exit(1);\n }\n\n const config = loadConfig();\n const workflowLabels = getWorkflowLabels(config);\n\n // Configuration status\n logger.bold(\"Configuration:\");\n if (configExists()) {\n logger.success(\" .gent.yml found\");\n } else {\n logger.warning(\" .gent.yml not found - using defaults\");\n }\n\n if (progressExists(config)) {\n const progress = readProgress(config);\n const lines = progress.split(\"\\n\").length;\n logger.success(` ${config.progress.file} found (${lines} lines)`);\n } else {\n logger.warning(` ${config.progress.file} not found`);\n }\n\n logger.newline();\n\n // AI Provider status\n logger.bold(\"AI Provider:\");\n const providerName = getProviderDisplayName(config.ai.provider);\n logger.info(` Active: ${colors.provider(providerName)}`);\n if (config.ai.fallback_provider) {\n const fallbackName = getProviderDisplayName(config.ai.fallback_provider);\n logger.info(` Fallback: ${fallbackName} (auto: ${config.ai.auto_fallback ? \"enabled\" : \"disabled\"})`);\n }\n logger.newline();\n\n // Prerequisites\n logger.bold(\"Prerequisites:\");\n const ghAuth = await checkGhAuth();\n if (ghAuth) {\n logger.success(\" GitHub CLI authenticated\");\n } else {\n logger.error(\" GitHub CLI not authenticated\");\n }\n\n // Check all AI providers\n const claudeOk = await checkClaudeCli();\n const geminiOk = await checkGeminiCli();\n\n const getProviderStatus = (provider: \"claude\" | \"gemini\"): string => {\n const isActive = config.ai.provider === provider;\n const isFallback = config.ai.fallback_provider === provider;\n const suffix = isActive ? \" (active)\" : isFallback ? \" (fallback)\" : \"\";\n return suffix;\n };\n\n if (claudeOk) {\n logger.success(` Claude CLI available${getProviderStatus(\"claude\")}`);\n } else {\n logger.error(` Claude CLI not found${getProviderStatus(\"claude\")}`);\n }\n\n if (geminiOk) {\n logger.success(` Gemini CLI available${getProviderStatus(\"gemini\")}`);\n } else {\n logger.error(` Gemini CLI not found${getProviderStatus(\"gemini\")}`);\n }\n\n logger.newline();\n\n // Git status\n logger.bold(\"Git Status:\");\n const currentBranch = await getCurrentBranch();\n const onMain = await isOnMainBranch();\n const uncommitted = await hasUncommittedChanges();\n const baseBranch = await getDefaultBranch();\n\n logger.info(` Branch: ${colors.branch(currentBranch)}`);\n\n if (onMain) {\n logger.info(\" On main branch - ready to start new work\");\n } else {\n const branchInfo = parseBranchName(currentBranch);\n if (branchInfo) {\n logger.info(` Issue: ${colors.issue(`#${branchInfo.issueNumber}`)}`);\n logger.info(` Type: ${branchInfo.type}`);\n }\n\n const commits = await getCommitsSinceBase(baseBranch);\n logger.info(` Commits ahead of ${baseBranch}: ${commits.length}`);\n\n const unpushed = await getUnpushedCommits();\n if (unpushed) {\n logger.warning(\" Has unpushed commits\");\n } else {\n logger.success(\" Up to date with remote\");\n }\n }\n\n if (uncommitted) {\n logger.warning(\" Has uncommitted changes\");\n }\n\n logger.newline();\n\n // Linked issue status\n if (!onMain) {\n const issueNumber = extractIssueNumber(currentBranch);\n if (issueNumber) {\n logger.bold(\"Linked Issue:\");\n try {\n const issue = await getIssue(issueNumber);\n logger.info(` #${issue.number}: ${issue.title}`);\n logger.info(` State: ${issue.state}`);\n logger.info(` Labels: ${issue.labels.join(\", \")}`);\n\n // Check workflow status\n if (issue.labels.includes(workflowLabels.ready)) {\n logger.info(` Workflow: ${colors.label(\"ai-ready\")}`);\n } else if (issue.labels.includes(workflowLabels.inProgress)) {\n logger.info(` Workflow: ${colors.label(\"ai-in-progress\")}`);\n } else if (issue.labels.includes(workflowLabels.completed)) {\n logger.info(` Workflow: ${colors.label(\"ai-completed\")}`);\n } else if (issue.labels.includes(workflowLabels.blocked)) {\n logger.info(` Workflow: ${colors.label(\"ai-blocked\")}`);\n }\n } catch {\n logger.warning(` Could not fetch issue #${issueNumber}`);\n }\n logger.newline();\n }\n\n // PR status\n logger.bold(\"Pull Request:\");\n const pr = await getPrForBranch();\n if (pr) {\n logger.success(` PR #${pr.number} exists`);\n logger.info(` ${colors.url(pr.url)}`);\n } else {\n logger.info(\" No PR created yet\");\n logger.dim(` Run ${colors.command(\"gent pr\")} to create one`);\n }\n logger.newline();\n }\n\n // Suggestions\n logger.bold(\"Suggested Actions:\");\n if (onMain) {\n logger.list([\n `${colors.command(\"gent list\")} - View ai-ready issues`,\n `${colors.command(\"gent run --auto\")} - Start working on highest priority issue`,\n `${colors.command(\"gent create <description>\")} - Create a new ticket`,\n ]);\n } else {\n const pr = await getPrForBranch();\n if (!pr) {\n logger.list([\n `${colors.command(\"gent pr\")} - Create a pull request`,\n `${colors.command(\"git push\")} - Push your changes`,\n ]);\n } else {\n logger.list([\n `Review and merge your PR`,\n `${colors.command(\"git checkout main\")} - Return to main branch`,\n ]);\n }\n }\n}\n"],"mappings":"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","names":["writeFileSync","existsSync","join","writeFileSync","join","existsSync","setupLabelsCommand","inquirer","execa","execa","execa","inquirer","chalk","chalk","inquirer","execa","execa","inquirer","inquirer","inquirer"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/commands/init.ts","../src/lib/progress.ts","../src/commands/create.ts","../src/lib/ai-provider.ts","../src/lib/prompts.ts","../src/commands/list.ts","../src/commands/run.ts","../src/lib/git.ts","../src/lib/branch.ts","../src/commands/pr.ts","../src/commands/status.ts"],"sourcesContent":["import { readFileSync } from \"node:fs\";\nimport { join, dirname } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { Command } from \"commander\";\nimport { initCommand } from \"./commands/init.js\";\nimport { setupLabelsCommand } from \"./commands/setup-labels.js\";\nimport { createCommand } from \"./commands/create.js\";\nimport { listCommand } from \"./commands/list.js\";\nimport { runCommand } from \"./commands/run.js\";\nimport { prCommand } from \"./commands/pr.js\";\nimport { statusCommand } from \"./commands/status.js\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst packageJson = JSON.parse(\n readFileSync(join(__dirname, \"../package.json\"), \"utf8\")\n);\nconst { version } = packageJson;\n\nconst program = new Command();\n\nprogram\n .name(\"gent\")\n .description(\"AI-powered GitHub workflow CLI - leverage AI (Claude or Gemini) to create tickets, implement features, and manage PRs\")\n .version(version);\n\nprogram\n .command(\"init\")\n .description(\"Initialize gent workflow in current repository\")\n .option(\"-f, --force\", \"Overwrite existing configuration\")\n .action(async (options) => {\n await initCommand(options);\n });\n\nprogram\n .command(\"setup-labels\")\n .description(\"Setup GitHub labels for AI workflow\")\n .action(async () => {\n await setupLabelsCommand();\n });\n\nprogram\n .command(\"create <description>\")\n .description(\"Create an AI-enhanced GitHub issue\")\n .option(\"-y, --yes\", \"Skip confirmation and create issue immediately\")\n .option(\"-p, --provider <provider>\", \"AI provider to use (claude or gemini)\")\n .action(async (description, options) => {\n await createCommand(description, { yes: options.yes, provider: options.provider });\n });\n\nprogram\n .command(\"list\")\n .description(\"List GitHub issues by label/status\")\n .option(\"-l, --label <label>\", \"Filter by label\")\n .option(\"-s, --status <status>\", \"Filter by workflow status (ready, in-progress, completed, blocked, all)\")\n .option(\"-n, --limit <number>\", \"Maximum number of issues to show\", \"20\")\n .action(async (options) => {\n await listCommand({\n label: options.label,\n status: options.status,\n limit: parseInt(options.limit, 10),\n });\n });\n\nprogram\n .command(\"run [issue-number]\")\n .description(\"Run AI to implement a GitHub issue\")\n .option(\"-a, --auto\", \"Auto-select highest priority ai-ready issue\")\n .option(\"-p, --provider <provider>\", \"AI provider to use (claude or gemini)\")\n .action(async (issueNumber, options) => {\n await runCommand(issueNumber, { auto: options.auto, provider: options.provider });\n });\n\nprogram\n .command(\"pr\")\n .description(\"Create an AI-enhanced pull request\")\n .option(\"-d, --draft\", \"Create as draft PR\")\n .option(\"-p, --provider <provider>\", \"AI provider to use (claude or gemini)\")\n .action(async (options) => {\n await prCommand({ draft: options.draft, provider: options.provider });\n });\n\nprogram\n .command(\"status\")\n .description(\"Show current workflow status\")\n .action(async () => {\n await statusCommand();\n });\n\nprogram.parse();","import { writeFileSync, existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport inquirer from \"inquirer\";\nimport { logger, colors } from \"../utils/logger.js\";\nimport { checkGitRepo } from \"../utils/validators.js\";\nimport { configExists, generateDefaultConfig, getConfigPath } from \"../lib/config.js\";\nimport { initializeProgress } from \"../lib/progress.js\";\nimport { loadConfig } from \"../lib/config.js\";\n\nconst DEFAULT_AGENT_MD = `# AI Agent Instructions\n\nThis file contains instructions for the AI when working on this repository.\n\n## Project Overview\n\n[Describe your project, its purpose, and key technologies used]\n\n## Code Patterns\n\n### Architecture\n[Document your architecture - e.g., MVC, Clean Architecture, etc.]\n\n### Naming Conventions\n[Document naming conventions for files, functions, variables, etc.]\n\n### Component Structure\n[If applicable, describe component/module structure]\n\n## Testing Requirements\n\n### Unit Tests\n- All new functions should have corresponding unit tests\n- Use [your testing framework] for unit tests\n- Aim for [X]% coverage on new code\n\n### Integration Tests\n[Document when and how to write integration tests]\n\n## Commit Conventions\n\nFollow conventional commits format:\n- \\`feat:\\` New feature\n- \\`fix:\\` Bug fix\n- \\`refactor:\\` Code improvement without behavior change\n- \\`test:\\` Testing additions\n- \\`chore:\\` Maintenance/dependencies\n- \\`docs:\\` Documentation\n\nAll AI commits should include the Co-Authored-By trailer as specified in the task prompt.\n\n## Important Files\n\n[List key files the AI should understand before making changes]\n\n- \\`src/index.ts\\` - Main entry point\n- \\`src/config/\\` - Configuration files\n- [Add more key files]\n\n## Constraints\n\n- [List any constraints or limitations]\n- [E.g., \"Do not modify files in /vendor\"]\n- [E.g., \"Always use async/await over callbacks\"]\n`;\n\nexport async function initCommand(options: { force?: boolean }): Promise<void> {\n logger.bold(\"Initializing gent workflow...\");\n logger.newline();\n\n // Check if we're in a git repo\n const isGitRepo = await checkGitRepo();\n if (!isGitRepo) {\n logger.error(\"Not a git repository. Please run 'git init' first.\");\n process.exit(1);\n }\n\n const cwd = process.cwd();\n\n // Check if already initialized\n if (configExists(cwd) && !options.force) {\n const { overwrite } = await inquirer.prompt([\n {\n type: \"confirm\",\n name: \"overwrite\",\n message: \"gent is already initialized. Overwrite existing config?\",\n default: false,\n },\n ]);\n\n if (!overwrite) {\n logger.info(\"Initialization cancelled.\");\n return;\n }\n }\n\n // Create .gent.yml\n const configPath = getConfigPath(cwd);\n writeFileSync(configPath, generateDefaultConfig(), \"utf-8\");\n logger.success(`Created ${colors.file(\".gent.yml\")}`);\n\n // Create AGENT.md\n const agentPath = join(cwd, \"AGENT.md\");\n if (!existsSync(agentPath) || options.force) {\n writeFileSync(agentPath, DEFAULT_AGENT_MD, \"utf-8\");\n logger.success(`Created ${colors.file(\"AGENT.md\")}`);\n } else {\n logger.info(`${colors.file(\"AGENT.md\")} already exists, skipping`);\n }\n\n // Create progress.txt\n const config = loadConfig(cwd);\n initializeProgress(config, cwd);\n logger.success(`Created ${colors.file(config.progress.file)}`);\n\n logger.newline();\n logger.box(\"Setup Complete\", `Next steps:\n1. Edit ${colors.file(\"AGENT.md\")} with your project-specific instructions\n2. Edit ${colors.file(\".gent.yml\")} to customize settings\n3. Run ${colors.command(\"gent setup-labels\")} to create GitHub labels\n4. Run ${colors.command(\"gent create <description>\")} to create your first ticket`);\n\n // Ask about setting up labels\n const { setupLabels } = await inquirer.prompt([\n {\n type: \"confirm\",\n name: \"setupLabels\",\n message: \"Would you like to setup GitHub labels now?\",\n default: true,\n },\n ]);\n\n if (setupLabels) {\n const { setupLabelsCommand } = await import(\"./setup-labels.js\");\n await setupLabelsCommand();\n }\n}\n","import { existsSync, readFileSync, writeFileSync, mkdirSync } from \"node:fs\";\nimport { join, dirname } from \"node:path\";\nimport type { GentConfig, ProgressEntry } from \"../types/index.js\";\n\nexport function getProgressPath(\n config: GentConfig,\n cwd: string = process.cwd()\n): string {\n return join(cwd, config.progress.file);\n}\n\nexport function progressExists(\n config: GentConfig,\n cwd: string = process.cwd()\n): boolean {\n return existsSync(getProgressPath(config, cwd));\n}\n\nexport function readProgress(\n config: GentConfig,\n cwd: string = process.cwd()\n): string {\n const path = getProgressPath(config, cwd);\n if (!existsSync(path)) {\n return \"\";\n }\n return readFileSync(path, \"utf-8\");\n}\n\nexport function appendProgress(\n config: GentConfig,\n entry: ProgressEntry,\n cwd: string = process.cwd()\n): void {\n const path = getProgressPath(config, cwd);\n const content = formatProgressEntry(entry);\n\n // Ensure directory exists\n const dir = dirname(path);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n\n // Read existing content\n let existing = \"\";\n if (existsSync(path)) {\n existing = readFileSync(path, \"utf-8\");\n }\n\n // Check if we need to archive\n const lines = existing.split(\"\\n\").length;\n if (lines > config.progress.archive_threshold) {\n archiveProgress(config, existing, cwd);\n existing = `# Progress Log (archived previous entries)\\n\\n`;\n }\n\n // Append new entry\n writeFileSync(path, existing + content, \"utf-8\");\n}\n\nexport function formatProgressEntry(entry: ProgressEntry): string {\n let content = `\\n[${entry.date}] ${entry.type}: ${entry.description}\\n`;\n\n if (entry.issue) {\n content += `- Completed GitHub issue #${entry.issue}\\n`;\n }\n\n if (entry.decisions.length > 0) {\n content += `- Key implementation decisions:\\n`;\n for (const decision of entry.decisions) {\n content += ` * ${decision}\\n`;\n }\n }\n\n if (entry.files.length > 0) {\n content += `- Files changed:\\n`;\n for (const file of entry.files) {\n content += ` * ${file}\\n`;\n }\n }\n\n if (entry.tests.length > 0) {\n content += `- Tests: ${entry.tests.join(\", \")}\\n`;\n }\n\n if (entry.concerns.length > 0) {\n content += `- Concerns for reviewers:\\n`;\n for (const concern of entry.concerns) {\n content += ` * ${concern}\\n`;\n }\n }\n\n if (entry.followUp.length > 0) {\n content += `- Follow-up tasks:\\n`;\n for (const task of entry.followUp) {\n content += ` * ${task}\\n`;\n }\n }\n\n if (entry.commit) {\n content += `- Commit: ${entry.commit}\\n`;\n }\n\n return content;\n}\n\nfunction archiveProgress(\n config: GentConfig,\n content: string,\n cwd: string\n): void {\n const archiveDir = join(cwd, config.progress.archive_dir);\n\n if (!existsSync(archiveDir)) {\n mkdirSync(archiveDir, { recursive: true });\n }\n\n const date = new Date().toISOString().split(\"T\")[0];\n const archivePath = join(archiveDir, `progress-${date}.txt`);\n\n writeFileSync(archivePath, content, \"utf-8\");\n}\n\nexport function initializeProgress(\n config: GentConfig,\n cwd: string = process.cwd()\n): void {\n const path = getProgressPath(config, cwd);\n\n if (existsSync(path)) {\n return;\n }\n\n const initialContent = `# Progress Log\n\nThis file tracks AI-assisted development progress.\nEach entry documents: date, feature, decisions, files changed, tests, and concerns.\n\n---\n`;\n\n const dir = dirname(path);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n\n writeFileSync(path, initialContent, \"utf-8\");\n}\n\nexport function getRecentProgress(\n config: GentConfig,\n cwd: string = process.cwd(),\n maxLines: number = 100\n): string {\n const content = readProgress(config, cwd);\n const lines = content.split(\"\\n\");\n\n if (lines.length <= maxLines) {\n return content;\n }\n\n return lines.slice(-maxLines).join(\"\\n\");\n}\n","import inquirer from \"inquirer\";\nimport chalk from \"chalk\";\nimport { logger, colors } from \"../utils/logger.js\";\nimport { withSpinner } from \"../utils/spinner.js\";\nimport { loadConfig, loadAgentInstructions } from \"../lib/config.js\";\nimport {\n buildTicketPrompt,\n parseTicketMeta,\n extractIssueBody,\n} from \"../lib/prompts.js\";\nimport { invokeAI, getProviderDisplayName } from \"../lib/ai-provider.js\";\nimport { createIssue } from \"../lib/github.js\";\nimport { buildIssueLabels } from \"../lib/labels.js\";\nimport { checkGhAuth, checkAIProvider } from \"../utils/validators.js\";\nimport type { AIProvider } from \"../types/index.js\";\n\nexport interface CreateOptions {\n yes?: boolean;\n provider?: AIProvider;\n}\n\ninterface TicketMeta {\n type: string;\n priority: string;\n risk: string;\n area: string;\n}\n\nexport async function createCommand(\n description: string,\n options: CreateOptions\n): Promise<void> {\n logger.bold(\"Creating AI-enhanced ticket...\");\n logger.newline();\n\n const config = loadConfig();\n\n // Determine which provider to use\n const provider = options.provider ?? config.ai.provider;\n const providerName = getProviderDisplayName(provider);\n\n // Validate prerequisites\n const [ghAuth, aiOk] = await Promise.all([\n checkGhAuth(),\n checkAIProvider(provider),\n ]);\n\n if (!ghAuth) {\n logger.error(\"Not authenticated with GitHub. Run 'gh auth login' first.\");\n process.exit(1);\n }\n\n if (!aiOk) {\n logger.error(`${providerName} CLI not found. Please install ${provider} CLI first.`);\n process.exit(1);\n }\n\n const agentInstructions = loadAgentInstructions();\n\n // Generate ticket with AI (may loop if user wants to regenerate)\n let aiOutput: string;\n let additionalHints: string | null = null;\n\n while (true) {\n // Build prompt and invoke AI\n const prompt = buildTicketPrompt(description, agentInstructions, additionalHints);\n\n try {\n // Show visual indicator before AI output\n console.log(chalk.dim(`┌─ Generating ticket with ${providerName}... ──────────────────────────┐`));\n logger.newline();\n const result = await invokeAI({ prompt, streamOutput: true }, config, options.provider);\n aiOutput = result.output;\n logger.newline();\n console.log(chalk.dim(\"└────────────────────────────────────────────────────────────┘\"));\n logger.newline();\n } catch (error) {\n logger.error(`${providerName} invocation failed: ${error}`);\n return;\n }\n\n // Parse metadata\n const meta = parseTicketMeta(aiOutput);\n if (!meta) {\n logger.warning(\"Could not parse metadata from AI output. Using defaults.\");\n }\n\n const finalMeta: TicketMeta = meta || {\n type: \"feature\",\n priority: \"medium\",\n risk: \"low\",\n area: \"shared\",\n };\n\n // Extract issue body (without META line) and append signature\n const issueBody = extractIssueBody(aiOutput) + `\\n\\n---\\n*Created with ${providerName} by [gent](https://github.com/Rotorsoft/gent)*`;\n\n // Generate title from description\n const title =\n description.length > 60 ? description.slice(0, 57) + \"...\" : description;\n\n // Build labels\n const labels = buildIssueLabels(finalMeta);\n\n // Show ticket preview\n displayTicketPreview(title, finalMeta, issueBody);\n\n // Skip confirmation if --yes flag is passed\n if (options.yes) {\n await createAndDisplayIssue(title, issueBody, labels, finalMeta);\n return;\n }\n\n // Ask for confirmation\n const { action } = await inquirer.prompt([\n {\n type: \"list\",\n name: \"action\",\n message: \"What would you like to do?\",\n choices: [\n { name: \"Create issue\", value: \"create\" },\n { name: \"Edit description and regenerate\", value: \"edit\" },\n { name: \"Cancel\", value: \"cancel\" },\n ],\n },\n ]);\n\n if (action === \"cancel\") {\n logger.info(\"Issue creation cancelled.\");\n return;\n }\n\n if (action === \"create\") {\n await createAndDisplayIssue(title, issueBody, labels, finalMeta);\n return;\n }\n\n // action === \"edit\" - prompt for additional hints\n const { hints } = await inquirer.prompt([\n {\n type: \"input\",\n name: \"hints\",\n message: \"Enter additional hints or context for the AI:\",\n },\n ]);\n\n if (hints.trim()) {\n additionalHints = additionalHints\n ? `${additionalHints}\\n${hints.trim()}`\n : hints.trim();\n }\n\n logger.newline();\n logger.info(\"Regenerating ticket with additional context...\");\n logger.newline();\n }\n}\n\nfunction displayTicketPreview(\n title: string,\n meta: TicketMeta,\n body: string\n): void {\n // Count lines for summary\n const lineCount = body.split(\"\\n\").length;\n\n // Section header helper\n const sectionHeader = (label: string) =>\n console.log(chalk.bold.cyan(`${label}`));\n\n // Display preview with clean sections\n console.log(chalk.bold.white(\"━━━ Ticket Preview ━━━\"));\n logger.newline();\n\n sectionHeader(\"Title\");\n console.log(` ${title}`);\n logger.newline();\n\n sectionHeader(\"Labels\");\n console.log(\n ` ${colors.label(`type:${meta.type}`)} ${colors.label(`priority:${meta.priority}`)} ${colors.label(`risk:${meta.risk}`)} ${colors.label(`area:${meta.area}`)}`\n );\n logger.newline();\n\n sectionHeader(`Body (${lineCount} lines)`);\n // Indent each line of the body for visual hierarchy\n const bodyLines = body.split(\"\\n\");\n for (const line of bodyLines) {\n console.log(` ${line}`);\n }\n\n logger.newline();\n console.log(chalk.bold.white(\"━━━━━━━━━━━━━━━━━━━━━━\"));\n logger.newline();\n}\n\nasync function createAndDisplayIssue(\n title: string,\n body: string,\n labels: string[],\n meta: TicketMeta\n): Promise<void> {\n let issueNumber: number;\n try {\n issueNumber = await withSpinner(\"Creating GitHub issue...\", async () => {\n return createIssue({\n title,\n body,\n labels,\n });\n });\n } catch (error) {\n logger.error(`Failed to create issue: ${error}`);\n return;\n }\n\n logger.newline();\n logger.success(`Created issue ${colors.issue(`#${issueNumber}`)}`);\n logger.newline();\n\n logger.box(\n \"Issue Created\",\n `Issue: ${colors.issue(`#${issueNumber}`)}\nType: ${colors.label(`type:${meta.type}`)}\nPriority: ${colors.label(`priority:${meta.priority}`)}\nRisk: ${colors.label(`risk:${meta.risk}`)}\nArea: ${colors.label(`area:${meta.area}`)}\n\nNext steps:\n1. Review the issue on GitHub\n2. Run ${colors.command(`gent run ${issueNumber}`)} to implement`\n );\n}\n","import { spawn } from \"child_process\";\nimport { execa, type ResultPromise } from \"execa\";\nimport type { GentConfig, AIProvider } from \"../types/index.js\";\nimport { logger, colors } from \"../utils/logger.js\";\n\nexport interface AIProviderOptions {\n prompt: string;\n permissionMode?: string;\n printOutput?: boolean;\n streamOutput?: boolean;\n}\n\nexport interface AIProviderResult {\n output: string;\n provider: AIProvider;\n rateLimited?: boolean;\n}\n\n/**\n * Invoke AI provider (non-interactive mode)\n * Returns output from the provider\n */\nexport async function invokeAI(\n options: AIProviderOptions,\n config: GentConfig,\n providerOverride?: AIProvider\n): Promise<AIProviderResult> {\n const provider = providerOverride ?? config.ai.provider;\n\n try {\n const output = provider === \"claude\"\n ? await invokeClaudeInternal(options)\n : await invokeGeminiInternal(options);\n\n return { output, provider };\n } catch (error) {\n // Check for rate limiting\n if (isRateLimitError(error, provider)) {\n // Try fallback if configured\n if (config.ai.auto_fallback && config.ai.fallback_provider && !providerOverride) {\n const fallback = config.ai.fallback_provider;\n logger.warning(`Rate limit reached on ${getProviderDisplayName(provider)}, switching to ${getProviderDisplayName(fallback)}...`);\n\n const output = fallback === \"claude\"\n ? await invokeClaudeInternal(options)\n : await invokeGeminiInternal(options);\n\n return { output, provider: fallback };\n }\n\n // Return rate limited error\n const err = error as Error;\n err.message = `Rate limited on ${getProviderDisplayName(provider)}`;\n (err as Error & { rateLimited: boolean }).rateLimited = true;\n throw err;\n }\n\n throw error;\n }\n}\n\n/**\n * Invoke AI provider in interactive mode (stdio inherited)\n * Used for implementation sessions\n */\nexport async function invokeAIInteractive(\n prompt: string,\n config: GentConfig,\n providerOverride?: AIProvider\n): Promise<{ result: ResultPromise; provider: AIProvider }> {\n const provider = providerOverride ?? config.ai.provider;\n\n if (provider === \"claude\") {\n const args = [\"--permission-mode\", config.claude.permission_mode, prompt];\n return {\n result: execa(\"claude\", args, { stdio: \"inherit\" }),\n provider,\n };\n } else {\n // Gemini CLI uses -i/--prompt-interactive for interactive mode with initial prompt\n // Without -i, the positional prompt runs in one-shot mode and exits\n return {\n result: execa(\"gemini\", [\"-i\", prompt], { stdio: \"inherit\" }),\n provider,\n };\n }\n}\n\n/**\n * Get display name for provider\n */\nexport function getProviderDisplayName(provider: AIProvider): string {\n return provider === \"claude\" ? \"Claude\" : \"Gemini\";\n}\n\n/**\n * Get email for provider co-author credit\n */\nexport function getProviderEmail(provider: AIProvider): string {\n return provider === \"claude\"\n ? \"noreply@anthropic.com\"\n : \"noreply@google.com\";\n}\n\n/**\n * Get colored provider name for display\n */\nexport function getProviderDisplay(provider: AIProvider): string {\n const name = getProviderDisplayName(provider);\n return provider === \"claude\"\n ? colors.command(name)\n : colors.label(name);\n}\n\n/**\n * Check if error is a rate limit error\n */\nfunction isRateLimitError(error: unknown, provider: AIProvider): boolean {\n if (!error || typeof error !== \"object\") return false;\n\n // Claude CLI uses exit code 2 for rate limiting\n if (provider === \"claude\" && \"exitCode\" in error && error.exitCode === 2) {\n return true;\n }\n\n // Gemini CLI may use different exit codes or error messages\n // Check for common rate limit patterns in error messages\n if (\"message\" in error && typeof error.message === \"string\") {\n const msg = error.message.toLowerCase();\n if (msg.includes(\"rate limit\") || msg.includes(\"quota exceeded\") || msg.includes(\"too many requests\")) {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * Internal Claude invocation\n */\nasync function invokeClaudeInternal(options: AIProviderOptions): Promise<string> {\n const args = [\"--print\"];\n\n if (options.permissionMode) {\n args.push(\"--permission-mode\", options.permissionMode);\n }\n\n args.push(options.prompt);\n\n if (options.printOutput) {\n // Stream output to console without capturing\n const subprocess = execa(\"claude\", args, {\n stdio: \"inherit\",\n });\n await subprocess;\n return \"\";\n } else if (options.streamOutput) {\n // Use native spawn for better streaming control\n return new Promise((resolve, reject) => {\n const child = spawn(\"claude\", args, {\n stdio: [\"inherit\", \"pipe\", \"pipe\"],\n });\n\n let output = \"\";\n\n child.stdout.on(\"data\", (chunk: Buffer) => {\n const text = chunk.toString();\n output += text;\n process.stdout.write(text);\n });\n\n child.stderr.on(\"data\", (chunk: Buffer) => {\n process.stderr.write(chunk);\n });\n\n child.on(\"close\", (code) => {\n if (code === 0) {\n resolve(output);\n } else {\n const error = new Error(`Claude exited with code ${code}`);\n (error as Error & { exitCode: number }).exitCode = code ?? 1;\n reject(error);\n }\n });\n\n child.on(\"error\", reject);\n });\n } else {\n const { stdout } = await execa(\"claude\", args);\n return stdout;\n }\n}\n\n/**\n * Internal Gemini invocation\n */\nasync function invokeGeminiInternal(options: AIProviderOptions): Promise<string> {\n // Gemini CLI uses different argument structure\n const args: string[] = [];\n\n // Add prompt\n args.push(options.prompt);\n\n if (options.printOutput) {\n const subprocess = execa(\"gemini\", args, {\n stdio: \"inherit\",\n });\n await subprocess;\n return \"\";\n } else if (options.streamOutput) {\n return new Promise((resolve, reject) => {\n const child = spawn(\"gemini\", args, {\n stdio: [\"inherit\", \"pipe\", \"pipe\"],\n });\n\n let output = \"\";\n\n child.stdout.on(\"data\", (chunk: Buffer) => {\n const text = chunk.toString();\n output += text;\n process.stdout.write(text);\n });\n\n child.stderr.on(\"data\", (chunk: Buffer) => {\n process.stderr.write(chunk);\n });\n\n child.on(\"close\", (code) => {\n if (code === 0) {\n resolve(output);\n } else {\n const error = new Error(`Gemini exited with code ${code}`);\n (error as Error & { exitCode: number }).exitCode = code ?? 1;\n reject(error);\n }\n });\n\n child.on(\"error\", reject);\n });\n } else {\n const { stdout } = await execa(\"gemini\", args);\n return stdout;\n }\n}\n","import type { GentConfig } from \"../types/index.js\";\nimport { getProviderDisplayName, getProviderEmail } from \"./ai-provider.js\";\n\nexport function buildTicketPrompt(\n description: string,\n agentInstructions: string | null,\n additionalHints: string | null = null\n): string {\n const basePrompt = `You are creating a GitHub issue for a software project following an AI-assisted development workflow.\n\nUser Request: ${description}\n\n${agentInstructions ? `Project-Specific Instructions:\\n${agentInstructions}\\n\\n` : \"\"}${additionalHints ? `Additional Context/Hints:\\n${additionalHints}\\n\\n` : \"\"}\n\nCreate a detailed GitHub issue following this exact template.\n\nIMPORTANT: Start your output IMMEDIATELY with \"## Description\" - do not include any preamble, commentary, or introduction before the template.\n\n## Description\n[Clear user-facing description of what needs to be done]\n\n## Technical Context\n**Type:** feature | fix | refactor | chore | docs | test\n**Category:** ui | api | database | workers | shared | testing | infra\n**Priority:** critical | high | medium | low\n**Risk:** low | medium | high\n\n### Architecture Notes\n- [Relevant patterns to follow]\n- [Related systems affected]\n- [Constraints or invariants]\n\n## Implementation Steps\n- [ ] Step 1: Specific technical task\n- [ ] Step 2: Specific technical task\n- [ ] Step 3: Specific technical task\n\n## Testing Requirements\n- **Unit tests:** [What to test]\n- **Integration tests:** [What to test if applicable]\n- **Manual verification:** [What to check]\n\n## Acceptance Criteria\n- [ ] Criterion 1\n- [ ] Criterion 2\n\n---\nIMPORTANT: After the issue content, on a new line, output ONLY the following metadata in this exact format:\nMETA:type=<type>,priority=<priority>,risk=<risk>,area=<area>\n\nExample: META:type=feature,priority=high,risk=low,area=ui`;\n\n return basePrompt;\n}\n\nexport function buildImplementationPrompt(\n issue: { number: number; title: string; body: string },\n agentInstructions: string | null,\n progressContent: string | null,\n config: GentConfig\n): string {\n const providerName = getProviderDisplayName(config.ai.provider);\n const providerEmail = getProviderEmail(config.ai.provider);\n\n return `GitHub Issue #${issue.number}: ${issue.title}\n\n${issue.body}\n\n${agentInstructions ? `## Project-Specific Instructions\\n${agentInstructions}\\n\\n` : \"\"}\n${progressContent ? `## Previous Progress\\n${progressContent}\\n\\n` : \"\"}\n\n## Your Task\n\n1. **Implement the feature/fix** following patterns from the project's AGENT.md or codebase conventions\n2. **Add unit tests** for any new functionality\n3. **Run validation** before committing:\n${config.validation.map((cmd) => ` - ${cmd}`).join(\"\\n\")}\n4. **Make an atomic commit** with a clear message following conventional commits format:\n - Use format: <type>: <description>\n - Include \"Completed GitHub issue #${issue.number}\" in body\n - End with: Co-Authored-By: ${providerName} <${providerEmail}>\n5. **Update ${config.progress.file}** - append a compact entry documenting your work:\n \\\n [YYYY-MM-DD] #${issue.number} <type>: <brief description>\n - Files: <comma-separated list of changed files>\n - Changes: <1-2 sentence summary of what was implemented>\n - Decisions: <key technical decisions made, if any>\n - Issues: <concerns or follow-ups for reviewers, if any>\n \\\n Keep entries minimal (4-6 lines max). Skip sections if not applicable.\n6. **Do NOT push** - the user will review and push manually\n\nFocus on clean, minimal implementation. Don't over-engineer.`;\n}\n\nexport function buildPrPrompt(\n issue: { number: number; title: string; body: string } | null,\n commits: string[],\n diffSummary: string\n): string {\n return `Generate a pull request description for the following changes.\n\n${issue ? `## Related Issue\\n#${issue.number}: ${issue.title}\\n\\n${issue.body}\\n\\n` : \"\"}\n\n## Commits\n${commits.map((c) => `- ${c}`).join(\"\\n\")}\n\n## Changed Files\n${diffSummary}\n\nGenerate a PR description in this format:\n\n## Summary\n- [1-3 bullet points summarizing the changes]\n\n## Test Plan\n- [ ] [Testing steps]\n\n${issue ? `Closes #${issue.number}` : \"\"}\n\nOnly output the PR description, nothing else.`;\n}\n\nexport function parseTicketMeta(\n output: string\n): { type: string; priority: string; risk: string; area: string } | null {\n const metaMatch = output.match(\n /META:type=(\\w+),priority=(\\w+),risk=(\\w+),area=(\\w+)/\n );\n\n if (!metaMatch) {\n return null;\n }\n\n return {\n type: metaMatch[1],\n priority: metaMatch[2],\n risk: metaMatch[3],\n area: metaMatch[4],\n };\n}\n\nexport function extractIssueBody(output: string): string {\n // Remove the META line from the output\n let body = output.replace(/\\n?META:type=\\w+,priority=\\w+,risk=\\w+,area=\\w+\\s*$/, \"\").trim();\n\n // Strip any preamble text before \"## Description\"\n const descriptionIndex = body.indexOf(\"## Description\");\n if (descriptionIndex > 0) {\n body = body.substring(descriptionIndex);\n }\n\n return body;\n}\n","import chalk from \"chalk\";\nimport { logger, colors } from \"../utils/logger.js\";\nimport { loadConfig } from \"../lib/config.js\";\nimport { listIssues } from \"../lib/github.js\";\nimport { getWorkflowLabels, sortByPriority, extractPriorityFromLabels, extractTypeFromLabels } from \"../lib/labels.js\";\nimport { checkGhAuth } from \"../utils/validators.js\";\nimport type { GitHubIssue } from \"../types/index.js\";\n\nexport interface ListOptions {\n label?: string;\n status?: \"ready\" | \"in-progress\" | \"completed\" | \"blocked\" | \"all\";\n limit?: number;\n}\n\nexport async function listCommand(options: ListOptions): Promise<void> {\n // Check gh auth\n const isAuthed = await checkGhAuth();\n if (!isAuthed) {\n logger.error(\"Not authenticated with GitHub. Run 'gh auth login' first.\");\n process.exit(1);\n }\n\n const config = loadConfig();\n const workflowLabels = getWorkflowLabels(config);\n\n // Build label filter\n const labels: string[] = [];\n\n if (options.label) {\n labels.push(options.label);\n }\n\n if (options.status && options.status !== \"all\") {\n switch (options.status) {\n case \"ready\":\n labels.push(workflowLabels.ready);\n break;\n case \"in-progress\":\n labels.push(workflowLabels.inProgress);\n break;\n case \"completed\":\n labels.push(workflowLabels.completed);\n break;\n case \"blocked\":\n labels.push(workflowLabels.blocked);\n break;\n }\n } else if (!options.status) {\n // Default to showing ai-ready issues\n labels.push(workflowLabels.ready);\n }\n\n let issues: GitHubIssue[];\n try {\n issues = await listIssues({\n labels: labels.length > 0 ? labels : undefined,\n state: \"open\",\n limit: options.limit || 20,\n });\n } catch (error) {\n logger.error(`Failed to fetch issues: ${error}`);\n return;\n }\n\n if (issues.length === 0) {\n logger.info(\"No issues found matching the criteria.\");\n return;\n }\n\n // Sort by priority\n sortByPriority(issues);\n\n logger.bold(`Found ${issues.length} issue(s):`);\n logger.newline();\n\n for (const issue of issues) {\n const type = extractTypeFromLabels(issue.labels);\n const priority = extractPriorityFromLabels(issue.labels);\n const status = getIssueStatus(issue.labels, workflowLabels);\n\n const priorityColor = getPriorityColor(priority);\n const statusColor = getStatusColor(status);\n\n console.log(\n ` ${colors.issue(`#${issue.number.toString().padStart(4)}`)} ` +\n `${priorityColor(`[${priority}]`.padEnd(10))} ` +\n `${statusColor(`[${status}]`.padEnd(14))} ` +\n `${colors.label(`[${type}]`.padEnd(10))} ` +\n issue.title.slice(0, 50) +\n (issue.title.length > 50 ? \"...\" : \"\")\n );\n }\n\n logger.newline();\n logger.dim(`Run ${colors.command(\"gent run <issue-number>\")} to implement an issue`);\n logger.dim(`Run ${colors.command(\"gent run --auto\")} to auto-select highest priority`);\n}\n\nfunction getIssueStatus(\n labels: string[],\n workflowLabels: ReturnType<typeof getWorkflowLabels>\n): string {\n if (labels.includes(workflowLabels.ready)) return \"ready\";\n if (labels.includes(workflowLabels.inProgress)) return \"in-progress\";\n if (labels.includes(workflowLabels.completed)) return \"completed\";\n if (labels.includes(workflowLabels.blocked)) return \"blocked\";\n return \"unknown\";\n}\n\nfunction getPriorityColor(priority: string): (text: string) => string {\n switch (priority) {\n case \"critical\":\n return chalk.red;\n case \"high\":\n return chalk.yellow;\n case \"medium\":\n return chalk.blue;\n case \"low\":\n return chalk.green;\n default:\n return chalk.gray;\n }\n}\n\nfunction getStatusColor(status: string): (text: string) => string {\n switch (status) {\n case \"ready\":\n return chalk.green;\n case \"in-progress\":\n return chalk.yellow;\n case \"completed\":\n return chalk.blue;\n case \"blocked\":\n return chalk.red;\n default:\n return chalk.gray;\n }\n}\n","import inquirer from \"inquirer\";\nimport { logger, colors } from \"../utils/logger.js\";\nimport { withSpinner } from \"../utils/spinner.js\";\nimport { loadConfig, loadAgentInstructions } from \"../lib/config.js\";\nimport { getIssue, listIssues, updateIssueLabels, addIssueComment } from \"../lib/github.js\";\nimport { buildImplementationPrompt } from \"../lib/prompts.js\";\nimport { invokeAIInteractive, getProviderDisplayName } from \"../lib/ai-provider.js\";\nimport { getCurrentBranch, isOnMainBranch, createBranch, branchExists, checkoutBranch, hasUncommittedChanges, getCurrentCommitSha, hasNewCommits } from \"../lib/git.js\";\nimport { generateBranchName } from \"../lib/branch.js\";\nimport { getWorkflowLabels, extractTypeFromLabels, sortByPriority } from \"../lib/labels.js\";\nimport { readProgress } from \"../lib/progress.js\";\nimport { checkGhAuth, checkAIProvider, isValidIssueNumber } from \"../utils/validators.js\";\nimport type { GitHubIssue, AIProvider } from \"../types/index.js\";\n\nexport interface RunOptions {\n auto?: boolean;\n provider?: AIProvider;\n}\n\nexport async function runCommand(\n issueNumberArg: string | undefined,\n options: RunOptions\n): Promise<void> {\n logger.bold(\"Running AI implementation workflow...\");\n logger.newline();\n\n const config = loadConfig();\n\n // Determine which provider to use\n const provider = options.provider ?? config.ai.provider;\n const providerName = getProviderDisplayName(provider);\n\n // Validate prerequisites\n const [ghAuth, aiOk] = await Promise.all([\n checkGhAuth(),\n checkAIProvider(provider),\n ]);\n\n if (!ghAuth) {\n logger.error(\"Not authenticated with GitHub. Run 'gh auth login' first.\");\n process.exit(1);\n }\n\n if (!aiOk) {\n logger.error(`${providerName} CLI not found. Please install ${provider} CLI first.`);\n process.exit(1);\n }\n\n // Check for uncommitted changes\n const hasChanges = await hasUncommittedChanges();\n if (hasChanges) {\n logger.warning(\"You have uncommitted changes.\");\n const { proceed } = await inquirer.prompt([\n {\n type: \"confirm\",\n name: \"proceed\",\n message: \"Continue anyway?\",\n default: false,\n },\n ]);\n if (!proceed) {\n logger.info(\"Aborting. Please commit or stash your changes first.\");\n process.exit(0);\n }\n }\n\n const workflowLabels = getWorkflowLabels(config);\n\n // Get issue number\n let issueNumber: number;\n\n if (options.auto) {\n // Auto-select highest priority ai-ready issue\n const autoIssue = await autoSelectIssue(workflowLabels.ready);\n if (!autoIssue) {\n logger.error(\"No ai-ready issues found.\");\n process.exit(1);\n }\n issueNumber = autoIssue.number;\n logger.info(`Auto-selected: ${colors.issue(`#${issueNumber}`)} - ${autoIssue.title}`);\n } else if (issueNumberArg) {\n if (!isValidIssueNumber(issueNumberArg)) {\n logger.error(\"Invalid issue number.\");\n process.exit(1);\n }\n issueNumber = parseInt(issueNumberArg, 10);\n } else {\n logger.error(\"Please provide an issue number or use --auto\");\n process.exit(1);\n }\n\n // Fetch issue details\n let issue: GitHubIssue;\n try {\n issue = await withSpinner(\"Fetching issue...\", async () => {\n return getIssue(issueNumber);\n });\n } catch (error) {\n logger.error(`Failed to fetch issue #${issueNumber}: ${error}`);\n return;\n }\n\n // Verify issue has ai-ready label\n if (!issue.labels.includes(workflowLabels.ready)) {\n logger.warning(`Issue #${issueNumber} does not have the '${workflowLabels.ready}' label.`);\n const { proceed } = await inquirer.prompt([\n {\n type: \"confirm\",\n name: \"proceed\",\n message: \"Continue anyway?\",\n default: false,\n },\n ]);\n if (!proceed) {\n return;\n }\n }\n\n logger.newline();\n logger.box(\"Issue Details\", `#${issue.number}: ${issue.title}\nLabels: ${issue.labels.join(\", \")}`);\n logger.newline();\n\n // Generate branch name\n const type = extractTypeFromLabels(issue.labels);\n const branchName = await generateBranchName(config, issueNumber, issue.title, type);\n\n // Handle branch\n const currentBranch = await getCurrentBranch();\n const onMain = await isOnMainBranch();\n\n if (await branchExists(branchName)) {\n logger.info(`Branch ${colors.branch(branchName)} already exists.`);\n const { action } = await inquirer.prompt([\n {\n type: \"list\",\n name: \"action\",\n message: \"What would you like to do?\",\n choices: [\n { name: \"Continue on existing branch\", value: \"continue\" },\n { name: \"Delete and recreate branch\", value: \"recreate\" },\n { name: \"Cancel\", value: \"cancel\" },\n ],\n },\n ]);\n\n if (action === \"cancel\") {\n return;\n } else if (action === \"continue\") {\n await checkoutBranch(branchName);\n } else {\n // Recreate would require deleting first - for safety, just checkout\n await checkoutBranch(branchName);\n }\n } else {\n if (!onMain) {\n logger.warning(`Not on main branch (currently on ${colors.branch(currentBranch)}).`);\n const { fromMain } = await inquirer.prompt([\n {\n type: \"confirm\",\n name: \"fromMain\",\n message: \"Create branch from main instead?\",\n default: true,\n },\n ]);\n\n if (fromMain) {\n await createBranch(branchName, \"main\");\n } else {\n await createBranch(branchName);\n }\n } else {\n await createBranch(branchName);\n }\n logger.success(`Created branch ${colors.branch(branchName)}`);\n }\n\n // Update issue labels\n try {\n await updateIssueLabels(issueNumber, {\n add: [workflowLabels.inProgress],\n remove: [workflowLabels.ready],\n });\n logger.success(`Updated issue labels: ${colors.label(workflowLabels.ready)} → ${colors.label(workflowLabels.inProgress)}`);\n } catch (error) {\n logger.warning(`Failed to update labels: ${error}`);\n }\n\n // Build implementation prompt\n const agentInstructions = loadAgentInstructions();\n const progressContent = readProgress(config);\n const prompt = buildImplementationPrompt(issue, agentInstructions, progressContent, config);\n\n logger.newline();\n logger.info(`Starting ${colors.provider(providerName)} implementation session...`);\n logger.dim(`${providerName} will implement the feature and create a commit.`);\n logger.dim(\"Review the changes before pushing.\");\n logger.newline();\n\n // Capture commit SHA before AI runs\n const beforeSha = await getCurrentCommitSha();\n\n // Track if operation was cancelled\n let wasCancelled = false;\n const handleSignal = () => {\n wasCancelled = true;\n };\n process.on(\"SIGINT\", handleSignal);\n process.on(\"SIGTERM\", handleSignal);\n\n // Invoke AI interactively\n let aiExitCode: number | undefined;\n let usedProvider = provider;\n try {\n const { result, provider: actualProvider } = await invokeAIInteractive(prompt, config, options.provider);\n usedProvider = actualProvider;\n aiExitCode = result.exitCode ?? undefined;\n } catch (error) {\n if (error && typeof error === \"object\" && \"exitCode\" in error) {\n aiExitCode = error.exitCode as number;\n }\n logger.error(`${getProviderDisplayName(usedProvider)} session failed: ${error}`);\n // Don't exit - allow user to see what happened\n } finally {\n // Clean up signal handlers\n process.off(\"SIGINT\", handleSignal);\n process.off(\"SIGTERM\", handleSignal);\n }\n\n // Post-completion\n logger.newline();\n\n // Check if any new commits were created\n const commitsCreated = await hasNewCommits(beforeSha);\n\n // Handle cancellation - don't change labels\n if (wasCancelled) {\n logger.warning(\"Operation was cancelled. Labels unchanged.\");\n return;\n }\n\n // Determine appropriate label based on whether work was done\n const usedProviderName = getProviderDisplayName(usedProvider);\n if (commitsCreated) {\n logger.success(`${usedProviderName} session completed with new commits.`);\n\n // Update labels to completed\n try {\n await updateIssueLabels(issueNumber, {\n add: [workflowLabels.completed],\n remove: [workflowLabels.inProgress],\n });\n logger.success(`Updated labels: ${colors.label(workflowLabels.inProgress)} → ${colors.label(workflowLabels.completed)}`);\n } catch (error) {\n logger.warning(`Failed to update labels: ${error}`);\n }\n\n // Post comment to issue\n try {\n await addIssueComment(\n issueNumber,\n `AI implementation completed on branch \\`${branchName}\\` using ${usedProviderName}.\\n\\nPlease review the changes and create a PR when ready.`\n );\n logger.success(\"Posted completion comment to issue\");\n } catch (error) {\n logger.warning(`Failed to post comment: ${error}`);\n }\n } else {\n // No commits created - check if it was a rate limit or other issue\n // Exit code 2 typically indicates rate limiting for the AI provider CLI\n // Gemini may use different patterns\n const isRateLimited = aiExitCode === 2;\n\n if (isRateLimited) {\n logger.warning(`${usedProviderName} session ended due to rate limits. No commits were created.`);\n\n // Set ai-blocked label\n try {\n await updateIssueLabels(issueNumber, {\n add: [workflowLabels.blocked],\n remove: [workflowLabels.inProgress],\n });\n logger.info(`Updated labels: ${colors.label(workflowLabels.inProgress)} → ${colors.label(workflowLabels.blocked)}`);\n } catch (error) {\n logger.warning(`Failed to update labels: ${error}`);\n }\n\n // Post comment about rate limiting\n try {\n await addIssueComment(\n issueNumber,\n `AI implementation was blocked due to API rate limits on branch \\`${branchName}\\` (${usedProviderName}).\\n\\nNo commits were created. Please retry later.`\n );\n logger.info(\"Posted rate-limit comment to issue\");\n } catch (error) {\n logger.warning(`Failed to post comment: ${error}`);\n }\n } else {\n logger.warning(`${usedProviderName} session completed but no commits were created. Labels unchanged.`);\n // Leave as ai-in-progress so it can be retried\n }\n\n return;\n }\n\n logger.newline();\n logger.box(\"Next Steps\", `1. Review changes: ${colors.command(\"git diff HEAD~1\")}\n2. Run tests: ${colors.command(\"npm test\")}\n3. Push branch: ${colors.command(\"git push -u origin \" + branchName)}\n4. Create PR: ${colors.command(\"gent pr\")}`);\n}\n\nasync function autoSelectIssue(readyLabel: string): Promise<GitHubIssue | null> {\n // Try critical first\n let issues = await listIssues({\n labels: [readyLabel, \"priority:critical\"],\n state: \"open\",\n limit: 1,\n });\n if (issues.length > 0) return issues[0];\n\n // Try high\n issues = await listIssues({\n labels: [readyLabel, \"priority:high\"],\n state: \"open\",\n limit: 1,\n });\n if (issues.length > 0) return issues[0];\n\n // Get any ai-ready and sort\n issues = await listIssues({\n labels: [readyLabel],\n state: \"open\",\n limit: 10,\n });\n\n if (issues.length === 0) return null;\n\n sortByPriority(issues);\n return issues[0];\n}\n","import { execa } from \"execa\";\n\nexport async function getCurrentBranch(): Promise<string> {\n const { stdout } = await execa(\"git\", [\"branch\", \"--show-current\"]);\n return stdout.trim();\n}\n\nexport async function isOnMainBranch(): Promise<boolean> {\n const branch = await getCurrentBranch();\n return branch === \"main\" || branch === \"master\";\n}\n\nexport async function getDefaultBranch(): Promise<string> {\n try {\n const { stdout } = await execa(\"git\", [\n \"symbolic-ref\",\n \"refs/remotes/origin/HEAD\",\n ]);\n return stdout.trim().replace(\"refs/remotes/origin/\", \"\");\n } catch {\n // Fallback to checking if main or master exists\n try {\n await execa(\"git\", [\"rev-parse\", \"--verify\", \"main\"]);\n return \"main\";\n } catch {\n return \"master\";\n }\n }\n}\n\nexport async function branchExists(name: string): Promise<boolean> {\n try {\n await execa(\"git\", [\"rev-parse\", \"--verify\", name]);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function createBranch(name: string, from?: string): Promise<void> {\n if (from) {\n await execa(\"git\", [\"checkout\", \"-b\", name, from]);\n } else {\n await execa(\"git\", [\"checkout\", \"-b\", name]);\n }\n}\n\nexport async function checkoutBranch(name: string): Promise<void> {\n await execa(\"git\", [\"checkout\", name]);\n}\n\nexport async function hasUncommittedChanges(): Promise<boolean> {\n const { stdout } = await execa(\"git\", [\"status\", \"--porcelain\"]);\n return stdout.trim().length > 0;\n}\n\nexport async function getUnpushedCommits(): Promise<boolean> {\n try {\n const { stdout } = await execa(\"git\", [\n \"log\",\n \"@{u}..HEAD\",\n \"--oneline\",\n ]);\n return stdout.trim().length > 0;\n } catch {\n // No upstream set\n return true;\n }\n}\n\nexport async function pushBranch(branch?: string): Promise<void> {\n const branchName = branch || (await getCurrentBranch());\n await execa(\"git\", [\"push\", \"-u\", \"origin\", branchName]);\n}\n\nexport async function getAuthorInitials(): Promise<string> {\n // Try git config user.initials first\n try {\n const { stdout } = await execa(\"git\", [\"config\", \"user.initials\"]);\n if (stdout.trim()) {\n return stdout.trim();\n }\n } catch {\n // Not set, continue\n }\n\n // Fall back to deriving from user.name\n try {\n const { stdout } = await execa(\"git\", [\"config\", \"user.name\"]);\n const name = stdout.trim();\n if (name) {\n // Extract initials from name (e.g., \"John Doe\" -> \"jd\")\n const parts = name.split(/\\s+/);\n return parts.map((p) => p[0]?.toLowerCase() || \"\").join(\"\");\n }\n } catch {\n // Not set\n }\n\n return \"dev\";\n}\n\nexport async function getRepoInfo(): Promise<{\n owner: string;\n repo: string;\n} | null> {\n try {\n const { stdout } = await execa(\"git\", [\n \"config\",\n \"--get\",\n \"remote.origin.url\",\n ]);\n const url = stdout.trim();\n\n // Handle SSH format: git@github.com:owner/repo.git\n const sshMatch = url.match(/git@github\\.com:([^/]+)\\/([^.]+)/);\n if (sshMatch) {\n return { owner: sshMatch[1], repo: sshMatch[2] };\n }\n\n // Handle HTTPS format: https://github.com/owner/repo.git\n const httpsMatch = url.match(/github\\.com\\/([^/]+)\\/([^.]+)/);\n if (httpsMatch) {\n return { owner: httpsMatch[1], repo: httpsMatch[2] };\n }\n\n return null;\n } catch {\n return null;\n }\n}\n\nexport async function getCommitsSinceBase(\n base: string = \"main\"\n): Promise<string[]> {\n try {\n const { stdout } = await execa(\"git\", [\n \"log\",\n `${base}..HEAD`,\n \"--pretty=format:%s\",\n ]);\n return stdout.trim().split(\"\\n\").filter(Boolean);\n } catch {\n return [];\n }\n}\n\nexport async function getDiffSummary(base: string = \"main\"): Promise<string> {\n try {\n const { stdout } = await execa(\"git\", [\n \"diff\",\n `${base}...HEAD`,\n \"--stat\",\n ]);\n return stdout.trim();\n } catch {\n return \"\";\n }\n}\n\nexport async function getCurrentCommitSha(): Promise<string> {\n const { stdout } = await execa(\"git\", [\"rev-parse\", \"HEAD\"]);\n return stdout.trim();\n}\n\nexport async function hasNewCommits(beforeSha: string): Promise<boolean> {\n const currentSha = await getCurrentCommitSha();\n return currentSha !== beforeSha;\n}\n","import type { GentConfig, BranchInfo } from \"../types/index.js\";\nimport { getAuthorInitials } from \"./git.js\";\nimport { sanitizeSlug } from \"../utils/validators.js\";\n\nexport async function generateBranchName(\n config: GentConfig,\n issueNumber: number,\n issueTitle: string,\n type: string\n): Promise<string> {\n const author = await resolveAuthor(config);\n const slug = sanitizeSlug(issueTitle);\n\n return config.branch.pattern\n .replace(\"{author}\", author)\n .replace(\"{type}\", type)\n .replace(\"{issue}\", String(issueNumber))\n .replace(\"{slug}\", slug);\n}\n\nasync function resolveAuthor(config: GentConfig): Promise<string> {\n switch (config.branch.author_source) {\n case \"env\": {\n const envValue = process.env[config.branch.author_env_var];\n if (envValue) {\n return envValue;\n }\n // Fall through to git\n return getAuthorInitials();\n }\n case \"git\":\n default:\n return getAuthorInitials();\n }\n}\n\nexport function parseBranchName(branchName: string): BranchInfo | null {\n // Pattern 1: author/type-issue-slug (e.g., ro/feature-123-add-login)\n const pattern1 = /^([^/]+)\\/(feature|fix|refactor|chore|docs|test)-(\\d+)-(.+)$/;\n const match1 = branchName.match(pattern1);\n if (match1) {\n return {\n name: branchName,\n author: match1[1],\n type: match1[2],\n issueNumber: parseInt(match1[3], 10),\n slug: match1[4],\n };\n }\n\n // Pattern 2: type/issue-slug (e.g., feature/123-add-login)\n const pattern2 = /^(feature|fix|refactor|chore|docs|test)\\/(\\d+)-(.+)$/;\n const match2 = branchName.match(pattern2);\n if (match2) {\n return {\n name: branchName,\n author: \"\",\n type: match2[1],\n issueNumber: parseInt(match2[2], 10),\n slug: match2[3],\n };\n }\n\n // Pattern 3: issue-slug (e.g., 123-add-login)\n const pattern3 = /^(\\d+)-(.+)$/;\n const match3 = branchName.match(pattern3);\n if (match3) {\n return {\n name: branchName,\n author: \"\",\n type: \"feature\",\n issueNumber: parseInt(match3[1], 10),\n slug: match3[2],\n };\n }\n\n // Pattern 4: Just look for issue number anywhere\n const issueMatch = branchName.match(/(\\d+)/);\n if (issueMatch) {\n return {\n name: branchName,\n author: \"\",\n type: \"feature\",\n issueNumber: parseInt(issueMatch[1], 10),\n slug: branchName,\n };\n }\n\n return null;\n}\n\nexport function extractIssueNumber(branchName: string): number | null {\n const info = parseBranchName(branchName);\n return info?.issueNumber ?? null;\n}\n","import inquirer from \"inquirer\";\nimport { logger, colors } from \"../utils/logger.js\";\nimport { withSpinner } from \"../utils/spinner.js\";\nimport { loadConfig } from \"../lib/config.js\";\nimport { getIssue, createPullRequest, getPrForBranch, assignIssue, getCurrentUser, updateIssueLabels } from \"../lib/github.js\";\nimport { buildPrPrompt } from \"../lib/prompts.js\";\nimport { invokeAI, getProviderDisplayName } from \"../lib/ai-provider.js\";\nimport { getCurrentBranch, isOnMainBranch, getDefaultBranch, getCommitsSinceBase, getDiffSummary, getUnpushedCommits, pushBranch } from \"../lib/git.js\";\nimport { extractIssueNumber } from \"../lib/branch.js\";\nimport { getWorkflowLabels } from \"../lib/labels.js\";\nimport { checkGhAuth, checkAIProvider } from \"../utils/validators.js\";\nimport type { GitHubIssue, AIProvider } from \"../types/index.js\";\n\nexport interface PrOptions {\n draft?: boolean;\n provider?: AIProvider;\n}\n\nexport async function prCommand(options: PrOptions): Promise<void> {\n logger.bold(\"Creating AI-enhanced pull request...\");\n logger.newline();\n\n const config = loadConfig();\n\n // Determine which provider to use\n const provider = options.provider ?? config.ai.provider;\n const providerName = getProviderDisplayName(provider);\n\n // Validate prerequisites\n const [ghAuth, aiOk] = await Promise.all([\n checkGhAuth(),\n checkAIProvider(provider),\n ]);\n\n if (!ghAuth) {\n logger.error(\"Not authenticated with GitHub. Run 'gh auth login' first.\");\n process.exit(1);\n }\n\n if (!aiOk) {\n logger.error(`${providerName} CLI not found. Please install ${provider} CLI first.`);\n process.exit(1);\n }\n\n // Check we're not on main\n if (await isOnMainBranch()) {\n logger.error(\"Cannot create PR from main/master branch.\");\n process.exit(1);\n }\n\n // Check for existing PR\n const existingPr = await getPrForBranch();\n if (existingPr) {\n logger.warning(`A PR already exists for this branch: ${colors.url(existingPr.url)}`);\n return;\n }\n\n const currentBranch = await getCurrentBranch();\n const baseBranch = await getDefaultBranch();\n\n logger.info(`Branch: ${colors.branch(currentBranch)}`);\n logger.info(`Base: ${colors.branch(baseBranch)}`);\n\n // Check if we need to push\n const hasUnpushed = await getUnpushedCommits();\n if (hasUnpushed) {\n logger.warning(\"Branch has unpushed commits.\");\n const { push } = await inquirer.prompt([\n {\n type: \"confirm\",\n name: \"push\",\n message: \"Push to remote before creating PR?\",\n default: true,\n },\n ]);\n\n if (push) {\n await withSpinner(\"Pushing branch...\", async () => {\n await pushBranch();\n });\n logger.success(\"Branch pushed\");\n }\n }\n\n // Extract issue number from branch\n const issueNumber = extractIssueNumber(currentBranch);\n let issue: GitHubIssue | null = null;\n\n if (issueNumber) {\n try {\n issue = await getIssue(issueNumber);\n logger.info(`Linked issue: ${colors.issue(`#${issueNumber}`)} - ${issue.title}`);\n } catch {\n logger.warning(`Could not fetch issue #${issueNumber}`);\n }\n } else {\n logger.warning(\"Could not extract issue number from branch name.\");\n }\n\n // Get commits and diff\n const commits = await getCommitsSinceBase(baseBranch);\n const diffSummary = await getDiffSummary(baseBranch);\n\n if (commits.length === 0) {\n logger.error(\"No commits found since base branch.\");\n return;\n }\n\n logger.info(`Commits: ${commits.length}`);\n logger.newline();\n\n // Generate PR description with AI\n const prompt = buildPrPrompt(issue, commits, diffSummary);\n\n let prBody: string;\n try {\n logger.info(`Generating PR description with ${colors.provider(providerName)}...`);\n logger.newline();\n const result = await invokeAI({ prompt, streamOutput: true }, config, options.provider);\n prBody = result.output;\n logger.newline();\n } catch (error) {\n logger.warning(`${providerName} invocation failed: ${error}`);\n // Fall back to basic description\n prBody = generateFallbackBody(issue, commits);\n }\n\n // Append signature footer\n prBody += `\\n\\n---\\n*Created with ${providerName} by [gent](https://github.com/Rotorsoft/gent)*`;\n\n // Generate title\n const prTitle = issue?.title || commits[0] || currentBranch;\n\n // Create PR\n let prUrl: string;\n try {\n prUrl = await withSpinner(\"Creating pull request...\", async () => {\n return createPullRequest({\n title: prTitle,\n body: prBody,\n base: baseBranch,\n draft: options.draft,\n });\n });\n } catch (error) {\n logger.error(`Failed to create PR: ${error}`);\n return;\n }\n\n // Assign issue to current user if linked\n if (issueNumber) {\n try {\n const user = await getCurrentUser();\n await assignIssue(issueNumber, user);\n logger.success(`Assigned issue #${issueNumber} to ${user}`);\n } catch {\n // Non-critical, ignore\n }\n\n // Update issue labels to ai-completed\n const workflowLabels = getWorkflowLabels(config);\n try {\n await updateIssueLabels(issueNumber, {\n add: [workflowLabels.completed],\n remove: [workflowLabels.inProgress],\n });\n logger.success(`Updated labels: ${colors.label(workflowLabels.inProgress)} → ${colors.label(workflowLabels.completed)}`);\n } catch {\n // Non-critical, ignore\n }\n }\n\n logger.newline();\n logger.success(`Pull request created!`);\n logger.newline();\n logger.highlight(prUrl);\n logger.newline();\n\n if (options.draft) {\n logger.dim(\"Created as draft. Mark as ready for review when done.\");\n }\n}\n\nfunction generateFallbackBody(\n issue: GitHubIssue | null,\n commits: string[]\n): string {\n let body = \"## Summary\\n\\n\";\n\n if (issue) {\n body += `Implements #${issue.number}: ${issue.title}\\n\\n`;\n }\n\n body += \"## Changes\\n\\n\";\n for (const commit of commits.slice(0, 10)) {\n body += `- ${commit}\\n`;\n }\n\n body += \"\\n## Test Plan\\n\\n- [ ] Tests pass\\n- [ ] Manual verification\\n\\n\";\n\n if (issue) {\n body += `Closes #${issue.number}\\n`;\n }\n\n return body;\n}\n","import { logger, colors } from \"../utils/logger.js\";\nimport { loadConfig } from \"../lib/config.js\";\nimport { getIssue, getPrForBranch } from \"../lib/github.js\";\nimport { getCurrentBranch, isOnMainBranch, hasUncommittedChanges, getUnpushedCommits, getCommitsSinceBase, getDefaultBranch } from \"../lib/git.js\";\nimport { extractIssueNumber, parseBranchName } from \"../lib/branch.js\";\nimport { getWorkflowLabels } from \"../lib/labels.js\";\nimport { progressExists, readProgress } from \"../lib/progress.js\";\nimport { configExists } from \"../lib/config.js\";\nimport { checkGhAuth, checkClaudeCli, checkGeminiCli, checkGitRepo } from \"../utils/validators.js\";\nimport { getProviderDisplayName } from \"../lib/ai-provider.js\";\n\nexport async function statusCommand(): Promise<void> {\n logger.bold(\"Gent Workflow Status\");\n logger.newline();\n\n // Check prerequisites\n const gitRepo = await checkGitRepo();\n if (!gitRepo) {\n logger.error(\"Not a git repository.\");\n process.exit(1);\n }\n\n const config = loadConfig();\n const workflowLabels = getWorkflowLabels(config);\n\n // Configuration status\n logger.bold(\"Configuration:\");\n if (configExists()) {\n logger.success(\" .gent.yml found\");\n } else {\n logger.warning(\" .gent.yml not found - using defaults\");\n }\n\n if (progressExists(config)) {\n const progress = readProgress(config);\n const lines = progress.split(\"\\n\").length;\n logger.success(` ${config.progress.file} found (${lines} lines)`);\n } else {\n logger.warning(` ${config.progress.file} not found`);\n }\n\n logger.newline();\n\n // AI Provider status\n logger.bold(\"AI Provider:\");\n const providerName = getProviderDisplayName(config.ai.provider);\n logger.info(` Active: ${colors.provider(providerName)}`);\n if (config.ai.fallback_provider) {\n const fallbackName = getProviderDisplayName(config.ai.fallback_provider);\n logger.info(` Fallback: ${fallbackName} (auto: ${config.ai.auto_fallback ? \"enabled\" : \"disabled\"})`);\n }\n logger.newline();\n\n // Prerequisites\n logger.bold(\"Prerequisites:\");\n const ghAuth = await checkGhAuth();\n if (ghAuth) {\n logger.success(\" GitHub CLI authenticated\");\n } else {\n logger.error(\" GitHub CLI not authenticated\");\n }\n\n // Check all AI providers\n const claudeOk = await checkClaudeCli();\n const geminiOk = await checkGeminiCli();\n\n const getProviderStatus = (provider: \"claude\" | \"gemini\"): string => {\n const isActive = config.ai.provider === provider;\n const isFallback = config.ai.fallback_provider === provider;\n const suffix = isActive ? \" (active)\" : isFallback ? \" (fallback)\" : \"\";\n return suffix;\n };\n\n if (claudeOk) {\n logger.success(` Claude CLI available${getProviderStatus(\"claude\")}`);\n } else {\n logger.error(` Claude CLI not found${getProviderStatus(\"claude\")}`);\n }\n\n if (geminiOk) {\n logger.success(` Gemini CLI available${getProviderStatus(\"gemini\")}`);\n } else {\n logger.error(` Gemini CLI not found${getProviderStatus(\"gemini\")}`);\n }\n\n logger.newline();\n\n // Git status\n logger.bold(\"Git Status:\");\n const currentBranch = await getCurrentBranch();\n const onMain = await isOnMainBranch();\n const uncommitted = await hasUncommittedChanges();\n const baseBranch = await getDefaultBranch();\n\n logger.info(` Branch: ${colors.branch(currentBranch)}`);\n\n if (onMain) {\n logger.info(\" On main branch - ready to start new work\");\n } else {\n const branchInfo = parseBranchName(currentBranch);\n if (branchInfo) {\n logger.info(` Issue: ${colors.issue(`#${branchInfo.issueNumber}`)}`);\n logger.info(` Type: ${branchInfo.type}`);\n }\n\n const commits = await getCommitsSinceBase(baseBranch);\n logger.info(` Commits ahead of ${baseBranch}: ${commits.length}`);\n\n const unpushed = await getUnpushedCommits();\n if (unpushed) {\n logger.warning(\" Has unpushed commits\");\n } else {\n logger.success(\" Up to date with remote\");\n }\n }\n\n if (uncommitted) {\n logger.warning(\" Has uncommitted changes\");\n }\n\n logger.newline();\n\n // Linked issue status\n if (!onMain) {\n const issueNumber = extractIssueNumber(currentBranch);\n if (issueNumber) {\n logger.bold(\"Linked Issue:\");\n try {\n const issue = await getIssue(issueNumber);\n logger.info(` #${issue.number}: ${issue.title}`);\n logger.info(` State: ${issue.state}`);\n logger.info(` Labels: ${issue.labels.join(\", \")}`);\n\n // Check workflow status\n if (issue.labels.includes(workflowLabels.ready)) {\n logger.info(` Workflow: ${colors.label(\"ai-ready\")}`);\n } else if (issue.labels.includes(workflowLabels.inProgress)) {\n logger.info(` Workflow: ${colors.label(\"ai-in-progress\")}`);\n } else if (issue.labels.includes(workflowLabels.completed)) {\n logger.info(` Workflow: ${colors.label(\"ai-completed\")}`);\n } else if (issue.labels.includes(workflowLabels.blocked)) {\n logger.info(` Workflow: ${colors.label(\"ai-blocked\")}`);\n }\n } catch {\n logger.warning(` Could not fetch issue #${issueNumber}`);\n }\n logger.newline();\n }\n\n // PR status\n logger.bold(\"Pull Request:\");\n const pr = await getPrForBranch();\n if (pr) {\n logger.success(` PR #${pr.number} exists`);\n logger.info(` ${colors.url(pr.url)}`);\n } else {\n logger.info(\" No PR created yet\");\n logger.dim(` Run ${colors.command(\"gent pr\")} to create one`);\n }\n logger.newline();\n }\n\n // Suggestions\n logger.bold(\"Suggested Actions:\");\n if (onMain) {\n logger.list([\n `${colors.command(\"gent list\")} - View ai-ready issues`,\n `${colors.command(\"gent run --auto\")} - Start working on highest priority issue`,\n `${colors.command(\"gent create <description>\")} - Create a new ticket`,\n ]);\n } else {\n const pr = await getPrForBranch();\n if (!pr) {\n logger.list([\n `${colors.command(\"gent pr\")} - Create a pull request`,\n `${colors.command(\"git push\")} - Push your changes`,\n ]);\n } else {\n logger.list([\n `Review and merge your PR`,\n `${colors.command(\"git checkout main\")} - Return to main branch`,\n ]);\n }\n }\n}\n"],"mappings":"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","names":["readFileSync","join","dirname","writeFileSync","existsSync","join","writeFileSync","join","existsSync","setupLabelsCommand","inquirer","inquirer","chalk","chalk","inquirer","execa","execa","inquirer","inquirer","inquirer","dirname","readFileSync","join"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@rotorsoft/gent",
3
- "version": "1.3.2",
4
- "description": "AI-powered GitHub workflow CLI - leverage Claude AI to create tickets, implement features, and manage PRs",
3
+ "version": "1.4.0",
4
+ "description": "AI-powered GitHub workflow CLI - leverage AI (Claude or Gemini) to create tickets, implement features, and manage PRs",
5
5
  "keywords": [
6
6
  "cli",
7
7
  "ai",
@@ -1,6 +1,6 @@
1
1
  # AI Agent Instructions
2
2
 
3
- This file contains instructions for Claude when working on this repository.
3
+ This file contains instructions for the AI when working on this repository.
4
4
 
5
5
  ## Project Overview
6
6
 
@@ -72,10 +72,7 @@ Follow conventional commits format:
72
72
  - `chore:` Maintenance/dependencies
73
73
  - `docs:` Documentation
74
74
 
75
- All AI commits should include:
76
- ```
77
- Co-Authored-By: Claude <noreply@anthropic.com>
78
- ```
75
+ All AI commits should include the Co-Authored-By trailer as specified in the task prompt.
79
76
 
80
77
  ## Important Files
81
78