@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
@@ -3,8 +3,12 @@
3
3
  *
4
4
  * This is the main facade that delegates to domain-specific storage modules.
5
5
  * Uses the unified workspace.db database with pmo_ prefixed tables.
6
+ *
7
+ * This module now supports Drizzle ORM for type-safe queries while maintaining
8
+ * backward compatibility with raw SQL queries during the migration period.
6
9
  */
7
10
  import Database from 'better-sqlite3';
11
+ import { createDrizzleConnection } from '../../database/drizzle.js';
8
12
  import { PMO_TABLES, PMO_SCHEMA_SQL, validateTicketSchema } from '../schema.js';
9
13
  import { runMigrations, seedBuiltinWorkflows, seedBuiltinPhases, seedBuiltinPhaseTemplates, seedBuiltinActions, seedBuiltinTicketTemplates, updateBoardTimestamp, } from './base.js';
10
14
  import { ProjectStorage } from './projects.js';
@@ -23,6 +27,7 @@ const T = PMO_TABLES;
23
27
  export class SQLiteStorage {
24
28
  type = 'sqlite';
25
29
  db;
30
+ drizzle;
26
31
  dbPath;
27
32
  // Domain-specific storage modules
28
33
  projectStorage;
@@ -43,10 +48,13 @@ export class SQLiteStorage {
43
48
  // Open database (creates if doesn't exist)
44
49
  this.db = new Database(dbPath);
45
50
  this.db.pragma('foreign_keys = ON');
51
+ // Create Drizzle ORM connection wrapping the same database
52
+ this.drizzle = createDrizzleConnection(this.db);
46
53
  // Create the storage context shared by all modules
47
54
  // Note: projectId is passed explicitly to operations, not stored in context
48
55
  const ctx = {
49
56
  db: this.db,
57
+ drizzle: this.drizzle,
50
58
  updateBoardTimestamp: (projectId) => updateBoardTimestamp(this.db, projectId),
51
59
  };
52
60
  // Initialize domain-specific storage modules
@@ -72,6 +80,12 @@ export class SQLiteStorage {
72
80
  getDatabase() {
73
81
  return this.db;
74
82
  }
83
+ /**
84
+ * Get the Drizzle ORM database connection for type-safe queries.
85
+ */
86
+ getDrizzle() {
87
+ return this.drizzle;
88
+ }
75
89
  /**
76
90
  * Ensure PMO tables exist in the database.
77
91
  */
@@ -7,6 +7,19 @@ import { StorageContext } from './types.js';
7
7
  export declare class ProjectStorage {
8
8
  private ctx;
9
9
  constructor(ctx: StorageContext);
10
+ /**
11
+ * Resolve a project identifier to its actual ID.
12
+ * Tries multiple strategies:
13
+ * 1. Exact ID match
14
+ * 2. Case-insensitive ID match
15
+ * 3. Exact name match
16
+ * 4. Case-insensitive name match
17
+ * 5. Slugified name match (matches slug of project name)
18
+ *
19
+ * @param identifier - Project ID, name, or slug to resolve
20
+ * @returns The actual project ID, or null if not found
21
+ */
22
+ resolveProjectId(identifier: string): string | null;
10
23
  /**
11
24
  * Initialize a project with a workflow.
12
25
  * @deprecated Use createProject with a template instead.
@@ -16,8 +29,10 @@ export declare class ProjectStorage {
16
29
  * Get the project board.
17
30
  * Columns are derived from the project's workflow statuses.
18
31
  * Tickets are sorted by priority (P0 first) then created_at (oldest first).
32
+ *
33
+ * @param projectIdOrName - Project ID, name, or slug. Will be resolved to actual ID.
19
34
  */
20
- getBoard(projectId: string): Promise<Board>;
35
+ getBoard(projectIdOrName: string): Promise<Board>;
21
36
  /**
22
37
  * Get the board as markdown.
23
38
  */
@@ -33,9 +48,9 @@ export declare class ProjectStorage {
33
48
  description?: string;
34
49
  }): Promise<Board>;
35
50
  /**
36
- * Get project board by ID.
51
+ * Get project board by ID, name, or slug.
37
52
  */
38
- getProjectBoard(projectId: string): Promise<Board | null>;
53
+ getProjectBoard(projectIdOrName: string): Promise<Board | null>;
39
54
  /**
40
55
  * Get tickets for a status (column).
41
56
  * Tickets are sorted by priority (P0 first) then created_at (oldest first).
@@ -52,28 +67,28 @@ export declare class ProjectStorage {
52
67
  ticketCount: number;
53
68
  }>>;
54
69
  /**
55
- * Delete a project.
70
+ * Delete a project by ID, name, or slug.
56
71
  */
57
- deleteProject(projectId: string): Promise<void>;
72
+ deleteProject(projectIdOrName: string): Promise<void>;
58
73
  /**
59
- * Get a project by ID.
74
+ * Get a project by ID, name, or slug.
60
75
  */
61
- getProject(id: string): Promise<Project | null>;
76
+ getProject(idOrName: string): Promise<Project | null>;
62
77
  /**
63
- * Update a project.
78
+ * Update a project by ID, name, or slug.
64
79
  */
65
- updateProject(id: string, changes: Partial<Project>): Promise<Project>;
80
+ updateProject(idOrName: string, changes: Partial<Project>): Promise<Project>;
66
81
  /**
67
82
  * List projects with optional filter.
68
83
  */
69
84
  listProjects(filter?: ProjectFilter): Promise<Project[]>;
70
85
  /**
71
- * Archive a project.
86
+ * Archive a project by ID, name, or slug.
72
87
  */
73
- archiveProject(id: string): Promise<Project>;
88
+ archiveProject(idOrName: string): Promise<Project>;
74
89
  /**
75
- * Unarchive a project.
90
+ * Unarchive a project by ID, name, or slug.
76
91
  */
77
- unarchiveProject(id: string): Promise<Project>;
92
+ unarchiveProject(idOrName: string): Promise<Project>;
78
93
  private rowToProject;
79
94
  }
@@ -4,7 +4,7 @@
4
4
  */
5
5
  import { PMO_TABLES } from '../schema.js';
6
6
  import { PMOError, } from '../types.js';
7
- import { generateEntityId } from '../utils.js';
7
+ import { generateEntityId, slugify } from '../utils.js';
8
8
  import { generateBoardMarkdown } from '../markdown.js';
9
9
  import { rowToTicket } from './helpers.js';
10
10
  const T = PMO_TABLES;
@@ -13,6 +13,59 @@ export class ProjectStorage {
13
13
  constructor(ctx) {
14
14
  this.ctx = ctx;
15
15
  }
16
+ /**
17
+ * Resolve a project identifier to its actual ID.
18
+ * Tries multiple strategies:
19
+ * 1. Exact ID match
20
+ * 2. Case-insensitive ID match
21
+ * 3. Exact name match
22
+ * 4. Case-insensitive name match
23
+ * 5. Slugified name match (matches slug of project name)
24
+ *
25
+ * @param identifier - Project ID, name, or slug to resolve
26
+ * @returns The actual project ID, or null if not found
27
+ */
28
+ resolveProjectId(identifier) {
29
+ if (!identifier)
30
+ return null;
31
+ // 1. Exact ID match
32
+ const exactMatch = this.ctx.db.prepare(`
33
+ SELECT id FROM ${T.projects} WHERE id = ?
34
+ `).get(identifier);
35
+ if (exactMatch)
36
+ return exactMatch.id;
37
+ // 2. Case-insensitive ID match
38
+ const caseInsensitiveId = this.ctx.db.prepare(`
39
+ SELECT id FROM ${T.projects} WHERE LOWER(id) = LOWER(?)
40
+ `).get(identifier);
41
+ if (caseInsensitiveId)
42
+ return caseInsensitiveId.id;
43
+ // 3. Exact name match
44
+ const nameMatch = this.ctx.db.prepare(`
45
+ SELECT id FROM ${T.projects} WHERE name = ?
46
+ `).get(identifier);
47
+ if (nameMatch)
48
+ return nameMatch.id;
49
+ // 4. Case-insensitive name match
50
+ const caseInsensitiveName = this.ctx.db.prepare(`
51
+ SELECT id FROM ${T.projects} WHERE LOWER(name) = LOWER(?)
52
+ `).get(identifier);
53
+ if (caseInsensitiveName)
54
+ return caseInsensitiveName.id;
55
+ // 5. Slugified name match - check if identifier is a slug of any project name
56
+ // Get all projects and compare slugified names
57
+ const allProjects = this.ctx.db.prepare(`
58
+ SELECT id, name FROM ${T.projects}
59
+ `).all();
60
+ const identifierLower = identifier.toLowerCase();
61
+ for (const project of allProjects) {
62
+ const projectSlug = slugify(project.name);
63
+ if (projectSlug === identifierLower || projectSlug === identifier) {
64
+ return project.id;
65
+ }
66
+ }
67
+ return null;
68
+ }
16
69
  /**
17
70
  * Initialize a project with a workflow.
18
71
  * @deprecated Use createProject with a template instead.
@@ -31,14 +84,21 @@ export class ProjectStorage {
31
84
  * Get the project board.
32
85
  * Columns are derived from the project's workflow statuses.
33
86
  * Tickets are sorted by priority (P0 first) then created_at (oldest first).
87
+ *
88
+ * @param projectIdOrName - Project ID, name, or slug. Will be resolved to actual ID.
34
89
  */
35
- async getBoard(projectId) {
36
- // Get project metadata with workflow
90
+ async getBoard(projectIdOrName) {
91
+ // Resolve project identifier to actual ID
92
+ const resolvedId = this.resolveProjectId(projectIdOrName);
93
+ if (!resolvedId) {
94
+ throw new PMOError('NOT_FOUND', `Project not found: ${projectIdOrName}. Run init() first.`);
95
+ }
96
+ // Get project metadata with workflow using resolved ID
37
97
  const projectRow = this.ctx.db.prepare(`
38
98
  SELECT id, name, workflow_id, updated_at FROM ${T.projects} WHERE id = ?
39
- `).get(projectId);
99
+ `).get(resolvedId);
40
100
  if (!projectRow) {
41
- throw new PMOError('NOT_FOUND', `Project not found: ${projectId}. Run init() first.`);
101
+ throw new PMOError('NOT_FOUND', `Project not found: ${projectIdOrName}. Run init() first.`);
42
102
  }
43
103
  // Get workflow statuses as columns
44
104
  const workflowId = projectRow.workflow_id || 'default';
@@ -53,7 +113,7 @@ export class ProjectStorage {
53
113
  name: status.name,
54
114
  position: status.position,
55
115
  status: status.category,
56
- tickets: await this.getTicketsForStatus(status.id, projectId),
116
+ tickets: await this.getTicketsForStatus(status.id, resolvedId),
57
117
  })));
58
118
  return {
59
119
  id: projectRow.id,
@@ -91,12 +151,17 @@ export class ProjectStorage {
91
151
  return this.getBoard(id);
92
152
  }
93
153
  /**
94
- * Get project board by ID.
154
+ * Get project board by ID, name, or slug.
95
155
  */
96
- async getProjectBoard(projectId) {
156
+ async getProjectBoard(projectIdOrName) {
157
+ // Resolve project identifier to actual ID
158
+ const resolvedId = this.resolveProjectId(projectIdOrName);
159
+ if (!resolvedId) {
160
+ return null;
161
+ }
97
162
  const projectRow = this.ctx.db.prepare(`
98
163
  SELECT id, name, template, description, workflow_id, updated_at FROM ${T.projects} WHERE id = ?
99
- `).get(projectId);
164
+ `).get(resolvedId);
100
165
  if (!projectRow) {
101
166
  return null;
102
167
  }
@@ -112,7 +177,7 @@ export class ProjectStorage {
112
177
  name: status.name,
113
178
  position: status.position,
114
179
  status: status.category,
115
- tickets: await this.getTicketsForStatus(status.id, projectId),
180
+ tickets: await this.getTicketsForStatus(status.id, resolvedId),
116
181
  })));
117
182
  return {
118
183
  id: projectRow.id,
@@ -165,35 +230,46 @@ export class ProjectStorage {
165
230
  }));
