@iloom/cli 0.9.0 → 0.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +21 -2
  3. package/dist/{ClaudeContextManager-X2Y72GRL.js → ClaudeContextManager-HR5JQKAI.js} +4 -4
  4. package/dist/{ClaudeService-7P32TTES.js → ClaudeService-TK7FMC2X.js} +3 -3
  5. package/dist/{GitHubService-ACZVNTJE.js → GitHubService-TGWJN4V4.js} +3 -3
  6. package/dist/{LoomLauncher-3I47SUPV.js → LoomLauncher-73NXL2CL.js} +4 -4
  7. package/dist/README.md +21 -2
  8. package/dist/{SettingsManager-QR7V2IW2.js → SettingsManager-AW3JTJHD.js} +2 -2
  9. package/dist/{build-IC4CJRMP.js → build-THZI572G.js} +6 -6
  10. package/dist/{chunk-Z6F5CUS6.js → chunk-3I4ONZRT.js} +3 -3
  11. package/dist/{chunk-THS5L54H.js → chunk-4CO6KG5S.js} +50 -3
  12. package/dist/chunk-4CO6KG5S.js.map +1 -0
  13. package/dist/{chunk-MZPRBNYC.js → chunk-6IIL5M2L.js} +2 -2
  14. package/dist/{chunk-2JPXGGP4.js → chunk-A7NJF73J.js} +2 -2
  15. package/dist/{chunk-H6ST2TGP.js → chunk-AR5QKYNE.js} +3 -3
  16. package/dist/{chunk-PL2FDYEK.js → chunk-CWRI4JC3.js} +2 -2
  17. package/dist/{chunk-I23OQB4Y.js → chunk-DGG2VY7B.js} +6 -5
  18. package/dist/chunk-DGG2VY7B.js.map +1 -0
  19. package/dist/{chunk-RNBIISBZ.js → chunk-FJDRTVJX.js} +50 -5
  20. package/dist/chunk-FJDRTVJX.js.map +1 -0
  21. package/dist/{chunk-NTTSUAVM.js → chunk-IZIYLYPK.js} +2 -2
  22. package/dist/{chunk-TGRK3CHF.js → chunk-KJTVU3HZ.js} +4 -4
  23. package/dist/{chunk-SC6X5EBG.js → chunk-KXGQYLFZ.js} +3 -3
  24. package/dist/{chunk-USSL2X4A.js → chunk-NUACL52E.js} +2 -2
  25. package/dist/{chunk-JT5LZRMI.js → chunk-NWMORW3U.js} +2 -2
  26. package/dist/{chunk-PVW6JE7E.js → chunk-OFDN5NKS.js} +4 -3
  27. package/dist/{chunk-PVW6JE7E.js.map → chunk-OFDN5NKS.js.map} +1 -1
  28. package/dist/{chunk-HZXBHMVM.js → chunk-R4YWBGY6.js} +3 -3
  29. package/dist/{chunk-XFEK2X2D.js → chunk-RI2YL6TK.js} +9 -3
  30. package/dist/chunk-RI2YL6TK.js.map +1 -0
  31. package/dist/{chunk-6Y3FTRJL.js → chunk-SOSQILHO.js} +102 -51
  32. package/dist/chunk-SOSQILHO.js.map +1 -0
  33. package/dist/{chunk-4GAJJUYS.js → chunk-TC7APDKU.js} +2 -2
  34. package/dist/{chunk-UDZCTLD6.js → chunk-ULSWCPQG.js} +3 -3
  35. package/dist/{chunk-5LVVQGB3.js → chunk-VPTAX5TR.js} +7 -7
  36. package/dist/chunk-VPTAX5TR.js.map +1 -0
  37. package/dist/{chunk-RD7OPXZK.js → chunk-W6DP5RVR.js} +3 -3
  38. package/dist/{chunk-XJHQVOT6.js → chunk-WHI5KEOX.js} +2 -2
  39. package/dist/{chunk-2HZX6AMR.js → chunk-YKFCCV6S.js} +2 -2
  40. package/dist/{chunk-OAVJR4PM.js → chunk-Z2TWEXR7.js} +2 -2
  41. package/dist/{cleanup-M6N7KV7E.js → cleanup-PJRIFFU4.js} +16 -16
  42. package/dist/cli.js +79 -62
  43. package/dist/cli.js.map +1 -1
  44. package/dist/{commit-ORHR53KW.js → commit-IVP3M4HG.js} +10 -9
  45. package/dist/commit-IVP3M4HG.js.map +1 -0
  46. package/dist/{compile-EOWJORKO.js → compile-R2J65HBQ.js} +6 -6
  47. package/dist/{contribute-4KCEOHSH.js → contribute-VDZXHK5Y.js} +4 -4
  48. package/dist/{dev-server-Q6M62ATG.js → dev-server-7F622OEO.js} +8 -8
  49. package/dist/{feedback-XRI7SGYX.js → feedback-E7VET7CL.js} +6 -6
  50. package/dist/{git-W3XUIFTR.js → git-2QDQ2X2S.js} +3 -3
  51. package/dist/{ignite-3FHQY23X.js → ignite-IW35CDBD.js} +10 -10
  52. package/dist/index.d.ts +18 -0
  53. package/dist/index.js +14 -6
  54. package/dist/index.js.map +1 -1
  55. package/dist/{init-ALYWKNWG.js → init-676DHF6R.js} +5 -5
  56. package/dist/issues-PJSOLOBJ.js +138 -0
  57. package/dist/issues-PJSOLOBJ.js.map +1 -0
  58. package/dist/{lint-IHUH45OC.js → lint-CJM7BAIM.js} +6 -6
  59. package/dist/mcp/issue-management-server.js +5 -4
  60. package/dist/mcp/issue-management-server.js.map +1 -1
  61. package/dist/{open-KWOV2OFO.js → open-544H7JF5.js} +8 -8
  62. package/dist/{plan-P6MXL7AU.js → plan-Q7ELXDLC.js} +12 -12
  63. package/dist/prompts/init-prompt.txt +39 -21
  64. package/dist/{rebase-AJOJOZUG.js → rebase-YND35CIE.js} +5 -5
  65. package/dist/{recap-GKJXMDXW.js → recap-3W7COH7D.js} +5 -5
  66. package/dist/{run-QEUVZF7J.js → run-QUXJKDQQ.js} +8 -8
  67. package/dist/schema/settings.schema.json +15 -0
  68. package/dist/{shell-DAAVG4YN.js → shell-QGECBLST.js} +5 -5
  69. package/dist/{summary-WNEYCO4S.js → summary-G2T4452H.js} +9 -9
  70. package/dist/{test-5GPWWO3P.js → test-EA5NQFDC.js} +6 -6
  71. package/dist/{test-git-EJUKDB7F.js → test-git-M7LSLEFL.js} +3 -3
  72. package/dist/{test-prefix-23TOBUXY.js → test-prefix-64NAAUON.js} +3 -3
  73. package/dist/{test-webserver-CKROHFBQ.js → test-webserver-OK6Z5FJM.js} +5 -5
  74. package/dist/{vscode-6TOLFCI2.js → vscode-AR5NNXXI.js} +5 -5
  75. package/package.json +1 -1
  76. package/dist/chunk-5LVVQGB3.js.map +0 -1
  77. package/dist/chunk-6Y3FTRJL.js.map +0 -1
  78. package/dist/chunk-I23OQB4Y.js.map +0 -1
  79. package/dist/chunk-RNBIISBZ.js.map +0 -1
  80. package/dist/chunk-THS5L54H.js.map +0 -1
  81. package/dist/chunk-XFEK2X2D.js.map +0 -1
  82. package/dist/commit-ORHR53KW.js.map +0 -1
  83. /package/dist/{ClaudeContextManager-X2Y72GRL.js.map → ClaudeContextManager-HR5JQKAI.js.map} +0 -0
  84. /package/dist/{ClaudeService-7P32TTES.js.map → ClaudeService-TK7FMC2X.js.map} +0 -0
  85. /package/dist/{GitHubService-ACZVNTJE.js.map → GitHubService-TGWJN4V4.js.map} +0 -0
  86. /package/dist/{LoomLauncher-3I47SUPV.js.map → LoomLauncher-73NXL2CL.js.map} +0 -0
  87. /package/dist/{SettingsManager-QR7V2IW2.js.map → SettingsManager-AW3JTJHD.js.map} +0 -0
  88. /package/dist/{build-IC4CJRMP.js.map → build-THZI572G.js.map} +0 -0
  89. /package/dist/{chunk-Z6F5CUS6.js.map → chunk-3I4ONZRT.js.map} +0 -0
  90. /package/dist/{chunk-MZPRBNYC.js.map → chunk-6IIL5M2L.js.map} +0 -0
  91. /package/dist/{chunk-2JPXGGP4.js.map → chunk-A7NJF73J.js.map} +0 -0
  92. /package/dist/{chunk-H6ST2TGP.js.map → chunk-AR5QKYNE.js.map} +0 -0
  93. /package/dist/{chunk-PL2FDYEK.js.map → chunk-CWRI4JC3.js.map} +0 -0
  94. /package/dist/{chunk-NTTSUAVM.js.map → chunk-IZIYLYPK.js.map} +0 -0
  95. /package/dist/{chunk-TGRK3CHF.js.map → chunk-KJTVU3HZ.js.map} +0 -0
  96. /package/dist/{chunk-SC6X5EBG.js.map → chunk-KXGQYLFZ.js.map} +0 -0
  97. /package/dist/{chunk-USSL2X4A.js.map → chunk-NUACL52E.js.map} +0 -0
  98. /package/dist/{chunk-JT5LZRMI.js.map → chunk-NWMORW3U.js.map} +0 -0
  99. /package/dist/{chunk-HZXBHMVM.js.map → chunk-R4YWBGY6.js.map} +0 -0
  100. /package/dist/{chunk-4GAJJUYS.js.map → chunk-TC7APDKU.js.map} +0 -0
  101. /package/dist/{chunk-UDZCTLD6.js.map → chunk-ULSWCPQG.js.map} +0 -0
  102. /package/dist/{chunk-RD7OPXZK.js.map → chunk-W6DP5RVR.js.map} +0 -0
  103. /package/dist/{chunk-XJHQVOT6.js.map → chunk-WHI5KEOX.js.map} +0 -0
  104. /package/dist/{chunk-2HZX6AMR.js.map → chunk-YKFCCV6S.js.map} +0 -0
  105. /package/dist/{chunk-OAVJR4PM.js.map → chunk-Z2TWEXR7.js.map} +0 -0
  106. /package/dist/{cleanup-M6N7KV7E.js.map → cleanup-PJRIFFU4.js.map} +0 -0
  107. /package/dist/{compile-EOWJORKO.js.map → compile-R2J65HBQ.js.map} +0 -0
  108. /package/dist/{contribute-4KCEOHSH.js.map → contribute-VDZXHK5Y.js.map} +0 -0
  109. /package/dist/{dev-server-Q6M62ATG.js.map → dev-server-7F622OEO.js.map} +0 -0
  110. /package/dist/{feedback-XRI7SGYX.js.map → feedback-E7VET7CL.js.map} +0 -0
  111. /package/dist/{git-W3XUIFTR.js.map → git-2QDQ2X2S.js.map} +0 -0
  112. /package/dist/{ignite-3FHQY23X.js.map → ignite-IW35CDBD.js.map} +0 -0
  113. /package/dist/{init-ALYWKNWG.js.map → init-676DHF6R.js.map} +0 -0
  114. /package/dist/{lint-IHUH45OC.js.map → lint-CJM7BAIM.js.map} +0 -0
  115. /package/dist/{open-KWOV2OFO.js.map → open-544H7JF5.js.map} +0 -0
  116. /package/dist/{plan-P6MXL7AU.js.map → plan-Q7ELXDLC.js.map} +0 -0
  117. /package/dist/{rebase-AJOJOZUG.js.map → rebase-YND35CIE.js.map} +0 -0
  118. /package/dist/{recap-GKJXMDXW.js.map → recap-3W7COH7D.js.map} +0 -0
  119. /package/dist/{run-QEUVZF7J.js.map → run-QUXJKDQQ.js.map} +0 -0
  120. /package/dist/{shell-DAAVG4YN.js.map → shell-QGECBLST.js.map} +0 -0
  121. /package/dist/{summary-WNEYCO4S.js.map → summary-G2T4452H.js.map} +0 -0
  122. /package/dist/{test-5GPWWO3P.js.map → test-EA5NQFDC.js.map} +0 -0
  123. /package/dist/{test-git-EJUKDB7F.js.map → test-git-M7LSLEFL.js.map} +0 -0
  124. /package/dist/{test-prefix-23TOBUXY.js.map → test-prefix-64NAAUON.js.map} +0 -0
  125. /package/dist/{test-webserver-CKROHFBQ.js.map → test-webserver-OK6Z5FJM.js.map} +0 -0
  126. /package/dist/{vscode-6TOLFCI2.js.map → vscode-AR5NNXXI.js.map} +0 -0
package/LICENSE CHANGED
@@ -20,7 +20,7 @@ it within your organization. What is prohibited is redistributing or offering
20
20
  access to this software (in original or modified form) as part of something
