@proletariat/cli 0.3.16 → 0.3.18

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 (338) hide show
  1. package/dist/commands/action/create.d.ts +1 -0
  2. package/dist/commands/action/create.js +74 -38
  3. package/dist/commands/action/delete.d.ts +1 -0
  4. package/dist/commands/action/delete.js +23 -24
  5. package/dist/commands/action/index.d.ts +1 -0
  6. package/dist/commands/action/index.js +5 -10
  7. package/dist/commands/action/list.d.ts +1 -0
  8. package/dist/commands/action/list.js +3 -1
  9. package/dist/commands/action/run.d.ts +1 -0
  10. package/dist/commands/action/run.js +44 -32
  11. package/dist/commands/action/show.d.ts +2 -0
  12. package/dist/commands/action/update.d.ts +1 -0
  13. package/dist/commands/action/update.js +80 -39
  14. package/dist/commands/agent/auth.d.ts +2 -0
  15. package/dist/commands/agent/auth.js +44 -3
  16. package/dist/commands/agent/discover.d.ts +2 -0
  17. package/dist/commands/agent/discover.js +35 -3
  18. package/dist/commands/agent/index.d.ts +1 -0
  19. package/dist/commands/agent/index.js +25 -45
  20. package/dist/commands/agent/list.d.ts +8 -3
  21. package/dist/commands/agent/list.js +16 -29
  22. package/dist/commands/agent/login.d.ts +1 -0
  23. package/dist/commands/agent/login.js +14 -32
  24. package/dist/commands/agent/rebuild.d.ts +1 -0
  25. package/dist/commands/agent/rebuild.js +2 -2
  26. package/dist/commands/agent/remove.d.ts +17 -0
  27. package/dist/commands/agent/remove.js +144 -0
  28. package/dist/commands/agent/restart.d.ts +1 -0
  29. package/dist/commands/agent/restart.js +2 -2
  30. package/dist/commands/agent/shell.d.ts +1 -0
  31. package/dist/commands/agent/shell.js +63 -76
  32. package/dist/commands/agent/staff/add.d.ts +1 -0
  33. package/dist/commands/agent/staff/add.js +7 -1
  34. package/dist/commands/agent/staff/index.d.ts +1 -0
  35. package/dist/commands/agent/staff/index.js +5 -4
  36. package/dist/commands/agent/staff/remove.d.ts +1 -0
  37. package/dist/commands/agent/status.d.ts +1 -0
  38. package/dist/commands/agent/status.js +11 -23
  39. package/dist/commands/agent/temp/cleanup.d.ts +1 -0
  40. package/dist/commands/agent/temp/index.d.ts +1 -0
  41. package/dist/commands/agent/temp/index.js +4 -3
  42. package/dist/commands/agent/themes/index.d.ts +1 -0
  43. package/dist/commands/agent/themes/index.js +9 -3
  44. package/dist/commands/agent/themes/set.d.ts +1 -0
  45. package/dist/commands/agent/themes/set.js +7 -1
  46. package/dist/commands/agent/visit.d.ts +1 -0
  47. package/dist/commands/agent/visit.js +11 -23
  48. package/dist/commands/autocomplete/setup.d.ts +11 -0
  49. package/dist/commands/autocomplete/setup.js +113 -8
  50. package/dist/commands/board/index.d.ts +4 -0
  51. package/dist/commands/board/index.js +32 -30
  52. package/dist/commands/board/watch.d.ts +2 -0
  53. package/dist/commands/branch/create.d.ts +1 -0
  54. package/dist/commands/branch/create.js +33 -41
  55. package/dist/commands/branch/index.d.ts +1 -0
  56. package/dist/commands/branch/list.d.ts +2 -0
  57. package/dist/commands/branch/validate.d.ts +2 -0
  58. package/dist/commands/branch/where.d.ts +1 -0
  59. package/dist/commands/claude.d.ts +6 -0
  60. package/dist/commands/claude.js +166 -116
  61. package/dist/commands/commit.d.ts +6 -0
  62. package/dist/commands/commit.js +68 -73
  63. package/dist/commands/config/index.d.ts +13 -0
  64. package/dist/commands/config/index.js +142 -98
  65. package/dist/commands/docker/clean.d.ts +2 -1
  66. package/dist/commands/docker/clean.js +20 -29
  67. package/dist/commands/docker/index.d.ts +1 -0
  68. package/dist/commands/docker/index.js +37 -41
  69. package/dist/commands/docker/prune.d.ts +2 -1
  70. package/dist/commands/docker/prune.js +20 -27
  71. package/dist/commands/docker/restart.d.ts +2 -1
  72. package/dist/commands/docker/restart.js +20 -29
  73. package/dist/commands/docker/stop.d.ts +2 -1
  74. package/dist/commands/docker/stop.js +20 -29
  75. package/dist/commands/epic/activate.d.ts +1 -0
  76. package/dist/commands/epic/archive.d.ts +1 -0
  77. package/dist/commands/epic/create.d.ts +1 -0
  78. package/dist/commands/epic/index.d.ts +1 -0
  79. package/dist/commands/epic/link/block.d.ts +1 -0
  80. package/dist/commands/epic/link/duplicates.d.ts +1 -0
  81. package/dist/commands/epic/link/index.d.ts +1 -0
  82. package/dist/commands/epic/link/relates.d.ts +1 -0
  83. package/dist/commands/epic/link/remove.d.ts +1 -0
  84. package/dist/commands/epic/list.d.ts +2 -0
  85. package/dist/commands/epic/move.d.ts +1 -0
  86. package/dist/commands/epic/progress.d.ts +1 -0
  87. package/dist/commands/epic/project.d.ts +1 -0
  88. package/dist/commands/epic/reorder.d.ts +1 -0
  89. package/dist/commands/epic/spec.d.ts +1 -0
  90. package/dist/commands/epic/ticket.d.ts +1 -0
  91. package/dist/commands/epic/view.d.ts +1 -0
  92. package/dist/commands/execution/index.d.ts +1 -0
  93. package/dist/commands/execution/index.js +9 -25
  94. package/dist/commands/execution/list.d.ts +2 -0
  95. package/dist/commands/execution/logs.d.ts +1 -0
  96. package/dist/commands/execution/logs.js +6 -16
  97. package/dist/commands/execution/stop.d.ts +1 -0
  98. package/dist/commands/execution/stop.js +4 -15
  99. package/dist/commands/gh/index.d.ts +1 -0
  100. package/dist/commands/gh/index.js +27 -27
  101. package/dist/commands/gh/login.d.ts +4 -0
  102. package/dist/commands/gh/login.js +31 -0
  103. package/dist/commands/gh/status.d.ts +4 -0
  104. package/dist/commands/gh/status.js +27 -4
  105. package/dist/commands/gh/token.d.ts +4 -0
  106. package/dist/commands/gh/token.js +49 -5
  107. package/dist/commands/phase/create.d.ts +1 -1
  108. package/dist/commands/phase/create.js +116 -74
  109. package/dist/commands/phase/delete.d.ts +1 -0
  110. package/dist/commands/phase/delete.js +23 -22
  111. package/dist/commands/phase/list.d.ts +1 -0
  112. package/dist/commands/phase/list.js +3 -5
  113. package/dist/commands/phase/move.d.ts +1 -0
  114. package/dist/commands/phase/move.js +39 -39
  115. package/dist/commands/phase/template/apply.d.ts +1 -0
  116. package/dist/commands/phase/template/create.d.ts +2 -0
  117. package/dist/commands/phase/template/delete.d.ts +1 -0
  118. package/dist/commands/phase/template/index.d.ts +1 -0
  119. package/dist/commands/phase/template/list.d.ts +1 -0
  120. package/dist/commands/phase/template/update.d.ts +2 -0
  121. package/dist/commands/phase/update.d.ts +1 -1
  122. package/dist/commands/phase/update.js +89 -55
  123. package/dist/commands/pmo/init.d.ts +2 -0
  124. package/dist/commands/pmo/init.js +84 -22
  125. package/dist/commands/pr/create.d.ts +12 -3
  126. package/dist/commands/pr/create.js +130 -147
  127. package/dist/commands/pr/index.d.ts +6 -3
  128. package/dist/commands/pr/index.js +41 -39
  129. package/dist/commands/pr/link.d.ts +7 -3
  130. package/dist/commands/pr/link.js +126 -150
  131. package/dist/commands/pr/status.d.ts +6 -3
  132. package/dist/commands/pr/status.js +101 -126
  133. package/dist/commands/project/archive.d.ts +1 -0
  134. package/dist/commands/project/archive.js +15 -20
  135. package/dist/commands/project/create.d.ts +1 -0
  136. package/dist/commands/project/create.js +13 -5
  137. package/dist/commands/project/delete.d.ts +1 -0
  138. package/dist/commands/project/delete.js +14 -28
  139. package/dist/commands/project/index.d.ts +1 -0
  140. package/dist/commands/project/index.js +0 -5
  141. package/dist/commands/project/list.d.ts +2 -0
  142. package/dist/commands/project/list.js +21 -3
  143. package/dist/commands/project/spec.d.ts +1 -0
  144. package/dist/commands/project/spec.js +17 -23
  145. package/dist/commands/project/unarchive.d.ts +2 -0
  146. package/dist/commands/project/unarchive.js +21 -2
  147. package/dist/commands/project/view.d.ts +1 -0
  148. package/dist/commands/project/view.js +34 -22
  149. package/dist/commands/repo/add.d.ts +2 -0
  150. package/dist/commands/repo/add.js +44 -1
  151. package/dist/commands/repo/index.d.ts +1 -0
  152. package/dist/commands/repo/index.js +20 -38
  153. package/dist/commands/repo/list.d.ts +2 -0
  154. package/dist/commands/repo/remove.d.ts +1 -0
  155. package/dist/commands/repo/remove.js +45 -63
  156. package/dist/commands/repo/view.d.ts +2 -0
  157. package/dist/commands/repo/view.js +30 -5
  158. package/dist/commands/roadmap/add-project.d.ts +1 -0
  159. package/dist/commands/roadmap/create.d.ts +1 -0
  160. package/dist/commands/roadmap/delete.d.ts +1 -0
  161. package/dist/commands/roadmap/generate.d.ts +1 -0
  162. package/dist/commands/roadmap/index.d.ts +1 -0
  163. package/dist/commands/roadmap/list.d.ts +2 -0
  164. package/dist/commands/roadmap/remove-project.d.ts +1 -0
  165. package/dist/commands/roadmap/reorder.d.ts +1 -0
  166. package/dist/commands/roadmap/update.d.ts +1 -0
  167. package/dist/commands/roadmap/view.d.ts +1 -0
  168. package/dist/commands/session/attach.d.ts +1 -0
  169. package/dist/commands/session/index.d.ts +1 -0
  170. package/dist/commands/session/index.js +8 -25
  171. package/dist/commands/session/list.d.ts +2 -0
  172. package/dist/commands/spec/create.d.ts +1 -1
  173. package/dist/commands/spec/create.js +64 -65
  174. package/dist/commands/spec/index.d.ts +1 -0
  175. package/dist/commands/spec/index.js +36 -22
  176. package/dist/commands/spec/link/depends.d.ts +1 -0
  177. package/dist/commands/spec/link/depends.js +6 -6
  178. package/dist/commands/spec/link/duplicates.d.ts +1 -0
  179. package/dist/commands/spec/link/duplicates.js +6 -6
  180. package/dist/commands/spec/link/index.d.ts +2 -1
  181. package/dist/commands/spec/link/index.js +0 -4
  182. package/dist/commands/spec/link/relates.d.ts +1 -0
  183. package/dist/commands/spec/link/relates.js +6 -6
  184. package/dist/commands/spec/link/remove.d.ts +2 -1
  185. package/dist/commands/spec/link/remove.js +6 -6
  186. package/dist/commands/spec/list.d.ts +2 -0
  187. package/dist/commands/spec/list.js +25 -0
  188. package/dist/commands/spec/plan.d.ts +2 -1
  189. package/dist/commands/spec/plan.js +19 -26
  190. package/dist/commands/spec/ticket.d.ts +2 -1
  191. package/dist/commands/spec/ticket.js +48 -34
  192. package/dist/commands/spec/view.d.ts +2 -1
  193. package/dist/commands/spec/view.js +25 -16
  194. package/dist/commands/status/create.d.ts +1 -1
  195. package/dist/commands/status/create.js +80 -64
  196. package/dist/commands/status/delete.d.ts +2 -1
  197. package/dist/commands/status/delete.js +26 -22
  198. package/dist/commands/status/index.d.ts +1 -0
  199. package/dist/commands/status/index.js +26 -19
  200. package/dist/commands/status/list.d.ts +1 -0
  201. package/dist/commands/status/list.js +12 -7
  202. package/dist/commands/status/move.d.ts +2 -1
  203. package/dist/commands/status/move.js +62 -61
  204. package/dist/commands/status/update.d.ts +2 -2
  205. package/dist/commands/status/update.js +110 -77
  206. package/dist/commands/template/delete.d.ts +1 -0
  207. package/dist/commands/template/delete.js +47 -48
  208. package/dist/commands/template/index.d.ts +1 -0
  209. package/dist/commands/template/index.js +26 -33
  210. package/dist/commands/template/list.d.ts +1 -0
  211. package/dist/commands/template/phase/create.d.ts +1 -0
  212. package/dist/commands/template/phase/create.js +6 -0
  213. package/dist/commands/template/phase/index.d.ts +1 -0
  214. package/dist/commands/template/phase/index.js +27 -26
  215. package/dist/commands/template/phase/update.d.ts +1 -0
  216. package/dist/commands/template/phase/update.js +6 -0
  217. package/dist/commands/template/ticket/index.d.ts +1 -0
  218. package/dist/commands/template/ticket/index.js +27 -26
  219. package/dist/commands/template/ticket/save.d.ts +1 -0
  220. package/dist/commands/template/ticket/save.js +6 -0
  221. package/dist/commands/terminal/title.d.ts +26 -0
  222. package/dist/commands/terminal/title.js +37 -3
  223. package/dist/commands/ticket/bulk.d.ts +1 -0
  224. package/dist/commands/ticket/complete.d.ts +1 -0
  225. package/dist/commands/ticket/complete.js +18 -14
  226. package/dist/commands/ticket/create.d.ts +1 -0
  227. package/dist/commands/ticket/create.js +45 -41
  228. package/dist/commands/ticket/delete.d.ts +1 -0
  229. package/dist/commands/ticket/delete.js +1 -1
  230. package/dist/commands/ticket/edit.d.ts +1 -0
  231. package/dist/commands/ticket/edit.js +1 -1
  232. package/dist/commands/ticket/epic.d.ts +1 -0
  233. package/dist/commands/ticket/epic.js +2 -2
  234. package/dist/commands/ticket/index.d.ts +1 -0
  235. package/dist/commands/ticket/link/block.d.ts +1 -0
  236. package/dist/commands/ticket/link/block.js +1 -1
  237. package/dist/commands/ticket/link/duplicates.d.ts +1 -0
  238. package/dist/commands/ticket/link/duplicates.js +1 -1
  239. package/dist/commands/ticket/link/index.d.ts +1 -0
  240. package/dist/commands/ticket/link/index.js +9 -8
  241. package/dist/commands/ticket/link/relates.d.ts +1 -0
  242. package/dist/commands/ticket/link/relates.js +1 -1
  243. package/dist/commands/ticket/link/remove.d.ts +1 -0
  244. package/dist/commands/ticket/link/remove.js +1 -1
  245. package/dist/commands/ticket/list.d.ts +2 -0
  246. package/dist/commands/ticket/move.d.ts +1 -0
  247. package/dist/commands/ticket/move.js +27 -19
  248. package/dist/commands/ticket/project.d.ts +1 -0
  249. package/dist/commands/ticket/project.js +3 -3
  250. package/dist/commands/ticket/reassign.d.ts +1 -0
  251. package/dist/commands/ticket/reassign.js +1 -1
  252. package/dist/commands/ticket/spec.d.ts +1 -0
  253. package/dist/commands/ticket/spec.js +3 -3
  254. package/dist/commands/ticket/status.d.ts +1 -0
  255. package/dist/commands/ticket/status.js +1 -1
  256. package/dist/commands/ticket/template/apply.d.ts +1 -0
  257. package/dist/commands/ticket/template/create.d.ts +2 -0
  258. package/dist/commands/ticket/template/delete.d.ts +1 -0
  259. package/dist/commands/ticket/template/index.d.ts +1 -0
  260. package/dist/commands/ticket/template/list.d.ts +1 -0
  261. package/dist/commands/ticket/template/save.d.ts +2 -0
  262. package/dist/commands/ticket/update.d.ts +1 -0
  263. package/dist/commands/ticket/update.js +1 -1
  264. package/dist/commands/ticket/view.d.ts +1 -0
  265. package/dist/commands/ticket/view.js +1 -1
  266. package/dist/commands/work/complete.d.ts +1 -0
  267. package/dist/commands/work/index.d.ts +1 -0
  268. package/dist/commands/work/ready.d.ts +1 -0
  269. package/dist/commands/work/revise.d.ts +1 -0
  270. package/dist/commands/work/spawn-all.d.ts +2 -0
  271. package/dist/commands/work/spawn-all.js +11 -4
  272. package/dist/commands/work/spawn.d.ts +1 -0
  273. package/dist/commands/work/spawn.js +261 -166
  274. package/dist/commands/work/start.d.ts +1 -0
  275. package/dist/commands/work/start.js +270 -189
  276. package/dist/commands/work/watch.d.ts +1 -0
  277. package/dist/commands/work/watch.js +63 -58
  278. package/dist/commands/workflow/create.d.ts +1 -0
  279. package/dist/commands/workflow/create.js +2 -4
  280. package/dist/commands/workflow/delete.d.ts +1 -0
  281. package/dist/commands/workflow/delete.js +21 -33
  282. package/dist/commands/workflow/index.d.ts +1 -0
  283. package/dist/commands/workflow/list.d.ts +1 -0
  284. package/dist/commands/workflow/list.js +3 -6
  285. package/dist/commands/workflow/switch.d.ts +2 -0
  286. package/dist/commands/workflow/switch.js +46 -21
  287. package/dist/commands/workflow/view.d.ts +1 -0
  288. package/dist/commands/workflow/view.js +18 -27
  289. package/dist/commands/workspace/remove.d.ts +2 -2
  290. package/dist/commands/workspace/remove.js +16 -21
  291. package/dist/commands/workspace/use.d.ts +2 -2
  292. package/dist/commands/workspace/use.js +12 -18
  293. package/dist/lib/agents/commands.d.ts +1 -1
  294. package/dist/lib/agents/commands.js +4 -4
  295. package/dist/lib/database/drizzle-schema.d.ts +5009 -0
  296. package/dist/lib/database/drizzle-schema.js +699 -0
  297. package/dist/lib/database/drizzle.d.ts +29 -0
  298. package/dist/lib/database/drizzle.js +37 -0
  299. package/dist/lib/database/index.d.ts +1 -0
  300. package/dist/lib/database/index.js +1 -1
  301. package/dist/lib/execution/config.d.ts +6 -0
  302. package/dist/lib/execution/config.js +31 -13
  303. package/dist/lib/execution/devcontainer.js +13 -7
  304. package/dist/lib/execution/runners.js +24 -7
  305. package/dist/lib/execution/spawner.js +19 -0
  306. package/dist/lib/flags/index.d.ts +4 -0
  307. package/dist/lib/flags/index.js +4 -0
  308. package/dist/lib/flags/resolver.d.ts +224 -0
  309. package/dist/lib/flags/resolver.js +313 -0
  310. package/dist/lib/pmo/base-command.d.ts +53 -3
  311. package/dist/lib/pmo/base-command.js +92 -13
  312. package/dist/lib/pmo/find-pmo.d.ts +1 -1
  313. package/dist/lib/pmo/find-pmo.js +4 -4
  314. package/dist/lib/pmo/index.d.ts +1 -1
  315. package/dist/lib/pmo/index.js +1 -1
  316. package/dist/lib/pmo/storage/helpers.js +2 -1
  317. package/dist/lib/pmo/storage/index.d.ts +9 -0
  318. package/dist/lib/pmo/storage/index.js +14 -0
  319. package/dist/lib/pmo/storage/projects.d.ts +28 -13
  320. package/dist/lib/pmo/storage/projects.js +110 -34
  321. package/dist/lib/pmo/storage/roadmaps.d.ts +2 -0
  322. package/dist/lib/pmo/storage/roadmaps.js +182 -111
  323. package/dist/lib/pmo/storage/specs.js +13 -16
  324. package/dist/lib/pmo/storage/subtasks.js +17 -2
  325. package/dist/lib/pmo/storage/tickets.d.ts +12 -2
  326. package/dist/lib/pmo/storage/tickets.js +63 -5
  327. package/dist/lib/pmo/storage/types.d.ts +7 -3
  328. package/dist/lib/pmo/storage/views.d.ts +12 -1
  329. package/dist/lib/pmo/storage/views.js +61 -6
  330. package/dist/lib/prompt-command.d.ts +90 -0
  331. package/dist/lib/prompt-command.js +102 -0
  332. package/dist/lib/prompt-json.d.ts +34 -4
  333. package/dist/lib/prompt-json.js +35 -3
  334. package/dist/lib/repos/index.js +15 -15
  335. package/dist/lib/workspace.d.ts +4 -3
  336. package/dist/lib/workspace.js +3 -3
  337. package/oclif.manifest.json +4610 -2997
  338. package/package.json +13 -5