166
231
  }
167
232
  /**
168
- * Delete a project.
233
+ * Delete a project by ID, name, or slug.
169
234
  */
170
- async deleteProject(projectId) {
171
- if (projectId === 'default') {
235
+ async deleteProject(projectIdOrName) {
236
+ // Resolve project identifier to actual ID
237
+ const resolvedId = this.resolveProjectId(projectIdOrName);
238
+ if (!resolvedId) {
239
+ throw new PMOError('NOT_FOUND', `Project not found: ${projectIdOrName}`);
240
+ }
241
+ if (resolvedId === 'default') {
172
242
  throw new PMOError('INVALID', 'Cannot delete the default project');
173
243
  }
174
- const result = this.ctx.db.prepare(`DELETE FROM ${T.projects} WHERE id = ?`).run(projectId);
244
+ const result = this.ctx.db.prepare(`DELETE FROM ${T.projects} WHERE id = ?`).run(resolvedId);
175
245
  if (result.changes === 0) {
176
- throw new PMOError('NOT_FOUND', `Project not found: ${projectId}`);
246
+ throw new PMOError('NOT_FOUND', `Project not found: ${projectIdOrName}`);
177
247
  }
178
248
  // Tickets are deleted via CASCADE
179
249
  }
180
250
  /**
181
- * Get a project by ID.
251
+ * Get a project by ID, name, or slug.
182
252
  */
183
- async getProject(id) {
184
- const row = this.ctx.db.prepare(`SELECT * FROM ${T.projects} WHERE id = ?`).get(id);
253
+ async getProject(idOrName) {
254
+ // Resolve project identifier to actual ID
255
+ const resolvedId = this.resolveProjectId(idOrName);
256
+ if (!resolvedId)
257
+ return null;
258
+ const row = this.ctx.db.prepare(`SELECT * FROM ${T.projects} WHERE id = ?`).get(resolvedId);
185
259
  if (!row)
186
260
  return null;
187
261
  return this.rowToProject(row);
188
262
  }
189
263
  /**
190
- * Update a project.
264
+ * Update a project by ID, name, or slug.
191
265
  */
192
- async updateProject(id, changes) {
193
- const existing = await this.getProject(id);
266
+ async updateProject(idOrName, changes) {
267
+ const existing = await this.getProject(idOrName);
194
268
  if (!existing) {
195
- throw new PMOError('NOT_FOUND', `Project not found: ${id}`);
269
+ throw new PMOError('NOT_FOUND', `Project not found: ${idOrName}`);
196
270
  }
271
+ // Use the resolved ID for the update
272
+ const resolvedId = existing.id;
197
273
  const updates = ['updated_at = ?'];
198
274
  const params = [Date.now()];
199
275
  if (changes.name !== undefined) {
@@ -224,9 +300,9 @@ export class ProjectStorage {
224
300
  updates.push('target_date = ?');
225
301
  params.push(changes.targetDate ? changes.targetDate.toISOString() : null);
226
302
  }
227
- params.push(id);
303
+ params.push(resolvedId);
228
304
  this.ctx.db.prepare(`UPDATE ${T.projects} SET ${updates.join(', ')} WHERE id = ?`).run(...params);
229
- return (await this.getProject(id));
305
+ return (await this.getProject(resolvedId));
230
306
  }
231
307
  /**
232
308
  * List projects with optional filter.
@@ -259,30 +335,30 @@ export class ProjectStorage {
259
335
  return rows.map((row) => this.rowToProject(row));
260
336
  }
261
337
  /**
262
- * Archive a project.
338
+ * Archive a project by ID, name, or slug.
263
339
  */
264
- async archiveProject(id) {
265
- const existing = await this.getProject(id);
340
+ async archiveProject(idOrName) {
341
+ const existing = await this.getProject(idOrName);
266
342
  if (!existing) {
267
- throw new PMOError('NOT_FOUND', `Project not found: ${id}`);
343
+ throw new PMOError('NOT_FOUND', `Project not found: ${idOrName}`);
268
344
  }
269
345
  if (existing.isArchived) {
270
346
  return existing;
271
347
  }
272
- return this.updateProject(id, { isArchived: true });
348
+ return this.updateProject(existing.id, { isArchived: true });
273
349
  }
274
350
  /**
275
- * Unarchive a project.
351
+ * Unarchive a project by ID, name, or slug.
276
352
  */
277
- async unarchiveProject(id) {
278
- const existing = await this.getProject(id);
353
+ async unarchiveProject(idOrName) {
354
+ const existing = await this.getProject(idOrName);
279
355
  if (!existing) {
280
- throw new PMOError('NOT_FOUND', `Project not found: ${id}`);
356
+ throw new PMOError('NOT_FOUND', `Project not found: ${idOrName}`);
281
357
  }
282
358
  if (!existing.isArchived) {
283
359
  return existing;
284
360
  }
285
- return this.updateProject(id, { isArchived: false });
361
+ return this.updateProject(existing.id, { isArchived: false });
286
362
  }
287
363
  rowToProject(row) {
288
364
  return {
@@ -1,6 +1,8 @@
1
1
  /**
2
2
  * Roadmap operations for PMO.
3
3
  * Roadmaps are curated collections of projects for documentation/visualization.
4
+ *
5
+ * This module uses Drizzle ORM for type-safe database queries.
4
6
  */
5
7
  import { Roadmap, RoadmapProject, RoadmapFilter, Project } from '../types.js';
6
8
  import { StorageContext } from './types.js';