21
21
  you sell or provide to others.
22
22
 
23
- Change Date: 2030-02-06
23
+ Change Date: 2030-02-16
24
24
  Change License: Apache License 2.0
25
25
 
26
26
  For clarity, on or after the Change Date, the Licensed Work will
package/README.md CHANGED
@@ -453,7 +453,26 @@ iloom creates isolated workspace settings for your editor. Color synchronization
453
453
  * **Supported:** VS Code, Cursor, Windsurf, Antigravity, WebStorm, IntelliJ, Sublime Text.
454
454
 
455
455
  * **Config:** Set your preference via `il init` or `il start --set ide.type=cursor`.
456
-
456
+
457
+ ### Git Operation Settings
458
+
459
+ Configure git operation timeouts for projects with long-running pre-commit hooks.
460
+
461
+ **.iloom/settings.json**
462
+ ```json
463
+ {
464
+ "git": {
465
+ "commitTimeout": 120000
466
+ }
467
+ }
468
+ ```
469
+
470
+ | Setting | Default | Range | Description |
471
+ |---------|---------|-------|-------------|
472
+ | `git.commitTimeout` | 60000 (60s) | 1000-600000 | Timeout in milliseconds for git commit operations. Increase if pre-commit hooks (linting, tests, type checking) exceed the default timeout. |
473
+
474
+ **When to increase:** If you see timeout errors during `il commit` or `il finish`, your pre-commit hooks are taking longer than the default 60 seconds. Set a higher value based on your typical hook duration.
475
+
457
476
 
458
477
  Advanced Features
459
478
  -----------------
@@ -600,7 +619,7 @@ License & Name
600
619
 
601
620
  * ❌ You cannot resell iloom itself as a product or SaaS.
602
621
 
603
- * Converts to Apache 2.0 on 2030-02-06.
622
+ * Converts to Apache 2.0 on 2030-02-16.
604
623
 
605
624
 
606
625
  See [LICENSE](https://raw.githubusercontent.com/iloom-ai/iloom-cli/main/LICENSE) for complete terms.
@@ -1,14 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  ClaudeContextManager
4
- } from "./chunk-OAVJR4PM.js";
5
- import "./chunk-MZPRBNYC.js";
4
+ } from "./chunk-Z2TWEXR7.js";
5
+ import "./chunk-6IIL5M2L.js";
6
6
  import "./chunk-QN47QVBX.js";
7
- import "./chunk-XFEK2X2D.js";
7
+ import "./chunk-RI2YL6TK.js";
8
8
  import "./chunk-FO5GGFOV.js";
9
9
  import "./chunk-6MLEBAYZ.js";
10
10
  import "./chunk-VT4PDUYT.js";
11
11
  export {
12
12
  ClaudeContextManager
13
13
  };
14
- //# sourceMappingURL=ClaudeContextManager-X2Y72GRL.js.map
14
+ //# sourceMappingURL=ClaudeContextManager-HR5JQKAI.js.map
@@ -1,13 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  ClaudeService
4
- } from "./chunk-MZPRBNYC.js";
4
+ } from "./chunk-6IIL5M2L.js";
5
5
  import "./chunk-QN47QVBX.js";
6
- import "./chunk-XFEK2X2D.js";
6
+ import "./chunk-RI2YL6TK.js";
7
7
  import "./chunk-FO5GGFOV.js";
8
8
  import "./chunk-6MLEBAYZ.js";
9
9
  import "./chunk-VT4PDUYT.js";
10
10
  export {
11
11
  ClaudeService
12
12
  };
13
- //# sourceMappingURL=ClaudeService-7P32TTES.js.map
13
+ //# sourceMappingURL=ClaudeService-TK7FMC2X.js.map
@@ -1,12 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  GitHubService
4
- } from "./chunk-PVW6JE7E.js";
5
- import "./chunk-THS5L54H.js";
4
+ } from "./chunk-OFDN5NKS.js";
5
+ import "./chunk-4CO6KG5S.js";
6
6
  import "./chunk-7JDMYTFZ.js";
7
7
  import "./chunk-6MLEBAYZ.js";
8
8
  import "./chunk-VT4PDUYT.js";
9
9
  export {
10
10
  GitHubService
11
11
  };
12
- //# sourceMappingURL=GitHubService-ACZVNTJE.js.map
12
+ //# sourceMappingURL=GitHubService-TGWJN4V4.js.map
@@ -4,13 +4,13 @@ import {
4
4
  } from "./chunk-O7VL5N6S.js";
5
5
  import {
6
6
  ClaudeContextManager
7
- } from "./chunk-OAVJR4PM.js";
8
- import "./chunk-MZPRBNYC.js";
7
+ } from "./chunk-Z2TWEXR7.js";
8
+ import "./chunk-6IIL5M2L.js";
9
9
  import "./chunk-QN47QVBX.js";
10
10
  import {
11
11
  getExecutablePath
12
12
  } from "./chunk-GYCR2LOU.js";
13
- import "./chunk-XFEK2X2D.js";
13
+ import "./chunk-RI2YL6TK.js";
14
14
  import {
15
15
  generateColorFromBranchName,
16
16
  hexToRgb
@@ -252,4 +252,4 @@ var LoomLauncher = class {
252
252
  export {
253
253
  LoomLauncher
254
254
  };
255
- //# sourceMappingURL=LoomLauncher-3I47SUPV.js.map
255
+ //# sourceMappingURL=LoomLauncher-73NXL2CL.js.map
package/dist/README.md CHANGED
@@ -453,7 +453,26 @@ iloom creates isolated workspace settings for your editor. Color synchronization
453
453
  * **Supported:** VS Code, Cursor, Windsurf, Antigravity, WebStorm, IntelliJ, Sublime Text.
454
454
 
455
455
  * **Config:** Set your preference via `il init` or `il start --set ide.type=cursor`.
456
-
456
+
457
+ ### Git Operation Settings
458
+
459
+ Configure git operation timeouts for projects with long-running pre-commit hooks.
460
+
461
+ **.iloom/settings.json**
462
+ ```json
463
+ {
464
+ "git": {
465
+ "commitTimeout": 120000
466
+ }
467
+ }
468
+ ```
469
+
470
+ | Setting | Default | Range | Description |
471
+ |---------|---------|-------|-------------|
472
+ | `git.commitTimeout` | 60000 (60s) | 1000-600000 | Timeout in milliseconds for git commit operations. Increase if pre-commit hooks (linting, tests, type checking) exceed the default timeout. |
473
+
474
+ **When to increase:** If you see timeout errors during `il commit` or `il finish`, your pre-commit hooks are taking longer than the default 60 seconds. Set a higher value based on your typical hook duration.
475
+
457
476
 
458
477
  Advanced Features
459
478
  -----------------
@@ -600,7 +619,7 @@ License & Name
600
619
 
601
620
  * ❌ You cannot resell iloom itself as a product or SaaS.
602
621
 
603
- * Converts to Apache 2.0 on 2030-02-06.
622
+ * Converts to Apache 2.0 on 2030-02-16.
604
623
 
605
624
 
606
625
  See [LICENSE](https://raw.githubusercontent.com/iloom-ai/iloom-cli/main/LICENSE) for complete terms.
@@ -15,7 +15,7 @@ import {
15
15
  WorkflowPermissionSchemaNoDefaults,
16
16
  WorkflowsSettingsSchema,
17
17
  WorkflowsSettingsSchemaNoDefaults
18
- } from "./chunk-XFEK2X2D.js";
18
+ } from "./chunk-RI2YL6TK.js";
19
19
  import "./chunk-VT4PDUYT.js";
20
20
  export {
21
21
  AgentSettingsSchema,
@@ -34,4 +34,4 @@ export {
34
34
  WorkflowsSettingsSchema,
35
35
  WorkflowsSettingsSchemaNoDefaults
36
36
  };
37
- //# sourceMappingURL=SettingsManager-QR7V2IW2.js.map
37
+ //# sourceMappingURL=SettingsManager-AW3JTJHD.js.map
@@ -1,13 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  ScriptCommandBase
4
- } from "./chunk-TGRK3CHF.js";
5
- import "./chunk-2HZX6AMR.js";
4
+ } from "./chunk-KJTVU3HZ.js";
5
+ import "./chunk-YKFCCV6S.js";
6
6
  import "./chunk-4LKGCFGG.js";
7
- import "./chunk-4GAJJUYS.js";
7
+ import "./chunk-TC7APDKU.js";
8
8
  import "./chunk-VOGGLPG5.js";
9
- import "./chunk-H6ST2TGP.js";
10
- import "./chunk-XFEK2X2D.js";
9
+ import "./chunk-AR5QKYNE.js";
10
+ import "./chunk-RI2YL6TK.js";
11
11
  import "./chunk-KBEIQP4G.js";
12
12
  import "./chunk-6MLEBAYZ.js";
13
13
  import "./chunk-VT4PDUYT.js";
@@ -24,4 +24,4 @@ var BuildCommand = class extends ScriptCommandBase {
24
24
  export {
25
25
  BuildCommand
26
26
  };
27
- //# sourceMappingURL=build-IC4CJRMP.js.map
27
+ //# sourceMappingURL=build-THZI572G.js.map
@@ -4,7 +4,7 @@ import {
4
4
  } from "./chunk-NXMDEL3F.js";
5
5
  import {
6
6
  IssueManagementProviderFactory
7
- } from "./chunk-UDZCTLD6.js";
7
+ } from "./chunk-ULSWCPQG.js";
8
8
  import {
9
9
  hasMultipleRemotes
10
10
  } from "./chunk-FXDYIV3K.js";
@@ -13,7 +13,7 @@ import {
13
13
  } from "./chunk-QN47QVBX.js";
14
14
  import {
15
15
  SettingsManager
16
- } from "./chunk-XFEK2X2D.js";
16
+ } from "./chunk-RI2YL6TK.js";
17
17
  import {
18
18
  MetadataManager
19
19
  } from "./chunk-KBEIQP4G.js";
@@ -369,4 +369,4 @@ var SessionSummaryService = class {
369
369
  export {
370
370
  SessionSummaryService
371
371
  };
372
- //# sourceMappingURL=chunk-Z6F5CUS6.js.map
372
+ //# sourceMappingURL=chunk-3I4ONZRT.js.map
@@ -86,7 +86,7 @@ async function fetchGhPR(prNumber, repo) {
86
86
  "view",
87
87
  String(prNumber),
88
88
  "--json",
89
- "number,title,body,state,headRefName,baseRefName,url,isDraft,mergeable,createdAt,updatedAt"
89
+ "number,title,body,state,headRefName,baseRefName,url,isDraft,isCrossRepository,mergeable,createdAt,updatedAt"
90
90
  ];
91
91
  if (repo) {
92
92
  args.push("--repo", repo);
@@ -409,6 +409,51 @@ async function removeIssueDependency(blockedIssueNumber, blockingIssueDatabaseId
409
409
  apiPath
410
410
  ]);
411
411
  }
412
+ async function fetchGitHubIssueList(options) {
413
+ const limit = (options == null ? void 0 : options.limit) ?? 100;
414
+ logger.debug("Fetching GitHub issue list", { limit, cwd: options == null ? void 0 : options.cwd });
415
+ const result = await executeGhCommand([
416
+ "issue",
417
+ "list",
418
+ "--state",
419
+ "open",
420
+ "--json",
421
+ "number,title,updatedAt,url,state",
422
+ "--limit",
423
+ String(limit),
424
+ "--search",
425
+ "sort:updated-desc"
426
+ ], (options == null ? void 0 : options.cwd) ? { cwd: options.cwd } : void 0);
427
+ return (result ?? []).map((item) => ({
428
+ id: String(item.number),
429
+ title: item.title,
430
+ updatedAt: item.updatedAt,
431
+ url: item.url,
432
+ state: item.state.toLowerCase()
433
+ }));
434
+ }
435
+ async function fetchGitHubPRList(options) {
436
+ const limit = (options == null ? void 0 : options.limit) ?? 100;
437
+ const fetchLimit = Math.max(limit * 2, 50);
438
+ logger.debug("Fetching GitHub PR list", { limit, fetchLimit, cwd: options == null ? void 0 : options.cwd });
439
+ const result = await executeGhCommand([
440
+ "pr",
441
+ "list",
442
+ "--state",
443
+ "open",
444
+ "--json",
445
+ "number,title,updatedAt,url,state,isDraft",
446
+ "--limit",
447
+ String(fetchLimit)
448
+ ], (options == null ? void 0 : options.cwd) ? { cwd: options.cwd } : void 0);
449
+ return (result ?? []).filter((item) => !item.isDraft).slice(0, limit).map((item) => ({
450
+ id: String(item.number),
451
+ title: `[PR] ${item.title}`,
452
+ updatedAt: item.updatedAt,
453
+ url: item.url,
454
+ state: item.state.toLowerCase()
455
+ }));
456
+ }
412
457
 