@@ -1,13 +1,10 @@
1
- import { Command, Args, Flags } from '@oclif/core';
2
- import * as path from 'node:path';
3
- import Database from 'better-sqlite3';
4
- import inquirer from 'inquirer';
5
- import { getPMOContext } from '../../lib/pmo/index.js';
1
+ import { Args, Flags } from '@oclif/core';
2
+ import { PMOCommand, pmoBaseFlags, } from '../../lib/pmo/index.js';
6
3
  import { styles } from '../../lib/styles.js';
7
- import { getWorkspaceInfo } from '../../lib/agents/commands.js';
8
4
  import { isGHInstalled, isGHAuthenticated, getPRByNumber, listOpenPRs, } from '../../lib/pr/index.js';
9
- import { shouldOutputJson, outputPromptAsJson, outputErrorAsJson, createMetadata, buildPromptConfig, } from '../../lib/prompt-json.js';
10
- export default class PRLink extends Command {
5
+ import { shouldOutputJson, outputErrorAsJson, createMetadata, } from '../../lib/prompt-json.js';
6
+ import { FlagResolver } from '../../lib/flags/index.js';
7
+ export default class PRLink extends PMOCommand {
11
8
  static description = 'Link an existing GitHub pull request to a ticket';
12
9
  static examples = [
13
10
  '<%= config.bin %> <%= command.id %>',
@@ -22,6 +19,7 @@ export default class PRLink extends Command {
22
19
  }),
23
20
  };
24
21
  static flags = {
22
+ ...pmoBaseFlags,
25
23
  pr: Flags.integer({
26
24
  char: 'p',
27
25
  description: 'PR number to link',
@@ -30,12 +28,15 @@ export default class PRLink extends Command {
30
28
  char: 'u',
31
29
  description: 'PR URL to link',
32
30
  }),
33
- json: Flags.boolean({
34
- description: 'Output prompt configuration as JSON (for AI agents/scripts)',
31
+ ticket: Flags.string({
32
+ description: 'Ticket ID to link (alternative to positional arg)',
33
+ }),
34
+ confirm: Flags.boolean({
35
+ description: 'Confirm overwriting existing PR link',
35
36
  default: false,
36
37
  }),
37
38
  };
38
- async run() {
39
+ async execute() {
39
40
  const { args, flags } = await this.parse(PRLink);
40
41
  // Check if JSON output mode is active
41
42
  const jsonMode = shouldOutputJson(flags);
@@ -54,159 +55,134 @@ export default class PRLink extends Command {
54
55
  if (!isGHAuthenticated()) {
55
56
  return handleError('GH_NOT_AUTHENTICATED', 'GitHub CLI is not authenticated. Run "gh auth login" first.');
56
57
  }
57
- // Get workspace and PMO context
58
- let workspaceInfo;
59
- try {
60
- workspaceInfo = getWorkspaceInfo();
61
- }
62
- catch {
58
+ // PMOCommand ensures we have storage access
59
+ if (!this.storage) {
63
60
  return handleError('NOT_IN_WORKSPACE', 'Not in a workspace. Run "prlt init" first.');
64
61
  }
65
- const { storage } = await getPMOContext({
66
- logger: (msg) => this.log(styles.muted(msg)),
67
- });
68
- const dbPath = path.join(workspaceInfo.path, '.proletariat', 'workspace.db');
69
- const db = new Database(dbPath);
70
- try {
71
- // Get ticket ID
72
- let ticketId = args.ticketId;
73
- if (!ticketId) {
74
- const projectId = flags.project;
75
- const allTickets = await storage.listTickets(projectId);
76
- const activeTickets = allTickets.filter(t => t.statusName && !t.statusName.toLowerCase().includes('done') && !t.statusName.toLowerCase().includes('archive'));
77
- if (activeTickets.length === 0) {
78
- await storage.close();
79
- db.close();
80
- if (jsonMode) {
81
- outputErrorAsJson('NO_ACTIVE_TICKETS', 'No active tickets found.', createMetadata('pr link', flags));
82
- this.exit(1);
83
- }
84
- this.log(styles.info('No active tickets found.'));
85
- return;
62
+ // Get ticket ID from args or flags
63
+ let ticketId = args.ticketId || flags.ticket;
64
+ if (!ticketId) {
65
+ const projectId = flags.project;
66
+ const allTickets = await this.storage.listTickets(projectId);
67
+ const activeTickets = allTickets.filter(t => t.statusName && !t.statusName.toLowerCase().includes('done') && !t.statusName.toLowerCase().includes('archive'));
68
+ if (activeTickets.length === 0) {
69
+ if (jsonMode) {
70
+ outputErrorAsJson('NO_ACTIVE_TICKETS', 'No active tickets found.', createMetadata('pr link', flags));
71
+ this.exit(1);
86
72
  }
87
- // Build choices once, use for both JSON and interactive modes
88
- const ticketChoices = activeTickets.map(t => ({
73
+ this.log(styles.info('No active tickets found.'));
74
+ return;
75
+ }
76
+ // Use FlagResolver for ticket selection
77
+ const resolver = new FlagResolver({
78
+ commandName: 'pr link',
79
+ baseCommand: 'prlt pr link',
80
+ jsonMode,
81
+ flags: { ticket: ticketId },
82
+ });
83
+ resolver.addPrompt({
84
+ flagName: 'ticket',
85
+ type: 'list',
86
+ message: 'Select ticket to link PR to:',
87
+ choices: () => activeTickets.map(t => ({
89
88
  name: `${t.id} - ${t.title} (${t.statusName})`,
90
89
  value: t.id,
91
- }));
92
- const ticketMessage = 'Select ticket to link PR to:';
93
- // In JSON mode, output ticket selection prompt and exit
94
- if (jsonMode) {
95
- outputPromptAsJson(buildPromptConfig('list', 'ticketId', ticketMessage, ticketChoices), createMetadata('pr link', flags));
96
- }
97
- const { selectedTicketId } = await inquirer.prompt([{
98
- type: 'list',
99
- name: 'selectedTicketId',
100
- message: ticketMessage,
101
- choices: ticketChoices,
102
- }]);
103
- ticketId = selectedTicketId;
90
+ })),
91
+ when: (ctx) => !ctx.flags.ticket,
92
+ });
93
+ const resolved = await resolver.resolve();
94
+ ticketId = resolved.ticket;
95
+ }
96
+ // Get ticket
97
+ const ticket = await this.storage.getTicket(ticketId);
98
+ if (!ticket) {
99
+ this.error(`Ticket "${ticketId}" not found.`);
100
+ }
101
+ // Check if ticket already has a PR linked
102
+ if (ticket.metadata?.pr_url && !flags.confirm) {
103
+ this.log(styles.info(`Ticket ${ticketId} already has a linked PR:`));
104
+ this.log(styles.muted(` URL: ${ticket.metadata.pr_url}`));
105
+ // Use FlagResolver for confirmation
106
+ const confirmResolver = new FlagResolver({
107
+ commandName: 'pr link',
108
+ baseCommand: `prlt pr link ${ticketId}`,
109
+ jsonMode,
110
+ flags: {},
111
+ });
112
+ confirmResolver.addPrompt({
113
+ flagName: 'confirm',
114
+ type: 'list',
115
+ message: 'Replace with a different PR?',
116
+ choices: () => [
117
+ { name: 'No', value: 'no' },
118
+ { name: 'Yes', value: 'yes' },
119
+ ],
120
+ });
121
+ const confirmResolved = await confirmResolver.resolve();
122
+ if (confirmResolved.confirm !== 'yes') {
123
+ return;
104
124
  }
105
- // Get ticket
106
- const ticket = await storage.getTicket(ticketId);
107
- if (!ticket) {
108
- await storage.close();
109
- db.close();
110
- this.error(`Ticket "${ticketId}" not found.`);
125
+ }
126
+ // Get PR number
127
+ let prNumber = flags.pr;
128
+ const prUrl = flags.url;
129
+ if (prUrl) {
130
+ // Extract PR number from URL
131
+ const urlMatch = prUrl.match(/\/pull\/(\d+)/);
132
+ if (urlMatch) {
133
+ prNumber = parseInt(urlMatch[1], 10);
111
134
  }
112
- // Check if ticket already has a PR linked
113
- if (ticket.metadata?.pr_url) {
114
- // Build choices once, use for both JSON and interactive modes
115
- const confirmChoices = [
116
- { name: 'No', value: 'false' },
117
- { name: 'Yes', value: 'true' },
118
- ];
119
- const confirmMessage = `Ticket ${ticketId} already has a linked PR (${ticket.metadata.pr_url}). Replace with a different PR?`;
120
- // In JSON mode, output overwrite confirmation prompt and exit
121
- if (jsonMode) {
122
- outputPromptAsJson(buildPromptConfig('list', 'overwrite', confirmMessage, confirmChoices), createMetadata('pr link', flags));
123
- }
124
- this.log(styles.info(`Ticket ${ticketId} already has a linked PR:`));
125
- this.log(styles.muted(` URL: ${ticket.metadata.pr_url}`));
126
- const { overwrite } = await inquirer.prompt([{
127
- type: 'list',
128
- name: 'overwrite',
129
- message: 'Replace with a different PR?',
130
- choices: confirmChoices.map(c => ({ name: c.name, value: c.value === 'true' })),
131
- default: false,
132
- }]);
133
- if (!overwrite) {
134
- await storage.close();
135
- db.close();
136
- return;
137
- }
135
+ else {
136
+ this.error('Invalid PR URL format. Expected: https://github.com/owner/repo/pull/123');
138
137
  }
139
- // Get PR number
140
- let prNumber = flags.pr;
141
- const prUrl = flags.url;
142
- if (prUrl) {
143
- // Extract PR number from URL
144
- const urlMatch = prUrl.match(/\/pull\/(\d+)/);
145
- if (urlMatch) {
146
- prNumber = parseInt(urlMatch[1], 10);
147
- }
148
- else {
149
- this.error('Invalid PR URL format. Expected: https://github.com/owner/repo/pull/123');
138
+ }
139
+ if (!prNumber) {
140
+ // List open PRs for selection
141
+ const openPRs = listOpenPRs();
142
+ if (openPRs.length === 0) {
143
+ if (jsonMode) {
144
+ outputErrorAsJson('NO_OPEN_PRS', 'No open PRs found. Create one first with "prlt pr create".', createMetadata('pr link', flags));
145
+ this.exit(1);
150
146
  }
147
+ this.error('No open PRs found. Create one first with "prlt pr create".');
151
148
  }
152
- if (!prNumber) {
153
- // List open PRs for selection
154
- const openPRs = listOpenPRs();
155
- if (openPRs.length === 0) {
156
- await storage.close();
157
- db.close();
158
- if (jsonMode) {
159
- outputErrorAsJson('NO_OPEN_PRS', 'No open PRs found. Create one first with "prlt pr create".', createMetadata('pr link', flags));
160
- this.exit(1);
161
- }
162
- this.error('No open PRs found. Create one first with "prlt pr create".');
163
- }
164
- // Build choices once, use for both JSON and interactive modes
165
- const prChoices = openPRs.map(pr => ({
149
+ // Use FlagResolver for PR selection
150
+ const prResolver = new FlagResolver({
151
+ commandName: 'pr link',
152
+ baseCommand: `prlt pr link ${ticketId}`,
153
+ jsonMode,
154
+ flags: {},
155
+ });
156
+ prResolver.addPrompt({
157
+ flagName: 'pr',
158
+ type: 'list',
159
+ message: 'Select PR to link:',
160
+ choices: () => openPRs.map(pr => ({
166
161
  name: `#${pr.number} - ${pr.title} (${pr.headBranch})`,
167
162
  value: String(pr.number),
168
- }));
169
- const prMessage = 'Select PR to link:';
170
- // In JSON mode, output PR selection prompt and exit
171
- if (jsonMode) {
172
- outputPromptAsJson(buildPromptConfig('list', 'prNumber', prMessage, prChoices), createMetadata('pr link', flags));
173
- }
174
- const { selectedPR } = await inquirer.prompt([{
175
- type: 'list',
176
- name: 'selectedPR',
177
- message: prMessage,
178
- choices: prChoices.map(c => ({ name: c.name, value: parseInt(c.value, 10) })),
179
- }]);
180
- prNumber = selectedPR;
181
- }
182
- // Get PR info
183
- const prInfo = getPRByNumber(prNumber);
184
- if (!prInfo) {
185
- await storage.close();
186
- db.close();
187
- this.error(`PR #${prNumber} not found.`);
188
- }
189
- // Link PR to ticket
190
- await storage.updateTicket(ticketId, {
191
- metadata: {
192
- ...ticket.metadata,
193
- pr_url: prInfo.url,
194
- pr_number: String(prInfo.number),
195
- pr_branch: prInfo.headBranch,
196
- },
163
+ })),
197
164
  });
198
- await storage.close();
199
- db.close();
200
- this.log('');
201
- this.log(styles.success(`PR linked to ticket!`));
202
- this.log(styles.muted(` Ticket: ${ticketId}`));
203
- this.log(styles.muted(` PR: #${prInfo.number} - ${prInfo.title}`));
204
- this.log(styles.muted(` URL: ${prInfo.url}`));
165
+ const prResolved = await prResolver.resolve();
166
+ prNumber = parseInt(prResolved.pr, 10);
205
167
  }
206
- catch (error) {
207
- await storage.close();
208
- db.close();
209
- throw error;
168
+ // Get PR info
169
+ const prInfo = getPRByNumber(prNumber);
170
+ if (!prInfo) {
171
+ this.error(`PR #${prNumber} not found.`);
210
172
  }
173
+ // Link PR to ticket
174
+ await this.storage.updateTicket(ticketId, {
175
+ metadata: {
176
+ ...ticket.metadata,
177
+ pr_url: prInfo.url,
178
+ pr_number: String(prInfo.number),
179
+ pr_branch: prInfo.headBranch,
180
+ },
181
+ });
182
+ this.log('');
183
+ this.log(styles.success(`PR linked to ticket!`));
184
+ this.log(styles.muted(` Ticket: ${ticketId}`));
185
+ this.log(styles.muted(` PR: #${prInfo.number} - ${prInfo.title}`));
186
+ this.log(styles.muted(` URL: ${prInfo.url}`));
211
187
  }
212
188
  }
@@ -1,12 +1,15 @@
1
- import { Command } from '@oclif/core';
2
- export default class PRStatus extends Command {
1
+ import { PMOCommand } from '../../lib/pmo/index.js';
2
+ export default class PRStatus extends PMOCommand {
3
3
  static description: string;
4
4
  static examples: string[];
5
5
  static args: {
6
6
  ticketId: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
7
7
  };
8
8
  static flags: {
9
+ ticket: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
10
+ machine: import("@oclif/core/interfaces").BooleanFlag<boolean>;
9
11
  json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
12
+ project: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
10
13
  };
11
- run(): Promise<void>;
14
+ execute(): Promise<void>;
12
15
  }
@@ -1,13 +1,10 @@
1
- import { Command, Args, Flags } from '@oclif/core';
2
- import * as path from 'node:path';
3
- import Database from 'better-sqlite3';
4
- import inquirer from 'inquirer';
5
- import { getPMOContext } from '../../lib/pmo/index.js';
1
+ import { Args, Flags } from '@oclif/core';
2
+ import { PMOCommand, pmoBaseFlags, } from '../../lib/pmo/index.js';
6
3
  import { styles } from '../../lib/styles.js';
7
- import { getWorkspaceInfo } from '../../lib/agents/commands.js';
8
4
  import { isGHInstalled, isGHAuthenticated, getPRByNumber, } from '../../lib/pr/index.js';
9
- import { shouldOutputJson, outputPromptAsJson, outputErrorAsJson, createMetadata, buildPromptConfig, } from '../../lib/prompt-json.js';
10
- export default class PRStatus extends Command {
5
+ import { shouldOutputJson, outputErrorAsJson, createMetadata, } from '../../lib/prompt-json.js';
6
+ import { FlagResolver } from '../../lib/flags/index.js';
7
+ export default class PRStatus extends PMOCommand {
11
8
  static description = 'View PR status for a ticket';
12
9
  static examples = [
13
10
  '<%= config.bin %> <%= command.id %>',
@@ -20,12 +17,12 @@ export default class PRStatus extends Command {
20
17
  }),
21
18
  };
22
19
  static flags = {
23
- json: Flags.boolean({
24
- description: 'Output prompt configuration as JSON (for AI agents/scripts)',
25
- default: false,
20
+ ...pmoBaseFlags,
21
+ ticket: Flags.string({
22
+ description: 'Ticket ID to check (alternative to positional arg)',
26
23
  }),
27
24
  };
28
- async run() {
25
+ async execute() {
29
26
  const { args, flags } = await this.parse(PRStatus);
30
27
  // Check if JSON output mode is active
31
28
  const jsonMode = shouldOutputJson(flags);
@@ -37,125 +34,103 @@ export default class PRStatus extends Command {
37
34
  }
38
35
  this.error(message);
39
36
  };
40
- // Get workspace and PMO context
41
- let workspaceInfo;
42
- try {
43
- workspaceInfo = getWorkspaceInfo();
44
- }
45
- catch {
37
+ // PMOCommand ensures we have storage access
38
+ if (!this.storage) {
46
39
  return handleError('NOT_IN_WORKSPACE', 'Not in a workspace. Run "prlt init" first.');
47
40
  }
48
- const { storage } = await getPMOContext({
49
- logger: (msg) => this.log(styles.muted(msg)),
50
- });
51
- const dbPath = path.join(workspaceInfo.path, '.proletariat', 'workspace.db');
52
- const db = new Database(dbPath);
53
- try {
54
- // Get ticket ID
55
- let ticketId = args.ticketId;
56
- if (!ticketId) {
57
- const projectId = flags.project;
58
- const allTickets = await storage.listTickets(projectId);
59
- // Filter to tickets that have a PR linked
60
- const ticketsWithPR = allTickets.filter(t => t.metadata?.pr_url);
61
- const ticketsWithoutPR = allTickets.filter(t => !t.metadata?.pr_url && t.statusName && !t.statusName.toLowerCase().includes('done'));
62
- if (ticketsWithPR.length === 0 && ticketsWithoutPR.length === 0) {
63
- await storage.close();
64
- db.close();
65
- this.log(styles.info('No tickets found.'));
66
- return;
67
- }
68
- // Build choices once, use for both JSON and interactive modes
69
- const ticketsWithPRChoices = ticketsWithPR.map(t => ({
70
- name: `${t.id} - ${t.title} [PR linked]`,
71
- value: t.id,
72
- }));
73
- const ticketsWithoutPRChoices = ticketsWithoutPR.slice(0, 10).map(t => ({
74
- name: `${t.id} - ${t.title} (${t.statusName})`,
75
- value: t.id,
76
- }));
77
- const ticketChoices = [...ticketsWithPRChoices, ...ticketsWithoutPRChoices];
78
- const message = 'Select ticket to check PR status:';
79
- // In JSON mode, output ticket selection prompt and exit
80
- if (jsonMode) {
81
- outputPromptAsJson(buildPromptConfig('list', 'ticketId', message, ticketChoices), createMetadata('pr status', flags));
82
- }
83
- // Build interactive choices with separator
84
- const interactiveChoices = [...ticketsWithPRChoices];
85
- if (ticketsWithoutPRChoices.length > 0) {
86
- interactiveChoices.push(new inquirer.Separator('── No PR Linked ──'));
87
- interactiveChoices.push(...ticketsWithoutPRChoices);
88
- }
89
- const { selectedTicketId } = await inquirer.prompt([{
90
- type: 'list',
91
- name: 'selectedTicketId',
92
- message,
93
- choices: interactiveChoices,
94
- }]);
95
- ticketId = selectedTicketId;
96
- }
97
- // Get ticket
98
- const ticket = await storage.getTicket(ticketId);
99
- if (!ticket) {
100
- await storage.close();
101
- db.close();
102
- this.error(`Ticket "${ticketId}" not found.`);
103
- }
104
- this.log('');
105
- this.log(styles.header(`PR Status: ${ticket.id}`));
106
- this.log(styles.muted(` Title: ${ticket.title}`));
107
- this.log(styles.muted(` Status: ${ticket.statusName}`));
108
- this.log('');
109
- if (!ticket.metadata?.pr_url) {
110
- this.log(styles.info('No PR linked to this ticket.'));
111
- this.log(styles.muted(' Use "prlt pr create" or "prlt pr link" to link a PR.'));
112
- await storage.close();
113
- db.close();
114
- return;
115
- }
116
- // Check gh CLI for live status
117
- if (!isGHInstalled() || !isGHAuthenticated()) {
118
- this.log(styles.muted(' PR URL:'), ticket.metadata.pr_url);
119
- this.log(styles.muted(' (Install and authenticate `gh` CLI for live status)'));
120
- await storage.close();
121
- db.close();
122
- return;
123
- }
124
- const prNumber = parseInt(ticket.metadata.pr_number || '0', 10);
125
- if (!prNumber) {
126
- this.log(styles.muted(' PR URL:'), ticket.metadata.pr_url);
127
- await storage.close();
128
- db.close();
41
+ // Get ticket ID from args or flags
42
+ let ticketId = args.ticketId || flags.ticket;
43
+ if (!ticketId) {
44
+ const projectId = flags.project;
45
+ const allTickets = await this.storage.listTickets(projectId);
46
+ // Filter to tickets that have a PR linked
47
+ const ticketsWithPR = allTickets.filter(t => t.metadata?.pr_url);
48
+ const ticketsWithoutPR = allTickets.filter(t => !t.metadata?.pr_url && t.statusName && !t.statusName.toLowerCase().includes('done'));
49
+ if (ticketsWithPR.length === 0 && ticketsWithoutPR.length === 0) {
50
+ this.log(styles.info('No tickets found.'));
129
51
  return;
130
52
  }
131
- const prInfo = getPRByNumber(prNumber);
132
- if (!prInfo) {
133
- this.log(styles.warning('Unable to fetch PR status (PR may have been deleted).'));
134
- this.log(styles.muted(' Stored URL:'), ticket.metadata.pr_url);
135
- await storage.close();
136
- db.close();
137
- return;
138
- }
139
- // Display PR status
140
- const stateEmoji = {
141
- OPEN: '🟢',
142
- CLOSED: '🔴',
143
- MERGED: '🟣',
144
- };
145
- this.log(styles.success(`${stateEmoji[prInfo.state]} PR #${prInfo.number}: ${prInfo.title}`));
146
- this.log('');
147
- this.log(styles.muted(` State: ${prInfo.state}${prInfo.isDraft ? ' (Draft)' : ''}`));
148
- this.log(styles.muted(` Branch: ${prInfo.headBranch} → ${prInfo.baseBranch}`));
149
- this.log(styles.muted(` URL: ${prInfo.url}`));
150
- this.log(styles.muted(` Created: ${new Date(prInfo.createdAt).toLocaleDateString()}`));
151
- this.log(styles.muted(` Updated: ${new Date(prInfo.updatedAt).toLocaleDateString()}`));
152
- await storage.close();
153
- db.close();
53
+ // Combine tickets for selection - prioritize those with PRs
54
+ const allSelectableTickets = [
55
+ ...ticketsWithPR.map(t => ({
56
+ id: t.id,
57
+ title: t.title,
58
+ hasPR: true,
59
+ statusName: t.statusName,
60
+ })),
61
+ ...ticketsWithoutPR.slice(0, 10).map(t => ({
62
+ id: t.id,
63
+ title: t.title,
64
+ hasPR: false,
65
+ statusName: t.statusName,
66
+ })),
67
+ ];
68
+ // Use FlagResolver for ticket selection
69
+ const resolver = new FlagResolver({
70
+ commandName: 'pr status',
71
+ baseCommand: 'prlt pr status',
72
+ jsonMode,
73
+ flags: { ticket: ticketId },
74
+ });
75
+ resolver.addPrompt({
76
+ flagName: 'ticket',
77
+ type: 'list',
78
+ message: 'Select ticket to check PR status:',
79
+ choices: () => allSelectableTickets.map(item => ({
80
+ name: item.hasPR
81
+ ? `${item.id} - ${item.title} [PR linked]`
82
+ : `${item.id} - ${item.title} (${item.statusName})`,
83
+ value: item.id,
84
+ })),
85
+ when: (ctx) => !ctx.flags.ticket,
86
+ });
87
+ const resolved = await resolver.resolve();
88
+ ticketId = resolved.ticket;
89
+ }
90
+ // Get ticket
91
+ const ticket = await this.storage.getTicket(ticketId);
92
+ if (!ticket) {
93
+ this.error(`Ticket "${ticketId}" not found.`);
94
+ }
95
+ this.log('');
96
+ this.log(styles.header(`PR Status: ${ticket.id}`));
97
+ this.log(styles.muted(` Title: ${ticket.title}`));
98
+ this.log(styles.muted(` Status: ${ticket.statusName}`));
99
+ this.log('');
100
+ if (!ticket.metadata?.pr_url) {
101
+ this.log(styles.info('No PR linked to this ticket.'));
102
+ this.log(styles.muted(' Use "prlt pr create" or "prlt pr link" to link a PR.'));
103
+ return;
154
104
  }
155
- catch (error) {
156
- await storage.close();
157
- db.close();
158
- throw error;
105
+ // Check gh CLI for live status
106
+ if (!isGHInstalled() || !isGHAuthenticated()) {
107
+ this.log(styles.muted(' PR URL:'), ticket.metadata.pr_url);
108
+ this.log(styles.muted(' (Install and authenticate `gh` CLI for live status)'));
109
+ return;
159
110
  }
111
+ const prNumber = parseInt(ticket.metadata.pr_number || '0', 10);
112
+ if (!prNumber) {
113
+ this.log(styles.muted(' PR URL:'), ticket.metadata.pr_url);
114
+ return;
115
+ }
116
+ const prInfo = getPRByNumber(prNumber);
117
+ if (!prInfo) {
118
+ this.log(styles.warning('Unable to fetch PR status (PR may have been deleted).'));
119
+ this.log(styles.muted(' Stored URL:'), ticket.metadata.pr_url);
120
+ return;
121
+ }
122
+ // Display PR status
123
+ const stateEmoji = {
124
+ OPEN: '🟢',
125
+ CLOSED: '🔴',
126
+ MERGED: '🟣',
127
+ };
128
+ this.log(styles.success(`${stateEmoji[prInfo.state]} PR #${prInfo.number}: ${prInfo.title}`));
129
+ this.log('');
130
+ this.log(styles.muted(` State: ${prInfo.state}${prInfo.isDraft ? ' (Draft)' : ''}`));
131
+ this.log(styles.muted(` Branch: ${prInfo.headBranch} → ${prInfo.baseBranch}`));
132
+ this.log(styles.muted(` URL: ${prInfo.url}`));
133
+ this.log(styles.muted(` Created: ${new Date(prInfo.createdAt).toLocaleDateString()}`));
134
+ this.log(styles.muted(` Updated: ${new Date(prInfo.updatedAt).toLocaleDateString()}`));
160
135
  }
161
136
  }
@@ -7,6 +7,7 @@ export default class ProjectArchive extends PMOCommand {
7
7
  };
8
8
  static flags: {
9
9
  force: import("@oclif/core/interfaces").BooleanFlag<boolean>;
10
+ machine: import("@oclif/core/interfaces").BooleanFlag<boolean>;
10
11
  json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
11
12
  project: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
12
13
  };