@proletariat/cli 0.2.0 → 0.3.0
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 +512 -253
- 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,333 @@
|
|
|
1
|
+
import { Args, Flags } from '@oclif/core';
|
|
2
|
+
import inquirer from 'inquirer';
|
|
3
|
+
import { PMOCommand, pmoBaseFlags, autoExportToBoard } from '../../lib/pmo/index.js';
|
|
4
|
+
import { styles } from '../../lib/styles.js';
|
|
5
|
+
import { shouldOutputJson, outputErrorAsJson, createMetadata, } from '../../lib/prompt-json.js';
|
|
6
|
+
export default class TicketEpic extends PMOCommand {
|
|
7
|
+
static description = 'Assign ticket(s) to an epic (parent-child relationship)';
|
|
8
|
+
static examples = [
|
|
9
|
+
'<%= config.bin %> <%= command.id %> TKT-001 EPIC-001',
|
|
10
|
+
'<%= config.bin %> <%= command.id %> TKT-001 --unlink',
|
|
11
|
+
'<%= config.bin %> <%= command.id %>',
|
|
12
|
+
'<%= config.bin %> <%= command.id %> --bulk --to-epic EPIC-001',
|
|
13
|
+
];
|
|
14
|
+
static args = {
|
|
15
|
+
id: Args.string({
|
|
16
|
+
description: 'Ticket ID',
|
|
17
|
+
required: false,
|
|
18
|
+
}),
|
|
19
|
+
'epic-id': Args.string({
|
|
20
|
+
description: 'Epic ID to link to',
|
|
21
|
+
required: false,
|
|
22
|
+
}),
|
|
23
|
+
};
|
|
24
|
+
static flags = {
|
|
25
|
+
...pmoBaseFlags,
|
|
26
|
+
json: Flags.boolean({
|
|
27
|
+
description: 'Output prompt configuration as JSON (for AI agents/scripts)',
|
|
28
|
+
default: false,
|
|
29
|
+
}),
|
|
30
|
+
unlink: Flags.boolean({
|
|
31
|
+
char: 'u',
|
|
32
|
+
description: 'Remove epic link instead of adding',
|
|
33
|
+
default: false,
|
|
34
|
+
}),
|
|
35
|
+
bulk: Flags.boolean({
|
|
36
|
+
char: 'b',
|
|
37
|
+
description: 'Enable bulk mode to link multiple tickets to an epic',
|
|
38
|
+
default: false,
|
|
39
|
+
}),
|
|
40
|
+
'to-epic': Flags.string({
|
|
41
|
+
description: 'Target epic ID (for bulk mode)',
|
|
42
|
+
}),
|
|
43
|
+
'from-epic': Flags.string({
|
|
44
|
+
description: 'Filter tickets by current epic (bulk mode)',
|
|
45
|
+
}),
|
|
46
|
+
force: Flags.boolean({
|
|
47
|
+
char: 'f',
|
|
48
|
+
description: 'Skip confirmation prompt (bulk mode)',
|
|
49
|
+
default: false,
|
|
50
|
+
}),
|
|
51
|
+
};
|
|
52
|
+
async execute() {
|
|
53
|
+
const { args, flags } = await this.parse(TicketEpic);
|
|
54
|
+
const filterProjectId = flags.project;
|
|
55
|
+
// Check if JSON output mode is active
|
|
56
|
+
const jsonMode = shouldOutputJson(flags);
|
|
57
|
+
// Bulk mode
|
|
58
|
+
if (flags.bulk) {
|
|
59
|
+
await this.executeBulk(flags);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
// Get all tickets
|
|
63
|
+
const allTickets = await this.storage.listTickets(filterProjectId);
|
|
64
|
+
if (allTickets.length === 0) {
|
|
65
|
+
if (jsonMode) {
|
|
66
|
+
outputErrorAsJson('NO_TICKETS', 'No tickets found.', createMetadata('ticket epic', flags));
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
this.log(styles.muted('\nNo tickets found.'));
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
// Get project for epics - use first ticket's project or prompt
|
|
73
|
+
const projectId = await this.requireProject();
|
|
74
|
+
// Get all epics
|
|
75
|
+
const epics = await this.storage.listEpics(projectId);
|
|
76
|
+
// Get epic_id for each ticket via direct DB query
|
|
77
|
+
const db = this.storage.db;
|
|
78
|
+
const getTicketEpicId = (ticketId) => {
|
|
79
|
+
const row = db.prepare(`SELECT epic_id FROM pmo_tickets WHERE id = ?`).get(ticketId);
|
|
80
|
+
return row?.epic_id || null;
|
|
81
|
+
};
|
|
82
|
+
let ticketId = args.id;
|
|
83
|
+
let epicId = args['epic-id'];
|
|
84
|
+
// If unlinking, we don't need an epic ID
|
|
85
|
+
if (flags.unlink) {
|
|
86
|
+
epicId = undefined;
|
|
87
|
+
}
|
|
88
|
+
// If no ticket ID provided, prompt for selection
|
|
89
|
+
if (!ticketId) {
|
|
90
|
+
const ticketChoices = allTickets.map((t) => {
|
|
91
|
+
const currentEpicId = getTicketEpicId(t.id);
|
|
92
|
+
const epicLabel = currentEpicId
|
|
93
|
+
? epics.find(e => e.id === currentEpicId)?.title || currentEpicId
|
|
94
|
+
: 'No epic';
|
|
95
|
+
return {
|
|
96
|
+
id: t.id,
|
|
97
|
+
name: `${t.id} - ${t.title} (${t.statusName || t.status}) [${epicLabel}]`,
|
|
98
|
+
};
|
|
99
|
+
});
|
|
100
|
+
const selected = await this.selectFromList({
|
|
101
|
+
message: 'Select ticket to link:',
|
|
102
|
+
items: ticketChoices,
|
|
103
|
+
getName: (t) => t.name,
|
|
104
|
+
getValue: (t) => t.id,
|
|
105
|
+
getCommand: (t) => `prlt ticket epic ${t.id} --json`,
|
|
106
|
+
jsonMode: jsonMode ? { flags, commandName: 'ticket epic' } : null,
|
|
107
|
+
});
|
|
108
|
+
if (!selected) {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
ticketId = selected;
|
|
112
|
+
}
|
|
113
|
+
// Validate ticket exists
|
|
114
|
+
const ticket = allTickets.find((t) => t.id === ticketId);
|
|
115
|
+
if (!ticket) {
|
|
116
|
+
this.error(`Ticket not found: ${ticketId}`);
|
|
117
|
+
}
|
|
118
|
+
const currentEpicId = getTicketEpicId(ticketId);
|
|
119
|
+
// If unlinking, just remove the link
|
|
120
|
+
if (flags.unlink) {
|
|
121
|
+
if (!currentEpicId) {
|
|
122
|
+
this.log(styles.muted(`\nTicket ${ticketId} is not linked to any epic.`));
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
const currentEpic = epics.find(e => e.id === currentEpicId);
|
|
126
|
+
// Update the ticket
|
|
127
|
+
db.prepare(`
|
|
128
|
+
UPDATE pmo_tickets
|
|
129
|
+
SET epic_id = NULL, updated_at = ?
|
|
130
|
+
WHERE id = ?
|
|
131
|
+
`).run(Date.now(), ticketId);
|
|
132
|
+
await autoExportToBoard(this.pmoPath, this.storage, (msg) => this.log(styles.muted(msg)));
|
|
133
|
+
this.log(styles.success(`\n✅ Unlinked ${styles.emphasis(ticketId)} from ${currentEpic?.title || currentEpicId}`));
|
|
134
|
+
this.log(styles.muted(` Title: ${ticket.title}`));
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
// If no epic ID provided, prompt for selection
|
|
138
|
+
if (!epicId) {
|
|
139
|
+
const epicChoices = epics.map(e => ({
|
|
140
|
+
id: e.id,
|
|
141
|
+
name: `${e.id} ${e.title} (${e.status})${e.id === currentEpicId ? ' ← current' : ''}`,
|
|
142
|
+
}));
|
|
143
|
+
if (epicChoices.length === 0) {
|
|
144
|
+
this.log(styles.muted('\nNo epics found. Create one with: prlt epic create'));
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
// Add "None" option if ticket has an epic
|
|
148
|
+
if (currentEpicId) {
|
|
149
|
+
epicChoices.push({ id: '__none__', name: 'None (remove epic link)' });
|
|
150
|
+
}
|
|
151
|
+
const selected = await this.selectFromList({
|
|
152
|
+
message: 'Link to which epic?',
|
|
153
|
+
items: epicChoices,
|
|
154
|
+
getName: (e) => e.name,
|
|
155
|
+
getValue: (e) => e.id,
|
|
156
|
+
getCommand: (e) => e.id === '__none__' ? `prlt ticket epic ${ticketId} --unlink --json` : `prlt ticket epic ${ticketId} ${e.id} --json`,
|
|
157
|
+
jsonMode: jsonMode ? { flags, commandName: 'ticket epic' } : null,
|
|
158
|
+
});
|
|
159
|
+
if (!selected) {
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
if (selected === '__none__') {
|
|
163
|
+
// Unlink
|
|
164
|
+
db.prepare(`
|
|
165
|
+
UPDATE pmo_tickets
|
|
166
|
+
SET epic_id = NULL, updated_at = ?
|
|
167
|
+
WHERE id = ?
|
|
168
|
+
`).run(Date.now(), ticketId);
|
|
169
|
+
const currentEpic = epics.find(e => e.id === currentEpicId);
|
|
170
|
+
await autoExportToBoard(this.pmoPath, this.storage, (msg) => this.log(styles.muted(msg)));
|
|
171
|
+
this.log(styles.success(`\n✅ Unlinked ${styles.emphasis(ticketId)} from ${currentEpic?.title || currentEpicId}`));
|
|
172
|
+
this.log(styles.muted(` Title: ${ticket.title}`));
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
epicId = selected;
|
|
176
|
+
}
|
|
177
|
+
// Validate epic exists
|
|
178
|
+
const epic = epics.find(e => e.id === epicId);
|
|
179
|
+
if (!epic) {
|
|
180
|
+
this.error(`Epic not found: ${epicId}`);
|
|
181
|
+
}
|
|
182
|
+
// Check if already linked to this epic
|
|
183
|
+
if (currentEpicId === epicId) {
|
|
184
|
+
this.log(styles.muted(`\nTicket ${ticketId} is already linked to ${epic.title}.`));
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
// Update the ticket
|
|
188
|
+
db.prepare(`
|
|
189
|
+
UPDATE pmo_tickets
|
|
190
|
+
SET epic_id = ?, updated_at = ?
|
|
191
|
+
WHERE id = ?
|
|
192
|
+
`).run(epicId, Date.now(), ticketId);
|
|
193
|
+
await autoExportToBoard(this.pmoPath, this.storage, (msg) => this.log(styles.muted(msg)));
|
|
194
|
+
this.log(styles.success(`\n✅ Linked ${styles.emphasis(ticketId)} to ${styles.emphasis(epicId)}`));
|
|
195
|
+
this.log(styles.muted(` Title: ${ticket.title}`));
|
|
196
|
+
this.log(styles.muted(` Epic: ${epic.title}`));
|
|
197
|
+
}
|
|
198
|
+
async executeBulk(flags) {
|
|
199
|
+
this.log(styles.emphasis('🔗 Link Tickets to Epic\n'));
|
|
200
|
+
// Get project first
|
|
201
|
+
const projectId = await this.requireProject();
|
|
202
|
+
// Get all tickets
|
|
203
|
+
const allTickets = await this.storage.listTickets(projectId);
|
|
204
|
+
if (allTickets.length === 0) {
|
|
205
|
+
this.log(styles.warning('No tickets found.'));
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
// Get epics from database
|
|
209
|
+
const db = this.storage.db;
|
|
210
|
+
const epics = db.prepare(`
|
|
211
|
+
SELECT id, title, status FROM pmo_epics
|
|
212
|
+
WHERE project_id = ?
|
|
213
|
+
ORDER BY status, title
|
|
214
|
+
`).all(projectId);
|
|
215
|
+
// Filter tickets if --from-epic specified
|
|
216
|
+
let filteredTickets = allTickets;
|
|
217
|
+
if (flags['from-epic']) {
|
|
218
|
+
// Get tickets with matching epic_id via metadata or direct query
|
|
219
|
+
const epicTickets = db.prepare(`
|
|
220
|
+
SELECT id FROM pmo_tickets
|
|
221
|
+
WHERE project_id = ? AND epic_id = ?
|
|
222
|
+
`).all(projectId, flags['from-epic']);
|
|
223
|
+
const epicTicketIds = new Set(epicTickets.map(t => t.id));
|
|
224
|
+
filteredTickets = allTickets.filter(t => epicTicketIds.has(t.id));
|
|
225
|
+
}
|
|
226
|
+
if (filteredTickets.length === 0) {
|
|
227
|
+
this.log(styles.warning('No tickets found matching filter.'));
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
// Get current epic for each ticket
|
|
231
|
+
const ticketEpics = new Map();
|
|
232
|
+
for (const ticket of filteredTickets) {
|
|
233
|
+
const row = db.prepare(`
|
|
234
|
+
SELECT epic_id FROM pmo_tickets WHERE id = ?
|
|
235
|
+
`).get(ticket.id);
|
|
236
|
+
ticketEpics.set(ticket.id, row?.epic_id || null);
|
|
237
|
+
}
|
|
238
|
+
// Select tickets to link
|
|
239
|
+
const { selectedTickets } = await inquirer.prompt([{
|
|
240
|
+
type: 'checkbox',
|
|
241
|
+
name: 'selectedTickets',
|
|
242
|
+
message: 'Select tickets to link:',
|
|
243
|
+
choices: filteredTickets.map(t => {
|
|
244
|
+
const epicId = ticketEpics.get(t.id);
|
|
245
|
+
const epicTitle = epicId ? epics.find(e => e.id === epicId)?.title || epicId : '(none)';
|
|
246
|
+
return {
|
|
247
|
+
name: `${t.id} - ${t.title} [Epic: ${epicTitle}]`,
|
|
248
|
+
value: t.id,
|
|
249
|
+
};
|
|
250
|
+
}),
|
|
251
|
+
}]);
|
|
252
|
+
if (selectedTickets.length === 0) {
|
|
253
|
+
this.log(styles.muted('No tickets selected.'));
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
// Select target epic
|
|
257
|
+
let targetEpic = flags['to-epic'];
|
|
258
|
+
if (targetEpic === undefined) {
|
|
259
|
+
const { epic } = await inquirer.prompt([{
|
|
260
|
+
type: 'list',
|
|
261
|
+
name: 'epic',
|
|
262
|
+
message: 'Link to which epic?',
|
|
263
|
+
choices: [
|
|
264
|
+
{ name: 'None (remove epic link)', value: null },
|
|
265
|
+
...epics.map(e => ({
|
|
266
|
+
name: `${e.title} (${e.status})`,
|
|
267
|
+
value: e.id,
|
|
268
|
+
})),
|
|
269
|
+
],
|
|
270
|
+
}]);
|
|
271
|
+
targetEpic = epic;
|
|
272
|
+
}
|
|
273
|
+
// Confirmation
|
|
274
|
+
if (!flags.force) {
|
|
275
|
+
const epicLabel = targetEpic
|
|
276
|
+
? epics.find(e => e.id === targetEpic)?.title || targetEpic
|
|
277
|
+
: 'None (removing link)';
|
|
278
|
+
this.log(styles.primary('\nWill link to epic:'));
|
|
279
|
+
this.log(styles.primary(` → ${epicLabel}\n`));
|
|
280
|
+
this.log(styles.primary('Tickets:'));
|
|
281
|
+
for (const ticketId of selectedTickets) {
|
|
282
|
+
const ticket = filteredTickets.find(t => t.id === ticketId);
|
|
283
|
+
this.log(styles.primary(` • ${ticketId}: ${ticket?.title}`));
|
|
284
|
+
}
|
|
285
|
+
this.log('');
|
|
286
|
+
const { confirm } = await inquirer.prompt([{
|
|
287
|
+
type: 'list',
|
|
288
|
+
name: 'confirm',
|
|
289
|
+
message: 'Continue?',
|
|
290
|
+
choices: [
|
|
291
|
+
{ name: 'No, cancel', value: false },
|
|
292
|
+
{ name: 'Yes, link tickets', value: true }
|
|
293
|
+
],
|
|
294
|
+
default: 0
|
|
295
|
+
}]);
|
|
296
|
+
if (!confirm) {
|
|
297
|
+
this.log(styles.muted('Operation cancelled.'));
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
this.log('');
|
|
302
|
+
// Link each ticket
|
|
303
|
+
let successCount = 0;
|
|
304
|
+
let failCount = 0;
|
|
305
|
+
for (const ticketId of selectedTickets) {
|
|
306
|
+
try {
|
|
307
|
+
db.prepare(`
|
|
308
|
+
UPDATE pmo_tickets
|
|
309
|
+
SET epic_id = ?, updated_at = ?
|
|
310
|
+
WHERE id = ?
|
|
311
|
+
`).run(targetEpic, Date.now(), ticketId);
|
|
312
|
+
const action = targetEpic ? `Linked to ${targetEpic}` : 'Removed epic link';
|
|
313
|
+
this.log(styles.success(`${ticketId}: ${action}`));
|
|
314
|
+
successCount++;
|
|
315
|
+
}
|
|
316
|
+
catch (error) {
|
|
317
|
+
this.log(styles.error(`Failed to link ${ticketId}: ${error instanceof Error ? error.message : String(error)}`));
|
|
318
|
+
failCount++;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
// Auto-export to kanban.md
|
|
322
|
+
await autoExportToBoard(this.pmoPath, this.storage, (msg) => this.log(styles.muted(msg)));
|
|
323
|
+
// Summary
|
|
324
|
+
this.log('');
|
|
325
|
+
if (successCount > 0) {
|
|
326
|
+
const action = targetEpic ? 'Linked' : 'Unlinked';
|
|
327
|
+
this.log(styles.success(`${action} ${successCount} ticket(s)`));
|
|
328
|
+
}
|
|
329
|
+
if (failCount > 0) {
|
|
330
|
+
this.log(styles.error(`Failed to link ${failCount} ticket(s)`));
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { PMOCommand } from '../../lib/pmo/index.js';
|
|
2
|
+
export default class Ticket extends PMOCommand {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static flags: {
|
|
6
|
+
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
7
|
+
project: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
8
|
+
};
|
|
9
|
+
protected getPMOOptions(): {
|
|
10
|
+
promptIfMultiple: boolean;
|
|
11
|
+
};
|
|
12
|
+
execute(): Promise<void>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { Flags } from '@oclif/core';
|
|
2
|
+
import inquirer from 'inquirer';
|
|
3
|
+
import { PMOCommand, pmoBaseFlags } from '../../lib/pmo/index.js';
|
|
4
|
+
import { shouldOutputJson, outputPromptAsJson, createMetadata, buildPromptConfig, } from '../../lib/prompt-json.js';
|
|
5
|
+
export default class Ticket extends PMOCommand {
|
|
6
|
+
static description = 'Interactive menu for ticket operations';
|
|
7
|
+
static examples = [
|
|
8
|
+
'<%= config.bin %> <%= command.id %>',
|
|
9
|
+
];
|
|
10
|
+
static flags = {
|
|
11
|
+
...pmoBaseFlags,
|
|
12
|
+
json: Flags.boolean({
|
|
13
|
+
description: 'Output prompt configuration as JSON (for AI agents/scripts)',
|
|
14
|
+
default: false,
|
|
15
|
+
}),
|
|
16
|
+
};
|
|
17
|
+
getPMOOptions() {
|
|
18
|
+
return { promptIfMultiple: false };
|
|
19
|
+
}
|
|
20
|
+
async execute() {
|
|
21
|
+
const { flags } = await this.parse(Ticket);
|
|
22
|
+
// Check if JSON output mode is active
|
|
23
|
+
const jsonMode = shouldOutputJson(flags);
|
|
24
|
+
// Define choices once, use for both JSON and interactive modes
|
|
25
|
+
// Each choice includes the full command for AI agents to execute
|
|
26
|
+
const menuChoices = [
|
|
27
|
+
{ name: 'Create new ticket', value: 'create', command: 'prlt ticket create --json' },
|
|
28
|
+
{ name: 'Create from template', value: 'template', command: 'prlt ticket template apply --json' },
|
|
29
|
+
{ name: 'List all tickets', value: 'list', command: 'prlt ticket list --format json' },
|
|
30
|
+
{ name: 'View ticket details', value: 'view', command: 'prlt ticket view --json' },
|
|
31
|
+
{ name: 'Edit ticket', value: 'edit', command: 'prlt ticket edit --json' },
|
|
32
|
+
{ name: 'Move ticket (column)', value: 'move', command: 'prlt ticket move --json' },
|
|
33
|
+
{ name: 'Move to different project', value: 'project', command: 'prlt ticket project --json' },
|
|
34
|
+
{ name: 'Assign to epic', value: 'epic', command: 'prlt ticket epic --json' },
|
|
35
|
+
{ name: 'Assign to spec', value: 'spec', command: 'prlt ticket spec --json' },
|
|
36
|
+
{ name: 'Manage dependencies', value: 'link', command: 'prlt ticket link --json' },
|
|
37
|
+
{ name: 'Manage templates', value: 'templates', command: 'prlt ticket template --json' },
|
|
38
|
+
{ name: 'Delete ticket', value: 'delete', command: 'prlt ticket delete --json' },
|
|
39
|
+
{ name: 'Cancel', value: 'cancel' },
|
|
40
|
+
];
|
|
41
|
+
const message = 'Ticket Operations - What would you like to do?';
|
|
42
|
+
// In JSON mode, output action selection prompt
|
|
43
|
+
if (jsonMode) {
|
|
44
|
+
outputPromptAsJson(buildPromptConfig('list', 'action', message, menuChoices), createMetadata('ticket', flags));
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
// Show interactive menu
|
|
48
|
+
const { action } = await inquirer.prompt([{
|
|
49
|
+
type: 'list',
|
|
50
|
+
name: 'action',
|
|
51
|
+
message: '🎫 ' + message,
|
|
52
|
+
choices: [
|
|
53
|
+
...menuChoices.slice(0, 10),
|
|
54
|
+
new inquirer.Separator('──────────────'),
|
|
55
|
+
menuChoices[10],
|
|
56
|
+
menuChoices[11],
|
|
57
|
+
menuChoices[12],
|
|
58
|
+
],
|
|
59
|
+
}]);
|
|
60
|
+
if (action === 'cancel') {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
// Run the selected subcommand
|
|
64
|
+
switch (action) {
|
|
65
|
+
case 'create':
|
|
66
|
+
await this.config.runCommand('ticket:create', []);
|
|
67
|
+
break;
|
|
68
|
+
case 'template':
|
|
69
|
+
await this.config.runCommand('ticket:template:apply', []);
|
|
70
|
+
break;
|
|
71
|
+
case 'list':
|
|
72
|
+
await this.config.runCommand('ticket:list', []);
|
|
73
|
+
break;
|
|
74
|
+
case 'view':
|
|
75
|
+
await this.config.runCommand('ticket:view', []);
|
|
76
|
+
break;
|
|
77
|
+
case 'edit':
|
|
78
|
+
await this.config.runCommand('ticket:edit', []);
|
|
79
|
+
break;
|
|
80
|
+
case 'move':
|
|
81
|
+
await this.config.runCommand('ticket:move', []);
|
|
82
|
+
break;
|
|
83
|
+
case 'project':
|
|
84
|
+
await this.config.runCommand('ticket:project', []);
|
|
85
|
+
break;
|
|
86
|
+
case 'epic':
|
|
87
|
+
await this.config.runCommand('ticket:epic', []);
|
|
88
|
+
break;
|
|
89
|
+
case 'spec':
|
|
90
|
+
await this.config.runCommand('ticket:spec', []);
|
|
91
|
+
break;
|
|
92
|
+
case 'link':
|
|
93
|
+
await this.config.runCommand('ticket:link', []);
|
|
94
|
+
break;
|
|
95
|
+
case 'templates':
|
|
96
|
+
await this.config.runCommand('ticket:template', []);
|
|
97
|
+
break;
|
|
98
|
+
case 'delete':
|
|
99
|
+
await this.config.runCommand('ticket:delete', []);
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { PMOCommand } from '../../../lib/pmo/index.js';
|
|
2
|
+
export default class TicketLinkBlock extends PMOCommand {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static args: {
|
|
6
|
+
id: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
7
|
+
blocker: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
8
|
+
};
|
|
9
|
+
static flags: {
|
|
10
|
+
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
11
|
+
project: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
};
|
|
13
|
+
execute(): Promise<void>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { Args, Flags } from '@oclif/core';
|
|
2
|
+
import { autoExportToBoard, PMOCommand, pmoBaseFlags } from '../../../lib/pmo/index.js';
|
|
3
|
+
import { styles } from '../../../lib/styles.js';
|
|
4
|
+
import { shouldOutputJson, outputErrorAsJson, createMetadata, } from '../../../lib/prompt-json.js';
|
|
5
|
+
export default class TicketLinkBlock extends PMOCommand {
|
|
6
|
+
static description = 'Add a blocking dependency (ticket is blocked by another)';
|
|
7
|
+
static examples = [
|
|
8
|
+
'<%= config.bin %> <%= command.id %> TKT-001 TKT-002 # TKT-001 is blocked by TKT-002',
|
|
9
|
+
'<%= config.bin %> <%= command.id %> TKT-001 # Interactive selection',
|
|
10
|
+
];
|
|
11
|
+
static args = {
|
|
12
|
+
id: Args.string({
|
|
13
|
+
description: 'Ticket ID that will be blocked',
|
|
14
|
+
required: true,
|
|
15
|
+
}),
|
|
16
|
+
blocker: Args.string({
|
|
17
|
+
description: 'Ticket ID that blocks this ticket',
|
|
18
|
+
required: false,
|
|
19
|
+
}),
|
|
20
|
+
};
|
|
21
|
+
static flags = {
|
|
22
|
+
...pmoBaseFlags,
|
|
23
|
+
json: Flags.boolean({
|
|
24
|
+
description: 'Output prompt configuration as JSON (for AI agents/scripts)',
|
|
25
|
+
default: false,
|
|
26
|
+
}),
|
|
27
|
+
};
|
|
28
|
+
async execute() {
|
|
29
|
+
const { args, flags } = await this.parse(TicketLinkBlock);
|
|
30
|
+
// Check if JSON output mode is active
|
|
31
|
+
const jsonMode = shouldOutputJson(flags);
|
|
32
|
+
// Helper to handle errors in JSON mode
|
|
33
|
+
const handleError = (code, message) => {
|
|
34
|
+
if (jsonMode) {
|
|
35
|
+
outputErrorAsJson(code, message, createMetadata('ticket link block', flags));
|
|
36
|
+
this.exit(1);
|
|
37
|
+
}
|
|
38
|
+
this.error(message);
|
|
39
|
+
};
|
|
40
|
+
const ticket = await this.storage.getTicket(args.id);
|
|
41
|
+
if (!ticket) {
|
|
42
|
+
return handleError('TICKET_NOT_FOUND', `Ticket not found: ${args.id}`);
|
|
43
|
+
}
|
|
44
|
+
let blockerId = args.blocker;
|
|
45
|
+
// If no blocker provided, prompt for selection
|
|
46
|
+
if (!blockerId) {
|
|
47
|
+
const projectId = flags.project;
|
|
48
|
+
const allTickets = await this.storage.listTickets(projectId);
|
|
49
|
+
const otherTickets = allTickets.filter(t => t.id !== args.id);
|
|
50
|
+
if (otherTickets.length === 0) {
|
|
51
|
+
if (jsonMode) {
|
|
52
|
+
outputErrorAsJson('NO_OTHER_TICKETS', 'No other tickets to create dependency with.', createMetadata('ticket link block', flags));
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
this.log(styles.muted('\nNo other tickets to create dependency with.'));
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
const selected = await this.selectFromList({
|
|
59
|
+
message: `Select ticket that blocks ${args.id}:`,
|
|
60
|
+
items: otherTickets,
|
|
61
|
+
getName: (t) => `${t.id} - ${t.title} (${t.statusName || t.status})`,
|
|
62
|
+
getValue: (t) => t.id,
|
|
63
|
+
getCommand: (t) => `prlt ticket link block ${args.id} ${t.id} --json`,
|
|
64
|
+
jsonMode: jsonMode ? { flags, commandName: 'ticket link block' } : null,
|
|
65
|
+
});
|
|
66
|
+
if (!selected) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
blockerId = selected;
|
|
70
|
+
}
|
|
71
|
+
const blockerTicket = await this.storage.getTicket(blockerId);
|
|
72
|
+
if (!blockerTicket) {
|
|
73
|
+
this.error(`Ticket not found: ${blockerId}`);
|
|
74
|
+
}
|
|
75
|
+
try {
|
|
76
|
+
await this.storage.createTicketDependency(args.id, blockerId, 'blocks');
|
|
77
|
+
await autoExportToBoard(this.pmoPath, this.storage, (msg) => this.log(styles.muted(msg)));
|
|
78
|
+
this.log(styles.success(`\n✅ ${styles.emphasis(args.id)} is blocked by ${styles.emphasis(blockerId)}`));
|
|
79
|
+
this.log(styles.muted(` ${ticket.title}`));
|
|
80
|
+
this.log(styles.muted(` blocked by: ${blockerTicket.title}`));
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
if (error instanceof Error) {
|
|
84
|
+
if (error.message.includes('already exists')) {
|
|
85
|
+
this.error('Dependency already exists');
|
|
86
|
+
}
|
|
87
|
+
if (error.message.includes('self-dependency')) {
|
|
88
|
+
this.error('Cannot create self-dependency');
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
throw error;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { PMOCommand } from '../../../lib/pmo/index.js';
|
|
2
|
+
export default class TicketLinkDuplicates extends PMOCommand {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static args: {
|
|
6
|
+
id: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
7
|
+
original: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
8
|
+
};
|
|
9
|
+
static flags: {
|
|
10
|
+
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
11
|
+
project: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
};
|
|
13
|
+
execute(): Promise<void>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { Args, Flags } from '@oclif/core';
|
|
2
|
+
import { autoExportToBoard, PMOCommand, pmoBaseFlags } from '../../../lib/pmo/index.js';
|
|
3
|
+
import { styles } from '../../../lib/styles.js';
|
|
4
|
+
import { shouldOutputJson, outputErrorAsJson, createMetadata, } from '../../../lib/prompt-json.js';
|
|
5
|
+
export default class TicketLinkDuplicates extends PMOCommand {
|
|
6
|
+
static description = 'Mark a ticket as duplicate of another';
|
|
7
|
+
static examples = [
|
|
8
|
+
'<%= config.bin %> <%= command.id %> TKT-001 TKT-002 # TKT-001 duplicates TKT-002',
|
|
9
|
+
'<%= config.bin %> <%= command.id %> TKT-001 # Interactive selection',
|
|
10
|
+
];
|
|
11
|
+
static args = {
|
|
12
|
+
id: Args.string({
|
|
13
|
+
description: 'Duplicate ticket ID',
|
|
14
|
+
required: true,
|
|
15
|
+
}),
|
|
16
|
+
original: Args.string({
|
|
17
|
+
description: 'Original ticket ID',
|
|
18
|
+
required: false,
|
|
19
|
+
}),
|
|
20
|
+
};
|
|
21
|
+
static flags = {
|
|
22
|
+
...pmoBaseFlags,
|
|
23
|
+
json: Flags.boolean({
|
|
24
|
+
description: 'Output prompt configuration as JSON (for AI agents/scripts)',
|
|
25
|
+
default: false,
|
|
26
|
+
}),
|
|
27
|
+
};
|
|
28
|
+
async execute() {
|
|
29
|
+
const { args, flags } = await this.parse(TicketLinkDuplicates);
|
|
30
|
+
// Check if JSON output mode is active
|
|
31
|
+
const jsonMode = shouldOutputJson(flags);
|
|
32
|
+
// Helper to handle errors in JSON mode
|
|
33
|
+
const handleError = (code, message) => {
|
|
34
|
+
if (jsonMode) {
|
|
35
|
+
outputErrorAsJson(code, message, createMetadata('ticket link duplicates', flags));
|
|
36
|
+
this.exit(1);
|
|
37
|
+
}
|
|
38
|
+
this.error(message);
|
|
39
|
+
};
|
|
40
|
+
const ticket = await this.storage.getTicket(args.id);
|
|
41
|
+
if (!ticket) {
|
|
42
|
+
return handleError('TICKET_NOT_FOUND', `Ticket not found: ${args.id}`);
|
|
43
|
+
}
|
|
44
|
+
let originalId = args.original;
|
|
45
|
+
if (!originalId) {
|
|
46
|
+
const projectId = flags.project;
|
|
47
|
+
const allTickets = await this.storage.listTickets(projectId);
|
|
48
|
+
const otherTickets = allTickets.filter(t => t.id !== args.id);
|
|
49
|
+
if (otherTickets.length === 0) {
|
|
50
|
+
if (jsonMode) {
|
|
51
|
+
outputErrorAsJson('NO_OTHER_TICKETS', 'No other tickets.', createMetadata('ticket link duplicates', flags));
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
this.log(styles.muted('\nNo other tickets.'));
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const selected = await this.selectFromList({
|
|
58
|
+
message: `Select the original ticket (${args.id} is a duplicate of):`,
|
|
59
|
+
items: otherTickets,
|
|
60
|
+
getName: (t) => `${t.id} - ${t.title} (${t.statusName || t.status})`,
|
|
61
|
+
getValue: (t) => t.id,
|
|
62
|
+
getCommand: (t) => `prlt ticket link duplicates ${args.id} ${t.id} --json`,
|
|
63
|
+
jsonMode: jsonMode ? { flags, commandName: 'ticket link duplicates' } : null,
|
|
64
|
+
});
|
|
65
|
+
if (!selected) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
originalId = selected;
|
|
69
|
+
}
|
|
70
|
+
const originalTicket = await this.storage.getTicket(originalId);
|
|
71
|
+
if (!originalTicket) {
|
|
72
|
+
this.error(`Ticket not found: ${originalId}`);
|
|
73
|
+
}
|
|
74
|
+
try {
|
|
75
|
+
await this.storage.createTicketDependency(args.id, originalId, 'duplicates');
|
|
76
|
+
await autoExportToBoard(this.pmoPath, this.storage, (msg) => this.log(styles.muted(msg)));
|
|
77
|
+
this.log(styles.success(`\n✅ ${styles.emphasis(args.id)} duplicates ${styles.emphasis(originalId)}`));
|
|
78
|
+
this.log(styles.muted(` ${ticket.title}`));
|
|
79
|
+
this.log(styles.muted(` duplicates: ${originalTicket.title}`));
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
if (error instanceof Error) {
|
|
83
|
+
if (error.message.includes('already exists')) {
|
|
84
|
+
this.error('Dependency already exists');
|
|
85
|
+
}
|
|
86
|
+
if (error.message.includes('self-dependency')) {
|
|
87
|
+
this.error('Cannot create self-dependency');
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
throw error;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|