413
458
  export {
414
459
  executeGhCommand,
@@ -431,6 +476,8 @@ export {
431
476
  getIssueDatabaseId,
432
477
  getIssueDependencies,
433
478
  createIssueDependency,
434
- removeIssueDependency
479
+ removeIssueDependency,
480
+ fetchGitHubIssueList,
481
+ fetchGitHubPRList
435
482
  };
436
- //# sourceMappingURL=chunk-THS5L54H.js.map
483
+ //# sourceMappingURL=chunk-4CO6KG5S.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/github.ts"],"sourcesContent":["import { execa } from 'execa'\nimport type {\n\tGitHubIssue,\n\tGitHubPullRequest,\n\tGitHubProject,\n\tGitHubAuthStatus,\n\tProjectItem,\n\tProjectField,\n} from '../types/github.js'\nimport { logger } from './logger.js'\n\n// Core GitHub CLI execution wrapper\nexport async function executeGhCommand<T = unknown>(\n\targs: string[],\n\toptions?: { cwd?: string; timeout?: number }\n): Promise<T> {\n\tconst result = await execa('gh', args, {\n\t\tcwd: options?.cwd ?? process.cwd(),\n\t\ttimeout: options?.timeout ?? 30000,\n\t\tencoding: 'utf8',\n\t})\n\n\t// Parse JSON output if --json flag, --format json, --jq, or GraphQL was used\n\tconst isJson =\n\t\targs.includes('--json') ||\n\t\targs.includes('--jq') ||\n\t\t(args.includes('--format') && args[args.indexOf('--format') + 1] === 'json') ||\n\t\t(args[0] === 'api' && args[1] === 'graphql')\n\tconst data = isJson ? JSON.parse(result.stdout) : result.stdout\n\n\treturn data as T\n}\n\n// Authentication checking\nexport async function checkGhAuth(): Promise<GitHubAuthStatus> {\n\ttry {\n\t\tconst output = await executeGhCommand<string>(['auth', 'status'])\n\n\t\t// Parse auth status output - handle both old and new formats\n\t\t// Old format: \"Logged in to github.com as username\"\n\t\t// New format: \"✓ Logged in to github.com account username (keyring)\"\n\n\t\t// Split output into lines to find the active account\n\t\tconst lines = output.split('\\n')\n\t\tlet username: string | undefined\n\t\tlet scopes: string[] = []\n\n\t\t// Find the active account (look for \"Active account: true\" or first account if none marked)\n\t\tfor (let i = 0; i < lines.length; i++) {\n\t\t\tconst line = lines[i]\n\n\t\t\t// Match new format: \"✓ Logged in to github.com account username\"\n\t\t\tconst newFormatMatch = line?.match(/Logged in to github\\.com account ([^\\s(]+)/)\n\t\t\tif (newFormatMatch) {\n\t\t\t\tconst accountName = newFormatMatch[1]\n\n\t\t\t\t// Check if this is the active account\n\t\t\t\tconst nextFewLines = lines.slice(i + 1, i + 5).join('\\n')\n\t\t\t\tconst isActive = nextFewLines.includes('Active account: true')\n\n\t\t\t\t// If this is the active account, or we haven't found one yet and there's no \"Active account\" marker\n\t\t\t\tif (isActive || (!username && !output.includes('Active account:'))) {\n\t\t\t\t\tusername = accountName\n\n\t\t\t\t\t// Find scopes for this account\n\t\t\t\t\tconst scopeMatch = nextFewLines.match(/Token scopes: (.+)/)\n\t\t\t\t\tif (scopeMatch?.[1]) {\n\t\t\t\t\t\tscopes = scopeMatch[1].split(', ').map(scope => scope.replace(/^'|'$/g, ''))\n\t\t\t\t\t}\n\n\t\t\t\t\t// If this is the active account, we're done\n\t\t\t\t\tif (isActive) break\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Fallback: match old format\n\t\t\tif (!username) {\n\t\t\t\tconst oldFormatMatch = line?.match(/Logged in to github\\.com as ([^\\s]+)/)\n\t\t\t\tif (oldFormatMatch) {\n\t\t\t\t\tusername = oldFormatMatch[1]\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// If scopes not yet extracted, try the old \"Token scopes\" format\n\t\tif (scopes.length === 0) {\n\t\t\tconst scopeMatch = output.match(/Token scopes: (.+)/)\n\t\t\tscopes = scopeMatch?.[1]?.split(', ').map(scope => scope.replace(/^'|'$/g, '')) ?? []\n\t\t}\n\n\t\treturn {\n\t\t\thasAuth: true,\n\t\t\tscopes,\n\t\t\t...(username && { username }),\n\t\t}\n\t} catch (error) {\n\t\t// Only return \"no auth\" for specific authentication errors\n\t\tif (error instanceof Error && 'stderr' in error && (error as {stderr?: string}).stderr?.includes('You are not logged into any GitHub hosts')) {\n\t\t\treturn { hasAuth: false, scopes: [] }\n\t\t}\n\t\t// Re-throw unexpected errors\n\t\tthrow error\n\t}\n}\n\nexport async function hasProjectScope(): Promise<boolean> {\n\tconst auth = await checkGhAuth()\n\treturn auth.scopes.includes('project')\n}\n\n// Issue fetching\nexport async function fetchGhIssue(\n\tissueNumber: number,\n\trepo?: string\n): Promise<GitHubIssue> {\n\tlogger.debug('Fetching GitHub issue', { issueNumber, repo })\n\n\tconst args = [\n\t\t'issue',\n\t\t'view',\n\t\tString(issueNumber),\n\t\t'--json',\n\t\t'number,title,body,state,labels,assignees,url,createdAt,updatedAt',\n\t]\n\n\tif (repo) {\n\t\targs.push('--repo', repo)\n\t}\n\n\treturn executeGhCommand<GitHubIssue>(args)\n}\n\n// PR fetching\nexport async function fetchGhPR(\n\tprNumber: number,\n\trepo?: string\n): Promise<GitHubPullRequest> {\n\tlogger.debug('Fetching GitHub PR', { prNumber, repo })\n\n\tconst args = [\n\t\t'pr',\n\t\t'view',\n\t\tString(prNumber),\n\t\t'--json',\n\t\t'number,title,body,state,headRefName,baseRefName,url,isDraft,isCrossRepository,mergeable,createdAt,updatedAt',\n\t]\n\n\tif (repo) {\n\t\targs.push('--repo', repo)\n\t}\n\n\treturn executeGhCommand<GitHubPullRequest>(args)\n}\n\n// Project operations\nexport async function fetchProjectList(\n\towner: string\n): Promise<GitHubProject[]> {\n\tconst result = await executeGhCommand<{ projects: GitHubProject[] }>([\n\t\t'project',\n\t\t'list',\n\t\t'--owner',\n\t\towner,\n\t\t'--limit',\n\t\t'100',\n\t\t'--format',\n\t\t'json',\n\t])\n\n\treturn result?.projects ?? []\n}\n\nexport async function fetchProjectItems(\n\tprojectNumber: number,\n\towner: string\n): Promise<ProjectItem[]> {\n\tconst result = await executeGhCommand<{ items: ProjectItem[] }>([\n\t\t'project',\n\t\t'item-list',\n\t\tString(projectNumber),\n\t\t'--owner',\n\t\towner,\n\t\t'--limit',\n\t\t'10000',\n\t\t'--format',\n\t\t'json',\n\t])\n\n\treturn result?.items ?? []\n}\n\nexport async function fetchProjectFields(\n\tprojectNumber: number,\n\towner: string\n): Promise<{ fields: ProjectField[] }> {\n\tconst result = await executeGhCommand<{ fields: ProjectField[] }>([\n\t\t'project',\n\t\t'field-list',\n\t\tString(projectNumber),\n\t\t'--owner',\n\t\towner,\n\t\t'--format',\n\t\t'json',\n\t])\n\n\treturn result ?? { fields: [] }\n}\n\nexport async function updateProjectItemField(\n\titemId: string,\n\tprojectId: string,\n\tfieldId: string,\n\toptionId: string\n): Promise<void> {\n\tawait executeGhCommand([\n\t\t'project',\n\t\t'item-edit',\n\t\t'--id',\n\t\titemId,\n\t\t'--project-id',\n\t\tprojectId,\n\t\t'--field-id',\n\t\tfieldId,\n\t\t'--single-select-option-id',\n\t\toptionId,\n\t\t'--format',\n\t\t'json',\n\t])\n}\n\n// GitHub Issue Operations\n\ninterface IssueCreateResponse {\n\tnumber: string | number\n\turl: string\n}\n\n/**\n * Create a new GitHub issue\n * @param title - The issue title\n * @param body - The issue body (markdown supported)\n * @param options - Optional configuration\n * @param options.repo - Repository in format \"owner/repo\" (uses current repo if not provided)\n * @param options.labels - Array of label names to add to the issue\n * @returns Issue metadata including number and URL\n */\nexport async function createIssue(\n\ttitle: string,\n\tbody: string,\n\toptions?: { repo?: string | undefined; labels?: string[] | undefined }\n): Promise<IssueCreateResponse> {\n\tconst { repo, labels } = options ?? {}\n\n\tlogger.debug('Creating GitHub issue', { title, repo, labels })\n\n\tconst args = [\n\t\t'issue',\n\t\t'create',\n\t\t'--title',\n\t\ttitle,\n\t\t'--body',\n\t\tbody,\n\t]\n\n\t// Add repo if provided\n\tif (repo) {\n\t\targs.splice(2, 0, '--repo', repo)\n\t}\n\n\t// Add labels if provided\n\tif (labels && labels.length > 0) {\n\t\targs.push('--label', labels.join(','))\n\t}\n\n\tconst execaOptions: { timeout: number; encoding: 'utf8'; cwd?: string } = {\n\t\ttimeout: 30000,\n\t\tencoding: 'utf8',\n\t}\n\n\tif (!repo) {\n\t\texecaOptions.cwd = process.cwd()\n\t}\n\n\tconst result = await execa('gh', args, execaOptions)\n\n\t// Parse the URL from the output (format: \"https://github.com/owner/repo/issues/123\")\n\tconst urlMatch = result.stdout.trim().match(/https:\\/\\/github\\.com\\/[^/]+\\/[^/]+\\/issues\\/(\\d+)/)\n\tif (!urlMatch?.[1]) {\n\t\tthrow new Error(`Failed to parse issue URL from gh output: ${result.stdout}`)\n\t}\n\n\tconst issueNumber = parseInt(urlMatch[1], 10)\n\tconst issueUrl = urlMatch[0]\n\n\treturn {\n\t\tnumber: issueNumber,\n\t\turl: issueUrl,\n\t}\n}\n\n/**\n * @deprecated Use createIssue with options.repo instead\n * Create a new GitHub issue in a specific repository\n * @param title - Issue title\n * @param body - Issue body (markdown)\n * @param repository - Repository in format \"owner/repo\"\n * @param labels - Optional array of label names to add to the issue\n * @returns Issue number and URL\n */\nexport async function createIssueInRepo(\n\ttitle: string,\n\tbody: string,\n\trepository: string,\n\tlabels?: string[]\n): Promise<IssueCreateResponse> {\n\treturn createIssue(title, body, { repo: repository, labels })\n}\n\n// GitHub Comment Operations\n\ninterface CommentResponse {\n\tid: number\n\turl: string\n\tcreated_at?: string\n\tupdated_at?: string\n}\n\ninterface RepoInfo {\n\towner: string\n\tname: string\n}\n\n/**\n * Create a comment on a GitHub issue\n * @param issueNumber - The issue number\n * @param body - The comment body (markdown supported)\n * @param repo - Optional repo in \"owner/repo\" format\n * @returns Comment metadata including ID and URL\n */\nexport async function createIssueComment(\n\tissueNumber: number,\n\tbody: string,\n\trepo?: string\n): Promise<CommentResponse> {\n\tlogger.debug('Creating issue comment', { issueNumber, repo })\n\n\tconst apiPath = repo\n\t\t? `repos/${repo}/issues/${issueNumber}/comments`\n\t\t: `repos/:owner/:repo/issues/${issueNumber}/comments`\n\n\treturn executeGhCommand<CommentResponse>([\n\t\t'api',\n\t\tapiPath,\n\t\t'-f',\n\t\t`body=${body}`,\n\t\t'--jq',\n\t\t'{id: .id, url: .html_url, created_at: .created_at}',\n\t])\n}\n\n/**\n * Update an existing GitHub comment\n * @param commentId - The comment ID\n * @param body - The updated comment body (markdown supported)\n * @param repo - Optional repo in \"owner/repo\" format\n * @returns Updated comment metadata\n */\nexport async function updateIssueComment(\n\tcommentId: number,\n\tbody: string,\n\trepo?: string\n): Promise<CommentResponse> {\n\tlogger.debug('Updating issue comment', { commentId, repo })\n\n\tconst apiPath = repo\n\t\t? `repos/${repo}/issues/comments/${commentId}`\n\t\t: `repos/:owner/:repo/issues/comments/${commentId}`\n\n\treturn executeGhCommand<CommentResponse>([\n\t\t'api',\n\t\tapiPath,\n\t\t'-X',\n\t\t'PATCH',\n\t\t'-f',\n\t\t`body=${body}`,\n\t\t'--jq',\n\t\t'{id: .id, url: .html_url, updated_at: .updated_at}',\n\t])\n}\n\n/**\n * Create a comment on a GitHub pull request\n * Note: PR comments use the same endpoint as issue comments\n * @param prNumber - The PR number\n * @param body - The comment body (markdown supported)\n * @param repo - Optional repo in \"owner/repo\" format\n * @returns Comment metadata including ID and URL\n */\nexport async function createPRComment(\n\tprNumber: number,\n\tbody: string,\n\trepo?: string\n): Promise<CommentResponse> {\n\tlogger.debug('Creating PR comment', { prNumber, repo })\n\n\tconst apiPath = repo\n\t\t? `repos/${repo}/issues/${prNumber}/comments`\n\t\t: `repos/:owner/:repo/issues/${prNumber}/comments`\n\n\t// PR comments use the issues endpoint\n\treturn executeGhCommand<CommentResponse>([\n\t\t'api',\n\t\tapiPath,\n\t\t'-f',\n\t\t`body=${body}`,\n\t\t'--jq',\n\t\t'{id: .id, url: .html_url, created_at: .created_at}',\n\t])\n}\n\n/**\n * Get repository owner and name from current directory\n * @returns Repository owner and name\n */\nexport async function getRepoInfo(): Promise<RepoInfo> {\n\tlogger.debug('Fetching repository info')\n\n\tconst result = await executeGhCommand<{ owner: { login: string }; name: string }>([\n\t\t'repo',\n\t\t'view',\n\t\t'--json',\n\t\t'owner,name',\n\t])\n\n\treturn {\n\t\towner: result.owner.login,\n\t\tname: result.name,\n\t}\n}\n\n// GitHub Sub-Issue Operations\n\n/**\n * Get the GraphQL node ID for a GitHub issue\n * Required for sub-issue API which uses node IDs, not issue numbers\n * @param issueNumber - The issue number\n * @param repo - Optional repo in \"owner/repo\" format\n * @returns GraphQL node ID (e.g., \"I_kwDOPvp_cc7...\")\n */\nexport async function getIssueNodeId(\n\tissueNumber: number,\n\trepo?: string\n): Promise<string> {\n\tlogger.debug('Fetching GitHub issue node ID', { issueNumber, repo })\n\n\tconst args = ['issue', 'view', String(issueNumber), '--json', 'id']\n\tif (repo) {\n\t\targs.push('--repo', repo)\n\t}\n\n\tconst result = await executeGhCommand<{ id: string }>(args)\n\treturn result.id\n}\n\n/**\n * Link a child issue to a parent issue using GitHub's sub-issue API\n * Requires GraphQL-Features: sub_issues header\n * @param parentNodeId - GraphQL node ID of the parent issue\n * @param childNodeId - GraphQL node ID of the child issue\n */\nexport async function addSubIssue(\n\tparentNodeId: string,\n\tchildNodeId: string\n): Promise<void> {\n\tlogger.debug('Linking child issue to parent', { parentNodeId, childNodeId })\n\n\tconst mutation = `\n\t\tmutation addSubIssue($parentId: ID!, $subIssueId: ID!) {\n\t\t\taddSubIssue(input: { issueId: $parentId, subIssueId: $subIssueId }) {\n\t\t\t\tissue { id }\n\t\t\t\tsubIssue { id }\n\t\t\t}\n\t\t}\n\t`\n\n\tawait executeGhCommand([\n\t\t'api', 'graphql',\n\t\t'-H', 'GraphQL-Features: sub_issues',\n\t\t'-f', `query=${mutation}`,\n\t\t'-F', `parentId=${parentNodeId}`,\n\t\t'-F', `subIssueId=${childNodeId}`,\n\t])\n}\n\n/**\n * Get sub-issues (children) of a parent GitHub issue\n * Uses GraphQL to query the sub-issue relationship\n * @param issueNumber - The parent issue number\n * @param repo - Optional repo in \"owner/repo\" format\n * @returns Array of child issues with id, title, url, and state\n */\nexport async function getSubIssues(\n\tissueNumber: number,\n\trepo?: string\n): Promise<Array<{ id: string; title: string; url: string; state: string }>> {\n\tlogger.debug('Fetching GitHub sub-issues', { issueNumber, repo })\n\n\t// Get the node ID for the parent issue\n\tconst parentNodeId = await getIssueNodeId(issueNumber, repo)\n\n\t// Query sub-issues using GraphQL\n\tconst query = `\n\t\tquery getSubIssues($parentId: ID!) {\n\t\t\tnode(id: $parentId) {\n\t\t\t\t... on Issue {\n\t\t\t\t\tsubIssues(first: 100) {\n\t\t\t\t\t\tnodes {\n\t\t\t\t\t\t\tnumber\n\t\t\t\t\t\t\ttitle\n\t\t\t\t\t\t\turl\n\t\t\t\t\t\t\tstate\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t`\n\n\tinterface SubIssueNode {\n\t\tnumber: number\n\t\ttitle: string\n\t\turl: string\n\t\tstate: string\n\t}\n\n\tinterface SubIssuesResponse {\n\t\tdata: {\n\t\t\tnode: {\n\t\t\t\tsubIssues: {\n\t\t\t\t\tnodes: SubIssueNode[]\n\t\t\t\t}\n\t\t\t} | null\n\t\t}\n\t}\n\n\ttry {\n\t\tconst result = await executeGhCommand<SubIssuesResponse>([\n\t\t\t'api', 'graphql',\n\t\t\t'-H', 'GraphQL-Features: sub_issues',\n\t\t\t'-f', `query=${query}`,\n\t\t\t'-F', `parentId=${parentNodeId}`,\n\t\t])\n\n\t\tconst subIssues = result.data.node?.subIssues?.nodes ?? []\n\n\t\treturn subIssues.map(issue => ({\n\t\t\tid: String(issue.number),\n\t\t\ttitle: issue.title,\n\t\t\turl: issue.url,\n\t\t\tstate: issue.state.toLowerCase(),\n\t\t}))\n\t} catch (error) {\n\t\t// Return empty array if sub-issues feature is not available or no children\n\t\tif (error instanceof Error) {\n\t\t\tconst errorMessage = error.message\n\t\t\tconst stderr = 'stderr' in error ? (error as { stderr?: string }).stderr ?? '' : ''\n\t\t\tconst combinedError = `${errorMessage} ${stderr}`\n\n\t\t\t// Check for feature not available or empty result\n\t\t\tif (combinedError.includes('sub_issues') || combinedError.includes('null')) {\n\t\t\t\treturn []\n\t\t\t}\n\t\t}\n\t\tthrow error\n\t}\n}\n\n// GitHub Issue Dependency Operations\n\n/**\n * GitHub dependency result from API\n */\ninterface GitHubDependency {\n\tid: number\n\tnumber: number\n\ttitle: string\n\tstate: string\n\thtml_url: string\n}\n\n/**\n * Get the internal database ID for a GitHub issue\n * Required for dependency API which uses database IDs, not node IDs\n * @param issueNumber - The issue number\n * @param repo - Optional repo in \"owner/repo\" format\n * @returns Internal GitHub issue database ID\n */\nexport async function getIssueDatabaseId(\n\tissueNumber: number,\n\trepo?: string\n): Promise<number> {\n\tlogger.debug('Fetching GitHub issue database ID', { issueNumber, repo })\n\n\tconst apiPath = repo\n\t\t? `repos/${repo}/issues/${issueNumber}`\n\t\t: `repos/:owner/:repo/issues/${issueNumber}`\n\n\tconst result = await executeGhCommand<{ id: number }>([\n\t\t'api',\n\t\tapiPath,\n\t\t'--jq',\n\t\t'{id: .id}',\n\t])\n\n\treturn result.id\n}\n\n/**\n * Get dependencies for a GitHub issue\n * Uses GitHub's issue dependencies API\n * @param issueNumber - The issue number\n * @param direction - 'blocking' for issues this blocks, 'blocked_by' for issues blocking this\n * @param repo - Optional repo in \"owner/repo\" format\n * @returns Array of dependency objects with id, title, url, state\n */\nexport async function getIssueDependencies(\n\tissueNumber: number,\n\tdirection: 'blocking' | 'blocked_by',\n\trepo?: string\n): Promise<Array<{ id: string; databaseId: number; title: string; url: string; state: string }>> {\n\tlogger.debug('Fetching GitHub issue dependencies', { issueNumber, direction, repo })\n\n\t// Use the dependencies API with the appropriate direction endpoint\n\tconst apiPath = repo\n\t\t? `repos/${repo}/issues/${issueNumber}/dependencies/${direction}`\n\t\t: `repos/:owner/:repo/issues/${issueNumber}/dependencies/${direction}`\n\n\ttry {\n\t\tconst result = await executeGhCommand<GitHubDependency[]>([\n\t\t\t'api',\n\t\t\t'-H', 'Accept: application/vnd.github+json',\n\t\t\t'-H', 'X-GitHub-Api-Version: 2022-11-28',\n\t\t\t'--jq', '.',\n\t\t\tapiPath,\n\t\t])\n\n\t\treturn (result ?? []).map(dep => ({\n\t\t\tid: String(dep.number),\n\t\t\tdatabaseId: dep.id,\n\t\t\ttitle: dep.title,\n\t\t\turl: dep.html_url,\n\t\t\tstate: dep.state,\n\t\t}))\n\t} catch (error) {\n\t\t// Return empty array for 404 on the dependencies endpoint\n\t\t// This indicates the issue exists but has no dependencies configured\n\t\tif (error instanceof Error) {\n\t\t\tconst errorMessage = error.message\n\t\t\tconst stderr = 'stderr' in error ? (error as { stderr?: string }).stderr ?? '' : ''\n\t\t\tconst combinedError = `${errorMessage} ${stderr}`\n\n\t\t\t// Check for 404 specifically on dependencies endpoint\n\t\t\tif (combinedError.includes('404') && combinedError.includes('dependencies')) {\n\t\t\t\treturn []\n\t\t\t}\n\t\t}\n\t\tthrow error\n\t}\n}\n\n/**\n * Create a dependency between two issues (A blocks B)\n * Uses GitHub's issue dependencies API\n * @param blockedIssueNumber - The issue number that is blocked\n * @param blockingIssueDatabaseId - The database ID of the issue that blocks\n * @param repo - Optional repo in \"owner/repo\" format\n * @throws Error with specific message for: dependency already exists, issue not found, or dependencies feature not enabled\n */\nexport async function createIssueDependency(\n\tblockedIssueNumber: number,\n\tblockingIssueDatabaseId: number,\n\trepo?: string\n): Promise<void> {\n\tlogger.debug('Creating GitHub issue dependency', { blockedIssueNumber, blockingIssueDatabaseId, repo })\n\n\t// POST to the blocked issue's blocked_by endpoint with the blocking issue's database ID\n\tconst apiPath = repo\n\t\t? `repos/${repo}/issues/${blockedIssueNumber}/dependencies/blocked_by`\n\t\t: `repos/:owner/:repo/issues/${blockedIssueNumber}/dependencies/blocked_by`\n\n\ttry {\n\t\tawait executeGhCommand([\n\t\t\t'api',\n\t\t\t'-X', 'POST',\n\t\t\t'-H', 'Accept: application/vnd.github+json',\n\t\t\t'-H', 'X-GitHub-Api-Version: 2022-11-28',\n\t\t\tapiPath,\n\t\t\t'-F', `issue_id=${blockingIssueDatabaseId}`,\n\t\t])\n\t} catch (error) {\n\t\tif (error instanceof Error) {\n\t\t\tconst errorMessage = error.message\n\t\t\tconst stderr = 'stderr' in error ? (error as { stderr?: string }).stderr ?? '' : ''\n\t\t\tconst combinedError = `${errorMessage} ${stderr}`\n\n\t\t\t// Check for dependency already exists (422 Unprocessable Entity)\n\t\t\tif (combinedError.includes('422') || combinedError.includes('already exists') || combinedError.includes('Unprocessable Entity')) {\n\t\t\t\tthrow new Error(`Dependency already exists: issue #${blockedIssueNumber} is already blocked by the specified issue`)\n\t\t\t}\n\n\t\t\t// Check for issue not found (404)\n\t\t\tif (combinedError.includes('404') || combinedError.includes('Not Found')) {\n\t\t\t\tthrow new Error(`Issue not found: unable to create dependency for issue #${blockedIssueNumber}. The issue may not exist or you may not have access to it.`)\n\t\t\t}\n\n\t\t\t// Check for dependencies feature not enabled (403 or specific error message)\n\t\t\tif (combinedError.includes('403') || combinedError.includes('Forbidden') || combinedError.includes('not enabled')) {\n\t\t\t\tthrow new Error(`Dependencies feature not enabled: the repository may not have issue dependencies enabled. This feature requires GitHub Enterprise or specific repository settings.`)\n\t\t\t}\n\t\t}\n\n\t\t// Re-throw the original error if it doesn't match any known patterns\n\t\tthrow error\n\t}\n}\n\n/**\n * Remove a dependency between two issues (A blocks B)\n * Uses GitHub's issue dependencies API\n * @param blockedIssueNumber - The issue number that is blocked\n * @param blockingIssueDatabaseId - The database ID of the issue that blocks\n * @param repo - Optional repo in \"owner/repo\" format\n */\nexport async function removeIssueDependency(\n\tblockedIssueNumber: number,\n\tblockingIssueDatabaseId: number,\n\trepo?: string\n): Promise<void> {\n\tlogger.debug('Removing GitHub issue dependency', { blockedIssueNumber, blockingIssueDatabaseId, repo })\n\n\t// DELETE from the blocked issue's blocked_by endpoint with the blocking issue's database ID\n\tconst apiPath = repo\n\t\t? `repos/${repo}/issues/${blockedIssueNumber}/dependencies/blocked_by/${blockingIssueDatabaseId}`\n\t\t: `repos/:owner/:repo/issues/${blockedIssueNumber}/dependencies/blocked_by/${blockingIssueDatabaseId}`\n\n\tawait executeGhCommand([\n\t\t'api',\n\t\t'-X', 'DELETE',\n\t\t'-H', 'Accept: application/vnd.github+json',\n\t\t'-H', 'X-GitHub-Api-Version: 2022-11-28',\n\t\tapiPath,\n\t])\n}\n\n// Issue List Operations (for il issues command)\n\nexport interface GitHubIssueListItem {\n\tid: string\n\ttitle: string\n\tupdatedAt: string\n\turl: string\n\tstate: string\n}\n\n/**\n * Fetch a list of open GitHub issues sorted by recently updated\n * @param options - Fetch options\n * @param options.limit - Maximum number of issues to return (default: 100)\n * @param options.cwd - Working directory for gh CLI (default: process.cwd())\n * @returns Array of issues\n */\nexport async function fetchGitHubIssueList(\n\toptions?: { limit?: number; cwd?: string }\n): Promise<GitHubIssueListItem[]> {\n\tconst limit = options?.limit ?? 100\n\n\tlogger.debug('Fetching GitHub issue list', { limit, cwd: options?.cwd })\n\n\tconst result = await executeGhCommand<Array<{\n\t\tnumber: number\n\t\ttitle: string\n\t\tupdatedAt: string\n\t\turl: string\n\t\tstate: string\n\t}>>([\n\t\t'issue',\n\t\t'list',\n\t\t'--state', 'open',\n\t\t'--json', 'number,title,updatedAt,url,state',\n\t\t'--limit', String(limit),\n\t\t'--search', 'sort:updated-desc',\n\t], options?.cwd ? { cwd: options.cwd } : undefined)\n\n\treturn (result ?? []).map(item => ({\n\t\tid: String(item.number),\n\t\ttitle: item.title,\n\t\tupdatedAt: item.updatedAt,\n\t\turl: item.url,\n\t\tstate: item.state.toLowerCase(),\n\t}))\n}\n\n/**\n * Fetch a list of open, non-draft GitHub PRs sorted by recently updated\n * @param options - Fetch options\n * @param options.limit - Maximum number of PRs to return (default: 100)\n * @param options.cwd - Working directory for gh CLI (default: process.cwd())\n * @returns Array of PRs mapped to GitHubIssueListItem (with [PR] title prefix)\n */\nexport async function fetchGitHubPRList(\n\toptions?: { limit?: number; cwd?: string }\n): Promise<GitHubIssueListItem[]> {\n\tconst limit = options?.limit ?? 100\n\t// Over-fetch to account for draft PRs that will be filtered out client-side\n\t// gh pr list has no --draft=false flag\n\tconst fetchLimit = Math.max(limit * 2, 50)\n\n\tlogger.debug('Fetching GitHub PR list', { limit, fetchLimit, cwd: options?.cwd })\n\n\tconst result = await executeGhCommand<Array<{\n\t\tnumber: number\n\t\ttitle: string\n\t\tupdatedAt: string\n\t\turl: string\n\t\tstate: string\n\t\tisDraft: boolean\n\t}>>([\n\t\t'pr', 'list',\n\t\t'--state', 'open',\n\t\t'--json', 'number,title,updatedAt,url,state,isDraft',\n\t\t'--limit', String(fetchLimit),\n\t], options?.cwd ? { cwd: options.cwd } : undefined)\n\n\treturn (result ?? [])\n\t\t.filter(item => !item.isDraft)\n\t\t.slice(0, limit)\n\t\t.map(item => ({\n\t\t\tid: String(item.number),\n\t\t\ttitle: `[PR] ${item.title}`,\n\t\t\tupdatedAt: item.updatedAt,\n\t\t\turl: item.url,\n\t\t\tstate: item.state.toLowerCase(),\n\t\t}))\n}\n"],"mappings":";;;;;;AAAA,SAAS,aAAa;AAYtB,eAAsB,iBACrB,MACA,SACa;AACb,QAAM,SAAS,MAAM,MAAM,MAAM,MAAM;AAAA,IACtC,MAAK,mCAAS,QAAO,QAAQ,IAAI;AAAA,IACjC,UAAS,mCAAS,YAAW;AAAA,IAC7B,UAAU;AAAA,EACX,CAAC;AAGD,QAAM,SACL,KAAK,SAAS,QAAQ,KACtB,KAAK,SAAS,MAAM,KACnB,KAAK,SAAS,UAAU,KAAK,KAAK,KAAK,QAAQ,UAAU,IAAI,CAAC,MAAM,UACpE,KAAK,CAAC,MAAM,SAAS,KAAK,CAAC,MAAM;AACnC,QAAM,OAAO,SAAS,KAAK,MAAM,OAAO,MAAM,IAAI,OAAO;AAEzD,SAAO;AACR;AAGA,eAAsB,cAAyC;AAlC/D;AAmCC,MAAI;AACH,UAAM,SAAS,MAAM,iBAAyB,CAAC,QAAQ,QAAQ,CAAC;AAOhE,UAAM,QAAQ,OAAO,MAAM,IAAI;AAC/B,QAAI;AACJ,QAAI,SAAmB,CAAC;AAGxB,aAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACtC,YAAM,OAAO,MAAM,CAAC;AAGpB,YAAM,iBAAiB,6BAAM,MAAM;AACnC,UAAI,gBAAgB;AACnB,cAAM,cAAc,eAAe,CAAC;AAGpC,cAAM,eAAe,MAAM,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,KAAK,IAAI;AACxD,cAAM,WAAW,aAAa,SAAS,sBAAsB;AAG7D,YAAI,YAAa,CAAC,YAAY,CAAC,OAAO,SAAS,iBAAiB,GAAI;AACnE,qBAAW;AAGX,gBAAM,aAAa,aAAa,MAAM,oBAAoB;AAC1D,cAAI,yCAAa,IAAI;AACpB,qBAAS,WAAW,CAAC,EAAE,MAAM,IAAI,EAAE,IAAI,WAAS,MAAM,QAAQ,UAAU,EAAE,CAAC;AAAA,UAC5E;AAGA,cAAI,SAAU;AAAA,QACf;AAAA,MACD;AAGA,UAAI,CAAC,UAAU;AACd,cAAM,iBAAiB,6BAAM,MAAM;AACnC,YAAI,gBAAgB;AACnB,qBAAW,eAAe,CAAC;AAAA,QAC5B;AAAA,MACD;AAAA,IACD;AAGA,QAAI,OAAO,WAAW,GAAG;AACxB,YAAM,aAAa,OAAO,MAAM,oBAAoB;AACpD,iBAAS,8CAAa,OAAb,mBAAiB,MAAM,MAAM,IAAI,WAAS,MAAM,QAAQ,UAAU,EAAE,OAAM,CAAC;AAAA,IACrF;AAEA,WAAO;AAAA,MACN,SAAS;AAAA,MACT;AAAA,MACA,GAAI,YAAY,EAAE,SAAS;AAAA,IAC5B;AAAA,EACD,SAAS,OAAO;AAEf,QAAI,iBAAiB,SAAS,YAAY,WAAU,WAA4B,WAA5B,mBAAoC,SAAS,8CAA6C;AAC7I,aAAO,EAAE,SAAS,OAAO,QAAQ,CAAC,EAAE;AAAA,IACrC;AAEA,UAAM;AAAA,EACP;AACD;AAEA,eAAsB,kBAAoC;AACzD,QAAM,OAAO,MAAM,YAAY;AAC/B,SAAO,KAAK,OAAO,SAAS,SAAS;AACtC;AAGA,eAAsB,aACrB,aACA,MACuB;AACvB,SAAO,MAAM,yBAAyB,EAAE,aAAa,KAAK,CAAC;AAE3D,QAAM,OAAO;AAAA,IACZ;AAAA,IACA;AAAA,IACA,OAAO,WAAW;AAAA,IAClB;AAAA,IACA;AAAA,EACD;AAEA,MAAI,MAAM;AACT,SAAK,KAAK,UAAU,IAAI;AAAA,EACzB;AAEA,SAAO,iBAA8B,IAAI;AAC1C;AAGA,eAAsB,UACrB,UACA,MAC6B;AAC7B,SAAO,MAAM,sBAAsB,EAAE,UAAU,KAAK,CAAC;AAErD,QAAM,OAAO;AAAA,IACZ;AAAA,IACA;AAAA,IACA,OAAO,QAAQ;AAAA,IACf;AAAA,IACA;AAAA,EACD;AAEA,MAAI,MAAM;AACT,SAAK,KAAK,UAAU,IAAI;AAAA,EACzB;AAEA,SAAO,iBAAoC,IAAI;AAChD;AAGA,eAAsB,iBACrB,OAC2B;AAC3B,QAAM,SAAS,MAAM,iBAAgD;AAAA,IACpE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD,CAAC;AAED,UAAO,iCAAQ,aAAY,CAAC;AAC7B;AAEA,eAAsB,kBACrB,eACA,OACyB;AACzB,QAAM,SAAS,MAAM,iBAA2C;AAAA,IAC/D;AAAA,IACA;AAAA,IACA,OAAO,aAAa;AAAA,IACpB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD,CAAC;AAED,UAAO,iCAAQ,UAAS,CAAC;AAC1B;AAEA,eAAsB,mBACrB,eACA,OACsC;AACtC,QAAM,SAAS,MAAM,iBAA6C;AAAA,IACjE;AAAA,IACA;AAAA,IACA,OAAO,aAAa;AAAA,IACpB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD,CAAC;AAED,SAAO,UAAU,EAAE,QAAQ,CAAC,EAAE;AAC/B;AAEA,eAAsB,uBACrB,QACA,WACA,SACA,UACgB;AAChB,QAAM,iBAAiB;AAAA,IACtB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD,CAAC;AACF;AAkBA,eAAsB,YACrB,OACA,MACA,SAC+B;AAC/B,QAAM,EAAE,MAAM,OAAO,IAAI,WAAW,CAAC;AAErC,SAAO,MAAM,yBAAyB,EAAE,OAAO,MAAM,OAAO,CAAC;AAE7D,QAAM,OAAO;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD;AAGA,MAAI,MAAM;AACT,SAAK,OAAO,GAAG,GAAG,UAAU,IAAI;AAAA,EACjC;AAGA,MAAI,UAAU,OAAO,SAAS,GAAG;AAChC,SAAK,KAAK,WAAW,OAAO,KAAK,GAAG,CAAC;AAAA,EACtC;AAEA,QAAM,eAAoE;AAAA,IACzE,SAAS;AAAA,IACT,UAAU;AAAA,EACX;AAEA,MAAI,CAAC,MAAM;AACV,iBAAa,MAAM,QAAQ,IAAI;AAAA,EAChC;AAEA,QAAM,SAAS,MAAM,MAAM,MAAM,MAAM,YAAY;AAGnD,QAAM,WAAW,OAAO,OAAO,KAAK,EAAE,MAAM,oDAAoD;AAChG,MAAI,EAAC,qCAAW,KAAI;AACnB,UAAM,IAAI,MAAM,6CAA6C,OAAO,MAAM,EAAE;AAAA,EAC7E;AAEA,QAAM,cAAc,SAAS,SAAS,CAAC,GAAG,EAAE;AAC5C,QAAM,WAAW,SAAS,CAAC;AAE3B,SAAO;AAAA,IACN,QAAQ;AAAA,IACR,KAAK;AAAA,EACN;AACD;AAyCA,eAAsB,mBACrB,aACA,MACA,MAC2B;AAC3B,SAAO,MAAM,0BAA0B,EAAE,aAAa,KAAK,CAAC;AAE5D,QAAM,UAAU,OACb,SAAS,IAAI,WAAW,WAAW,cACnC,6BAA6B,WAAW;AAE3C,SAAO,iBAAkC;AAAA,IACxC;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ,IAAI;AAAA,IACZ;AAAA,IACA;AAAA,EACD,CAAC;AACF;AASA,eAAsB,mBACrB,WACA,MACA,MAC2B;AAC3B,SAAO,MAAM,0BAA0B,EAAE,WAAW,KAAK,CAAC;AAE1D,QAAM,UAAU,OACb,SAAS,IAAI,oBAAoB,SAAS,KAC1C,sCAAsC,SAAS;AAElD,SAAO,iBAAkC;AAAA,IACxC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ,IAAI;AAAA,IACZ;AAAA,IACA;AAAA,EACD,CAAC;AACF;AAUA,eAAsB,gBACrB,UACA,MACA,MAC2B;AAC3B,SAAO,MAAM,uBAAuB,EAAE,UAAU,KAAK,CAAC;AAEtD,QAAM,UAAU,OACb,SAAS,IAAI,WAAW,QAAQ,cAChC,6BAA6B,QAAQ;AAGxC,SAAO,iBAAkC;AAAA,IACxC;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ,IAAI;AAAA,IACZ;AAAA,IACA;AAAA,EACD,CAAC;AACF;AAMA,eAAsB,cAAiC;AACtD,SAAO,MAAM,0BAA0B;AAEvC,QAAM,SAAS,MAAM,iBAA6D;AAAA,IACjF;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD,CAAC;AAED,SAAO;AAAA,IACN,OAAO,OAAO,MAAM;AAAA,IACpB,MAAM,OAAO;AAAA,EACd;AACD;AAWA,eAAsB,eACrB,aACA,MACkB;AAClB,SAAO,MAAM,iCAAiC,EAAE,aAAa,KAAK,CAAC;AAEnE,QAAM,OAAO,CAAC,SAAS,QAAQ,OAAO,WAAW,GAAG,UAAU,IAAI;AAClE,MAAI,MAAM;AACT,SAAK,KAAK,UAAU,IAAI;AAAA,EACzB;AAEA,QAAM,SAAS,MAAM,iBAAiC,IAAI;AAC1D,SAAO,OAAO;AACf;AAQA,eAAsB,YACrB,cACA,aACgB;AAChB,SAAO,MAAM,iCAAiC,EAAE,cAAc,YAAY,CAAC;AAE3E,QAAM,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AASjB,QAAM,iBAAiB;AAAA,IACtB;AAAA,IAAO;AAAA,IACP;AAAA,IAAM;AAAA,IACN;AAAA,IAAM,SAAS,QAAQ;AAAA,IACvB;AAAA,IAAM,YAAY,YAAY;AAAA,IAC9B;AAAA,IAAM,cAAc,WAAW;AAAA,EAChC,CAAC;AACF;AASA,eAAsB,aACrB,aACA,MAC4E;AAxf7E;AAyfC,SAAO,MAAM,8BAA8B,EAAE,aAAa,KAAK,CAAC;AAGhE,QAAM,eAAe,MAAM,eAAe,aAAa,IAAI;AAG3D,QAAM,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAkCd,MAAI;AACH,UAAM,SAAS,MAAM,iBAAoC;AAAA,MACxD;AAAA,MAAO;AAAA,MACP;AAAA,MAAM;AAAA,MACN;AAAA,MAAM,SAAS,KAAK;AAAA,MACpB;AAAA,MAAM,YAAY,YAAY;AAAA,IAC/B,CAAC;AAED,UAAM,cAAY,kBAAO,KAAK,SAAZ,mBAAkB,cAAlB,mBAA6B,UAAS,CAAC;AAEzD,WAAO,UAAU,IAAI,YAAU;AAAA,MAC9B,IAAI,OAAO,MAAM,MAAM;AAAA,MACvB,OAAO,MAAM;AAAA,MACb,KAAK,MAAM;AAAA,MACX,OAAO,MAAM,MAAM,YAAY;AAAA,IAChC,EAAE;AAAA,EACH,SAAS,OAAO;AAEf,QAAI,iBAAiB,OAAO;AAC3B,YAAM,eAAe,MAAM;AAC3B,YAAM,SAAS,YAAY,QAAS,MAA8B,UAAU,KAAK;AACjF,YAAM,gBAAgB,GAAG,YAAY,IAAI,MAAM;AAG/C,UAAI,cAAc,SAAS,YAAY,KAAK,cAAc,SAAS,MAAM,GAAG;AAC3E,eAAO,CAAC;AAAA,MACT;AAAA,IACD;AACA,UAAM;AAAA,EACP;AACD;AAsBA,eAAsB,mBACrB,aACA,MACkB;AAClB,SAAO,MAAM,qCAAqC,EAAE,aAAa,KAAK,CAAC;AAEvE,QAAM,UAAU,OACb,SAAS,IAAI,WAAW,WAAW,KACnC,6BAA6B,WAAW;AAE3C,QAAM,SAAS,MAAM,iBAAiC;AAAA,IACrD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD,CAAC;AAED,SAAO,OAAO;AACf;AAUA,eAAsB,qBACrB,aACA,WACA,MACgG;AAChG,SAAO,MAAM,sCAAsC,EAAE,aAAa,WAAW,KAAK,CAAC;AAGnF,QAAM,UAAU,OACb,SAAS,IAAI,WAAW,WAAW,iBAAiB,SAAS,KAC7D,6BAA6B,WAAW,iBAAiB,SAAS;AAErE,MAAI;AACH,UAAM,SAAS,MAAM,iBAAqC;AAAA,MACzD;AAAA,MACA;AAAA,MAAM;AAAA,MACN;AAAA,MAAM;AAAA,MACN;AAAA,MAAQ;AAAA,MACR;AAAA,IACD,CAAC;AAED,YAAQ,UAAU,CAAC,GAAG,IAAI,UAAQ;AAAA,MACjC,IAAI,OAAO,IAAI,MAAM;AAAA,MACrB,YAAY,IAAI;AAAA,MAChB,OAAO,IAAI;AAAA,MACX,KAAK,IAAI;AAAA,MACT,OAAO,IAAI;AAAA,IACZ,EAAE;AAAA,EACH,SAAS,OAAO;AAGf,QAAI,iBAAiB,OAAO;AAC3B,YAAM,eAAe,MAAM;AAC3B,YAAM,SAAS,YAAY,QAAS,MAA8B,UAAU,KAAK;AACjF,YAAM,gBAAgB,GAAG,YAAY,IAAI,MAAM;AAG/C,UAAI,cAAc,SAAS,KAAK,KAAK,cAAc,SAAS,cAAc,GAAG;AAC5E,eAAO,CAAC;AAAA,MACT;AAAA,IACD;AACA,UAAM;AAAA,EACP;AACD;AAUA,eAAsB,sBACrB,oBACA,yBACA,MACgB;AAChB,SAAO,MAAM,oCAAoC,EAAE,oBAAoB,yBAAyB,KAAK,CAAC;AAGtG,QAAM,UAAU,OACb,SAAS,IAAI,WAAW,kBAAkB,6BAC1C,6BAA6B,kBAAkB;AAElD,MAAI;AACH,UAAM,iBAAiB;AAAA,MACtB;AAAA,MACA;AAAA,MAAM;AAAA,MACN;AAAA,MAAM;AAAA,MACN;AAAA,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MAAM,YAAY,uBAAuB;AAAA,IAC1C,CAAC;AAAA,EACF,SAAS,OAAO;AACf,QAAI,iBAAiB,OAAO;AAC3B,YAAM,eAAe,MAAM;AAC3B,YAAM,SAAS,YAAY,QAAS,MAA8B,UAAU,KAAK;AACjF,YAAM,gBAAgB,GAAG,YAAY,IAAI,MAAM;AAG/C,UAAI,cAAc,SAAS,KAAK,KAAK,cAAc,SAAS,gBAAgB,KAAK,cAAc,SAAS,sBAAsB,GAAG;AAChI,cAAM,IAAI,MAAM,qCAAqC,kBAAkB,4CAA4C;AAAA,MACpH;AAGA,UAAI,cAAc,SAAS,KAAK,KAAK,cAAc,SAAS,WAAW,GAAG;AACzE,cAAM,IAAI,MAAM,2DAA2D,kBAAkB,6DAA6D;AAAA,MAC3J;AAGA,UAAI,cAAc,SAAS,KAAK,KAAK,cAAc,SAAS,WAAW,KAAK,cAAc,SAAS,aAAa,GAAG;AAClH,cAAM,IAAI,MAAM,oKAAoK;AAAA,MACrL;AAAA,IACD;AAGA,UAAM;AAAA,EACP;AACD;AASA,eAAsB,sBACrB,oBACA,yBACA,MACgB;AAChB,SAAO,MAAM,oCAAoC,EAAE,oBAAoB,yBAAyB,KAAK,CAAC;AAGtG,QAAM,UAAU,OACb,SAAS,IAAI,WAAW,kBAAkB,4BAA4B,uBAAuB,KAC7F,6BAA6B,kBAAkB,4BAA4B,uBAAuB;AAErG,QAAM,iBAAiB;AAAA,IACtB;AAAA,IACA;AAAA,IAAM;AAAA,IACN;AAAA,IAAM;AAAA,IACN;AAAA,IAAM;AAAA,IACN;AAAA,EACD,CAAC;AACF;AAmBA,eAAsB,qBACrB,SACiC;AACjC,QAAM,SAAQ,mCAAS,UAAS;AAEhC,SAAO,MAAM,8BAA8B,EAAE,OAAO,KAAK,mCAAS,IAAI,CAAC;AAEvE,QAAM,SAAS,MAAM,iBAMjB;AAAA,IACH;AAAA,IACA;AAAA,IACA;AAAA,IAAW;AAAA,IACX;AAAA,IAAU;AAAA,IACV;AAAA,IAAW,OAAO,KAAK;AAAA,IACvB;AAAA,IAAY;AAAA,EACb,IAAG,mCAAS,OAAM,EAAE,KAAK,QAAQ,IAAI,IAAI,MAAS;AAElD,UAAQ,UAAU,CAAC,GAAG,IAAI,WAAS;AAAA,IAClC,IAAI,OAAO,KAAK,MAAM;AAAA,IACtB,OAAO,KAAK;AAAA,IACZ,WAAW,KAAK;AAAA,IAChB,KAAK,KAAK;AAAA,IACV,OAAO,KAAK,MAAM,YAAY;AAAA,EAC/B,EAAE;AACH;AASA,eAAsB,kBACrB,SACiC;AACjC,QAAM,SAAQ,mCAAS,UAAS;AAGhC,QAAM,aAAa,KAAK,IAAI,QAAQ,GAAG,EAAE;AAEzC,SAAO,MAAM,2BAA2B,EAAE,OAAO,YAAY,KAAK,mCAAS,IAAI,CAAC;AAEhF,QAAM,SAAS,MAAM,iBAOjB;AAAA,IACH;AAAA,IAAM;AAAA,IACN;AAAA,IAAW;AAAA,IACX;AAAA,IAAU;AAAA,IACV;AAAA,IAAW,OAAO,UAAU;AAAA,EAC7B,IAAG,mCAAS,OAAM,EAAE,KAAK,QAAQ,IAAI,IAAI,MAAS;AAElD,UAAQ,UAAU,CAAC,GACjB,OAAO,UAAQ,CAAC,KAAK,OAAO,EAC5B,MAAM,GAAG,KAAK,EACd,IAAI,WAAS;AAAA,IACb,IAAI,OAAO,KAAK,MAAM;AAAA,IACtB,OAAO,QAAQ,KAAK,KAAK;AAAA,IACzB,WAAW,KAAK;AAAA,IAChB,KAAK,KAAK;AAAA,IACV,OAAO,KAAK,MAAM,YAAY;AAAA,EAC/B,EAAE;AACJ;","names":[]}
@@ -4,7 +4,7 @@ import {
4
4
  } from "./chunk-QN47QVBX.js";
5
5
  import {
6
6
  SettingsManager
7
- } from "./chunk-XFEK2X2D.js";
7
+ } from "./chunk-RI2YL6TK.js";
8
8
  import {
9
9
  detectClaudeCli,
10
10
  launchClaude,
@@ -119,4 +119,4 @@ var ClaudeService = class {
119
119
  export {
120
120
  ClaudeService
121
121
  };
122
- //# sourceMappingURL=chunk-MZPRBNYC.js.map
122
+ //# sourceMappingURL=chunk-6IIL5M2L.js.map
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  ProcessManager
4
- } from "./chunk-NTTSUAVM.js";
4
+ } from "./chunk-IZIYLYPK.js";
5
5
  import {
6
6
  detectPackageManager,
7
7
  runScript
@@ -217,4 +217,4 @@ var DevServerManager = class {
217
217
  export {
218
218
  DevServerManager
219
219
  };
220
- //# sourceMappingURL=chunk-2JPXGGP4.js.map
220
+ //# sourceMappingURL=chunk-A7NJF73J.js.map
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  SettingsManager
4
- } from "./chunk-XFEK2X2D.js";
4
+ } from "./chunk-RI2YL6TK.js";
5
5
  import {
6
6
  MetadataManager
7
7
  } from "./chunk-KBEIQP4G.js";
