@proletariat/cli 0.2.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +561 -251
- package/bin/dev.cmd +3 -0
- package/bin/dev.js +5 -0
- package/bin/run.cmd +3 -0
- package/bin/run.js +23 -0
- package/dist/commands/action/create.d.ts +21 -0
- package/dist/commands/action/create.js +126 -0
- package/dist/commands/action/delete.d.ts +17 -0
- package/dist/commands/action/delete.js +78 -0
- package/dist/commands/action/index.d.ts +15 -0
- package/dist/commands/action/index.js +107 -0
- package/dist/commands/action/list.d.ts +14 -0
- package/dist/commands/action/list.js +89 -0
- package/dist/commands/action/run.d.ts +19 -0
- package/dist/commands/action/run.js +179 -0
- package/dist/commands/action/show.d.ts +15 -0
- package/dist/commands/action/show.js +47 -0
- package/dist/commands/action/update.d.ts +22 -0
- package/dist/commands/action/update.js +168 -0
- package/dist/commands/agent/index.d.ts +13 -0
- package/dist/commands/agent/index.js +131 -0
- package/dist/commands/agent/list.d.ts +7 -0
- package/dist/commands/agent/list.js +126 -0
- package/dist/commands/agent/login.d.ts +16 -0
- package/dist/commands/agent/login.js +146 -0
- package/dist/commands/agent/rebuild.d.ts +18 -0
- package/dist/commands/agent/rebuild.js +133 -0
- package/dist/commands/agent/restart.d.ts +17 -0
- package/dist/commands/agent/restart.js +116 -0
- package/dist/commands/agent/shell.d.ts +23 -0
- package/dist/commands/agent/shell.js +378 -0
- package/dist/commands/agent/staff/add.d.ts +15 -0
- package/dist/commands/agent/staff/add.js +281 -0
- package/dist/commands/agent/staff/index.d.ts +14 -0
- package/dist/commands/agent/staff/index.js +90 -0
- package/dist/commands/agent/staff/list.d.ts +7 -0
- package/dist/commands/agent/staff/list.js +90 -0
- package/dist/commands/agent/staff/remove.d.ts +16 -0
- package/dist/commands/agent/staff/remove.js +137 -0
- package/dist/commands/agent/status.d.ts +17 -0
- package/dist/commands/agent/status.js +139 -0
- package/dist/commands/agent/temp/cleanup.d.ts +23 -0
- package/dist/commands/agent/temp/cleanup.js +388 -0
- package/dist/commands/agent/temp/index.d.ts +14 -0
- package/dist/commands/agent/temp/index.js +82 -0
- package/dist/commands/agent/temp/list.d.ts +7 -0
- package/dist/commands/agent/temp/list.js +108 -0
- package/dist/commands/agent/themes/add-names.d.ts +10 -0
- package/dist/commands/agent/themes/add-names.js +67 -0
- package/dist/commands/agent/themes/create.d.ts +13 -0
- package/dist/commands/agent/themes/create.js +66 -0
- package/dist/commands/agent/themes/index.d.ts +9 -0
- package/dist/commands/agent/themes/index.js +194 -0
- package/dist/commands/agent/themes/list.d.ts +6 -0
- package/dist/commands/agent/themes/list.js +41 -0
- package/dist/commands/agent/themes/set.d.ts +12 -0
- package/dist/commands/agent/themes/set.js +77 -0
- package/dist/commands/agent/visit.d.ts +16 -0
- package/dist/commands/agent/visit.js +88 -0
- package/dist/commands/autocomplete/setup.d.ts +14 -0
- package/dist/commands/autocomplete/setup.js +154 -0
- package/dist/commands/board/index.d.ts +17 -0
- package/dist/commands/board/index.js +255 -0
- package/dist/commands/board/watch.d.ts +13 -0
- package/dist/commands/board/watch.js +52 -0
- package/dist/commands/branch/create.d.ts +50 -0
- package/dist/commands/branch/create.js +624 -0
- package/dist/commands/branch/index.d.ts +13 -0
- package/dist/commands/branch/index.js +50 -0
- package/dist/commands/branch/list.d.ts +17 -0
- package/dist/commands/branch/list.js +120 -0
- package/dist/commands/branch/validate.d.ts +15 -0
- package/dist/commands/branch/validate.js +73 -0
- package/dist/commands/commit.d.ts +71 -0
- package/dist/commands/commit.js +499 -0
- package/dist/commands/docker/clean.d.ts +13 -0
- package/dist/commands/docker/clean.js +224 -0
- package/dist/commands/docker/index.d.ts +19 -0
- package/dist/commands/docker/index.js +274 -0
- package/dist/commands/docker/list.d.ts +16 -0
- package/dist/commands/docker/list.js +200 -0
- package/dist/commands/docker/logs.d.ts +14 -0
- package/dist/commands/docker/logs.js +118 -0
- package/dist/commands/docker/prune.d.ts +14 -0
- package/dist/commands/docker/prune.js +211 -0
- package/dist/commands/docker/restart.d.ts +14 -0
- package/dist/commands/docker/restart.js +129 -0
- package/dist/commands/docker/shell.d.ts +14 -0
- package/dist/commands/docker/shell.js +103 -0
- package/dist/commands/docker/start.d.ts +12 -0
- package/dist/commands/docker/start.js +92 -0
- package/dist/commands/docker/status.d.ts +7 -0
- package/dist/commands/docker/status.js +40 -0
- package/dist/commands/docker/stop.d.ts +14 -0
- package/dist/commands/docker/stop.js +134 -0
- package/dist/commands/docker/sync.d.ts +15 -0
- package/dist/commands/docker/sync.js +112 -0
- package/dist/commands/epic/activate.d.ts +13 -0
- package/dist/commands/epic/activate.js +118 -0
- package/dist/commands/epic/archive.d.ts +14 -0
- package/dist/commands/epic/archive.js +132 -0
- package/dist/commands/epic/create.d.ts +15 -0
- package/dist/commands/epic/create.js +137 -0
- package/dist/commands/epic/index.d.ts +13 -0
- package/dist/commands/epic/index.js +88 -0
- package/dist/commands/epic/link/block.d.ts +14 -0
- package/dist/commands/epic/link/block.js +79 -0
- package/dist/commands/epic/link/duplicates.d.ts +14 -0
- package/dist/commands/epic/link/duplicates.js +66 -0
- package/dist/commands/epic/link/index.d.ts +19 -0
- package/dist/commands/epic/link/index.js +242 -0
- package/dist/commands/epic/link/relates.d.ts +14 -0
- package/dist/commands/epic/link/relates.js +66 -0
- package/dist/commands/epic/link/remove.d.ts +16 -0
- package/dist/commands/epic/link/remove.js +89 -0
- package/dist/commands/epic/list.d.ts +11 -0
- package/dist/commands/epic/list.js +87 -0
- package/dist/commands/epic/move.d.ts +15 -0
- package/dist/commands/epic/move.js +184 -0
- package/dist/commands/epic/progress.d.ts +16 -0
- package/dist/commands/epic/progress.js +166 -0
- package/dist/commands/epic/project.d.ts +15 -0
- package/dist/commands/epic/project.js +219 -0
- package/dist/commands/epic/reorder.d.ts +21 -0
- package/dist/commands/epic/reorder.js +160 -0
- package/dist/commands/epic/spec.d.ts +15 -0
- package/dist/commands/epic/spec.js +191 -0
- package/dist/commands/epic/ticket.d.ts +18 -0
- package/dist/commands/epic/ticket.js +291 -0
- package/dist/commands/epic/view.d.ts +13 -0
- package/dist/commands/epic/view.js +117 -0
- package/dist/commands/execution/index.d.ts +13 -0
- package/dist/commands/execution/index.js +70 -0
- package/dist/commands/execution/list.d.ts +15 -0
- package/dist/commands/execution/list.js +144 -0
- package/dist/commands/execution/logs.d.ts +18 -0
- package/dist/commands/execution/logs.js +161 -0
- package/dist/commands/execution/stop.d.ts +22 -0
- package/dist/commands/execution/stop.js +248 -0
- package/dist/commands/gh/index.d.ts +9 -0
- package/dist/commands/gh/index.js +53 -0
- package/dist/commands/gh/login.d.ts +6 -0
- package/dist/commands/gh/login.js +57 -0
- package/dist/commands/gh/status.d.ts +6 -0
- package/dist/commands/gh/status.js +48 -0
- package/dist/commands/gh/token.d.ts +6 -0
- package/dist/commands/gh/token.js +59 -0
- package/dist/commands/init.d.ts +26 -0
- package/dist/commands/init.js +200 -0
- package/dist/commands/phase/create.d.ts +22 -0
- package/dist/commands/phase/create.js +123 -0
- package/dist/commands/phase/delete.d.ts +17 -0
- package/dist/commands/phase/delete.js +73 -0
- package/dist/commands/phase/list.d.ts +12 -0
- package/dist/commands/phase/list.js +76 -0
- package/dist/commands/phase/move.d.ts +17 -0
- package/dist/commands/phase/move.js +115 -0
- package/dist/commands/phase/template/apply.d.ts +17 -0
- package/dist/commands/phase/template/apply.js +106 -0
- package/dist/commands/phase/template/create.d.ts +16 -0
- package/dist/commands/phase/template/create.js +58 -0
- package/dist/commands/phase/template/delete.d.ts +17 -0
- package/dist/commands/phase/template/delete.js +98 -0
- package/dist/commands/phase/template/index.d.ts +15 -0
- package/dist/commands/phase/template/index.js +128 -0
- package/dist/commands/phase/template/list.d.ts +16 -0
- package/dist/commands/phase/template/list.js +95 -0
- package/dist/commands/phase/template/update.d.ts +17 -0
- package/dist/commands/phase/template/update.js +89 -0
- package/dist/commands/phase/update.d.ts +23 -0
- package/dist/commands/phase/update.js +174 -0
- package/dist/commands/pmo/init.d.ts +25 -0
- package/dist/commands/pmo/init.js +341 -0
- package/dist/commands/pr/create.d.ts +17 -0
- package/dist/commands/pr/create.js +242 -0
- package/dist/commands/pr/index.d.ts +9 -0
- package/dist/commands/pr/index.js +68 -0
- package/dist/commands/pr/link.d.ts +14 -0
- package/dist/commands/pr/link.js +212 -0
- package/dist/commands/pr/status.d.ts +12 -0
- package/dist/commands/pr/status.js +161 -0
- package/dist/commands/project/archive.d.ts +17 -0
- package/dist/commands/project/archive.js +83 -0
- package/dist/commands/project/create.d.ts +22 -0
- package/dist/commands/project/create.js +143 -0
- package/dist/commands/project/delete.d.ts +17 -0
- package/dist/commands/project/delete.js +128 -0
- package/dist/commands/project/index.d.ts +13 -0
- package/dist/commands/project/index.js +64 -0
- package/dist/commands/project/list.d.ts +14 -0
- package/dist/commands/project/list.js +96 -0
- package/dist/commands/project/spec.d.ts +18 -0
- package/dist/commands/project/spec.js +216 -0
- package/dist/commands/project/unarchive.d.ts +15 -0
- package/dist/commands/project/unarchive.js +35 -0
- package/dist/commands/project/view.d.ts +16 -0
- package/dist/commands/project/view.js +94 -0
- package/dist/commands/repo/add.d.ts +21 -0
- package/dist/commands/repo/add.js +118 -0
- package/dist/commands/repo/index.d.ts +13 -0
- package/dist/commands/repo/index.js +114 -0
- package/dist/commands/repo/list.d.ts +13 -0
- package/dist/commands/repo/list.js +96 -0
- package/dist/commands/repo/remove.d.ts +23 -0
- package/dist/commands/repo/remove.js +217 -0
- package/dist/commands/repo/view.d.ts +15 -0
- package/dist/commands/repo/view.js +99 -0
- package/dist/commands/session/attach.d.ts +40 -0
- package/dist/commands/session/attach.js +307 -0
- package/dist/commands/session/index.d.ts +13 -0
- package/dist/commands/session/index.js +64 -0
- package/dist/commands/session/list.d.ts +21 -0
- package/dist/commands/session/list.js +181 -0
- package/dist/commands/spec/create.d.ts +19 -0
- package/dist/commands/spec/create.js +130 -0
- package/dist/commands/spec/index.d.ts +13 -0
- package/dist/commands/spec/index.js +68 -0
- package/dist/commands/spec/link/depends.d.ts +14 -0
- package/dist/commands/spec/link/depends.js +64 -0
- package/dist/commands/spec/link/duplicates.d.ts +14 -0
- package/dist/commands/spec/link/duplicates.js +63 -0
- package/dist/commands/spec/link/index.d.ts +19 -0
- package/dist/commands/spec/link/index.js +200 -0
- package/dist/commands/spec/link/relates.d.ts +14 -0
- package/dist/commands/spec/link/relates.js +63 -0
- package/dist/commands/spec/link/remove.d.ts +16 -0
- package/dist/commands/spec/link/remove.js +94 -0
- package/dist/commands/spec/list.d.ts +12 -0
- package/dist/commands/spec/list.js +75 -0
- package/dist/commands/spec/plan.d.ts +15 -0
- package/dist/commands/spec/plan.js +108 -0
- package/dist/commands/spec/ticket.d.ts +18 -0
- package/dist/commands/spec/ticket.js +160 -0
- package/dist/commands/spec/view.d.ts +15 -0
- package/dist/commands/spec/view.js +163 -0
- package/dist/commands/status/create.d.ts +21 -0
- package/dist/commands/status/create.js +140 -0
- package/dist/commands/status/delete.d.ts +13 -0
- package/dist/commands/status/delete.js +77 -0
- package/dist/commands/status/index.d.ts +14 -0
- package/dist/commands/status/index.js +91 -0
- package/dist/commands/status/list.d.ts +12 -0
- package/dist/commands/status/list.js +93 -0
- package/dist/commands/status/move.d.ts +14 -0
- package/dist/commands/status/move.js +120 -0
- package/dist/commands/status/update.d.ts +20 -0
- package/dist/commands/status/update.js +180 -0
- package/dist/commands/template/delete.d.ts +15 -0
- package/dist/commands/template/delete.js +142 -0
- package/dist/commands/template/index.d.ts +10 -0
- package/dist/commands/template/index.js +64 -0
- package/dist/commands/template/list.d.ts +18 -0
- package/dist/commands/template/list.js +157 -0
- package/dist/commands/template/phase/apply.d.ts +14 -0
- package/dist/commands/template/phase/apply.js +41 -0
- package/dist/commands/template/phase/create.d.ts +12 -0
- package/dist/commands/template/phase/create.js +29 -0
- package/dist/commands/template/phase/delete.d.ts +13 -0
- package/dist/commands/template/phase/delete.js +34 -0
- package/dist/commands/template/phase/index.d.ts +10 -0
- package/dist/commands/template/phase/index.js +62 -0
- package/dist/commands/template/phase/list.d.ts +11 -0
- package/dist/commands/template/phase/list.js +34 -0
- package/dist/commands/template/phase/update.d.ts +13 -0
- package/dist/commands/template/phase/update.js +35 -0
- package/dist/commands/template/ticket/apply.d.ts +17 -0
- package/dist/commands/template/ticket/apply.js +58 -0
- package/dist/commands/template/ticket/delete.d.ts +13 -0
- package/dist/commands/template/ticket/delete.js +34 -0
- package/dist/commands/template/ticket/index.d.ts +10 -0
- package/dist/commands/template/ticket/index.js +62 -0
- package/dist/commands/template/ticket/list.d.ts +11 -0
- package/dist/commands/template/ticket/list.js +34 -0
- package/dist/commands/template/ticket/save.d.ts +13 -0
- package/dist/commands/template/ticket/save.js +35 -0
- package/dist/commands/ticket/bulk.d.ts +13 -0
- package/dist/commands/ticket/bulk.js +145 -0
- package/dist/commands/ticket/complete.d.ts +16 -0
- package/dist/commands/ticket/complete.js +170 -0
- package/dist/commands/ticket/create.d.ts +22 -0
- package/dist/commands/ticket/create.js +390 -0
- package/dist/commands/ticket/delete.d.ts +16 -0
- package/dist/commands/ticket/delete.js +178 -0
- package/dist/commands/ticket/edit.d.ts +27 -0
- package/dist/commands/ticket/edit.js +322 -0
- package/dist/commands/ticket/epic.d.ts +20 -0
- package/dist/commands/ticket/epic.js +333 -0
- package/dist/commands/ticket/index.d.ts +13 -0
- package/dist/commands/ticket/index.js +103 -0
- package/dist/commands/ticket/link/block.d.ts +14 -0
- package/dist/commands/ticket/link/block.js +94 -0
- package/dist/commands/ticket/link/duplicates.d.ts +14 -0
- package/dist/commands/ticket/link/duplicates.js +93 -0
- package/dist/commands/ticket/link/index.d.ts +19 -0
- package/dist/commands/ticket/link/index.js +239 -0
- package/dist/commands/ticket/link/relates.d.ts +14 -0
- package/dist/commands/ticket/link/relates.js +93 -0
- package/dist/commands/ticket/link/remove.d.ts +16 -0
- package/dist/commands/ticket/link/remove.js +128 -0
- package/dist/commands/ticket/list.d.ts +24 -0
- package/dist/commands/ticket/list.js +431 -0
- package/dist/commands/ticket/move.d.ts +18 -0
- package/dist/commands/ticket/move.js +212 -0
- package/dist/commands/ticket/project.d.ts +18 -0
- package/dist/commands/ticket/project.js +254 -0
- package/dist/commands/ticket/reassign.d.ts +19 -0
- package/dist/commands/ticket/reassign.js +279 -0
- package/dist/commands/ticket/spec.d.ts +18 -0
- package/dist/commands/ticket/spec.js +259 -0
- package/dist/commands/ticket/status.d.ts +13 -0
- package/dist/commands/ticket/status.js +87 -0
- package/dist/commands/ticket/template/apply.d.ts +25 -0
- package/dist/commands/ticket/template/apply.js +249 -0
- package/dist/commands/ticket/template/create.d.ts +19 -0
- package/dist/commands/ticket/template/create.js +210 -0
- package/dist/commands/ticket/template/delete.d.ts +17 -0
- package/dist/commands/ticket/template/delete.js +92 -0
- package/dist/commands/ticket/template/index.d.ts +15 -0
- package/dist/commands/ticket/template/index.js +118 -0
- package/dist/commands/ticket/template/list.d.ts +16 -0
- package/dist/commands/ticket/template/list.js +110 -0
- package/dist/commands/ticket/template/save.d.ts +14 -0
- package/dist/commands/ticket/template/save.js +110 -0
- package/dist/commands/ticket/update.d.ts +18 -0
- package/dist/commands/ticket/update.js +325 -0
- package/dist/commands/ticket/view.d.ts +13 -0
- package/dist/commands/ticket/view.js +80 -0
- package/dist/commands/whoami.d.ts +9 -0
- package/dist/commands/whoami.js +103 -0
- package/dist/commands/work/complete.d.ts +13 -0
- package/dist/commands/work/complete.js +121 -0
- package/dist/commands/work/index.d.ts +13 -0
- package/dist/commands/work/index.js +70 -0
- package/dist/commands/work/ready.d.ts +24 -0
- package/dist/commands/work/ready.js +290 -0
- package/dist/commands/work/revise.d.ts +19 -0
- package/dist/commands/work/revise.js +377 -0
- package/dist/commands/work/spawn-all.d.ts +17 -0
- package/dist/commands/work/spawn-all.js +58 -0
- package/dist/commands/work/spawn.d.ts +29 -0
- package/dist/commands/work/spawn.js +728 -0
- package/dist/commands/work/start.d.ts +39 -0
- package/dist/commands/work/start.js +1393 -0
- package/dist/commands/work/watch.d.ts +31 -0
- package/dist/commands/work/watch.js +359 -0
- package/dist/commands/workflow/create.d.ts +18 -0
- package/dist/commands/workflow/create.js +119 -0
- package/dist/commands/workflow/delete.d.ts +17 -0
- package/dist/commands/workflow/delete.js +119 -0
- package/dist/commands/workflow/index.d.ts +15 -0
- package/dist/commands/workflow/index.js +75 -0
- package/dist/commands/workflow/list.d.ts +15 -0
- package/dist/commands/workflow/list.js +75 -0
- package/dist/commands/workflow/switch.d.ts +13 -0
- package/dist/commands/workflow/switch.js +117 -0
- package/dist/commands/workflow/view.d.ts +16 -0
- package/dist/commands/workflow/view.js +114 -0
- package/dist/commands/workspace/add.d.ts +12 -0
- package/dist/commands/workspace/add.js +74 -0
- package/dist/commands/workspace/list.d.ts +9 -0
- package/dist/commands/workspace/list.js +153 -0
- package/dist/commands/workspace/remove.d.ts +13 -0
- package/dist/commands/workspace/remove.js +98 -0
- package/dist/commands/workspace/use.d.ts +12 -0
- package/dist/commands/workspace/use.js +111 -0
- package/dist/hooks/init.d.ts +11 -0
- package/dist/hooks/init.js +57 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/lib/agents/commands.d.ts +189 -0
- package/dist/lib/agents/commands.js +893 -0
- package/dist/lib/agents/index.d.ts +54 -0
- package/dist/lib/agents/index.js +382 -0
- package/dist/lib/branch/index.d.ts +120 -0
- package/dist/lib/branch/index.js +334 -0
- package/dist/lib/colors.d.ts +94 -0
- package/dist/lib/colors.js +68 -0
- package/dist/lib/commands/docker-command.d.ts +21 -0
- package/dist/lib/commands/docker-command.js +27 -0
- package/dist/lib/database/index.d.ts +176 -0
- package/dist/lib/database/index.js +581 -0
- package/dist/lib/docker/resolve.d.ts +38 -0
- package/dist/lib/docker/resolve.js +175 -0
- package/dist/lib/execution/config.d.ts +150 -0
- package/dist/lib/execution/config.js +541 -0
- package/dist/lib/execution/devcontainer.d.ts +85 -0
- package/dist/lib/execution/devcontainer.js +594 -0
- package/dist/lib/execution/index.d.ts +10 -0
- package/dist/lib/execution/index.js +10 -0
- package/dist/lib/execution/runners.d.ts +53 -0
- package/dist/lib/execution/runners.js +1182 -0
- package/dist/lib/execution/spawner.d.ts +85 -0
- package/dist/lib/execution/spawner.js +548 -0
- package/dist/lib/execution/storage.d.ts +159 -0
- package/dist/lib/execution/storage.js +425 -0
- package/dist/lib/execution/types.d.ts +145 -0
- package/dist/lib/execution/types.js +157 -0
- package/dist/lib/init/index.d.ts +75 -0
- package/dist/lib/init/index.js +355 -0
- package/dist/lib/machine-config.d.ts +170 -0
- package/dist/lib/machine-config.js +386 -0
- package/dist/lib/pmo/base-command.d.ts +195 -0
- package/dist/lib/pmo/base-command.js +319 -0
- package/dist/lib/pmo/create-spec-folders.d.ts +43 -0
- package/dist/lib/pmo/create-spec-folders.js +64 -0
- package/dist/lib/pmo/epic-files.d.ts +56 -0
- package/dist/lib/pmo/epic-files.js +195 -0
- package/dist/lib/pmo/find-pmo.d.ts +14 -0
- package/dist/lib/pmo/find-pmo.js +172 -0
- package/dist/lib/pmo/index.d.ts +109 -0
- package/dist/lib/pmo/index.js +501 -0
- package/dist/lib/pmo/markdown.d.ts +31 -0
- package/dist/lib/pmo/markdown.js +245 -0
- package/dist/lib/pmo/pmo-context.d.ts +27 -0
- package/dist/lib/pmo/pmo-context.js +44 -0
- package/dist/lib/pmo/schema.d.ts +82 -0
- package/dist/lib/pmo/schema.js +531 -0
- package/dist/lib/pmo/spec-parser.d.ts +25 -0
- package/dist/lib/pmo/spec-parser.js +205 -0
- package/dist/lib/pmo/spec-types.d.ts +43 -0
- package/dist/lib/pmo/spec-types.js +7 -0
- package/dist/lib/pmo/storage/actions.d.ts +34 -0
- package/dist/lib/pmo/storage/actions.js +177 -0
- package/dist/lib/pmo/storage/base.d.ts +47 -0
- package/dist/lib/pmo/storage/base.js +858 -0
- package/dist/lib/pmo/storage/dependencies.d.ts +61 -0
- package/dist/lib/pmo/storage/dependencies.js +267 -0
- package/dist/lib/pmo/storage/epics.d.ts +46 -0
- package/dist/lib/pmo/storage/epics.js +243 -0
- package/dist/lib/pmo/storage/helpers.d.ts +33 -0
- package/dist/lib/pmo/storage/helpers.js +148 -0
- package/dist/lib/pmo/storage/index.d.ts +186 -0
- package/dist/lib/pmo/storage/index.js +689 -0
- package/dist/lib/pmo/storage/phases.d.ts +65 -0
- package/dist/lib/pmo/storage/phases.js +392 -0
- package/dist/lib/pmo/storage/projects.d.ts +79 -0
- package/dist/lib/pmo/storage/projects.js +303 -0
- package/dist/lib/pmo/storage/specs.d.ts +77 -0
- package/dist/lib/pmo/storage/specs.js +389 -0
- package/dist/lib/pmo/storage/statuses.d.ts +63 -0
- package/dist/lib/pmo/storage/statuses.js +404 -0
- package/dist/lib/pmo/storage/subtasks.d.ts +37 -0
- package/dist/lib/pmo/storage/subtasks.js +184 -0
- package/dist/lib/pmo/storage/templates.d.ts +40 -0
- package/dist/lib/pmo/storage/templates.js +210 -0
- package/dist/lib/pmo/storage/tickets.d.ts +57 -0
- package/dist/lib/pmo/storage/tickets.js +453 -0
- package/dist/lib/pmo/storage/types.d.ts +200 -0
- package/dist/lib/pmo/storage/types.js +5 -0
- package/dist/lib/pmo/storage/views.d.ts +44 -0
- package/dist/lib/pmo/storage/views.js +355 -0
- package/dist/lib/pmo/storage-sqlite.d.ts +7 -0
- package/dist/lib/pmo/storage-sqlite.js +7 -0
- package/dist/lib/pmo/sync-manager.d.ts +92 -0
- package/dist/lib/pmo/sync-manager.js +229 -0
- package/dist/lib/pmo/types.d.ts +710 -0
- package/dist/lib/pmo/types.js +108 -0
- package/dist/lib/pmo/utils.d.ts +122 -0
- package/dist/lib/pmo/utils.js +174 -0
- package/dist/lib/pmo/watcher.d.ts +43 -0
- package/dist/lib/pmo/watcher.js +208 -0
- package/dist/lib/pr/index.d.ts +150 -0
- package/dist/lib/pr/index.js +483 -0
- package/dist/lib/prompt-json.d.ts +231 -0
- package/dist/lib/prompt-json.js +213 -0
- package/dist/lib/repos/index.d.ts +81 -0
- package/dist/lib/repos/index.js +679 -0
- package/dist/lib/styles.d.ts +98 -0
- package/dist/lib/styles.js +195 -0
- package/dist/lib/themes.d.ts +128 -0
- package/dist/lib/themes.js +301 -0
- package/dist/lib/ui/BoardUI.d.ts +21 -0
- package/dist/lib/ui/BoardUI.js +85 -0
- package/dist/lib/ui/ClaimTicketUI.d.ts +17 -0
- package/dist/lib/ui/ClaimTicketUI.js +64 -0
- package/dist/lib/ui/CreateTicketUI.d.ts +13 -0
- package/dist/lib/ui/CreateTicketUI.js +101 -0
- package/dist/lib/workspace.d.ts +66 -0
- package/dist/lib/workspace.js +204 -0
- package/oclif.manifest.json +10593 -0
- package/package.json +103 -56
- package/LICENSE +0 -21
- package/dist/bin/prlt.d.ts +0 -11
- package/dist/bin/prlt.d.ts.map +0 -1
- package/dist/bin/prlt.js +0 -144
- package/dist/bin/prlt.js.map +0 -1
- package/dist/lib/config/index.d.ts +0 -14
- package/dist/lib/config/index.d.ts.map +0 -1
- package/dist/lib/config/index.js +0 -142
- package/dist/lib/config/index.js.map +0 -1
- package/dist/lib/config/upgrade.d.ts +0 -2
- package/dist/lib/config/upgrade.d.ts.map +0 -1
- package/dist/lib/config/upgrade.js +0 -248
- package/dist/lib/config/upgrade.js.map +0 -1
- package/dist/lib/themes/index.d.ts +0 -8
- package/dist/lib/themes/index.d.ts.map +0 -1
- package/dist/lib/themes/index.js +0 -80
- package/dist/lib/themes/index.js.map +0 -1
- package/dist/lib/utils/helpers.d.ts +0 -4
- package/dist/lib/utils/helpers.d.ts.map +0 -1
- package/dist/lib/utils/helpers.js +0 -39
- package/dist/lib/utils/helpers.js.map +0 -1
- package/dist/lib/utils/logger.d.ts +0 -4
- package/dist/lib/utils/logger.d.ts.map +0 -1
- package/dist/lib/utils/logger.js +0 -28
- package/dist/lib/utils/logger.js.map +0 -1
- package/dist/lib/workspace/index.d.ts +0 -13
- package/dist/lib/workspace/index.d.ts.map +0 -1
- package/dist/lib/workspace/index.js +0 -116
- package/dist/lib/workspace/index.js.map +0 -1
- package/dist/lib/worktree/index.d.ts +0 -7
- package/dist/lib/worktree/index.d.ts.map +0 -1
- package/dist/lib/worktree/index.js +0 -362
- package/dist/lib/worktree/index.js.map +0 -1
- package/dist/lib/worktree/migrate.d.ts +0 -2
- package/dist/lib/worktree/migrate.d.ts.map +0 -1
- package/dist/lib/worktree/migrate.js +0 -214
- package/dist/lib/worktree/migrate.js.map +0 -1
- package/dist/lib/worktree/repair.d.ts +0 -3
- package/dist/lib/worktree/repair.d.ts.map +0 -1
- package/dist/lib/worktree/repair.js +0 -320
- package/dist/lib/worktree/repair.js.map +0 -1
- package/dist/types/index.d.ts +0 -57
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/index.js +0 -3
- package/dist/types/index.js.map +0 -1
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dependency operations for tickets, specs, and epics.
|
|
3
|
+
*/
|
|
4
|
+
import { EpicDependency, EpicDependencyType, SpecDependency, SpecDependencyType, Ticket, TicketDependency, TicketDependencyType } from '../types.js';
|
|
5
|
+
import { StorageContext } from './types.js';
|
|
6
|
+
export declare class DependencyStorage {
|
|
7
|
+
private ctx;
|
|
8
|
+
constructor(ctx: StorageContext);
|
|
9
|
+
/**
|
|
10
|
+
* Create a dependency between two tickets.
|
|
11
|
+
*/
|
|
12
|
+
createTicketDependency(ticketId: string, dependsOnTicketId: string, dependencyType?: TicketDependencyType): Promise<TicketDependency>;
|
|
13
|
+
/**
|
|
14
|
+
* Delete a ticket dependency.
|
|
15
|
+
*/
|
|
16
|
+
deleteTicketDependency(ticketId: string, dependsOnTicketId: string, dependencyType?: TicketDependencyType): Promise<void>;
|
|
17
|
+
/**
|
|
18
|
+
* List dependencies for a ticket.
|
|
19
|
+
*/
|
|
20
|
+
listTicketDependencies(ticketId: string): Promise<TicketDependency[]>;
|
|
21
|
+
/**
|
|
22
|
+
* Get tickets that this ticket depends on (blockers).
|
|
23
|
+
*/
|
|
24
|
+
getTicketBlockers(ticketId: string): Promise<Ticket[]>;
|
|
25
|
+
/**
|
|
26
|
+
* Get tickets that depend on this ticket (blocking).
|
|
27
|
+
*/
|
|
28
|
+
getTicketsBlockedBy(ticketId: string): Promise<Ticket[]>;
|
|
29
|
+
/**
|
|
30
|
+
* Check if a ticket is blocked by incomplete dependencies.
|
|
31
|
+
*/
|
|
32
|
+
isTicketBlocked(ticketId: string): Promise<boolean>;
|
|
33
|
+
/**
|
|
34
|
+
* Create a dependency between two specs.
|
|
35
|
+
*/
|
|
36
|
+
createSpecDependency(specId: string, dependsOnSpecId: string, dependencyType?: SpecDependencyType): Promise<SpecDependency>;
|
|
37
|
+
/**
|
|
38
|
+
* Delete a spec dependency.
|
|
39
|
+
*/
|
|
40
|
+
deleteSpecDependency(specId: string, dependsOnSpecId: string, dependencyType?: SpecDependencyType): Promise<void>;
|
|
41
|
+
/**
|
|
42
|
+
* List dependencies for a spec.
|
|
43
|
+
*/
|
|
44
|
+
listSpecDependencies(specId: string): Promise<SpecDependency[]>;
|
|
45
|
+
/**
|
|
46
|
+
* Create a dependency between two epics.
|
|
47
|
+
*/
|
|
48
|
+
createEpicDependency(epicId: string, dependsOnEpicId: string, dependencyType?: EpicDependencyType): Promise<EpicDependency>;
|
|
49
|
+
/**
|
|
50
|
+
* Delete an epic dependency.
|
|
51
|
+
*/
|
|
52
|
+
deleteEpicDependency(epicId: string, dependsOnEpicId: string, dependencyType?: EpicDependencyType): Promise<void>;
|
|
53
|
+
/**
|
|
54
|
+
* List dependencies for an epic.
|
|
55
|
+
*/
|
|
56
|
+
listEpicDependencies(epicId: string): Promise<EpicDependency[]>;
|
|
57
|
+
/**
|
|
58
|
+
* Check if an epic is blocked by incomplete dependencies.
|
|
59
|
+
*/
|
|
60
|
+
isEpicBlocked(epicId: string): Promise<boolean>;
|
|
61
|
+
}
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dependency operations for tickets, specs, and epics.
|
|
3
|
+
*/
|
|
4
|
+
import { PMO_TABLES } from '../schema.js';
|
|
5
|
+
import { PMOError, } from '../types.js';
|
|
6
|
+
import { rowToTicket } from './helpers.js';
|
|
7
|
+
const T = PMO_TABLES;
|
|
8
|
+
export class DependencyStorage {
|
|
9
|
+
ctx;
|
|
10
|
+
constructor(ctx) {
|
|
11
|
+
this.ctx = ctx;
|
|
12
|
+
}
|
|
13
|
+
// =========================================================================
|
|
14
|
+
// Ticket Dependencies
|
|
15
|
+
// =========================================================================
|
|
16
|
+
/**
|
|
17
|
+
* Create a dependency between two tickets.
|
|
18
|
+
*/
|
|
19
|
+
async createTicketDependency(ticketId, dependsOnTicketId, dependencyType = 'blocks') {
|
|
20
|
+
// Validate tickets exist
|
|
21
|
+
const ticket = this.ctx.db.prepare(`SELECT id FROM ${T.tickets} WHERE id = ?`).get(ticketId);
|
|
22
|
+
if (!ticket)
|
|
23
|
+
throw new PMOError('NOT_FOUND', `Ticket not found: ${ticketId}`);
|
|
24
|
+
const dependsOn = this.ctx.db.prepare(`SELECT id FROM ${T.tickets} WHERE id = ?`).get(dependsOnTicketId);
|
|
25
|
+
if (!dependsOn)
|
|
26
|
+
throw new PMOError('NOT_FOUND', `Ticket not found: ${dependsOnTicketId}`);
|
|
27
|
+
try {
|
|
28
|
+
this.ctx.db.prepare(`
|
|
29
|
+
INSERT INTO ${T.ticket_dependencies} (ticket_id, depends_on_ticket_id, dependency_type)
|
|
30
|
+
VALUES (?, ?, ?)
|
|
31
|
+
`).run(ticketId, dependsOnTicketId, dependencyType);
|
|
32
|
+
return {
|
|
33
|
+
ticketId,
|
|
34
|
+
dependsOnTicketId,
|
|
35
|
+
dependencyType,
|
|
36
|
+
createdAt: new Date(),
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
if (error instanceof Error && error.message.includes('UNIQUE constraint')) {
|
|
41
|
+
throw new PMOError('CONFLICT', 'Dependency already exists');
|
|
42
|
+
}
|
|
43
|
+
if (error instanceof Error && error.message.includes('CHECK constraint')) {
|
|
44
|
+
throw new PMOError('INVALID', 'Cannot create self-dependency');
|
|
45
|
+
}
|
|
46
|
+
throw error;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Delete a ticket dependency.
|
|
51
|
+
*/
|
|
52
|
+
async deleteTicketDependency(ticketId, dependsOnTicketId, dependencyType) {
|
|
53
|
+
let query = `DELETE FROM ${T.ticket_dependencies} WHERE ticket_id = ? AND depends_on_ticket_id = ?`;
|
|
54
|
+
const params = [ticketId, dependsOnTicketId];
|
|
55
|
+
if (dependencyType) {
|
|
56
|
+
query += ' AND dependency_type = ?';
|
|
57
|
+
params.push(dependencyType);
|
|
58
|
+
}
|
|
59
|
+
const result = this.ctx.db.prepare(query).run(...params);
|
|
60
|
+
if (result.changes === 0) {
|
|
61
|
+
throw new PMOError('NOT_FOUND', 'Dependency not found');
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* List dependencies for a ticket.
|
|
66
|
+
*/
|
|
67
|
+
async listTicketDependencies(ticketId) {
|
|
68
|
+
const rows = this.ctx.db.prepare(`
|
|
69
|
+
SELECT ticket_id, depends_on_ticket_id, dependency_type, created_at
|
|
70
|
+
FROM ${T.ticket_dependencies}
|
|
71
|
+
WHERE ticket_id = ?
|
|
72
|
+
ORDER BY created_at DESC
|
|
73
|
+
`).all(ticketId);
|
|
74
|
+
return rows.map((row) => ({
|
|
75
|
+
ticketId: row.ticket_id,
|
|
76
|
+
dependsOnTicketId: row.depends_on_ticket_id,
|
|
77
|
+
dependencyType: row.dependency_type,
|
|
78
|
+
createdAt: new Date(row.created_at),
|
|
79
|
+
}));
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Get tickets that this ticket depends on (blockers).
|
|
83
|
+
*/
|
|
84
|
+
async getTicketBlockers(ticketId) {
|
|
85
|
+
const rows = this.ctx.db.prepare(`
|
|
86
|
+
SELECT t.*,
|
|
87
|
+
ws.id as column_id,
|
|
88
|
+
ws.name as column_name,
|
|
89
|
+
ws.position as position
|
|
90
|
+
FROM ${T.tickets} t
|
|
91
|
+
JOIN ${T.ticket_dependencies} d ON t.id = d.depends_on_ticket_id
|
|
92
|
+
LEFT JOIN ${T.workflow_statuses} ws ON t.status_id = ws.id
|
|
93
|
+
WHERE d.ticket_id = ? AND d.dependency_type = 'blocks'
|
|
94
|
+
`).all(ticketId);
|
|
95
|
+
return Promise.all(rows.map((row) => rowToTicket(this.ctx.db, row)));
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Get tickets that depend on this ticket (blocking).
|
|
99
|
+
*/
|
|
100
|
+
async getTicketsBlockedBy(ticketId) {
|
|
101
|
+
const rows = this.ctx.db.prepare(`
|
|
102
|
+
SELECT t.*,
|
|
103
|
+
ws.id as column_id,
|
|
104
|
+
ws.name as column_name,
|
|
105
|
+
ws.position as position
|
|
106
|
+
FROM ${T.tickets} t
|
|
107
|
+
JOIN ${T.ticket_dependencies} d ON t.id = d.ticket_id
|
|
108
|
+
LEFT JOIN ${T.workflow_statuses} ws ON t.status_id = ws.id
|
|
109
|
+
WHERE d.depends_on_ticket_id = ? AND d.dependency_type = 'blocks'
|
|
110
|
+
`).all(ticketId);
|
|
111
|
+
return Promise.all(rows.map((row) => rowToTicket(this.ctx.db, row)));
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Check if a ticket is blocked by incomplete dependencies.
|
|
115
|
+
*/
|
|
116
|
+
async isTicketBlocked(ticketId) {
|
|
117
|
+
const blockers = await this.getTicketBlockers(ticketId);
|
|
118
|
+
return blockers.some((t) => t.status !== 'done' && t.status !== 'canceled');
|
|
119
|
+
}
|
|
120
|
+
// =========================================================================
|
|
121
|
+
// Spec Dependencies
|
|
122
|
+
// =========================================================================
|
|
123
|
+
/**
|
|
124
|
+
* Create a dependency between two specs.
|
|
125
|
+
*/
|
|
126
|
+
async createSpecDependency(specId, dependsOnSpecId, dependencyType = 'depends_on') {
|
|
127
|
+
// Validate specs exist
|
|
128
|
+
const spec = this.ctx.db.prepare(`SELECT id FROM ${T.specs} WHERE id = ?`).get(specId);
|
|
129
|
+
if (!spec)
|
|
130
|
+
throw new PMOError('NOT_FOUND', `Spec not found: ${specId}`);
|
|
131
|
+
const dependsOn = this.ctx.db.prepare(`SELECT id FROM ${T.specs} WHERE id = ?`).get(dependsOnSpecId);
|
|
132
|
+
if (!dependsOn)
|
|
133
|
+
throw new PMOError('NOT_FOUND', `Spec not found: ${dependsOnSpecId}`);
|
|
134
|
+
try {
|
|
135
|
+
this.ctx.db.prepare(`
|
|
136
|
+
INSERT INTO ${T.spec_dependencies} (spec_id, depends_on_spec_id, dependency_type)
|
|
137
|
+
VALUES (?, ?, ?)
|
|
138
|
+
`).run(specId, dependsOnSpecId, dependencyType);
|
|
139
|
+
return {
|
|
140
|
+
specId,
|
|
141
|
+
dependsOnSpecId,
|
|
142
|
+
dependencyType,
|
|
143
|
+
createdAt: new Date(),
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
catch (error) {
|
|
147
|
+
if (error instanceof Error && error.message.includes('UNIQUE constraint')) {
|
|
148
|
+
throw new PMOError('CONFLICT', 'Dependency already exists');
|
|
149
|
+
}
|
|
150
|
+
if (error instanceof Error && error.message.includes('CHECK constraint')) {
|
|
151
|
+
throw new PMOError('INVALID', 'Cannot create self-dependency');
|
|
152
|
+
}
|
|
153
|
+
throw error;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Delete a spec dependency.
|
|
158
|
+
*/
|
|
159
|
+
async deleteSpecDependency(specId, dependsOnSpecId, dependencyType) {
|
|
160
|
+
let query = `DELETE FROM ${T.spec_dependencies} WHERE spec_id = ? AND depends_on_spec_id = ?`;
|
|
161
|
+
const params = [specId, dependsOnSpecId];
|
|
162
|
+
if (dependencyType) {
|
|
163
|
+
query += ' AND dependency_type = ?';
|
|
164
|
+
params.push(dependencyType);
|
|
165
|
+
}
|
|
166
|
+
const result = this.ctx.db.prepare(query).run(...params);
|
|
167
|
+
if (result.changes === 0) {
|
|
168
|
+
throw new PMOError('NOT_FOUND', 'Dependency not found');
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* List dependencies for a spec.
|
|
173
|
+
*/
|
|
174
|
+
async listSpecDependencies(specId) {
|
|
175
|
+
const rows = this.ctx.db.prepare(`
|
|
176
|
+
SELECT spec_id, depends_on_spec_id, dependency_type, created_at
|
|
177
|
+
FROM ${T.spec_dependencies}
|
|
178
|
+
WHERE spec_id = ?
|
|
179
|
+
ORDER BY created_at DESC
|
|
180
|
+
`).all(specId);
|
|
181
|
+
return rows.map((row) => ({
|
|
182
|
+
specId: row.spec_id,
|
|
183
|
+
dependsOnSpecId: row.depends_on_spec_id,
|
|
184
|
+
dependencyType: row.dependency_type,
|
|
185
|
+
createdAt: new Date(row.created_at),
|
|
186
|
+
}));
|
|
187
|
+
}
|
|
188
|
+
// =========================================================================
|
|
189
|
+
// Epic Dependencies
|
|
190
|
+
// =========================================================================
|
|
191
|
+
/**
|
|
192
|
+
* Create a dependency between two epics.
|
|
193
|
+
*/
|
|
194
|
+
async createEpicDependency(epicId, dependsOnEpicId, dependencyType = 'blocks') {
|
|
195
|
+
// Validate epics exist
|
|
196
|
+
const epic = this.ctx.db.prepare(`SELECT id FROM ${T.epics} WHERE id = ?`).get(epicId);
|
|
197
|
+
if (!epic)
|
|
198
|
+
throw new PMOError('NOT_FOUND', `Epic not found: ${epicId}`);
|
|
199
|
+
const dependsOn = this.ctx.db.prepare(`SELECT id FROM ${T.epics} WHERE id = ?`).get(dependsOnEpicId);
|
|
200
|
+
if (!dependsOn)
|
|
201
|
+
throw new PMOError('NOT_FOUND', `Epic not found: ${dependsOnEpicId}`);
|
|
202
|
+
try {
|
|
203
|
+
this.ctx.db.prepare(`
|
|
204
|
+
INSERT INTO ${T.epic_dependencies} (epic_id, depends_on_epic_id, dependency_type)
|
|
205
|
+
VALUES (?, ?, ?)
|
|
206
|
+
`).run(epicId, dependsOnEpicId, dependencyType);
|
|
207
|
+
return {
|
|
208
|
+
epicId,
|
|
209
|
+
dependsOnEpicId,
|
|
210
|
+
dependencyType,
|
|
211
|
+
createdAt: new Date(),
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
catch (error) {
|
|
215
|
+
if (error instanceof Error && error.message.includes('UNIQUE constraint')) {
|
|
216
|
+
throw new PMOError('CONFLICT', 'Dependency already exists');
|
|
217
|
+
}
|
|
218
|
+
if (error instanceof Error && error.message.includes('CHECK constraint')) {
|
|
219
|
+
throw new PMOError('INVALID', 'Cannot create self-dependency');
|
|
220
|
+
}
|
|
221
|
+
throw error;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Delete an epic dependency.
|
|
226
|
+
*/
|
|
227
|
+
async deleteEpicDependency(epicId, dependsOnEpicId, dependencyType) {
|
|
228
|
+
let query = `DELETE FROM ${T.epic_dependencies} WHERE epic_id = ? AND depends_on_epic_id = ?`;
|
|
229
|
+
const params = [epicId, dependsOnEpicId];
|
|
230
|
+
if (dependencyType) {
|
|
231
|
+
query += ' AND dependency_type = ?';
|
|
232
|
+
params.push(dependencyType);
|
|
233
|
+
}
|
|
234
|
+
const result = this.ctx.db.prepare(query).run(...params);
|
|
235
|
+
if (result.changes === 0) {
|
|
236
|
+
throw new PMOError('NOT_FOUND', 'Dependency not found');
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* List dependencies for an epic.
|
|
241
|
+
*/
|
|
242
|
+
async listEpicDependencies(epicId) {
|
|
243
|
+
const rows = this.ctx.db.prepare(`
|
|
244
|
+
SELECT epic_id, depends_on_epic_id, dependency_type, created_at
|
|
245
|
+
FROM ${T.epic_dependencies}
|
|
246
|
+
WHERE epic_id = ?
|
|
247
|
+
ORDER BY created_at DESC
|
|
248
|
+
`).all(epicId);
|
|
249
|
+
return rows.map((row) => ({
|
|
250
|
+
epicId: row.epic_id,
|
|
251
|
+
dependsOnEpicId: row.depends_on_epic_id,
|
|
252
|
+
dependencyType: row.dependency_type,
|
|
253
|
+
createdAt: new Date(row.created_at),
|
|
254
|
+
}));
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Check if an epic is blocked by incomplete dependencies.
|
|
258
|
+
*/
|
|
259
|
+
async isEpicBlocked(epicId) {
|
|
260
|
+
const rows = this.ctx.db.prepare(`
|
|
261
|
+
SELECT e.status FROM ${T.epics} e
|
|
262
|
+
JOIN ${T.epic_dependencies} d ON e.id = d.depends_on_epic_id
|
|
263
|
+
WHERE d.epic_id = ? AND d.dependency_type = 'blocks'
|
|
264
|
+
`).all(epicId);
|
|
265
|
+
return rows.some((r) => r.status !== 'complete' && r.status !== 'dropped');
|
|
266
|
+
}
|
|
267
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Epic operations for PMO.
|
|
3
|
+
*/
|
|
4
|
+
import { Epic, EpicFilter, Ticket } from '../types.js';
|
|
5
|
+
import { StorageContext } from './types.js';
|
|
6
|
+
export declare class EpicStorage {
|
|
7
|
+
private ctx;
|
|
8
|
+
constructor(ctx: StorageContext);
|
|
9
|
+
/**
|
|
10
|
+
* Create a new epic.
|
|
11
|
+
*/
|
|
12
|
+
createEpic(projectId: string, epic: Partial<Epic>): Promise<Epic>;
|
|
13
|
+
/**
|
|
14
|
+
* Get an epic by ID.
|
|
15
|
+
*/
|
|
16
|
+
getEpic(id: string): Promise<Epic | null>;
|
|
17
|
+
/**
|
|
18
|
+
* List epics with optional filters.
|
|
19
|
+
*/
|
|
20
|
+
listEpics(projectId: string, filter?: EpicFilter): Promise<Epic[]>;
|
|
21
|
+
/**
|
|
22
|
+
* Reorder an epic to a new position.
|
|
23
|
+
*/
|
|
24
|
+
reorderEpic(projectId: string, epicId: string, newPosition: number): Promise<Epic>;
|
|
25
|
+
/**
|
|
26
|
+
* Update an epic.
|
|
27
|
+
*/
|
|
28
|
+
updateEpic(id: string, changes: Partial<Epic>): Promise<Epic>;
|
|
29
|
+
/**
|
|
30
|
+
* Delete an epic.
|
|
31
|
+
*/
|
|
32
|
+
deleteEpic(id: string): Promise<void>;
|
|
33
|
+
/**
|
|
34
|
+
* Get tickets for an epic.
|
|
35
|
+
*/
|
|
36
|
+
getTicketsForEpic(projectId: string, epicId: string): Promise<Ticket[]>;
|
|
37
|
+
/**
|
|
38
|
+
* Link a ticket to an epic.
|
|
39
|
+
*/
|
|
40
|
+
linkTicketToEpic(ticketId: string, epicId: string): Promise<void>;
|
|
41
|
+
/**
|
|
42
|
+
* Unlink a ticket from its epic.
|
|
43
|
+
*/
|
|
44
|
+
unlinkTicketFromEpic(ticketId: string): Promise<void>;
|
|
45
|
+
private rowToEpic;
|
|
46
|
+
}
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Epic operations for PMO.
|
|
3
|
+
*/
|
|
4
|
+
import { PMO_TABLES } from '../schema.js';
|
|
5
|
+
import { PMOError } from '../types.js';
|
|
6
|
+
import { generateEntityId } from '../utils.js';
|
|
7
|
+
import { rowToTicket } from './helpers.js';
|
|
8
|
+
const T = PMO_TABLES;
|
|
9
|
+
export class EpicStorage {
|
|
10
|
+
ctx;
|
|
11
|
+
constructor(ctx) {
|
|
12
|
+
this.ctx = ctx;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Create a new epic.
|
|
16
|
+
*/
|
|
17
|
+
async createEpic(projectId, epic) {
|
|
18
|
+
const id = epic.id || generateEntityId(this.ctx.db, 'epic');
|
|
19
|
+
const title = epic.title || 'Untitled Epic';
|
|
20
|
+
const status = epic.status || 'active';
|
|
21
|
+
const now = Date.now();
|
|
22
|
+
// Get next position if not provided
|
|
23
|
+
let position = epic.position;
|
|
24
|
+
if (position === undefined) {
|
|
25
|
+
const maxPos = this.ctx.db.prepare(`
|
|
26
|
+
SELECT COALESCE(MAX(position), -1) as max_pos FROM ${T.epics} WHERE project_id = ?
|
|
27
|
+
`).get(projectId);
|
|
28
|
+
position = maxPos.max_pos + 1;
|
|
29
|
+
}
|
|
30
|
+
this.ctx.db.prepare(`
|
|
31
|
+
INSERT INTO ${T.epics} (id, project_id, title, description, status, position, file_path, spec_id, created_at, updated_at)
|
|
32
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
33
|
+
`).run(id, projectId, title, epic.description || null, status, position, epic.filePath || null, epic.specId || null, now, now);
|
|
34
|
+
this.ctx.updateBoardTimestamp(projectId);
|
|
35
|
+
return {
|
|
36
|
+
id,
|
|
37
|
+
projectId,
|
|
38
|
+
title,
|
|
39
|
+
description: epic.description,
|
|
40
|
+
status,
|
|
41
|
+
position,
|
|
42
|
+
filePath: epic.filePath,
|
|
43
|
+
specId: epic.specId,
|
|
44
|
+
createdAt: new Date(now),
|
|
45
|
+
updatedAt: new Date(now),
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Get an epic by ID.
|
|
50
|
+
*/
|
|
51
|
+
async getEpic(id) {
|
|
52
|
+
const row = this.ctx.db.prepare(`
|
|
53
|
+
SELECT * FROM ${T.epics} WHERE id = ?
|
|
54
|
+
`).get(id);
|
|
55
|
+
if (!row)
|
|
56
|
+
return null;
|
|
57
|
+
return this.rowToEpic(row);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* List epics with optional filters.
|
|
61
|
+
*/
|
|
62
|
+
async listEpics(projectId, filter) {
|
|
63
|
+
let query = `SELECT * FROM ${T.epics} WHERE project_id = ?`;
|
|
64
|
+
const params = [projectId];
|
|
65
|
+
if (filter?.status) {
|
|
66
|
+
query += ' AND status = ?';
|
|
67
|
+
params.push(filter.status);
|
|
68
|
+
}
|
|
69
|
+
if (filter?.search) {
|
|
70
|
+
query += ' AND (title LIKE ? OR description LIKE ?)';
|
|
71
|
+
params.push(`%${filter.search}%`, `%${filter.search}%`);
|
|
72
|
+
}
|
|
73
|
+
query += ' ORDER BY position ASC, created_at ASC';
|
|
74
|
+
const rows = this.ctx.db.prepare(query).all(...params);
|
|
75
|
+
return rows.map((row) => this.rowToEpic(row));
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Reorder an epic to a new position.
|
|
79
|
+
*/
|
|
80
|
+
async reorderEpic(projectId, epicId, newPosition) {
|
|
81
|
+
const epic = await this.getEpic(epicId);
|
|
82
|
+
if (!epic) {
|
|
83
|
+
throw new Error(`Epic not found: ${epicId}`);
|
|
84
|
+
}
|
|
85
|
+
const oldPosition = epic.position;
|
|
86
|
+
if (oldPosition === newPosition) {
|
|
87
|
+
return epic;
|
|
88
|
+
}
|
|
89
|
+
if (newPosition < oldPosition) {
|
|
90
|
+
this.ctx.db.prepare(`
|
|
91
|
+
UPDATE ${T.epics}
|
|
92
|
+
SET position = position + 1, updated_at = ?
|
|
93
|
+
WHERE project_id = ? AND position >= ? AND position < ?
|
|
94
|
+
`).run(Date.now(), projectId, newPosition, oldPosition);
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
this.ctx.db.prepare(`
|
|
98
|
+
UPDATE ${T.epics}
|
|
99
|
+
SET position = position - 1, updated_at = ?
|
|
100
|
+
WHERE project_id = ? AND position > ? AND position <= ?
|
|
101
|
+
`).run(Date.now(), projectId, oldPosition, newPosition);
|
|
102
|
+
}
|
|
103
|
+
this.ctx.db.prepare(`
|
|
104
|
+
UPDATE ${T.epics}
|
|
105
|
+
SET position = ?, updated_at = ?
|
|
106
|
+
WHERE id = ?
|
|
107
|
+
`).run(newPosition, Date.now(), epicId);
|
|
108
|
+
this.ctx.updateBoardTimestamp(projectId);
|
|
109
|
+
return (await this.getEpic(epicId));
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Update an epic.
|
|
113
|
+
*/
|
|
114
|
+
async updateEpic(id, changes) {
|
|
115
|
+
const epic = await this.getEpic(id);
|
|
116
|
+
if (!epic) {
|
|
117
|
+
throw new PMOError('NOT_FOUND', `Epic not found: ${id}`);
|
|
118
|
+
}
|
|
119
|
+
const updates = [];
|
|
120
|
+
const params = [];
|
|
121
|
+
if (changes.title !== undefined) {
|
|
122
|
+
updates.push('title = ?');
|
|
123
|
+
params.push(changes.title);
|
|
124
|
+
}
|
|
125
|
+
if (changes.description !== undefined) {
|
|
126
|
+
updates.push('description = ?');
|
|
127
|
+
params.push(changes.description);
|
|
128
|
+
}
|
|
129
|
+
if (changes.status !== undefined) {
|
|
130
|
+
updates.push('status = ?');
|
|
131
|
+
params.push(changes.status);
|
|
132
|
+
}
|
|
133
|
+
if (changes.filePath !== undefined) {
|
|
134
|
+
updates.push('file_path = ?');
|
|
135
|
+
params.push(changes.filePath);
|
|
136
|
+
}
|
|
137
|
+
if (changes.specId !== undefined) {
|
|
138
|
+
updates.push('spec_id = ?');
|
|
139
|
+
params.push(changes.specId || null);
|
|
140
|
+
}
|
|
141
|
+
if (updates.length > 0) {
|
|
142
|
+
updates.push('updated_at = ?');
|
|
143
|
+
params.push(Date.now());
|
|
144
|
+
params.push(id);
|
|
145
|
+
this.ctx.db.prepare(`UPDATE ${T.epics} SET ${updates.join(', ')} WHERE id = ?`).run(...params);
|
|
146
|
+
}
|
|
147
|
+
this.ctx.updateBoardTimestamp(epic.projectId);
|
|
148
|
+
return (await this.getEpic(id));
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Delete an epic.
|
|
152
|
+
*/
|
|
153
|
+
async deleteEpic(id) {
|
|
154
|
+
const epic = await this.getEpic(id);
|
|
155
|
+
if (!epic) {
|
|
156
|
+
throw new PMOError('NOT_FOUND', `Epic not found: ${id}`);
|
|
157
|
+
}
|
|
158
|
+
// Unlink tickets from this epic
|
|
159
|
+
this.ctx.db.prepare(`
|
|
160
|
+
UPDATE ${T.tickets} SET epic_id = NULL WHERE epic_id = ?
|
|
161
|
+
`).run(id);
|
|
162
|
+
this.ctx.db.prepare(`DELETE FROM ${T.epics} WHERE id = ?`).run(id);
|
|
163
|
+
this.ctx.updateBoardTimestamp(epic.projectId);
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Get tickets for an epic.
|
|
167
|
+
*/
|
|
168
|
+
async getTicketsForEpic(projectId, epicId) {
|
|
169
|
+
const rows = this.ctx.db.prepare(`
|
|
170
|
+
SELECT t.*,
|
|
171
|
+
ws.id as column_id,
|
|
172
|
+
ws.position as position,
|
|
173
|
+
ws.name as column_name
|
|
174
|
+
FROM ${T.tickets} t
|
|
175
|
+
LEFT JOIN ${T.workflow_statuses} ws ON t.status_id = ws.id
|
|
176
|
+
WHERE t.project_id = ? AND t.epic_id = ?
|
|
177
|
+
ORDER BY ws.position,
|
|
178
|
+
CASE t.priority
|
|
179
|
+
WHEN 'P0' THEN 0
|
|
180
|
+
WHEN 'P1' THEN 1
|
|
181
|
+
WHEN 'P2' THEN 2
|
|
182
|
+
WHEN 'P3' THEN 3
|
|
183
|
+
ELSE 4
|
|
184
|
+
END,
|
|
185
|
+
t.created_at ASC
|
|
186
|
+
`).all(projectId, epicId);
|
|
187
|
+
return Promise.all(rows.map((row) => rowToTicket(this.ctx.db, row)));
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Link a ticket to an epic.
|
|
191
|
+
*/
|
|
192
|
+
async linkTicketToEpic(ticketId, epicId) {
|
|
193
|
+
// Verify ticket exists and get its project
|
|
194
|
+
const ticket = this.ctx.db.prepare(`
|
|
195
|
+
SELECT id, project_id FROM ${T.tickets} WHERE id = ?
|
|
196
|
+
`).get(ticketId);
|
|
197
|
+
if (!ticket) {
|
|
198
|
+
throw new PMOError('NOT_FOUND', `Ticket not found: ${ticketId}`, ticketId);
|
|
199
|
+
}
|
|
200
|
+
// Verify epic exists
|
|
201
|
+
const epic = await this.getEpic(epicId);
|
|
202
|
+
if (!epic) {
|
|
203
|
+
throw new PMOError('NOT_FOUND', `Epic not found: ${epicId}`);
|
|
204
|
+
}
|
|
205
|
+
this.ctx.db.prepare(`
|
|
206
|
+
UPDATE ${T.tickets}
|
|
207
|
+
SET epic_id = ?, updated_at = ?
|
|
208
|
+
WHERE id = ?
|
|
209
|
+
`).run(epicId, Date.now(), ticketId);
|
|
210
|
+
this.ctx.updateBoardTimestamp(ticket.project_id);
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Unlink a ticket from its epic.
|
|
214
|
+
*/
|
|
215
|
+
async unlinkTicketFromEpic(ticketId) {
|
|
216
|
+
// Get ticket's project for board timestamp update
|
|
217
|
+
const ticket = this.ctx.db.prepare(`
|
|
218
|
+
SELECT project_id FROM ${T.tickets} WHERE id = ?
|
|
219
|
+
`).get(ticketId);
|
|
220
|
+
this.ctx.db.prepare(`
|
|
221
|
+
UPDATE ${T.tickets}
|
|
222
|
+
SET epic_id = NULL, updated_at = ?
|
|
223
|
+
WHERE id = ?
|
|
224
|
+
`).run(Date.now(), ticketId);
|
|
225
|
+
if (ticket) {
|
|
226
|
+
this.ctx.updateBoardTimestamp(ticket.project_id);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
rowToEpic(row) {
|
|
230
|
+
return {
|
|
231
|
+
id: row.id,
|
|
232
|
+
projectId: row.project_id,
|
|
233
|
+
title: row.title,
|
|
234
|
+
description: row.description || undefined,
|
|
235
|
+
status: row.status,
|
|
236
|
+
position: row.position,
|
|
237
|
+
filePath: row.file_path || undefined,
|
|
238
|
+
specId: row.spec_id || undefined,
|
|
239
|
+
createdAt: new Date(row.created_at),
|
|
240
|
+
updatedAt: new Date(row.updated_at),
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Helper functions for converting database rows to domain types.
|
|
3
|
+
*/
|
|
4
|
+
import Database from 'better-sqlite3';
|
|
5
|
+
import { AcceptanceCriterion, Spec, StateCategory, Ticket } from '../types.js';
|
|
6
|
+
import { SpecRow, TicketRow, WorkflowStatusRow } from './types.js';
|
|
7
|
+
/**
|
|
8
|
+
* Convert a database row to a Ticket object.
|
|
9
|
+
* Fetches related data (subtasks, metadata, status info).
|
|
10
|
+
*/
|
|
11
|
+
export declare function rowToTicket(db: Database.Database, row: TicketRow): Promise<Ticket>;
|
|
12
|
+
/**
|
|
13
|
+
* Get acceptance criteria for a ticket (sync version).
|
|
14
|
+
*/
|
|
15
|
+
export declare function getAcceptanceCriteriaSync(db: Database.Database, ticketId: string): AcceptanceCriterion[];
|
|
16
|
+
/**
|
|
17
|
+
* Convert a database row to a Spec object.
|
|
18
|
+
*/
|
|
19
|
+
export declare function rowToSpec(row: SpecRow): Spec;
|
|
20
|
+
/**
|
|
21
|
+
* Convert a workflow status database row to WorkflowStatus.
|
|
22
|
+
*/
|
|
23
|
+
export declare function rowToStatus(row: WorkflowStatusRow): {
|
|
24
|
+
id: string;
|
|
25
|
+
workflowId: string;
|
|
26
|
+
name: string;
|
|
27
|
+
category: StateCategory;
|
|
28
|
+
position: number;
|
|
29
|
+
color: string | undefined;
|
|
30
|
+
description: string | undefined;
|
|
31
|
+
isDefault: boolean;
|
|
32
|
+
createdAt: Date;
|
|
33
|
+
};
|