hub-launch 1.0.3

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 (331) hide show
  1. package/CHANGELOG.md +144 -0
  2. package/README.md +195 -0
  3. package/bin/hublaunch +20 -0
  4. package/dist/commands/checkout.d.ts +7 -0
  5. package/dist/commands/checkout.d.ts.map +1 -0
  6. package/dist/commands/checkout.js +164 -0
  7. package/dist/commands/checkout.js.map +1 -0
  8. package/dist/commands/clean.d.ts +7 -0
  9. package/dist/commands/clean.d.ts.map +1 -0
  10. package/dist/commands/clean.js +206 -0
  11. package/dist/commands/clean.js.map +1 -0
  12. package/dist/commands/close.d.ts +7 -0
  13. package/dist/commands/close.d.ts.map +1 -0
  14. package/dist/commands/close.js +109 -0
  15. package/dist/commands/close.js.map +1 -0
  16. package/dist/commands/create.d.ts +7 -0
  17. package/dist/commands/create.d.ts.map +1 -0
  18. package/dist/commands/create.js +367 -0
  19. package/dist/commands/create.js.map +1 -0
  20. package/dist/commands/diff.d.ts +7 -0
  21. package/dist/commands/diff.d.ts.map +1 -0
  22. package/dist/commands/diff.js +98 -0
  23. package/dist/commands/diff.js.map +1 -0
  24. package/dist/commands/execute.d.ts +7 -0
  25. package/dist/commands/execute.d.ts.map +1 -0
  26. package/dist/commands/execute.js +376 -0
  27. package/dist/commands/execute.js.map +1 -0
  28. package/dist/commands/init.d.ts +8 -0
  29. package/dist/commands/init.d.ts.map +1 -0
  30. package/dist/commands/init.js +1243 -0
  31. package/dist/commands/init.js.map +1 -0
  32. package/dist/commands/interactive.d.ts +12 -0
  33. package/dist/commands/interactive.d.ts.map +1 -0
  34. package/dist/commands/interactive.js +1071 -0
  35. package/dist/commands/interactive.js.map +1 -0
  36. package/dist/commands/launch.d.ts +16 -0
  37. package/dist/commands/launch.d.ts.map +1 -0
  38. package/dist/commands/launch.js +684 -0
  39. package/dist/commands/launch.js.map +1 -0
  40. package/dist/commands/login.d.ts +40 -0
  41. package/dist/commands/login.d.ts.map +1 -0
  42. package/dist/commands/login.js +469 -0
  43. package/dist/commands/login.js.map +1 -0
  44. package/dist/commands/logs.d.ts +22 -0
  45. package/dist/commands/logs.d.ts.map +1 -0
  46. package/dist/commands/logs.js +105 -0
  47. package/dist/commands/logs.js.map +1 -0
  48. package/dist/commands/merge.d.ts +7 -0
  49. package/dist/commands/merge.d.ts.map +1 -0
  50. package/dist/commands/merge.js +240 -0
  51. package/dist/commands/merge.js.map +1 -0
  52. package/dist/commands/preview.d.ts +7 -0
  53. package/dist/commands/preview.d.ts.map +1 -0
  54. package/dist/commands/preview.js +160 -0
  55. package/dist/commands/preview.js.map +1 -0
  56. package/dist/commands/project.d.ts +18 -0
  57. package/dist/commands/project.d.ts.map +1 -0
  58. package/dist/commands/project.js +352 -0
  59. package/dist/commands/project.js.map +1 -0
  60. package/dist/commands/respond.d.ts +7 -0
  61. package/dist/commands/respond.d.ts.map +1 -0
  62. package/dist/commands/respond.js +112 -0
  63. package/dist/commands/respond.js.map +1 -0
  64. package/dist/commands/setPriority.d.ts +7 -0
  65. package/dist/commands/setPriority.d.ts.map +1 -0
  66. package/dist/commands/setPriority.js +112 -0
  67. package/dist/commands/setPriority.js.map +1 -0
  68. package/dist/commands/track.d.ts +7 -0
  69. package/dist/commands/track.d.ts.map +1 -0
  70. package/dist/commands/track.js +140 -0
  71. package/dist/commands/track.js.map +1 -0
  72. package/dist/commands/upload.d.ts +21 -0
  73. package/dist/commands/upload.d.ts.map +1 -0
  74. package/dist/commands/upload.js +145 -0
  75. package/dist/commands/upload.js.map +1 -0
  76. package/dist/commands/view.d.ts +7 -0
  77. package/dist/commands/view.d.ts.map +1 -0
  78. package/dist/commands/view.js +168 -0
  79. package/dist/commands/view.js.map +1 -0
  80. package/dist/commands/watch.d.ts +7 -0
  81. package/dist/commands/watch.d.ts.map +1 -0
  82. package/dist/commands/watch.js +438 -0
  83. package/dist/commands/watch.js.map +1 -0
  84. package/dist/commands/worktree.d.ts +7 -0
  85. package/dist/commands/worktree.d.ts.map +1 -0
  86. package/dist/commands/worktree.js +122 -0
  87. package/dist/commands/worktree.js.map +1 -0
  88. package/dist/config/command-names.d.ts +16 -0
  89. package/dist/config/command-names.d.ts.map +1 -0
  90. package/dist/config/command-names.js +17 -0
  91. package/dist/config/command-names.js.map +1 -0
  92. package/dist/config/constants.d.ts +12 -0
  93. package/dist/config/constants.d.ts.map +1 -0
  94. package/dist/config/constants.js +12 -0
  95. package/dist/config/constants.js.map +1 -0
  96. package/dist/config/index.d.ts +47 -0
  97. package/dist/config/index.d.ts.map +1 -0
  98. package/dist/config/index.js +175 -0
  99. package/dist/config/index.js.map +1 -0
  100. package/dist/index.d.ts +3 -0
  101. package/dist/index.d.ts.map +1 -0
  102. package/dist/index.js +148 -0
  103. package/dist/index.js.map +1 -0
  104. package/dist/services/api/HulaApiClient.d.ts +170 -0
  105. package/dist/services/api/HulaApiClient.d.ts.map +1 -0
  106. package/dist/services/api/HulaApiClient.js +233 -0
  107. package/dist/services/api/HulaApiClient.js.map +1 -0
  108. package/dist/services/diff/DiffService.d.ts +44 -0
  109. package/dist/services/diff/DiffService.d.ts.map +1 -0
  110. package/dist/services/diff/DiffService.js +126 -0
  111. package/dist/services/diff/DiffService.js.map +1 -0
  112. package/dist/services/editor/EditorService.d.ts +53 -0
  113. package/dist/services/editor/EditorService.d.ts.map +1 -0
  114. package/dist/services/editor/EditorService.js +161 -0
  115. package/dist/services/editor/EditorService.js.map +1 -0
  116. package/dist/services/git/GitService.d.ts +124 -0
  117. package/dist/services/git/GitService.d.ts.map +1 -0
  118. package/dist/services/git/GitService.js +423 -0
  119. package/dist/services/git/GitService.js.map +1 -0
  120. package/dist/services/git/WorktreeService.d.ts +144 -0
  121. package/dist/services/git/WorktreeService.d.ts.map +1 -0
  122. package/dist/services/git/WorktreeService.js +505 -0
  123. package/dist/services/git/WorktreeService.js.map +1 -0
  124. package/dist/services/github/ActionsService.d.ts +66 -0
  125. package/dist/services/github/ActionsService.d.ts.map +1 -0
  126. package/dist/services/github/ActionsService.js +114 -0
  127. package/dist/services/github/ActionsService.js.map +1 -0
  128. package/dist/services/github/AssetUploadService.d.ts +103 -0
  129. package/dist/services/github/AssetUploadService.d.ts.map +1 -0
  130. package/dist/services/github/AssetUploadService.js +299 -0
  131. package/dist/services/github/AssetUploadService.js.map +1 -0
  132. package/dist/services/github/BatchCopilotDetectionService.d.ts +58 -0
  133. package/dist/services/github/BatchCopilotDetectionService.d.ts.map +1 -0
  134. package/dist/services/github/BatchCopilotDetectionService.js +321 -0
  135. package/dist/services/github/BatchCopilotDetectionService.js.map +1 -0
  136. package/dist/services/github/CopilotDetectionService.d.ts +40 -0
  137. package/dist/services/github/CopilotDetectionService.d.ts.map +1 -0
  138. package/dist/services/github/CopilotDetectionService.js +280 -0
  139. package/dist/services/github/CopilotDetectionService.js.map +1 -0
  140. package/dist/services/github/CopilotService.d.ts +27 -0
  141. package/dist/services/github/CopilotService.d.ts.map +1 -0
  142. package/dist/services/github/CopilotService.js +249 -0
  143. package/dist/services/github/CopilotService.js.map +1 -0
  144. package/dist/services/github/DeploymentDetectionService.d.ts +38 -0
  145. package/dist/services/github/DeploymentDetectionService.d.ts.map +1 -0
  146. package/dist/services/github/DeploymentDetectionService.js +104 -0
  147. package/dist/services/github/DeploymentDetectionService.js.map +1 -0
  148. package/dist/services/github/GithubAppService.d.ts +40 -0
  149. package/dist/services/github/GithubAppService.d.ts.map +1 -0
  150. package/dist/services/github/GithubAppService.js +187 -0
  151. package/dist/services/github/GithubAppService.js.map +1 -0
  152. package/dist/services/github/IssueService.d.ts +65 -0
  153. package/dist/services/github/IssueService.d.ts.map +1 -0
  154. package/dist/services/github/IssueService.js +231 -0
  155. package/dist/services/github/IssueService.js.map +1 -0
  156. package/dist/services/github/LabelService.d.ts +36 -0
  157. package/dist/services/github/LabelService.d.ts.map +1 -0
  158. package/dist/services/github/LabelService.js +122 -0
  159. package/dist/services/github/LabelService.js.map +1 -0
  160. package/dist/services/github/PRService.d.ts +77 -0
  161. package/dist/services/github/PRService.d.ts.map +1 -0
  162. package/dist/services/github/PRService.js +287 -0
  163. package/dist/services/github/PRService.js.map +1 -0
  164. package/dist/services/github/ProjectService.d.ts +144 -0
  165. package/dist/services/github/ProjectService.d.ts.map +1 -0
  166. package/dist/services/github/ProjectService.js +804 -0
  167. package/dist/services/github/ProjectService.js.map +1 -0
  168. package/dist/services/hooks/HookExecutor.d.ts +66 -0
  169. package/dist/services/hooks/HookExecutor.d.ts.map +1 -0
  170. package/dist/services/hooks/HookExecutor.js +227 -0
  171. package/dist/services/hooks/HookExecutor.js.map +1 -0
  172. package/dist/services/hooks/index.d.ts +2 -0
  173. package/dist/services/hooks/index.d.ts.map +1 -0
  174. package/dist/services/hooks/index.js +2 -0
  175. package/dist/services/hooks/index.js.map +1 -0
  176. package/dist/services/logs/LogFormatterService.d.ts +17 -0
  177. package/dist/services/logs/LogFormatterService.d.ts.map +1 -0
  178. package/dist/services/logs/LogFormatterService.js +35 -0
  179. package/dist/services/logs/LogFormatterService.js.map +1 -0
  180. package/dist/services/logs/TempFileService.d.ts +27 -0
  181. package/dist/services/logs/TempFileService.d.ts.map +1 -0
  182. package/dist/services/logs/TempFileService.js +90 -0
  183. package/dist/services/logs/TempFileService.js.map +1 -0
  184. package/dist/services/logs/index.d.ts +3 -0
  185. package/dist/services/logs/index.d.ts.map +1 -0
  186. package/dist/services/logs/index.js +4 -0
  187. package/dist/services/logs/index.js.map +1 -0
  188. package/dist/services/plan/PlanService.d.ts +70 -0
  189. package/dist/services/plan/PlanService.d.ts.map +1 -0
  190. package/dist/services/plan/PlanService.js +211 -0
  191. package/dist/services/plan/PlanService.js.map +1 -0
  192. package/dist/services/polling/GitHubDirectPollingAdapter.d.ts +16 -0
  193. package/dist/services/polling/GitHubDirectPollingAdapter.d.ts.map +1 -0
  194. package/dist/services/polling/GitHubDirectPollingAdapter.js +87 -0
  195. package/dist/services/polling/GitHubDirectPollingAdapter.js.map +1 -0
  196. package/dist/services/polling/HulaServerPollingAdapter.d.ts +23 -0
  197. package/dist/services/polling/HulaServerPollingAdapter.d.ts.map +1 -0
  198. package/dist/services/polling/HulaServerPollingAdapter.js +78 -0
  199. package/dist/services/polling/HulaServerPollingAdapter.js.map +1 -0
  200. package/dist/services/polling/IStatusPollingAdapter.d.ts +29 -0
  201. package/dist/services/polling/IStatusPollingAdapter.d.ts.map +1 -0
  202. package/dist/services/polling/IStatusPollingAdapter.js +2 -0
  203. package/dist/services/polling/IStatusPollingAdapter.js.map +1 -0
  204. package/dist/services/polling/StatusPollingAdapterFactory.d.ts +14 -0
  205. package/dist/services/polling/StatusPollingAdapterFactory.d.ts.map +1 -0
  206. package/dist/services/polling/StatusPollingAdapterFactory.js +41 -0
  207. package/dist/services/polling/StatusPollingAdapterFactory.js.map +1 -0
  208. package/dist/services/polling/index.d.ts +5 -0
  209. package/dist/services/polling/index.d.ts.map +1 -0
  210. package/dist/services/polling/index.js +5 -0
  211. package/dist/services/polling/index.js.map +1 -0
  212. package/dist/services/preview/PreviewService.d.ts +86 -0
  213. package/dist/services/preview/PreviewService.d.ts.map +1 -0
  214. package/dist/services/preview/PreviewService.js +439 -0
  215. package/dist/services/preview/PreviewService.js.map +1 -0
  216. package/dist/services/tracking/ProjectTrackingAdapter.d.ts +41 -0
  217. package/dist/services/tracking/ProjectTrackingAdapter.d.ts.map +1 -0
  218. package/dist/services/tracking/ProjectTrackingAdapter.js +230 -0
  219. package/dist/services/tracking/ProjectTrackingAdapter.js.map +1 -0
  220. package/dist/services/tracking/RemoteTrackingAdapter.d.ts +62 -0
  221. package/dist/services/tracking/RemoteTrackingAdapter.d.ts.map +1 -0
  222. package/dist/services/tracking/RemoteTrackingAdapter.js +242 -0
  223. package/dist/services/tracking/RemoteTrackingAdapter.js.map +1 -0
  224. package/dist/services/tracking/TrackingAdapterFactory.d.ts +25 -0
  225. package/dist/services/tracking/TrackingAdapterFactory.d.ts.map +1 -0
  226. package/dist/services/tracking/TrackingAdapterFactory.js +55 -0
  227. package/dist/services/tracking/TrackingAdapterFactory.js.map +1 -0
  228. package/dist/services/tracking/TrackingService.d.ts +104 -0
  229. package/dist/services/tracking/TrackingService.d.ts.map +1 -0
  230. package/dist/services/tracking/TrackingService.js +256 -0
  231. package/dist/services/tracking/TrackingService.js.map +1 -0
  232. package/dist/services/tracking/UntrackedIssuesService.d.ts +20 -0
  233. package/dist/services/tracking/UntrackedIssuesService.d.ts.map +1 -0
  234. package/dist/services/tracking/UntrackedIssuesService.js +148 -0
  235. package/dist/services/tracking/UntrackedIssuesService.js.map +1 -0
  236. package/dist/services/tracking/local-file-migration.d.ts +16 -0
  237. package/dist/services/tracking/local-file-migration.d.ts.map +1 -0
  238. package/dist/services/tracking/local-file-migration.js +86 -0
  239. package/dist/services/tracking/local-file-migration.js.map +1 -0
  240. package/dist/templates/planning-instructions.md +752 -0
  241. package/dist/templates/proceed-instructions.md +453 -0
  242. package/dist/templates/scripts/hula-fix-commit.sh +110 -0
  243. package/dist/templates/scripts/hula-fix-setup.sh +145 -0
  244. package/dist/templates/scripts/hula-launch-run.sh +89 -0
  245. package/dist/templates/scripts/hula-merge-local.sh +138 -0
  246. package/dist/templates/scripts/hula-merge-remote.sh +74 -0
  247. package/dist/templates/scripts/hula-read-config.sh +38 -0
  248. package/dist/templates/scripts/hula-verify-gather.sh +135 -0
  249. package/dist/templates/scripts/hula-verify-post.sh +84 -0
  250. package/dist/templates/skills/hula-confirm/SKILL.md +361 -0
  251. package/dist/templates/skills/hula-create/SKILL.md +211 -0
  252. package/dist/templates/skills/hula-fix/SKILL.md +224 -0
  253. package/dist/templates/skills/hula-launch/SKILL.md +159 -0
  254. package/dist/templates/skills/hula-log/SKILL.md +105 -0
  255. package/dist/templates/skills/hula-merge/SKILL.md +387 -0
  256. package/dist/templates/skills/hula-plan/SKILL.md +148 -0
  257. package/dist/templates/skills/hula-upload/SKILL.md +115 -0
  258. package/dist/templates/skills/hula-verify/SKILL.md +754 -0
  259. package/dist/types/common.schema.d.ts +46 -0
  260. package/dist/types/common.schema.d.ts.map +1 -0
  261. package/dist/types/common.schema.js +60 -0
  262. package/dist/types/common.schema.js.map +1 -0
  263. package/dist/types/config.schema.d.ts +443 -0
  264. package/dist/types/config.schema.d.ts.map +1 -0
  265. package/dist/types/config.schema.js +126 -0
  266. package/dist/types/config.schema.js.map +1 -0
  267. package/dist/types/index.d.ts +6 -0
  268. package/dist/types/index.d.ts.map +1 -0
  269. package/dist/types/index.js +7 -0
  270. package/dist/types/index.js.map +1 -0
  271. package/dist/types/issue.schema.d.ts +136 -0
  272. package/dist/types/issue.schema.d.ts.map +1 -0
  273. package/dist/types/issue.schema.js +49 -0
  274. package/dist/types/issue.schema.js.map +1 -0
  275. package/dist/types/pr.schema.d.ts +118 -0
  276. package/dist/types/pr.schema.d.ts.map +1 -0
  277. package/dist/types/pr.schema.js +40 -0
  278. package/dist/types/pr.schema.js.map +1 -0
  279. package/dist/types/tracking.schema.d.ts +340 -0
  280. package/dist/types/tracking.schema.d.ts.map +1 -0
  281. package/dist/types/tracking.schema.js +56 -0
  282. package/dist/types/tracking.schema.js.map +1 -0
  283. package/dist/utils/browser-launcher.d.ts +60 -0
  284. package/dist/utils/browser-launcher.d.ts.map +1 -0
  285. package/dist/utils/browser-launcher.js +263 -0
  286. package/dist/utils/browser-launcher.js.map +1 -0
  287. package/dist/utils/cache.d.ts +44 -0
  288. package/dist/utils/cache.d.ts.map +1 -0
  289. package/dist/utils/cache.js +94 -0
  290. package/dist/utils/cache.js.map +1 -0
  291. package/dist/utils/config-parser.d.ts +16 -0
  292. package/dist/utils/config-parser.d.ts.map +1 -0
  293. package/dist/utils/config-parser.js +210 -0
  294. package/dist/utils/config-parser.js.map +1 -0
  295. package/dist/utils/editor.d.ts +21 -0
  296. package/dist/utils/editor.d.ts.map +1 -0
  297. package/dist/utils/editor.js +213 -0
  298. package/dist/utils/editor.js.map +1 -0
  299. package/dist/utils/git-utils.d.ts +5 -0
  300. package/dist/utils/git-utils.d.ts.map +1 -0
  301. package/dist/utils/git-utils.js +18 -0
  302. package/dist/utils/git-utils.js.map +1 -0
  303. package/dist/utils/github-cli.d.ts +62 -0
  304. package/dist/utils/github-cli.d.ts.map +1 -0
  305. package/dist/utils/github-cli.js +492 -0
  306. package/dist/utils/github-cli.js.map +1 -0
  307. package/dist/utils/logger.d.ts +45 -0
  308. package/dist/utils/logger.d.ts.map +1 -0
  309. package/dist/utils/logger.js +118 -0
  310. package/dist/utils/logger.js.map +1 -0
  311. package/dist/utils/open-url.d.ts +19 -0
  312. package/dist/utils/open-url.d.ts.map +1 -0
  313. package/dist/utils/open-url.js +37 -0
  314. package/dist/utils/open-url.js.map +1 -0
  315. package/dist/utils/project-resolver.d.ts +13 -0
  316. package/dist/utils/project-resolver.d.ts.map +1 -0
  317. package/dist/utils/project-resolver.js +35 -0
  318. package/dist/utils/project-resolver.js.map +1 -0
  319. package/dist/utils/prompts.d.ts +80 -0
  320. package/dist/utils/prompts.d.ts.map +1 -0
  321. package/dist/utils/prompts.js +326 -0
  322. package/dist/utils/prompts.js.map +1 -0
  323. package/dist/utils/shell.d.ts +54 -0
  324. package/dist/utils/shell.d.ts.map +1 -0
  325. package/dist/utils/shell.js +152 -0
  326. package/dist/utils/shell.js.map +1 -0
  327. package/dist/utils/validators.d.ts +32 -0
  328. package/dist/utils/validators.d.ts.map +1 -0
  329. package/dist/utils/validators.js +64 -0
  330. package/dist/utils/validators.js.map +1 -0
  331. package/package.json +73 -0