@@ -375,7 +375,7 @@ async function getDefaultBranch(path2 = process.cwd()) {
375
375
  }
376
376
  async function findAllBranchesForIssue(issueNumber, path2 = process.cwd(), settingsManager) {
377
377
  if (!settingsManager) {
378
- const { SettingsManager: SM } = await import("./SettingsManager-QR7V2IW2.js");
378
+ const { SettingsManager: SM } = await import("./SettingsManager-AW3JTJHD.js");
379
379
  settingsManager = new SM();
380
380
  }
381
381
  const protectedBranches = await settingsManager.getProtectedBranches(path2);
@@ -738,4 +738,4 @@ export {
738
738
  removePlaceholderCommitFromHead,
739
739
  removePlaceholderCommitFromHistory
740
740
  };
741
- //# sourceMappingURL=chunk-H6ST2TGP.js.map
741
+ //# sourceMappingURL=chunk-AR5QKYNE.js.map
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  generateIssueManagementMcpConfig
4
- } from "./chunk-XJHQVOT6.js";
4
+ } from "./chunk-WHI5KEOX.js";
5
5
  import {
6
6
  openBrowser
7
7
  } from "./chunk-YETJNRQM.js";
@@ -244,4 +244,4 @@ export {
244
244
  IssueEnhancementService,
245
245
  capitalizeFirstLetter
246
246
  };
