@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,259 @@
|
|
|
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 TicketSpec extends PMOCommand {
|
|
7
|
+
static description = 'Assign a spec to ticket(s)';
|
|
8
|
+
static examples = [
|
|
9
|
+
'<%= config.bin %> <%= command.id %> TKT-001 SPEC-001',
|
|
10
|
+
'<%= config.bin %> <%= command.id %> TKT-001',
|
|
11
|
+
'<%= config.bin %> <%= command.id %>',
|
|
12
|
+
'<%= config.bin %> <%= command.id %> TKT-001 --unlink',
|
|
13
|
+
'<%= config.bin %> <%= command.id %> --bulk --spec SPEC-001',
|
|
14
|
+
];
|
|
15
|
+
static args = {
|
|
16
|
+
ticketId: Args.string({
|
|
17
|
+
description: 'Ticket ID',
|
|
18
|
+
required: false,
|
|
19
|
+
}),
|
|
20
|
+
specId: Args.string({
|
|
21
|
+
description: 'Spec ID to link',
|
|
22
|
+
required: false,
|
|
23
|
+
}),
|
|
24
|
+
};
|
|
25
|
+
static flags = {
|
|
26
|
+
...pmoBaseFlags,
|
|
27
|
+
json: Flags.boolean({
|
|
28
|
+
description: 'Output prompt configuration as JSON (for AI agents/scripts)',
|
|
29
|
+
default: false,
|
|
30
|
+
}),
|
|
31
|
+
unlink: Flags.boolean({
|
|
32
|
+
char: 'u',
|
|
33
|
+
description: 'Remove spec from ticket instead of adding',
|
|
34
|
+
default: false,
|
|
35
|
+
}),
|
|
36
|
+
bulk: Flags.boolean({
|
|
37
|
+
char: 'b',
|
|
38
|
+
description: 'Enable bulk mode to assign spec to multiple tickets',
|
|
39
|
+
default: false,
|
|
40
|
+
}),
|
|
41
|
+
spec: Flags.string({
|
|
42
|
+
char: 's',
|
|
43
|
+
description: 'Spec ID to assign (for bulk mode)',
|
|
44
|
+
}),
|
|
45
|
+
};
|
|
46
|
+
async execute() {
|
|
47
|
+
const { args, flags } = await this.parse(TicketSpec);
|
|
48
|
+
const projectId = flags.project;
|
|
49
|
+
// Check if JSON output mode is active
|
|
50
|
+
const jsonMode = shouldOutputJson(flags);
|
|
51
|
+
// Bulk mode
|
|
52
|
+
if (flags.bulk) {
|
|
53
|
+
await this.executeBulk(flags, projectId);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
// Get all tickets
|
|
57
|
+
const tickets = await this.storage.listTickets(projectId);
|
|
58
|
+
if (tickets.length === 0) {
|
|
59
|
+
if (jsonMode) {
|
|
60
|
+
outputErrorAsJson('NO_TICKETS', 'No tickets found.', createMetadata('ticket spec', flags));
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
this.log(styles.muted('\nNo tickets found. Create one with: prlt ticket create'));
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
let ticketId = args.ticketId;
|
|
67
|
+
// If no ticket ID provided, prompt for selection
|
|
68
|
+
if (!ticketId) {
|
|
69
|
+
const ticketChoices = tickets.map(t => {
|
|
70
|
+
const specLabel = t.specId ? ` [spec: ${t.specId}]` : '';
|
|
71
|
+
return {
|
|
72
|
+
id: t.id,
|
|
73
|
+
name: `${t.id} - ${t.title}${specLabel}`,
|
|
74
|
+
};
|
|
75
|
+
});
|
|
76
|
+
const selected = await this.selectFromList({
|
|
77
|
+
message: 'Select ticket:',
|
|
78
|
+
items: ticketChoices,
|
|
79
|
+
getName: (t) => t.name,
|
|
80
|
+
getValue: (t) => t.id,
|
|
81
|
+
getCommand: (t) => `prlt ticket spec ${t.id} --json`,
|
|
82
|
+
jsonMode: jsonMode ? { flags, commandName: 'ticket spec' } : null,
|
|
83
|
+
});
|
|
84
|
+
if (!selected) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
ticketId = selected;
|
|
88
|
+
}
|
|
89
|
+
// Validate ticket exists
|
|
90
|
+
const ticket = tickets.find(t => t.id === ticketId);
|
|
91
|
+
if (!ticket) {
|
|
92
|
+
this.error(`Ticket not found: ${ticketId}`);
|
|
93
|
+
}
|
|
94
|
+
// Handle unlink
|
|
95
|
+
if (flags.unlink) {
|
|
96
|
+
if (!ticket.specId) {
|
|
97
|
+
this.log(styles.muted(`\nTicket ${ticketId} is not linked to any spec.`));
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
const oldSpecId = ticket.specId;
|
|
101
|
+
await this.storage.updateTicket(ticketId, { specId: undefined });
|
|
102
|
+
await autoExportToBoard(this.pmoPath, this.storage, (msg) => this.log(styles.muted(msg)));
|
|
103
|
+
this.log(styles.success(`\n✅ Unlinked spec "${styles.emphasis(oldSpecId)}" from ticket ${styles.emphasis(ticketId)}`));
|
|
104
|
+
}
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
// Get all specs
|
|
108
|
+
const specs = await this.storage.listSpecs();
|
|
109
|
+
if (specs.length === 0) {
|
|
110
|
+
this.log(styles.muted('\nNo specs found.'));
|
|
111
|
+
const actionChoices = [
|
|
112
|
+
{ id: 'create', name: 'Create a new spec' },
|
|
113
|
+
{ id: 'cancel', name: 'Cancel' },
|
|
114
|
+
];
|
|
115
|
+
const action = await this.selectFromList({
|
|
116
|
+
message: 'What would you like to do?',
|
|
117
|
+
items: actionChoices,
|
|
118
|
+
getName: (a) => a.name,
|
|
119
|
+
getValue: (a) => a.id,
|
|
120
|
+
getCommand: (a) => a.id === 'create' ? 'prlt spec create --json' : '',
|
|
121
|
+
jsonMode: jsonMode ? { flags, commandName: 'ticket spec' } : null,
|
|
122
|
+
});
|
|
123
|
+
if (action === 'create') {
|
|
124
|
+
await this.config.runCommand('spec:create', []);
|
|
125
|
+
}
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
let specId = args.specId;
|
|
129
|
+
// If no spec ID provided, prompt for selection
|
|
130
|
+
if (!specId) {
|
|
131
|
+
const selected = await this.selectFromList({
|
|
132
|
+
message: `Select spec to link to ${ticketId}:`,
|
|
133
|
+
items: specs,
|
|
134
|
+
getName: (s) => `${s.id} - ${s.title} (${s.status})`,
|
|
135
|
+
getValue: (s) => s.id,
|
|
136
|
+
getCommand: (s) => `prlt ticket spec ${ticketId} ${s.id} --json`,
|
|
137
|
+
jsonMode: jsonMode ? { flags, commandName: 'ticket spec' } : null,
|
|
138
|
+
});
|
|
139
|
+
if (!selected) {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
specId = selected;
|
|
143
|
+
}
|
|
144
|
+
// Validate spec exists
|
|
145
|
+
const spec = specs.find(s => s.id === specId);
|
|
146
|
+
if (!spec) {
|
|
147
|
+
this.error(`Spec not found: ${specId}`);
|
|
148
|
+
}
|
|
149
|
+
// Check if already linked
|
|
150
|
+
if (ticket.specId === specId) {
|
|
151
|
+
this.log(styles.muted(`\nTicket "${ticketId}" is already linked to spec "${specId}".`));
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
// Warn if ticket has different spec
|
|
155
|
+
if (ticket.specId) {
|
|
156
|
+
this.log(styles.warning(`Ticket "${ticketId}" is currently linked to spec "${ticket.specId}"`));
|
|
157
|
+
this.log(styles.muted(`This will replace the existing spec link.`));
|
|
158
|
+
}
|
|
159
|
+
// Reconciliation: Check if ticket's epic has a different spec
|
|
160
|
+
if (ticket.epicId) {
|
|
161
|
+
const epic = await this.storage.getEpic(ticket.epicId);
|
|
162
|
+
if (epic?.specId && epic.specId !== specId) {
|
|
163
|
+
this.log(styles.warning(`\n⚠️ Epic "${ticket.epicId}" uses spec "${epic.specId}", but you're assigning "${specId}" to this ticket.`));
|
|
164
|
+
const actionChoices = [
|
|
165
|
+
{ id: 'proceed', name: `Proceed anyway (ticket will have different spec than epic)` },
|
|
166
|
+
{ id: 'use_epic', name: `Use epic's spec instead (${epic.specId})` },
|
|
167
|
+
{ id: 'cancel', name: 'Cancel' },
|
|
168
|
+
];
|
|
169
|
+
const action = await this.selectFromList({
|
|
170
|
+
message: 'How to handle spec mismatch?',
|
|
171
|
+
items: actionChoices,
|
|
172
|
+
getName: (a) => a.name,
|
|
173
|
+
getValue: (a) => a.id,
|
|
174
|
+
getCommand: (a) => a.id === 'use_epic' ? `prlt ticket spec ${ticketId} ${epic.specId} --json` : `prlt ticket spec ${ticketId} ${specId} --json`,
|
|
175
|
+
jsonMode: jsonMode ? { flags, commandName: 'ticket spec' } : null,
|
|
176
|
+
});
|
|
177
|
+
if (action === 'cancel' || !action) {
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
if (action === 'use_epic') {
|
|
181
|
+
specId = epic.specId;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
// Link spec to ticket
|
|
186
|
+
await this.storage.updateTicket(ticketId, { specId });
|
|
187
|
+
await autoExportToBoard(this.pmoPath, this.storage, (msg) => this.log(styles.muted(msg)));
|
|
188
|
+
this.log(styles.success(`\n✅ Linked ticket ${styles.emphasis(ticketId)} to spec ${styles.emphasis(specId)}`));
|
|
189
|
+
this.log(styles.muted(` Spec: ${spec.title}`));
|
|
190
|
+
this.log(styles.muted(`\nView ticket: prlt ticket view ${ticketId}`));
|
|
191
|
+
}
|
|
192
|
+
async executeBulk(flags, projectId) {
|
|
193
|
+
this.log(styles.emphasis('📄 Bulk Assign Spec to Tickets\n'));
|
|
194
|
+
// Get all tickets
|
|
195
|
+
const tickets = await this.storage.listTickets(projectId);
|
|
196
|
+
if (tickets.length === 0) {
|
|
197
|
+
this.log(styles.muted('\nNo tickets found.'));
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
// Select tickets
|
|
201
|
+
const { selectedTickets } = await inquirer.prompt([{
|
|
202
|
+
type: 'checkbox',
|
|
203
|
+
name: 'selectedTickets',
|
|
204
|
+
message: 'Select tickets to update:',
|
|
205
|
+
choices: tickets.map(t => {
|
|
206
|
+
const specLabel = t.specId ? ` [spec: ${t.specId}]` : '';
|
|
207
|
+
return {
|
|
208
|
+
name: `${t.id} - ${t.title}${specLabel}`,
|
|
209
|
+
value: t.id,
|
|
210
|
+
};
|
|
211
|
+
}),
|
|
212
|
+
}]);
|
|
213
|
+
if (selectedTickets.length === 0) {
|
|
214
|
+
this.log(styles.muted('No tickets selected.'));
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
// Handle unlink
|
|
218
|
+
if (flags.unlink) {
|
|
219
|
+
for (const ticketId of selectedTickets) {
|
|
220
|
+
await this.storage.updateTicket(ticketId, { specId: undefined });
|
|
221
|
+
this.log(styles.success(` Unlinked spec from ${ticketId}`));
|
|
222
|
+
}
|
|
223
|
+
await autoExportToBoard(this.pmoPath, this.storage, (msg) => this.log(styles.muted(msg)));
|
|
224
|
+
this.log(styles.success(`\n✅ Unlinked spec from ${selectedTickets.length} ticket(s)`));
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
// Get spec to assign
|
|
228
|
+
let specId = flags.spec;
|
|
229
|
+
if (!specId) {
|
|
230
|
+
const specs = await this.storage.listSpecs();
|
|
231
|
+
if (specs.length === 0) {
|
|
232
|
+
this.log(styles.muted('\nNo specs found. Create one with: prlt spec create'));
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
const { selected } = await inquirer.prompt([{
|
|
236
|
+
type: 'list',
|
|
237
|
+
name: 'selected',
|
|
238
|
+
message: 'Select spec to assign:',
|
|
239
|
+
choices: specs.map(s => ({
|
|
240
|
+
name: `${s.id} - ${s.title} (${s.status})`,
|
|
241
|
+
value: s.id,
|
|
242
|
+
})),
|
|
243
|
+
}]);
|
|
244
|
+
specId = selected;
|
|
245
|
+
}
|
|
246
|
+
// Validate spec
|
|
247
|
+
const spec = await this.storage.getSpec(specId);
|
|
248
|
+
if (!spec) {
|
|
249
|
+
this.error(`Spec not found: ${specId}`);
|
|
250
|
+
}
|
|
251
|
+
// Assign spec to all selected tickets
|
|
252
|
+
for (const ticketId of selectedTickets) {
|
|
253
|
+
await this.storage.updateTicket(ticketId, { specId });
|
|
254
|
+
this.log(styles.success(` Linked ${ticketId} to ${specId}`));
|
|
255
|
+
}
|
|
256
|
+
await autoExportToBoard(this.pmoPath, this.storage, (msg) => this.log(styles.muted(msg)));
|
|
257
|
+
this.log(styles.success(`\n✅ Linked ${selectedTickets.length} ticket(s) to spec "${spec.title}"`));
|
|
258
|
+
}
|
|
259
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { PMOCommand } from '../../lib/pmo/index.js';
|
|
2
|
+
export default class TicketStatus extends PMOCommand {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static args: {
|
|
6
|
+
ticketId: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
7
|
+
};
|
|
8
|
+
static flags: {
|
|
9
|
+
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
10
|
+
project: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
};
|
|
12
|
+
execute(): Promise<void>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { Args, Flags } from '@oclif/core';
|
|
2
|
+
import { PMOCommand, pmoBaseFlags } from '../../lib/pmo/index.js';
|
|
3
|
+
import { styles, formatPriority, formatCategory } from '../../lib/styles.js';
|
|
4
|
+
import { shouldOutputJson, outputErrorAsJson, createMetadata, } from '../../lib/prompt-json.js';
|
|
5
|
+
export default class TicketStatus extends PMOCommand {
|
|
6
|
+
static description = 'Show ticket status and details';
|
|
7
|
+
static examples = [
|
|
8
|
+
'<%= config.bin %> <%= command.id %>',
|
|
9
|
+
'<%= config.bin %> <%= command.id %> TICK-001',
|
|
10
|
+
];
|
|
11
|
+
static args = {
|
|
12
|
+
ticketId: Args.string({
|
|
13
|
+
description: 'Ticket ID - prompts with dropdown if not provided',
|
|
14
|
+
required: false,
|
|
15
|
+
}),
|
|
16
|
+
};
|
|
17
|
+
static flags = {
|
|
18
|
+
...pmoBaseFlags,
|
|
19
|
+
json: Flags.boolean({
|
|
20
|
+
description: 'Output prompt configuration as JSON (for AI agents/scripts)',
|
|
21
|
+
default: false,
|
|
22
|
+
}),
|
|
23
|
+
};
|
|
24
|
+
async execute() {
|
|
25
|
+
const { args, flags } = await this.parse(TicketStatus);
|
|
26
|
+
const projectId = flags.project;
|
|
27
|
+
// Check if JSON output mode is active
|
|
28
|
+
const jsonMode = shouldOutputJson(flags);
|
|
29
|
+
// Helper to handle errors in JSON mode
|
|
30
|
+
const handleError = (code, message) => {
|
|
31
|
+
if (jsonMode) {
|
|
32
|
+
outputErrorAsJson(code, message, createMetadata('ticket status', flags));
|
|
33
|
+
this.exit(1);
|
|
34
|
+
}
|
|
35
|
+
this.error(message);
|
|
36
|
+
};
|
|
37
|
+
// Get ticketId - prompt if not provided
|
|
38
|
+
let ticketId = args.ticketId;
|
|
39
|
+
if (!ticketId) {
|
|
40
|
+
// Get all tickets for selection
|
|
41
|
+
const allTickets = await this.storage.listTickets(projectId);
|
|
42
|
+
if (allTickets.length === 0) {
|
|
43
|
+
return handleError('NO_TICKETS', 'No tickets found. Create a ticket first with "prlt ticket create".');
|
|
44
|
+
}
|
|
45
|
+
// Use helper for ticket selection (handles JSON mode automatically)
|
|
46
|
+
const selected = await this.selectFromList({
|
|
47
|
+
message: 'Select ticket:',
|
|
48
|
+
items: allTickets,
|
|
49
|
+
getName: (t) => `${t.id} - ${t.title} (${t.statusName})`,
|
|
50
|
+
getValue: (t) => t.id,
|
|
51
|
+
getCommand: (t) => `prlt ticket status ${t.id} --json`,
|
|
52
|
+
jsonMode: jsonMode ? { flags, commandName: 'ticket status' } : null,
|
|
53
|
+
});
|
|
54
|
+
if (!selected) {
|
|
55
|
+
return; // Cancelled or JSON mode (already exited)
|
|
56
|
+
}
|
|
57
|
+
ticketId = selected;
|
|
58
|
+
}
|
|
59
|
+
// Get ticket
|
|
60
|
+
const ticket = await this.storage.getTicket(ticketId);
|
|
61
|
+
if (!ticket) {
|
|
62
|
+
this.error(`Ticket "${ticketId}" not found.`);
|
|
63
|
+
}
|
|
64
|
+
// Display ticket status
|
|
65
|
+
this.log('');
|
|
66
|
+
this.log(styles.emphasis(`🎫 ${ticket.id}: ${ticket.title}`));
|
|
67
|
+
this.log('');
|
|
68
|
+
this.log(` ${styles.muted('Status:')} ${ticket.statusName}`);
|
|
69
|
+
this.log(` ${styles.muted('Priority:')} ${formatPriority(ticket.priority)}`);
|
|
70
|
+
if (ticket.category) {
|
|
71
|
+
this.log(` ${styles.muted('Category:')} ${formatCategory(ticket.category)}`);
|
|
72
|
+
}
|
|
73
|
+
if (ticket.description) {
|
|
74
|
+
this.log(` ${styles.muted('Description:')}`);
|
|
75
|
+
this.log(` ${ticket.description.split('\n').map((line) => ` ${line}`).join('\n')}`);
|
|
76
|
+
}
|
|
77
|
+
if (ticket.subtasks && ticket.subtasks.length > 0) {
|
|
78
|
+
const completedSubtasks = ticket.subtasks.filter((s) => s.done).length;
|
|
79
|
+
this.log(` ${styles.muted('Subtasks:')} ${completedSubtasks}/${ticket.subtasks.length} completed`);
|
|
80
|
+
ticket.subtasks.forEach((subtask) => {
|
|
81
|
+
const icon = subtask.done ? '☑' : '☐';
|
|
82
|
+
this.log(` ${icon} ${subtask.title}`);
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
this.log('');
|
|
86
|
+
}
|
|
87
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { PMOCommand } from '../../../lib/pmo/index.js';
|
|
2
|
+
export default class TicketTemplateApply extends PMOCommand {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static args: {
|
|
6
|
+
template: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
7
|
+
};
|
|
8
|
+
static flags: {
|
|
9
|
+
title: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
+
column: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
priority: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
category: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
+
assignee: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
|
+
owner: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
15
|
+
status: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
16
|
+
labels: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
17
|
+
description: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
18
|
+
interactive: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
19
|
+
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
20
|
+
'no-subtasks': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
21
|
+
epic: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
22
|
+
project: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
23
|
+
};
|
|
24
|
+
execute(): Promise<void>;
|
|
25
|
+
}
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
import { Flags, Args } from '@oclif/core';
|
|
2
|
+
import inquirer from 'inquirer';
|
|
3
|
+
import { PMOCommand, pmoBaseFlags, autoExportToBoard } from '../../../lib/pmo/index.js';
|
|
4
|
+
import { PRIORITIES, PRIORITY_LABELS } from '../../../lib/pmo/types.js';
|
|
5
|
+
import { styles } from '../../../lib/styles.js';
|
|
6
|
+
import { shouldOutputJson, outputPromptAsJson, outputErrorAsJson, createMetadata, buildFormPromptConfig, } from '../../../lib/prompt-json.js';
|
|
7
|
+
export default class TicketTemplateApply extends PMOCommand {
|
|
8
|
+
static description = 'Create a new ticket from a template';
|
|
9
|
+
static examples = [
|
|
10
|
+
'<%= config.bin %> <%= command.id %> bug-report',
|
|
11
|
+
'<%= config.bin %> <%= command.id %> feature-request --title "Add dark mode"',
|
|
12
|
+
'<%= config.bin %> <%= command.id %> bug-report --project my-project',
|
|
13
|
+
'<%= config.bin %> <%= command.id %> bug-report -t "Login fails" -c Backlog',
|
|
14
|
+
];
|
|
15
|
+
static args = {
|
|
16
|
+
template: Args.string({
|
|
17
|
+
description: 'Template ID to use',
|
|
18
|
+
required: false,
|
|
19
|
+
}),
|
|
20
|
+
};
|
|
21
|
+
static flags = {
|
|
22
|
+
...pmoBaseFlags,
|
|
23
|
+
title: Flags.string({
|
|
24
|
+
char: 't',
|
|
25
|
+
description: 'Ticket title (overrides template pattern)',
|
|
26
|
+
}),
|
|
27
|
+
column: Flags.string({
|
|
28
|
+
char: 'c',
|
|
29
|
+
description: 'Column to place the ticket in',
|
|
30
|
+
}),
|
|
31
|
+
priority: Flags.string({
|
|
32
|
+
char: 'p',
|
|
33
|
+
description: 'Priority (overrides template default)',
|
|
34
|
+
options: [...PRIORITIES],
|
|
35
|
+
}),
|
|
36
|
+
category: Flags.string({
|
|
37
|
+
description: 'Category (overrides template default)',
|
|
38
|
+
}),
|
|
39
|
+
assignee: Flags.string({
|
|
40
|
+
char: 'a',
|
|
41
|
+
description: 'Assignee (overrides template default)',
|
|
42
|
+
}),
|
|
43
|
+
owner: Flags.string({
|
|
44
|
+
char: 'o',
|
|
45
|
+
description: 'Owner (overrides template default)',
|
|
46
|
+
}),
|
|
47
|
+
status: Flags.string({
|
|
48
|
+
char: 's',
|
|
49
|
+
description: 'Status ID (overrides template default)',
|
|
50
|
+
}),
|
|
51
|
+
labels: Flags.string({
|
|
52
|
+
char: 'l',
|
|
53
|
+
description: 'Labels (comma-separated, overrides template default)',
|
|
54
|
+
}),
|
|
55
|
+
description: Flags.string({
|
|
56
|
+
char: 'd',
|
|
57
|
+
description: 'Description (overrides template)',
|
|
58
|
+
}),
|
|
59
|
+
interactive: Flags.boolean({
|
|
60
|
+
char: 'i',
|
|
61
|
+
description: 'Interactive mode - prompt for values',
|
|
62
|
+
default: false,
|
|
63
|
+
}),
|
|
64
|
+
json: Flags.boolean({
|
|
65
|
+
description: 'Output prompt configuration as JSON (for AI agents/scripts)',
|
|
66
|
+
default: false,
|
|
67
|
+
}),
|
|
68
|
+
'no-subtasks': Flags.boolean({
|
|
69
|
+
description: 'Do not create suggested subtasks',
|
|
70
|
+
default: false,
|
|
71
|
+
}),
|
|
72
|
+
epic: Flags.string({
|
|
73
|
+
char: 'e',
|
|
74
|
+
description: 'Link ticket to an epic',
|
|
75
|
+
}),
|
|
76
|
+
};
|
|
77
|
+
async execute() {
|
|
78
|
+
const { args, flags } = await this.parse(TicketTemplateApply);
|
|
79
|
+
// This command requires project context - get projectId and board info
|
|
80
|
+
const projectId = await this.requireProject();
|
|
81
|
+
const board = await this.storage.getBoard(projectId);
|
|
82
|
+
const columns = board.columns.map(col => col.name);
|
|
83
|
+
const projectName = board.name;
|
|
84
|
+
// Check if JSON output mode is active
|
|
85
|
+
const jsonMode = shouldOutputJson(flags);
|
|
86
|
+
// Helper to handle errors in JSON mode
|
|
87
|
+
const handleError = (code, message) => {
|
|
88
|
+
if (jsonMode) {
|
|
89
|
+
outputErrorAsJson(code, message, createMetadata('ticket template apply', flags));
|
|
90
|
+
this.exit(1);
|
|
91
|
+
}
|
|
92
|
+
this.error(message);
|
|
93
|
+
};
|
|
94
|
+
// Get the template - prompt for selection if not provided
|
|
95
|
+
let templateId = args.template;
|
|
96
|
+
if (!templateId) {
|
|
97
|
+
const templates = await this.storage.listTicketTemplates();
|
|
98
|
+
if (templates.length === 0) {
|
|
99
|
+
return handleError('NO_TEMPLATES', `No ticket templates found.\nCreate one with: prlt ticket template save <ticket-id> "Template Name"`);
|
|
100
|
+
}
|
|
101
|
+
const { selectedTemplate } = await inquirer.prompt([{
|
|
102
|
+
type: 'list',
|
|
103
|
+
name: 'selectedTemplate',
|
|
104
|
+
message: 'Select a template:',
|
|
105
|
+
choices: templates.map(t => ({
|
|
106
|
+
name: `${t.name}${t.description ? ` - ${t.description}` : ''}`,
|
|
107
|
+
value: t.id,
|
|
108
|
+
})),
|
|
109
|
+
}]);
|
|
110
|
+
templateId = selectedTemplate;
|
|
111
|
+
}
|
|
112
|
+
const template = await this.storage.getTicketTemplate(templateId);
|
|
113
|
+
if (!template) {
|
|
114
|
+
return handleError('TEMPLATE_NOT_FOUND', `Template not found: ${templateId}\nRun 'prlt ticket template list' to see available templates.`);
|
|
115
|
+
}
|
|
116
|
+
// Validate epic if provided
|
|
117
|
+
if (flags.epic) {
|
|
118
|
+
const epic = await this.storage.getEpic(flags.epic);
|
|
119
|
+
if (!epic) {
|
|
120
|
+
this.error(`Epic not found: ${flags.epic}. Use 'prlt epic list' to see available epics.`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
// Determine ticket data
|
|
124
|
+
let title = flags.title || template.titlePattern || '';
|
|
125
|
+
let column = flags.column || columns[0];
|
|
126
|
+
let priority = flags.priority || template.defaultPriority;
|
|
127
|
+
let category = flags.category || template.defaultCategory;
|
|
128
|
+
let assignee = flags.assignee || template.defaultAssignee;
|
|
129
|
+
let owner = flags.owner || template.defaultOwner;
|
|
130
|
+
let statusId = flags.status || template.defaultStatusId;
|
|
131
|
+
let labels = flags.labels ? flags.labels.split(',').map(l => l.trim()).filter(l => l) : template.defaultLabels;
|
|
132
|
+
let description = flags.description || template.descriptionTemplate;
|
|
133
|
+
// Interactive mode - prompt for values
|
|
134
|
+
if (flags.interactive || !title) {
|
|
135
|
+
// Build choices once - single source of truth
|
|
136
|
+
const columnChoices = columns.map(c => ({ name: c, value: c }));
|
|
137
|
+
const priorityChoices = [
|
|
138
|
+
{ name: 'None', value: '' },
|
|
139
|
+
...PRIORITIES.map(p => ({ name: PRIORITY_LABELS[p], value: p })),
|
|
140
|
+
];
|
|
141
|
+
// Define fields once - single source of truth for both JSON and interactive modes
|
|
142
|
+
const fields = [
|
|
143
|
+
{ type: 'input', name: 'title', message: 'Ticket title:', default: title || undefined },
|
|
144
|
+
{ type: 'list', name: 'column', message: 'Column:', choices: columnChoices, default: column },
|
|
145
|
+
{ type: 'list', name: 'priority', message: 'Priority:', choices: priorityChoices, default: priority },
|
|
146
|
+
{ type: 'input', name: 'category', message: 'Category:', default: category },
|
|
147
|
+
{ type: 'input', name: 'assignee', message: 'Assignee:', default: assignee },
|
|
148
|
+
{ type: 'input', name: 'owner', message: 'Owner:', default: owner },
|
|
149
|
+
{ type: 'editor', name: 'description', message: 'Description:', default: description },
|
|
150
|
+
];
|
|
151
|
+
// In JSON mode, output form prompts
|
|
152
|
+
if (jsonMode) {
|
|
153
|
+
outputPromptAsJson(buildFormPromptConfig(fields), createMetadata('ticket template apply', flags));
|
|
154
|
+
}
|
|
155
|
+
// Build inquirer prompts from fields, adding validators and inquirer-specific options
|
|
156
|
+
const answers = await inquirer.prompt(fields.map(field => ({
|
|
157
|
+
...field,
|
|
158
|
+
// Convert empty string to undefined for priority choices in inquirer
|
|
159
|
+
choices: field.name === 'priority' && field.choices
|
|
160
|
+
? field.choices.map(c => ({ ...c, value: c.value || undefined }))
|
|
161
|
+
: field.name === 'column'
|
|
162
|
+
? columns // Use simple array for column in interactive mode
|
|
163
|
+
: field.choices,
|
|
164
|
+
// Add validator for title
|
|
165
|
+
validate: field.name === 'title'
|
|
166
|
+
? ((input) => input.length > 0 || 'Title is required')
|
|
167
|
+
: undefined,
|
|
168
|
+
// Update editor message for interactive mode
|
|
169
|
+
message: field.name === 'description' ? 'Description (opens editor):' : field.message,
|
|
170
|
+
// Add waitForUseInput for editor
|
|
171
|
+
waitForUseInput: field.type === 'editor' ? false : undefined,
|
|
172
|
+
})));
|
|
173
|
+
title = answers.title;
|
|
174
|
+
column = answers.column;
|
|
175
|
+
priority = answers.priority;
|
|
176
|
+
category = answers.category || undefined;
|
|
177
|
+
assignee = answers.assignee || undefined;
|
|
178
|
+
owner = answers.owner || undefined;
|
|
179
|
+
description = answers.description || undefined;
|
|
180
|
+
}
|
|
181
|
+
// Validate column
|
|
182
|
+
if (!columns.includes(column)) {
|
|
183
|
+
this.error(`Invalid column "${column}". Available columns: ${columns.join(', ')}`);
|
|
184
|
+
}
|
|
185
|
+
// Validate status ID if provided
|
|
186
|
+
if (statusId) {
|
|
187
|
+
const status = await this.storage.getStatus(statusId);
|
|
188
|
+
if (!status) {
|
|
189
|
+
// Get project's workflow to list available statuses
|
|
190
|
+
const projectInfo = await this.storage.getProject(projectId);
|
|
191
|
+
const workflowId = projectInfo?.workflowId;
|
|
192
|
+
const statuses = workflowId ? await this.storage.listStatuses(workflowId) : [];
|
|
193
|
+
const statusNames = statuses.map(s => `${s.id} (${s.name})`).join(', ');
|
|
194
|
+
this.error(`Invalid status "${statusId}". Available statuses: ${statusNames}`);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
// Create the ticket
|
|
198
|
+
const ticket = await this.storage.createTicket(projectId, {
|
|
199
|
+
title,
|
|
200
|
+
statusName: column,
|
|
201
|
+
priority,
|
|
202
|
+
category,
|
|
203
|
+
assignee,
|
|
204
|
+
owner,
|
|
205
|
+
statusId,
|
|
206
|
+
labels,
|
|
207
|
+
description,
|
|
208
|
+
epicId: flags.epic,
|
|
209
|
+
});
|
|
210
|
+
// Add subtasks from template (unless disabled)
|
|
211
|
+
if (!flags['no-subtasks'] && template.suggestedSubtasks.length > 0) {
|
|
212
|
+
for (const subtask of template.suggestedSubtasks) {
|
|
213
|
+
await this.storage.addSubtask(ticket.id, subtask.title);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
// Auto-export to board.md
|
|
217
|
+
await autoExportToBoard(this.pmoPath, this.storage, (msg) => this.log(styles.muted(msg)));
|
|
218
|
+
this.log(styles.success(`\nCreated ticket ${styles.emphasis(ticket.id)} from template "${template.name}"`));
|
|
219
|
+
this.log(styles.muted(` Project: ${projectName}`));
|
|
220
|
+
this.log(styles.muted(` Title: ${ticket.title}`));
|
|
221
|
+
this.log(styles.muted(` Status: ${ticket.statusName}`));
|
|
222
|
+
if (priority) {
|
|
223
|
+
this.log(styles.muted(` Priority: ${priority}`));
|
|
224
|
+
}
|
|
225
|
+
if (category) {
|
|
226
|
+
this.log(styles.muted(` Category: ${category}`));
|
|
227
|
+
}
|
|
228
|
+
if (assignee) {
|
|
229
|
+
this.log(styles.muted(` Assignee: ${assignee}`));
|
|
230
|
+
}
|
|
231
|
+
if (owner) {
|
|
232
|
+
this.log(styles.muted(` Owner: ${owner}`));
|
|
233
|
+
}
|
|
234
|
+
if (statusId) {
|
|
235
|
+
this.log(styles.muted(` Status: ${statusId}`));
|
|
236
|
+
}
|
|
237
|
+
if (labels && labels.length > 0) {
|
|
238
|
+
this.log(styles.muted(` Labels: ${labels.join(', ')}`));
|
|
239
|
+
}
|
|
240
|
+
if (flags.epic) {
|
|
241
|
+
this.log(styles.muted(` Epic: ${flags.epic}`));
|
|
242
|
+
}
|
|
243
|
+
if (!flags['no-subtasks'] && template.suggestedSubtasks.length > 0) {
|
|
244
|
+
this.log(styles.muted(` Subtasks: ${template.suggestedSubtasks.length} created`));
|
|
245
|
+
}
|
|
246
|
+
this.log('');
|
|
247
|
+
this.log(styles.muted(`View ticket: prlt ticket view ${ticket.id}`));
|
|
248
|
+
}
|
|
249
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { PMOCommand } from '../../../lib/pmo/index.js';
|
|
2
|
+
export default class TicketTemplateCreate extends PMOCommand {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static args: {
|
|
6
|
+
name: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
7
|
+
};
|
|
8
|
+
static flags: {
|
|
9
|
+
description: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
+
'title-pattern': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
priority: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
category: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
+
project: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
|
+
};
|
|
15
|
+
protected getPMOOptions(): {
|
|
16
|
+
promptIfMultiple: boolean;
|
|
17
|
+
};
|
|
18
|
+
execute(): Promise<void>;
|
|
19
|
+
}
|