@@ -0,0 +1,104 @@
1
+ import { type TrackedPlan, type Priority, type IssueStatus } from '../../types/index.js';
2
+ type TrackedIssue = TrackedPlan;
3
+ /**
4
+ * Interface for tracking data adapter
5
+ * Dependency Inversion Principle
6
+ */
7
+ export interface ITrackingAdapter {
8
+ read(): Promise<TrackedIssue[]>;
9
+ write(issues: TrackedIssue[]): Promise<void>;
10
+ add?(issue: TrackedIssue): Promise<void>;
11
+ remove?(trackingName: string): Promise<void>;
12
+ updatePriority?(trackingName: string, priority: string): Promise<void>;
13
+ }
14
+ /**
15
+ * Service for managing tracked issues
16
+ * Single Responsibility: Issue tracking operations
17
+ */
18
+ export declare class TrackingService {
19
+ private adapter;
20
+ constructor(adapter: ITrackingAdapter);
21
+ /**
22
+ * Returns the authenticated user id from the underlying adapter, if it
23
+ * supports the concept (currently only RemoteTrackingAdapter). Returns
24
+ * null when unsupported (e.g. local file adapter) or when the adapter
25
+ * has not yet observed the id.
26
+ */
27
+ getCurrentUserId(): string | null;
28
+ /**
29
+ * Get all tracked issues
30
+ */
31
+ getAll(): Promise<TrackedIssue[]>;
32
+ /**
33
+ * Get a specific tracked issue by number
34
+ */
35
+ getByNumber(issueNumber: number): Promise<TrackedIssue | null>;
36
+ /**
37
+ * Check if an issue is tracked
38
+ */
39
+ exists(issueNumber: number): Promise<boolean>;
40
+ /**
41
+ * Add a new issue to tracking
42
+ */
43
+ add(issue: TrackedIssue): Promise<void>;
44
+ /**
45
+ * Remove an issue from tracking by number.
46
+ * WARNING: Matches the first issue with this number regardless of repo.
47
+ * Prefer removeByName() for cross-repo safety.
48
+ */
49
+ remove(issueNumber: number): Promise<void>;
50
+ /**
51
+ * Remove an issue from tracking by name (owner/repo#number).
52
+ * Safe for cross-repo scenarios where multiple repos may share the same issue number.
53
+ */
54
+ removeByName(issueName: string): Promise<void>;
55
+ /**
56
+ * Update a tracked issue
57
+ */
58
+ update(issueNumber: number, updates: Partial<TrackedIssue>): Promise<void>;
59
+ /**
60
+ * Update issue status
61
+ */
62
+ updateStatus(issueNumber: number, status: IssueStatus): Promise<void>;
63
+ /**
64
+ * Update issue priority
65
+ */
66
+ updatePriority(issueNumber: number, priority: Priority): Promise<void>;
67
+ /**
68
+ * Update deployment status
69
+ */
70
+ updateDeploymentStatus(issueNumber: number, status: 'pending' | 'success' | 'failed', timestamp?: string): Promise<void>;
71
+ /**
72
+ * Mark that Copilot was notified about deployment failure
73
+ */
74
+ markDeploymentNotified(issueNumber: number, timestamp: string): Promise<void>;
75
+ /**
76
+ * Get issues by status
77
+ */
78
+ getByStatus(status: IssueStatus): Promise<TrackedIssue[]>;
79
+ /**
80
+ * Get issues by priority
81
+ */
82
+ getByPriority(priority: Priority): Promise<TrackedIssue[]>;
83
+ /**
84
+ * Sort issues by criteria
85
+ */
86
+ sortIssues(issues: TrackedIssue[], sortBy: 'created' | 'updated' | 'number' | 'priority', direction?: 'asc' | 'desc'): TrackedIssue[];
87
+ /**
88
+ * Clean up closed issues from GitHub
89
+ * Since we only track 4 active statuses, this checks GitHub for closed issues
90
+ */
91
+ cleanClosed(): Promise<number>;
92
+ }
93
+ /**
94
+ * File-based tracking adapter
95
+ * Open/Closed Principle: Can extend with new adapters
96
+ */
97
+ export declare class TrackingFileAdapter implements ITrackingAdapter {
98
+ private filePath;
99
+ constructor(filePath: string);
100
+ read(): Promise<TrackedIssue[]>;
101
+ write(issues: TrackedIssue[]): Promise<void>;
102
+ }
103
+ export {};
104
+ //# sourceMappingURL=TrackingService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TrackingService.d.ts","sourceRoot":"","sources":["../../../src/services/tracking/TrackingService.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,256 @@
1
+ import { readFile, writeFile, mkdir } from 'fs/promises';
2
+ import { existsSync } from 'fs';
3
+ import { dirname } from 'path';
4
+ import { logger } from '../../utils/logger.js';
5
+ import { TrackedPlansSchema, PROJECT_FIELD_OPTIONS, } from '../../types/index.js';
6
+ /**
7
+ * Service for managing tracked issues
8
+ * Single Responsibility: Issue tracking operations
9
+ */
10
+ export class TrackingService {
11
+ adapter;
12
+ constructor(adapter) {
13
+ this.adapter = adapter;
14
+ }
15
+ /**
16
+ * Returns the authenticated user id from the underlying adapter, if it
17
+ * supports the concept (currently only RemoteTrackingAdapter). Returns
18
+ * null when unsupported (e.g. local file adapter) or when the adapter
19
+ * has not yet observed the id.
20
+ */
21
+ getCurrentUserId() {
22
+ const adapter = this.adapter;
23
+ return adapter.getCurrentUserId?.() ?? null;
24
+ }
25
+ /**
26
+ * Get all tracked issues
27
+ */
28
+ async getAll() {
29
+ return this.adapter.read();
30
+ }
31
+ /**
32
+ * Get a specific tracked issue by number
33
+ */
34
+ async getByNumber(issueNumber) {
35
+ const issues = await this.getAll();
36
+ return issues.find((i) => i.number === issueNumber) ?? null;
37
+ }
38
+ /**
39
+ * Check if an issue is tracked
40
+ */
41
+ async exists(issueNumber) {
42
+ const issue = await this.getByNumber(issueNumber);
43
+ return issue !== null;
44
+ }
45
+ /**
46
+ * Add a new issue to tracking
47
+ */
48
+ async add(issue) {
49
+ const issues = await this.getAll();
50
+ // Check if already tracked
51
+ const existing = issues.find((i) => i.number === issue.number);
52
+ if (existing) {
53
+ logger.warning(`Issue #${issue.number} is already tracked`);
54
+ return;
55
+ }
56
+ // Use adapter's add method if available (for remote tracking)
57
+ // Otherwise fall back to write method (for local file tracking)
58
+ if (typeof this.adapter.add === 'function') {
59
+ await this.adapter.add(issue);
60
+ }
61
+ else {
62
+ issues.push(issue);
63
+ await this.adapter.write(issues);
64
+ }
65
+ logger.success(`Added issue #${issue.number} to tracking`);
66
+ }
67
+ /**
68
+ * Remove an issue from tracking by number.
69
+ * WARNING: Matches the first issue with this number regardless of repo.
70
+ * Prefer removeByName() for cross-repo safety.
71
+ */
72
+ async remove(issueNumber) {
73
+ const issues = await this.getAll();
74
+ const issueToRemove = issues.find((i) => i.number === issueNumber);
75
+ if (!issueToRemove) {
76
+ logger.warning(`Issue #${issueNumber} is not tracked`);
77
+ return;
78
+ }
79
+ // Use adapter's remove method if available (for remote tracking)
80
+ // Otherwise fall back to write method (for local file tracking)
81
+ if (typeof this.adapter.remove === 'function') {
82
+ await this.adapter.remove(issueToRemove.name);
83
+ }
84
+ else {
85
+ const filtered = issues.filter((i) => i.number !== issueNumber);
86
+ await this.adapter.write(filtered);
87
+ }
88
+ logger.success(`Removed issue #${issueNumber} from tracking`);
89
+ }
90
+ /**
91
+ * Remove an issue from tracking by name (owner/repo#number).
92
+ * Safe for cross-repo scenarios where multiple repos may share the same issue number.
93
+ */
94
+ async removeByName(issueName) {
95
+ if (typeof this.adapter.remove === 'function') {
96
+ // Let the adapter handle lookup + removal in a single pass
97
+ // (avoids a redundant getAll() → listIssues() call)
98
+ await this.adapter.remove(issueName);
99
+ }
100
+ else {
101
+ const issues = await this.getAll();
102
+ const filtered = issues.filter((i) => i.name !== issueName);
103
+ if (filtered.length === issues.length) {
104
+ logger.warning(`Issue ${issueName} is not tracked`);
105
+ return;
106
+ }
107
+ await this.adapter.write(filtered);
108
+ }
109
+ logger.success(`Removed issue ${issueName} from tracking`);
110
+ }
111
+ /**
112
+ * Update a tracked issue
113
+ */
114
+ async update(issueNumber, updates) {
115
+ const issues = await this.getAll();
116
+ const index = issues.findIndex((i) => i.number === issueNumber);
117
+ if (index === -1) {
118
+ logger.error(`Issue #${issueNumber} is not tracked`);
119
+ return;
120
+ }
121
+ const existingIssue = issues[index];
122
+ if (!existingIssue)
123
+ return;
124
+ issues[index] = {
125
+ ...existingIssue,
126
+ ...updates,
127
+ updatedAt: new Date().toISOString(),
128
+ };
129
+ await this.adapter.write(issues);
130
+ logger.debug(`Updated issue #${issueNumber}`);
131
+ }
132
+ /**
133
+ * Update issue status
134
+ */
135
+ async updateStatus(issueNumber, status) {
136
+ await this.update(issueNumber, { trackingStatus: status });
137
+ }
138
+ /**
139
+ * Update issue priority
140
+ */
141
+ async updatePriority(issueNumber, priority) {
142
+ await this.update(issueNumber, { priority });
143
+ }
144
+ /**
145
+ * Update deployment status
146
+ */
147
+ async updateDeploymentStatus(issueNumber, status, timestamp) {
148
+ const updates = { deploymentStatus: status };
149
+ // Clear deploymentNotifiedAt when deployment succeeds (so future failures trigger notification)
150
+ if (status === 'success') {
151
+ updates.deploymentNotifiedAt = undefined;
152
+ }
153
+ await this.update(issueNumber, updates);
154
+ logger.debug(`Updated deployment status for #${issueNumber} to ${status}${timestamp ? ` at ${timestamp}` : ''}`);
155
+ }
156
+ /**
157
+ * Mark that Copilot was notified about deployment failure
158
+ */
159
+ async markDeploymentNotified(issueNumber, timestamp) {
160
+ await this.update(issueNumber, { deploymentNotifiedAt: timestamp });
161
+ logger.debug(`Marked deployment notification sent for #${issueNumber} at ${timestamp}`);
162
+ }
163
+ /**
164
+ * Get issues by status
165
+ */
166
+ async getByStatus(status) {
167
+ const issues = await this.getAll();
168
+ return issues.filter((i) => i.trackingStatus === status);
169
+ }
170
+ /**
171
+ * Get issues by priority
172
+ */
173
+ async getByPriority(priority) {
174
+ const issues = await this.getAll();
175
+ return issues.filter((i) => i.priority === priority);
176
+ }
177
+ /**
178
+ * Sort issues by criteria
179
+ */
180
+ sortIssues(issues, sortBy, direction = 'desc') {
181
+ const sorted = [...issues].sort((a, b) => {
182
+ let comparison = 0;
183
+ switch (sortBy) {
184
+ case 'created':
185
+ comparison =
186
+ new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime();
187
+ break;
188
+ case 'updated':
189
+ comparison =
190
+ new Date(a.updatedAt).getTime() - new Date(b.updatedAt).getTime();
191
+ break;
192
+ case 'number':
193
+ comparison = (a.number ?? 0) - (b.number ?? 0);
194
+ break;
195
+ case 'priority':
196
+ const priorityOrder = PROJECT_FIELD_OPTIONS.PRIORITY;
197
+ comparison =
198
+ priorityOrder.indexOf(a.priority) -
199
+ priorityOrder.indexOf(b.priority);
200
+ break;
201
+ }
202
+ return direction === 'desc' ? -comparison : comparison;
203
+ });
204
+ return sorted;
205
+ }
206
+ /**
207
+ * Clean up closed issues from GitHub
208
+ * Since we only track 4 active statuses, this checks GitHub for closed issues
209
+ */
210
+ async cleanClosed() {
211
+ // This method is kept for backwards compatibility with clean command
212
+ // It now checks GitHub issue state instead of tracking status
213
+ // The actual implementation is in the clean command which checks GitHub API
214
+ return 0;
215
+ }
216
+ }
217
+ /**
218
+ * File-based tracking adapter
219
+ * Open/Closed Principle: Can extend with new adapters
220
+ */
221
+ export class TrackingFileAdapter {
222
+ filePath;
223
+ constructor(filePath) {
224
+ this.filePath = filePath;
225
+ }
226
+ async read() {
227
+ if (!existsSync(this.filePath)) {
228
+ return [];
229
+ }
230
+ try {
231
+ const content = await readFile(this.filePath, 'utf-8');
232
+ const data = JSON.parse(content);
233
+ const validated = TrackedPlansSchema.parse(data);
234
+ return validated.plans;
235
+ }
236
+ catch (error) {
237
+ logger.warning(`Error reading tracking file: ${String(error)}`);
238
+ return [];
239
+ }
240
+ }
241
+ async write(issues) {
242
+ const data = {
243
+ version: '3.0',
244
+ lastUpdated: new Date().toISOString(),
245
+ plans: issues,
246
+ };
247
+ const validated = TrackedPlansSchema.parse(data);
248
+ // Ensure directory exists
249
+ const dir = dirname(this.filePath);
250
+ if (!existsSync(dir)) {
251
+ await mkdir(dir, { recursive: true });
252
+ }
253
+ await writeFile(this.filePath, JSON.stringify(validated, null, 2), 'utf-8');
254
+ }
255
+ }
256
+ //# sourceMappingURL=TrackingService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TrackingService.js","sourceRoot":"","sources":["../../../src/services/tracking/TrackingService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAChC,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAC/B,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAC/C,OAAO,EAGL,kBAAkB,EAGlB,qBAAqB,GACtB,MAAM,sBAAsB,CAAC;AAqB9B;;;GAGG;AACH,MAAM,OAAO,eAAe;IACN;IAApB,YAAoB,OAAyB;QAAzB,YAAO,GAAP,OAAO,CAAkB;IAAG,CAAC;IAEjD;;;;;OAKG;IACH,gBAAgB;QACd,MAAM,OAAO,GAAG,IAAI,CAAC,OAAqD,CAAC;QAC3E,OAAO,OAAO,CAAC,gBAAgB,EAAE,EAAE,IAAI,IAAI,CAAC;IAC9C,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,MAAM;QACV,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;IAC7B,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,WAAW,CAAC,WAAmB;QACnC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC;QACnC,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,WAAW,CAAC,IAAI,IAAI,CAAC;IAC9D,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,MAAM,CAAC,WAAmB;QAC9B,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC;QAClD,OAAO,KAAK,KAAK,IAAI,CAAC;IACxB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,GAAG,CAAC,KAAmB;QAC3B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC;QAEnC,2BAA2B;QAC3B,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM,CAAC,CAAC;QAC/D,IAAI,QAAQ,EAAE,CAAC;YACb,MAAM,CAAC,OAAO,CAAC,UAAU,KAAK,CAAC,MAAM,qBAAqB,CAAC,CAAC;YAC5D,OAAO;QACT,CAAC;QAED,8DAA8D;QAC9D,gEAAgE;QAChE,IAAI,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,KAAK,UAAU,EAAE,CAAC;YAC3C,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAChC,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACnB,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACnC,CAAC;QAED,MAAM,CAAC,OAAO,CAAC,gBAAgB,KAAK,CAAC,MAAM,cAAc,CAAC,CAAC;IAC7D,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,MAAM,CAAC,WAAmB;QAC9B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC;QACnC,MAAM,aAAa,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC;QAEnE,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,MAAM,CAAC,OAAO,CAAC,UAAU,WAAW,iBAAiB,CAAC,CAAC;YACvD,OAAO;QACT,CAAC;QAED,iEAAiE;QACjE,gEAAgE;QAChE,IAAI,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;YAC9C,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;QAChD,CAAC;aAAM,CAAC;YACN,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC;YAChE,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QACrC,CAAC;QAED,MAAM,CAAC,OAAO,CAAC,kBAAkB,WAAW,gBAAgB,CAAC,CAAC;IAChE,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,YAAY,CAAC,SAAiB;QAClC,IAAI,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;YAC9C,2DAA2D;YAC3D,oDAAoD;YACpD,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QACvC,CAAC;aAAM,CAAC;YACN,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC;YACnC,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC;YAC5D,IAAI,QAAQ,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,EAAE,CAAC;gBACtC,MAAM,CAAC,OAAO,CAAC,SAAS,SAAS,iBAAiB,CAAC,CAAC;gBACpD,OAAO;YACT,CAAC;YACD,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QACrC,CAAC;QAED,MAAM,CAAC,OAAO,CAAC,iBAAiB,SAAS,gBAAgB,CAAC,CAAC;IAC7D,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,MAAM,CACV,WAAmB,EACnB,OAA8B;QAE9B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC;QACnC,MAAM,KAAK,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC;QAEhE,IAAI,KAAK,KAAK,CAAC,CAAC,EAAE,CAAC;YACjB,MAAM,CAAC,KAAK,CAAC,UAAU,WAAW,iBAAiB,CAAC,CAAC;YACrD,OAAO;QACT,CAAC;QAED,MAAM,aAAa,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;QACpC,IAAI,CAAC,aAAa;YAAE,OAAO;QAE3B,MAAM,CAAC,KAAK,CAAC,GAAG;YACd,GAAG,aAAa;YAChB,GAAG,OAAO;YACV,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACpC,CAAC;QAEF,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACjC,MAAM,CAAC,KAAK,CAAC,kBAAkB,WAAW,EAAE,CAAC,CAAC;IAChD,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,YAAY,CAAC,WAAmB,EAAE,MAAmB;QACzD,MAAM,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC,CAAC;IAC7D,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,cAAc,CAAC,WAAmB,EAAE,QAAkB;QAC1D,MAAM,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;IAC/C,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,sBAAsB,CAC1B,WAAmB,EACnB,MAAwC,EACxC,SAAkB;QAElB,MAAM,OAAO,GAA0B,EAAE,gBAAgB,EAAE,MAAM,EAAE,CAAC;QAEpE,gGAAgG;QAChG,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,OAAO,CAAC,oBAAoB,GAAG,SAAS,CAAC;QAC3C,CAAC;QAED,MAAM,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QACxC,MAAM,CAAC,KAAK,CACV,kCAAkC,WAAW,OAAO,MAAM,GACxD,SAAS,CAAC,CAAC,CAAC,OAAO,SAAS,EAAE,CAAC,CAAC,CAAC,EACnC,EAAE,CACH,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,sBAAsB,CAC1B,WAAmB,EACnB,SAAiB;QAEjB,MAAM,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,oBAAoB,EAAE,SAAS,EAAE,CAAC,CAAC;QACpE,MAAM,CAAC,KAAK,CACV,4CAA4C,WAAW,OAAO,SAAS,EAAE,CAC1E,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,WAAW,CAAC,MAAmB;QACnC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC;QACnC,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,cAAc,KAAK,MAAM,CAAC,CAAC;IAC3D,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,aAAa,CAAC,QAAkB;QACpC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC;QACnC,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC;IACvD,CAAC;IAED;;OAEG;IACH,UAAU,CACR,MAAsB,EACtB,MAAqD,EACrD,YAA4B,MAAM;QAElC,MAAM,MAAM,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YACvC,IAAI,UAAU,GAAG,CAAC,CAAC;YAEnB,QAAQ,MAAM,EAAE,CAAC;gBACf,KAAK,SAAS;oBACZ,UAAU;wBACR,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CAAC;oBACpE,MAAM;gBACR,KAAK,SAAS;oBACZ,UAAU;wBACR,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CAAC;oBACpE,MAAM;gBACR,KAAK,QAAQ;oBACX,UAAU,GAAG,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC;oBAC/C,MAAM;gBACR,KAAK,UAAU;oBACb,MAAM,aAAa,GAAG,qBAAqB,CAAC,QAAQ,CAAC;oBACrD,UAAU;wBACR,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC;4BACjC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;oBACpC,MAAM;YACV,CAAC;YAED,OAAO,SAAS,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC;QACzD,CAAC,CAAC,CAAC;QAEH,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,WAAW;QACf,qEAAqE;QACrE,8DAA8D;QAC9D,4EAA4E;QAC5E,OAAO,CAAC,CAAC;IACX,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,OAAO,mBAAmB;IACV;IAApB,YAAoB,QAAgB;QAAhB,aAAQ,GAAR,QAAQ,CAAQ;IAAG,CAAC;IAExC,KAAK,CAAC,IAAI;QACR,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC/B,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YACvD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAiB,CAAC;YACjD,MAAM,SAAS,GAAG,kBAAkB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACjD,OAAO,SAAS,CAAC,KAAK,CAAC;QACzB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,OAAO,CAAC,gCAAgC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAChE,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,MAAsB;QAChC,MAAM,IAAI,GAAiB;YACzB,OAAO,EAAE,KAAK;YACd,WAAW,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACrC,KAAK,EAAE,MAAM;SACd,CAAC;QAEF,MAAM,SAAS,GAAG,kBAAkB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAEjD,0BAA0B;QAC1B,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACnC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACrB,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACxC,CAAC;QAED,MAAM,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IAC9E,CAAC;CACF"}
@@ -0,0 +1,20 @@
1
+ import type { Config } from '../../types/index.js';
2
+ import type { TrackingService } from './TrackingService.js';
3
+ /**
4
+ * Service for managing untracked assigned issues
5
+ * Helps users track issues they're assigned to but didn't create
6
+ */
7
+ export declare class UntrackedIssuesService {
8
+ /**
9
+ * Find issues assigned to user but not created by them and not tracked
10
+ */
11
+ findUntrackedAssignedIssues(trackingService: TrackingService): Promise<Array<{
12
+ number: number;
13
+ title: string;
14
+ }>>;
15
+ /**
16
+ * Prompt user to add untracked assigned issues to tracking
17
+ */
18
+ promptToAddUntrackedAssignedIssues(config: Config, trackingService: TrackingService): Promise<void>;
19
+ }
20
+ //# sourceMappingURL=UntrackedIssuesService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UntrackedIssuesService.d.ts","sourceRoot":"","sources":["../../../src/services/tracking/UntrackedIssuesService.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAA+B,MAAM,sBAAsB,CAAC;AAEhF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE5D;;;GAGG;AACH,qBAAa,sBAAsB;IACjC;;OAEG;IACG,2BAA2B,CAC/B,eAAe,EAAE,eAAe,GAC/B,OAAO,CAAC,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IA8FpD;;OAEG;IACG,kCAAkC,CACtC,MAAM,EAAE,MAAM,EACd,eAAe,EAAE,eAAe,GAC/B,OAAO,CAAC,IAAI,CAAC;CAqGjB"}
@@ -0,0 +1,148 @@
1
+ import { logger } from '../../utils/logger.js';
2
+ import { IssueService } from '../github/IssueService.js';
3
+ import { getRepoInfo, ghGraphQL } from '../../utils/github-cli.js';
4
+ import { confirm, input, selectPriority } from '../../utils/prompts.js';
5
+ import { STATUS } from '../../types/common.schema.js';
6
+ /**
7
+ * Service for managing untracked assigned issues
8
+ * Helps users track issues they're assigned to but didn't create
9
+ */
10
+ export class UntrackedIssuesService {
11
+ /**
12
+ * Find issues assigned to user but not created by them and not tracked
13
+ */
14
+ async findUntrackedAssignedIssues(trackingService) {
15
+ try {
16
+ const repo = await getRepoInfo();
17
+ const trackedIssues = await trackingService.getAll();
18
+ const trackedNumbers = new Set(trackedIssues.map((i) => i.number));
19
+ // GraphQL query to fetch open issues assigned to the current user
20
+ // First get viewer login, then use search to find issues assigned to them
21
+ const viewerQuery = `
22
+ query {
23
+ viewer {
24
+ login
25
+ }
26
+ }
27
+ `;
28
+ const viewerResponse = await ghGraphQL(viewerQuery, {});
29
+ const username = viewerResponse.data.viewer.login;
30
+ // Now search for issues assigned to this user
31
+ const query = `
32
+ query($owner: String!, $name: String!, $assignee: String!) {
33
+ repository(owner: $owner, name: $name) {
34
+ issues(first: 100, states: OPEN, filterBy: {assignee: $assignee}, orderBy: {field: UPDATED_AT, direction: DESC}) {
35
+ nodes {
36
+ number
37
+ title
38
+ author {
39
+ login
40
+ }
41
+ assignees(first: 10) {
42
+ nodes {
43
+ login
44
+ }
45
+ }
46
+ }
47
+ }
48
+ }
49
+ }
50
+ `;
51
+ const response = await ghGraphQL(query, {
52
+ owner: repo.owner,
53
+ name: repo.name,
54
+ assignee: username,
55
+ });
56
+ const untrackedAssigned = [];
57
+ for (const issue of response.data.repository.issues.nodes) {
58
+ // Skip if already tracked
59
+ if (trackedNumbers.has(issue.number))
60
+ continue;
61
+ // Check if assigned to user
62
+ const isAssigned = issue.assignees.nodes.some((assignee) => assignee.login === username);
63
+ // Include all assigned issues (regardless of author)
64
+ if (isAssigned) {
65
+ untrackedAssigned.push({
66
+ number: issue.number,
67
+ title: issue.title,
68
+ });
69
+ }
70
+ }
71
+ return untrackedAssigned;
72
+ }
73
+ catch (error) {
74
+ logger.debug(`Error finding untracked assigned issues: ${error instanceof Error ? error.message : String(error)}`);
75
+ return [];
76
+ }
77
+ }
78
+ /**
79
+ * Prompt user to add untracked assigned issues to tracking
80
+ */
81
+ async promptToAddUntrackedAssignedIssues(config, trackingService) {
82
+ const untrackedAssigned = await this.findUntrackedAssignedIssues(trackingService);
83
+ if (untrackedAssigned.length === 0) {
84
+ return;
85
+ }
86
+ logger.blank();
87
+ logger.warning(`Found ${untrackedAssigned.length} issue(s) assigned to you that are not being tracked:`);
88
+ logger.blank();
89
+ const repo = await getRepoInfo();
90
+ untrackedAssigned.forEach((issue, index) => {
91
+ logger.info(` ${index + 1}) Issue ${repo.owner}/${repo.name}#${issue.number}: ${issue.title}`);
92
+ });
93
+ logger.blank();
94
+ const shouldAdd = await confirm('Would you like to add these to tracking?', false);
95
+ if (!shouldAdd) {
96
+ logger.info("Skipped adding assigned issues. You can add them later using 'hublaunch track'.");
97
+ logger.blank();
98
+ return;
99
+ }
100
+ // Add each issue to tracking
101
+ const issueService = new IssueService();
102
+ let addedCount = 0;
103
+ for (const untrackedIssue of untrackedAssigned) {
104
+ try {
105
+ logger.blank();
106
+ logger.info(`Issue #${untrackedIssue.number}: ${untrackedIssue.title}`);
107
+ const issueName = await input("Enter a short name to reference this issue (e.g., 'feature-x' or 'bug-fix-y'):");
108
+ if (!issueName || issueName.trim() === '') {
109
+ logger.warning('Skipped - issue name cannot be empty');
110
+ continue;
111
+ }
112
+ // Select priority
113
+ const priorityLevels = config.priorityLevels ?? [
114
+ { name: 'Critical', emoji: '🔴', color: 'red' },
115
+ { name: 'High', emoji: '🟠', color: 'orange' },
116
+ { name: 'Medium', emoji: '🟡', color: 'yellow' },
117
+ { name: 'Low', emoji: '🟢', color: 'green' },
118
+ { name: 'Minimal', emoji: '⚪', color: 'gray' },
119
+ ];
120
+ const priority = await selectPriority('Select priority for this issue:', priorityLevels);
121
+ // Get full issue details
122
+ const issue = await issueService.get(untrackedIssue.number);
123
+ const trackedIssue = {
124
+ name: issueName,
125
+ number: issue.number,
126
+ planPath: '',
127
+ trackingStatus: STATUS.UNASSIGNED,
128
+ priority: priority,
129
+ createdAt: issue.createdAt,
130
+ updatedAt: issue.updatedAt,
131
+ assignees: issue.assignees,
132
+ };
133
+ await trackingService.add(trackedIssue);
134
+ addedCount++;
135
+ logger.success(`Added issue #${issue.number} to tracking`);
136
+ }
137
+ catch (error) {
138
+ logger.warning(`Could not add issue #${untrackedIssue.number}: ${error instanceof Error ? error.message : String(error)}`);
139
+ }
140
+ }
141
+ logger.blank();
142
+ if (addedCount > 0) {
143
+ logger.success(`✓ Added ${addedCount} issue(s) to tracking`);
144
+ }
145
+ logger.blank();
146
+ }
147
+ }
148
+ //# sourceMappingURL=UntrackedIssuesService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UntrackedIssuesService.js","sourceRoot":"","sources":["../../../src/services/tracking/UntrackedIssuesService.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Idempotent. Renames `<dir>/trackedIssues.json` to
3
+ * `<dir>/trackedPlans.json` if the new file does not already exist, then
4
+ * rewrites the JSON payload to the new schema (renames
5
+ * `repoOwner`/`repoName` fields, drops `job*` fields, sets `version: '3.0'`).
6
+ *
7
+ * Safe to call once per process. No-op when neither file is present, or
8
+ * when the user configured a custom (non-default) `trackingFile` name.
9
+ */
10
+ export declare function migrateLocalTrackingFile(configuredFilePath: string): Promise<void>;
11
+ export declare function transformLegacyTrackingJson(input: unknown): {
12
+ version: string;
13
+ lastUpdated: string;
14
+ plans: Array<Record<string, unknown>>;
15
+ };
16
+ //# sourceMappingURL=local-file-migration.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-file-migration.d.ts","sourceRoot":"","sources":["../../../src/services/tracking/local-file-migration.ts"],"names":[],"mappings":"AAQA;;;;;;;;GAQG;AACH,wBAAsB,wBAAwB,CAC5C,kBAAkB,EAAE,MAAM,GACzB,OAAO,CAAC,IAAI,CAAC,CAgDf;AASD,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,OAAO,GAAG;IAC3D,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACvC,CAiCA"}
@@ -0,0 +1,86 @@
1
+ import { existsSync } from 'node:fs';
2
+ import { readFile, rename, writeFile } from 'node:fs/promises';
3
+ import { dirname, join } from 'node:path';
4
+ import { logger } from '../../utils/logger.js';
5
+ const LEGACY_DEFAULT = 'trackedIssues.json';
6
+ const NEW_DEFAULT = 'trackedPlans.json';
7
+ /**
8
+ * Idempotent. Renames `<dir>/trackedIssues.json` to
9
+ * `<dir>/trackedPlans.json` if the new file does not already exist, then
10
+ * rewrites the JSON payload to the new schema (renames
11
+ * `repoOwner`/`repoName` fields, drops `job*` fields, sets `version: '3.0'`).
12
+ *
13
+ * Safe to call once per process. No-op when neither file is present, or
14
+ * when the user configured a custom (non-default) `trackingFile` name.
15
+ */
16
+ export async function migrateLocalTrackingFile(configuredFilePath) {
17
+ const dir = dirname(configuredFilePath);
18
+ const legacyPath = join(dir, LEGACY_DEFAULT);
19
+ const newPath = join(dir, NEW_DEFAULT);
20
+ // Honor a non-default configured path: only migrate if user is on
21
+ // the new default name AND the legacy default file is present.
22
+ if (!configuredFilePath.endsWith(NEW_DEFAULT) || !existsSync(legacyPath)) {
23
+ return;
24
+ }
25
+ if (existsSync(newPath)) {
26
+ logger.warning(`Both trackedIssues.json and trackedPlans.json exist in ${dir}. ` +
27
+ `Using trackedPlans.json; please remove the legacy file manually.`);
28
+ return;
29
+ }
30
+ // Rename
31
+ await rename(legacyPath, newPath);
32
+ // Transform JSON
33
+ let raw;
34
+ try {
35
+ raw = await readFile(newPath, 'utf-8');
36
+ }
37
+ catch {
38
+ logger.warning(`Renamed ${LEGACY_DEFAULT} → ${NEW_DEFAULT} but could not read content.`);
39
+ return;
40
+ }
41
+ let parsed;
42
+ try {
43
+ parsed = JSON.parse(raw);
44
+ }
45
+ catch {
46
+ logger.warning(`${NEW_DEFAULT} after rename is not valid JSON; leaving untouched.`);
47
+ return;
48
+ }
49
+ const migrated = transformLegacyTrackingJson(parsed);
50
+ await writeFile(newPath, JSON.stringify(migrated, null, 2) + '\n', 'utf-8');
51
+ logger.info(`Migrated local tracking file: ${LEGACY_DEFAULT} → ${NEW_DEFAULT}`);
52
+ }
53
+ export function transformLegacyTrackingJson(input) {
54
+ const doc = (input ?? {});
55
+ const items = doc.plans ?? doc.issues ?? [];
56
+ const plans = items.map((row) => {
57
+ const out = { ...row };
58
+ if ('repoOwner' in out) {
59
+ out.projectOwner = out.repoOwner;
60
+ delete out.repoOwner;
61
+ }
62
+ if ('repoName' in out) {
63
+ out.projectName = out.repoName;
64
+ delete out.repoName;
65
+ }
66
+ for (const k of [
67
+ 'jobStatus',
68
+ 'jobPid',
69
+ 'jobStartedAt',
70
+ 'jobCompletedAt',
71
+ 'jobExitCode',
72
+ 'jobOutputPath',
73
+ 'jobLogPath',
74
+ 'jobStartedBy',
75
+ ]) {
76
+ delete out[k];
77
+ }
78
+ return out;
79
+ });
80
+ return {
81
+ version: '3.0',
82
+ lastUpdated: doc.lastUpdated ?? new Date().toISOString(),
83
+ plans,
84
+ };
85
+ }
86
+ //# sourceMappingURL=local-file-migration.js.map