247
- //# sourceMappingURL=chunk-PL2FDYEK.js.map
247
+ //# sourceMappingURL=chunk-CWRI4JC3.js.map
@@ -4,7 +4,7 @@ import {
4
4
  } from "./chunk-YETJNRQM.js";
5
5
  import {
6
6
  IssueManagementProviderFactory
7
- } from "./chunk-UDZCTLD6.js";
7
+ } from "./chunk-ULSWCPQG.js";
8
8
  import {
9
9
  getConfiguredRepoFromSettings,
10
10
  getEffectivePRTargetRemote,
@@ -12,7 +12,7 @@ import {
12
12
  } from "./chunk-FXDYIV3K.js";
13
13
  import {
14
14
  executeGhCommand
15
- } from "./chunk-THS5L54H.js";
15
+ } from "./chunk-4CO6KG5S.js";
16
16
  import {
17
17
  detectClaudeCli,
18
18
  launchClaude
@@ -298,10 +298,11 @@ Then retry: il finish`
298
298
  * @param branchName - Branch to create PR from (used as --head)
299
299
  * @param title - PR title
300
300
  * @param body - PR body
301
+ * @param baseBranch - Base branch to target (used as --base)
301
302
  * @param cwd - Working directory
302
303
  * @returns PR URL and number
303
304
  */
304
- async createDraftPR(branchName, title, body, cwd) {
305
+ async createDraftPR(branchName, title, body, baseBranch, cwd) {
305
306
  try {
306
307
  const targetRemote = await getEffectivePRTargetRemote(this.settings, cwd);
307
308
  let headValue = branchName;
@@ -313,7 +314,7 @@ Then retry: il finish`
313
314
  getLogger().debug(`Fork workflow detected, using head: ${headValue}`);
314
315
  }
315
316
  }
316
- const args = ["pr", "create", "--head", headValue, "--title", title, "--body", body, "--draft"];
317
+ const args = ["pr", "create", "--head", headValue, "--title", title, "--body", body, "--base", baseBranch, "--draft"];
317
318
  if (targetRemote !== "origin") {
318
319
  const repo = await getConfiguredRepoFromSettings(this.settings, cwd);
319
320
  args.push("--repo", repo);
@@ -358,4 +359,4 @@ Then retry: il start`
358
359
  export {
359
360
  PRManager
360
361
  };
361
- //# sourceMappingURL=chunk-I23OQB4Y.js.map
362
+ //# sourceMappingURL=chunk-DGG2VY7B.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/PRManager.ts"],"sourcesContent":["import { executeGhCommand } from '../utils/github.js'\nimport { launchClaude, detectClaudeCli } from '../utils/claude.js'\nimport { getEffectivePRTargetRemote, getConfiguredRepoFromSettings, parseGitRemotes } from '../utils/remote.js'\nimport { openBrowser } from '../utils/browser.js'\nimport { getLogger } from '../utils/logger-context.js'\nimport type { IloomSettings } from './SettingsManager.js'\nimport { IssueManagementProviderFactory } from '../mcp/IssueManagementProviderFactory.js'\n\ninterface ExistingPR {\n\tnumber: number\n\turl: string\n}\n\ninterface PRCreationResult {\n\turl: string\n\tnumber: number\n\twasExisting: boolean\n}\n\nexport class PRManager {\n\tconstructor(private settings: IloomSettings) {\n\t\t// Uses getLogger() for all logging operations\n\t}\n\n\t/**\n\t * Get the issue prefix from the configured provider\n\t */\n\tpublic get issuePrefix(): string {\n\t\tconst providerType = this.settings.issueManagement?.provider ?? 'github'\n\t\tconst provider = IssueManagementProviderFactory.create(providerType)\n\t\treturn provider.issuePrefix\n\t}\n\n\t/**\n\t * Check if a PR already exists for the given branch\n\t * @param branchName - Branch to check\n\t * @param cwd - Working directory\n\t * @returns Existing PR info or null if none found\n\t */\n\tasync checkForExistingPR(branchName: string, cwd?: string): Promise<ExistingPR | null> {\n\t\ttry {\n\t\t\tconst prList = await executeGhCommand<Array<{ number: number; url: string }>>(\n\t\t\t\t['pr', 'list', '--head', branchName, '--state', 'open', '--json', 'number,url'],\n\t\t\t\tcwd ? { cwd } : undefined\n\t\t\t)\n\n\t\t\tif (prList.length > 0) {\n\t\t\t\treturn prList[0] ?? null // Return first match\n\t\t\t}\n\n\t\t\treturn null\n\t\t} catch (error) {\n\t\tgetLogger().debug('Error checking for existing PR', { error })\n\t\t\treturn null\n\t\t}\n\t}\n\n\t/**\n\t * Generate PR body using Claude if available, otherwise use simple template\n\t * @param issueNumber - Issue number to include in body\n\t * @param worktreePath - Path to worktree for context\n\t * @returns PR body markdown\n\t */\n\tasync generatePRBody(issueNumber: string | number | undefined, worktreePath: string): Promise<string> {\n\t\t// Try Claude first for rich body generation\n\t\tconst hasClaudeCli = await detectClaudeCli()\n\n\t\tif (hasClaudeCli) {\n\t\t\ttry {\n\t\t\t\tconst prompt = this.buildPRBodyPrompt(issueNumber)\n\n\t\t\t\tconst body = await launchClaude(prompt, {\n\t\t\t\t\theadless: true,\n\t\t\t\t\taddDir: worktreePath,\n\t\t\t\t\ttimeout: 30000,\n\t\t\t\t\tnoSessionPersistence: true, // Utility operation - don't persist session\n\t\t\t\t})\n\n\t\t\t\tif (body && typeof body === 'string' && body.trim()) {\n\t\t\t\t\tconst sanitized = this.sanitizeClaudeOutput(body)\n\t\t\t\t\tif (sanitized) {\n\t\t\t\t\t\treturn sanitized\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\tgetLogger().debug('Claude PR body generation failed, using template', { error })\n\t\t\t}\n\t\t}\n\n\t\t// Fallback to simple template\n\t\tlet body = 'This PR contains changes from the iloom workflow.\\n\\n'\n\n\t\tif (issueNumber) {\n\t\t\tbody += `Fixes ${this.issuePrefix}${issueNumber}`\n\t\t}\n\n\t\treturn body\n\t}\n\n\t/**\n\t * Build structured XML prompt for PR body generation\n\t * Uses XML format for clear task definition and output expectations\n\t */\n\tprivate buildPRBodyPrompt(issueNumber?: string | number): string {\n\t\tconst issueContext = issueNumber\n\t\t\t? `\\n<IssueContext>\nThis PR is associated with issue ${this.issuePrefix}${issueNumber}.\nInclude \"Fixes ${this.issuePrefix}${issueNumber}\" at the end of the body on its own line.\n</IssueContext>`\n\t\t\t: ''\n\n\t\tconst examplePrefix = this.issuePrefix || '' // Use empty string for Linear examples\n\t\treturn `<Task>\nYou are a software engineer writing a pull request body for this repository.\nExamine the changes in the git repository and generate a concise, professional PR description.\n</Task>\n\n<Requirements>\n<Format>Write 2-3 sentences summarizing what was changed and why.${issueNumber ? `\\n\\nEnd with \"Fixes ${this.issuePrefix}${issueNumber}\" on its own line.` : ''}</Format>\n<Tone>Professional and concise</Tone>\n<Focus>Summarize the changes and their purpose</Focus>\n<NoMeta>CRITICAL: Do NOT include ANY explanatory text, analysis, or meta-commentary. Output ONLY the raw PR body text.</NoMeta>\n<Examples>\nGood: \"Add user authentication with JWT tokens to secure the API endpoints. This includes login and registration endpoints with proper password hashing.\n\nFixes ${examplePrefix}42\"\nGood: \"Fix navigation bug in sidebar menu that caused incorrect highlighting on nested routes.\"\nBad: \"Here's the PR body:\\n\\n---\\n\\nAdd user authentication...\"\nBad: \"Based on the changes, I'll write: Fix navigation bug...\"\n</Examples>\n${issueContext}\n</Requirements>\n\n<Output>\nIMPORTANT: Your entire response will be used directly as the GitHub pull request body.\nDo not include any explanatory text, headers, or separators before or after the body.\nStart your response immediately with the PR body text.\n</Output>`\n\t}\n\n\t/**\n\t * Sanitize Claude output to remove meta-commentary and clean formatting\n\t * Handles cases where Claude includes explanatory text despite instructions\n\t */\n\tprivate sanitizeClaudeOutput(rawOutput: string): string {\n\t\tlet cleaned = rawOutput.trim()\n\n\t\t// Remove common meta-commentary patterns (case-insensitive)\n\t\tconst metaPatterns = [\n\t\t\t/^.*?based on.*?changes.*?:/i,\n\t\t\t/^.*?looking at.*?files.*?:/i,\n\t\t\t/^.*?examining.*?:/i,\n\t\t\t/^.*?analyzing.*?:/i,\n\t\t\t/^.*?i'll.*?generate.*?:/i,\n\t\t\t/^.*?let me.*?:/i,\n\t\t\t/^.*?here.*?is.*?(?:the\\s+)?(?:pr|pull request).*?body.*?:/i,\n\t\t\t/^.*?here's.*?(?:the\\s+)?(?:pr|pull request).*?body.*?:/i,\n\t\t]\n\n\t\tfor (const pattern of metaPatterns) {\n\t\t\tcleaned = cleaned.replace(pattern, '').trim()\n\t\t}\n\n\t\t// Remove leading separator lines (---, ===, etc.)\n\t\tcleaned = cleaned.replace(/^[-=]{3,}\\s*/m, '').trim()\n\n\t\t// Extract content after separators only if it looks like meta-commentary\n\t\tif (cleaned.includes(':')) {\n\t\t\tconst colonIndex = cleaned.indexOf(':')\n\t\t\tconst beforeColon = cleaned.substring(0, colonIndex).trim().toLowerCase()\n\n\t\t\t// Only split if the text before colon looks like meta-commentary\n\t\t\tconst metaIndicators = [\n\t\t\t\t'here is the pr body',\n\t\t\t\t'here is the pull request body',\n\t\t\t\t'pr body',\n\t\t\t\t'pull request body',\n\t\t\t\t'here is',\n\t\t\t\t\"here's\",\n\t\t\t\t'the body should be',\n\t\t\t\t'i suggest',\n\t\t\t\t'my suggestion'\n\t\t\t]\n\n\t\t\tconst isMetaCommentary = metaIndicators.some(indicator => beforeColon.includes(indicator))\n\n\t\t\tif (isMetaCommentary) {\n\t\t\t\tconst afterColon = cleaned.substring(colonIndex + 1).trim()\n\t\t\t\t// Remove leading separator after colon\n\t\t\t\tconst afterSeparator = afterColon.replace(/^[-=]{3,}\\s*/m, '').trim()\n\t\t\t\tif (afterSeparator && afterSeparator.length > 10) {\n\t\t\t\t\tcleaned = afterSeparator\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Remove quotes if the entire message is wrapped in them\n\t\tif ((cleaned.startsWith('\"') && cleaned.endsWith('\"')) ||\n\t\t\t(cleaned.startsWith(\"'\") && cleaned.endsWith(\"'\"))) {\n\t\t\tcleaned = cleaned.slice(1, -1).trim()\n\t\t}\n\n\t\treturn cleaned\n\t}\n\n\t/**\n\t * Create a GitHub PR for the branch\n\t * @param branchName - Branch to create PR from (used as --head)\n\t * @param title - PR title\n\t * @param body - PR body\n\t * @param baseBranch - Base branch to target (usually main/master)\n\t * @param cwd - Working directory\n\t * @returns PR URL\n\t */\n\tasync createPR(\n\t\tbranchName: string,\n\t\ttitle: string,\n\t\tbody: string,\n\t\tbaseBranch: string,\n\t\tcwd?: string\n\t): Promise<string> {\n\t\ttry {\n\t\t\t// Get the target remote for the PR\n\t\t\tconst targetRemote = await getEffectivePRTargetRemote(this.settings, cwd)\n\n\t\t\t// Determine the correct --head value\n\t\t\t// For fork workflows (target != origin), we need \"username:branch\" format\n\t\t\t// See: https://github.com/cli/cli/issues/2691\n\t\t\tlet headValue = branchName\n\n\t\t\tif (targetRemote !== 'origin') {\n\t\t\t\t// Fork workflow: need to specify the head as \"owner:branch\"\n\t\t\t\t// Get the owner of the origin remote (where we pushed the branch)\n\t\t\t\tconst remotes = await parseGitRemotes(cwd)\n\t\t\t\tconst originRemote = remotes.find(r => r.name === 'origin')\n\n\t\t\t\tif (originRemote) {\n\t\t\t\t\theadValue = `${originRemote.owner}:${branchName}`\n\t\t\t\tgetLogger().debug(`Fork workflow detected, using head: ${headValue}`)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Build gh pr create command\n\t\t\t// Note: gh pr create returns a plain URL string, not JSON\n\t\t\tconst args = ['pr', 'create', '--head', headValue, '--title', title, '--body', body, '--base', baseBranch]\n\n\t\t\t// If target remote is not 'origin', we need to specify the repo\n\t\t\tif (targetRemote !== 'origin') {\n\t\t\t\tconst repo = await getConfiguredRepoFromSettings(this.settings, cwd)\n\t\t\t\targs.push('--repo', repo)\n\t\t\t}\n\n\t\t\t// gh pr create returns the PR URL as plain text (not JSON)\n\t\t\tconst result = await executeGhCommand<string>(args, cwd ? { cwd } : undefined)\n\n\t\t\t// Result is a string URL like \"https://github.com/owner/repo/pull/123\"\n\t\t\tconst url = typeof result === 'string' ? result.trim() : String(result).trim()\n\n\t\t\tif (!url.includes('github.com') || !url.includes('/pull/')) {\n\t\t\t\tthrow new Error(`Unexpected response from gh pr create: ${url}`)\n\t\t\t}\n\n\t\t\treturn url\n\t\t} catch (error) {\n\t\t\tconst errorMessage = error instanceof Error ? error.message : String(error)\n\n\t\t\t// Provide helpful error message for common GraphQL errors\n\t\t\tif (errorMessage.includes(\"Head sha can't be blank\") || errorMessage.includes(\"No commits between\")) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Failed to create pull request: ${errorMessage}\\n\\n` +\n\t\t\t\t\t`This error typically occurs when:\\n` +\n\t\t\t\t\t` - The branch was not fully pushed to the remote\\n` +\n\t\t\t\t\t` - There's a race condition between push and PR creation\\n` +\n\t\t\t\t\t` - The branch has no commits ahead of the base branch\\n\\n` +\n\t\t\t\t\t`Try running: git push -u origin ${branchName}\\n` +\n\t\t\t\t\t`Then retry: il finish`\n\t\t\t\t)\n\t\t\t}\n\n\t\t\tthrow new Error(`Failed to create pull request: ${errorMessage}`)\n\t\t}\n\t}\n\n\t/**\n\t * Open PR URL in browser\n\t * @param url - PR URL to open\n\t */\n\tasync openPRInBrowser(url: string): Promise<void> {\n\t\ttry {\n\t\t\tawait openBrowser(url)\n\t\tgetLogger().debug('Opened PR in browser', { url })\n\t\t} catch (error) {\n\t\t\t// Don't fail the whole operation if browser opening fails\n\t\tgetLogger().warn('Failed to open PR in browser', { error })\n\t\t}\n\t}\n\n\t/**\n\t * Complete PR workflow: check for existing, create if needed, optionally open in browser\n\t * @param branchName - Branch to create PR from\n\t * @param title - PR title\n\t * @param issueNumber - Optional issue number for body generation\n\t * @param baseBranch - Base branch to target\n\t * @param worktreePath - Path to worktree\n\t * @param openInBrowser - Whether to open PR in browser\n\t * @returns PR creation result\n\t */\n\tasync createOrOpenPR(\n\t\tbranchName: string,\n\t\ttitle: string,\n\t\tissueNumber: string | number | undefined,\n\t\tbaseBranch: string,\n\t\tworktreePath: string,\n\t\topenInBrowser: boolean\n\t): Promise<PRCreationResult> {\n\t\t// Check for existing PR\n\t\tconst existingPR = await this.checkForExistingPR(branchName, worktreePath)\n\n\t\tif (existingPR) {\n\t\tgetLogger().info(`Pull request already exists: ${existingPR.url}`)\n\n\t\t\tif (openInBrowser) {\n\t\t\t\tawait this.openPRInBrowser(existingPR.url)\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\turl: existingPR.url,\n\t\t\t\tnumber: existingPR.number,\n\t\t\t\twasExisting: true,\n\t\t\t}\n\t\t}\n\n\t\t// Generate PR body\n\t\tconst body = await this.generatePRBody(issueNumber, worktreePath)\n\n\t\t// Create new PR\n\tgetLogger().info('Creating pull request...')\n\t\tconst url = await this.createPR(branchName, title, body, baseBranch, worktreePath)\n\n\t\t// Extract PR number from URL\n\t\tconst prNumber = this.extractPRNumberFromUrl(url)\n\n\t\tif (openInBrowser) {\n\t\t\tawait this.openPRInBrowser(url)\n\t\t}\n\n\t\treturn {\n\t\t\turl,\n\t\t\tnumber: prNumber,\n\t\t\twasExisting: false,\n\t\t}\n\t}\n\n\t/**\n\t * Extract PR number from GitHub PR URL\n\t * @param url - PR URL (e.g., https://github.com/owner/repo/pull/123)\n\t * @returns PR number\n\t */\n\tprivate extractPRNumberFromUrl(url: string): number {\n\t\tconst match = url.match(/\\/pull\\/(\\d+)/)\n\t\tif (match?.[1]) {\n\t\t\treturn parseInt(match[1], 10)\n\t\t}\n\t\tthrow new Error(`Could not extract PR number from URL: ${url}`)\n\t}\n\n\t/**\n\t * Create a draft PR for the branch\n\t * Used by github-draft-pr mode during il start\n\t * @param branchName - Branch to create PR from (used as --head)\n\t * @param title - PR title\n\t * @param body - PR body\n\t * @param baseBranch - Base branch to target (used as --base)\n\t * @param cwd - Working directory\n\t * @returns PR URL and number\n\t */\n\tasync createDraftPR(\n\t\tbranchName: string,\n\t\ttitle: string,\n\t\tbody: string,\n\t\tbaseBranch: string,\n\t\tcwd?: string\n\t): Promise<{ url: string; number: number }> {\n\t\ttry {\n\t\t\t// Get the target remote for the PR\n\t\t\tconst targetRemote = await getEffectivePRTargetRemote(this.settings, cwd)\n\n\t\t\t// Determine the correct --head value\n\t\t\t// For fork workflows (target != origin), we need \"username:branch\" format\n\t\t\tlet headValue = branchName\n\n\t\t\tif (targetRemote !== 'origin') {\n\t\t\t\t// Fork workflow: need to specify the head as \"owner:branch\"\n\t\t\t\tconst remotes = await parseGitRemotes(cwd)\n\t\t\t\tconst originRemote = remotes.find(r => r.name === 'origin')\n\n\t\t\t\tif (originRemote) {\n\t\t\t\t\theadValue = `${originRemote.owner}:${branchName}`\n\t\t\t\t\tgetLogger().debug(`Fork workflow detected, using head: ${headValue}`)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Build gh pr create command with --draft flag\n\t\t\tconst args = ['pr', 'create', '--head', headValue, '--title', title, '--body', body, '--base', baseBranch, '--draft']\n\n\t\t\t// If target remote is not 'origin', we need to specify the repo\n\t\t\tif (targetRemote !== 'origin') {\n\t\t\t\tconst repo = await getConfiguredRepoFromSettings(this.settings, cwd)\n\t\t\t\targs.push('--repo', repo)\n\t\t\t}\n\n\t\t\t// gh pr create returns the PR URL as plain text (not JSON)\n\t\t\tconst result = await executeGhCommand<string>(args, cwd ? { cwd } : undefined)\n\n\t\t\t// Result is a string URL like \"https://github.com/owner/repo/pull/123\"\n\t\t\tconst url = typeof result === 'string' ? result.trim() : String(result).trim()\n\n\t\t\tif (!url.includes('github.com') || !url.includes('/pull/')) {\n\t\t\t\tthrow new Error(`Unexpected response from gh pr create --draft: ${url}`)\n\t\t\t}\n\n\t\t\tconst number = this.extractPRNumberFromUrl(url)\n\n\t\t\treturn { url, number }\n\t\t} catch (error) {\n\t\t\tconst errorMessage = error instanceof Error ? error.message : String(error)\n\n\t\t\t// Provide helpful error message for common errors\n\t\t\tif (errorMessage.includes(\"Head sha can't be blank\") || errorMessage.includes(\"No commits between\")) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Failed to create draft pull request: ${errorMessage}\\n\\n` +\n\t\t\t\t\t`This error typically occurs when:\\n` +\n\t\t\t\t\t` - The branch was not fully pushed to the remote\\n` +\n\t\t\t\t\t` - The branch has no commits ahead of the base branch\\n\\n` +\n\t\t\t\t\t`Try running: git push -u origin ${branchName}\\n` +\n\t\t\t\t\t`Then retry: il start`\n\t\t\t\t)\n\t\t\t}\n\n\t\t\tthrow new Error(`Failed to create draft pull request: ${errorMessage}`)\n\t\t}\n\t}\n\n\t/**\n\t * Mark a draft PR as ready for review\n\t * Used by github-draft-pr mode during il finish\n\t * @param prNumber - PR number to mark ready\n\t * @param cwd - Working directory\n\t */\n\tasync markPRReady(prNumber: number, cwd?: string): Promise<void> {\n\t\tconst args = ['pr', 'ready', String(prNumber)]\n\t\tawait executeGhCommand(args, cwd ? { cwd } : undefined)\n\t\tgetLogger().info(`Marked PR #${prNumber} as ready for review`)\n\t}\n}\n"],"mappings":"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","names":["body"]}
@@ -54,8 +54,9 @@ function getLinearApiToken() {
54
54
  }
55
55
  return token;
56
56
  }
57
- function createLinearClient() {
58
- return new LinearClient({ apiKey: getLinearApiToken() });
57
+ function createLinearClient(apiToken) {
58
+ const token = apiToken ?? getLinearApiToken();
59
+ return new LinearClient({ apiKey: token });
59
60
  }
60
61
  function handleLinearError(error, context) {
61
62
  logger.debug(`${context}: Handling error`, { error });
@@ -304,10 +305,10 @@ async function fetchLinearIssueComments(identifier) {
304
305
  handleLinearError(error, "fetchLinearIssueComments");
305
306
  }
306
307
  }
307
- async function getLinearChildIssues(identifier) {
308
+ async function getLinearChildIssues(identifier, options) {
308
309
  try {
309
310
  logger.debug(`Fetching child issues for Linear issue: ${identifier}`);
310
- const client = createLinearClient();
311
+ const client = createLinearClient(options == null ? void 0 : options.apiToken);
311
312
  const issue = await client.issue(identifier);
312
313
  if (!issue) {
313
314
  throw new LinearServiceError("NOT_FOUND", `Linear issue ${identifier} not found`);
@@ -422,6 +423,49 @@ async function deleteLinearIssueRelation(relationId) {
422
423
  handleLinearError(error, "deleteLinearIssueRelation");
423
424
  }
424
425
  }
426
+ async function fetchLinearIssueList(teamKey, options) {
427
+ try {
428
+ const limit = (options == null ? void 0 : options.limit) ?? 100;
429
+ logger.debug(`Fetching Linear issue list for team ${teamKey}`, { limit });
430
+ const client = createLinearClient(options == null ? void 0 : options.apiToken);
431
+ const teams = await client.teams();
432
+ const team = teams.nodes.find((t) => t.key === teamKey);
433
+ if (!team) {
434
+ throw new LinearServiceError("NOT_FOUND", `Linear team ${teamKey} not found`);
435
+ }
436
+ const issues = await team.issues({
437
+ first: limit,
438
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- PaginationOrderBy is a const enum incompatible with isolatedModules
439
+ orderBy: "updatedAt",
440
+ filter: {
441
+ state: {
442
+ type: {
443
+ nin: ["completed", "canceled"]
444
+ }
445
+ }
446
+ }
447
+ });
448
+ const results = await Promise.all(
449
+ issues.nodes.map(async (issue) => {
450
+ const stateObj = await issue.state;
451
+ const state = (stateObj == null ? void 0 : stateObj.name) ?? "unknown";
452
+ return {
453
+ id: issue.identifier,
454
+ title: issue.title,
455
+ updatedAt: issue.updatedAt.toISOString(),
456
+ url: issue.url,
457
+ state
458
+ };
459
+ })
460
+ );
461
+ return results;
462
+ } catch (error) {
463
+ if (error instanceof LinearServiceError) {
464
+ throw error;
465
+ }
466
+ handleLinearError(error, "fetchLinearIssueList");
467
+ }
468
+ }
425
469
  async function findLinearIssueRelation(blockingIdentifier, blockedIdentifier) {
426
470
  try {
427
471
  logger.debug(`Finding Linear issue relation: ${blockingIdentifier} blocks ${blockedIdentifier}`);
@@ -470,6 +514,7 @@ export {
470
514
  createLinearIssueRelation,
471
515
  getLinearIssueDependencies,
472
516
  deleteLinearIssueRelation,
517
+ fetchLinearIssueList,
473
518
  findLinearIssueRelation
474
519
  };
475
- //# sourceMappingURL=chunk-RNBIISBZ.js.map
520
+ //# sourceMappingURL=chunk-FJDRTVJX.js.map