@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,219 @@
|
|
|
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, outputPromptAsJson, outputErrorAsJson, createMetadata, buildPromptConfig, } from '../../lib/prompt-json.js';
|
|
6
|
+
export default class EpicProject extends PMOCommand {
|
|
7
|
+
static description = 'Move an epic to a different project (optionally with its tickets)';
|
|
8
|
+
static examples = [
|
|
9
|
+
'<%= config.bin %> <%= command.id %> EPIC-001 new-project',
|
|
10
|
+
'<%= config.bin %> <%= command.id %> EPIC-001 new-project --with-tickets',
|
|
11
|
+
'<%= config.bin %> <%= command.id %> EPIC-001',
|
|
12
|
+
'<%= config.bin %> <%= command.id %>',
|
|
13
|
+
];
|
|
14
|
+
static args = {
|
|
15
|
+
epicId: Args.string({
|
|
16
|
+
description: 'Epic ID',
|
|
17
|
+
required: false,
|
|
18
|
+
}),
|
|
19
|
+
targetProject: Args.string({
|
|
20
|
+
description: 'Target project ID',
|
|
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
|
+
'with-tickets': Flags.boolean({
|
|
31
|
+
char: 't',
|
|
32
|
+
description: 'Also move all tickets assigned to this epic',
|
|
33
|
+
default: false,
|
|
34
|
+
}),
|
|
35
|
+
};
|
|
36
|
+
async execute() {
|
|
37
|
+
const { args, flags } = await this.parse(EpicProject);
|
|
38
|
+
// Check if JSON output mode is active
|
|
39
|
+
const jsonMode = shouldOutputJson(flags);
|
|
40
|
+
// Helper to handle errors in JSON mode
|
|
41
|
+
const handleError = (code, message) => {
|
|
42
|
+
if (jsonMode) {
|
|
43
|
+
outputErrorAsJson(code, message, createMetadata('epic project', flags));
|
|
44
|
+
this.exit(1);
|
|
45
|
+
}
|
|
46
|
+
this.error(message);
|
|
47
|
+
};
|
|
48
|
+
const sourceProjectId = await this.requireProject();
|
|
49
|
+
// Get epic ID
|
|
50
|
+
let epicId = args.epicId;
|
|
51
|
+
if (!epicId) {
|
|
52
|
+
const epics = await this.storage.listEpics(sourceProjectId);
|
|
53
|
+
if (epics.length === 0) {
|
|
54
|
+
if (jsonMode) {
|
|
55
|
+
outputErrorAsJson('NO_EPICS', 'No epics found in this project.', createMetadata('epic project', flags));
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
this.log(styles.muted('\nNo epics found in this project.'));
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
// In JSON mode, output epic selection prompt
|
|
62
|
+
if (jsonMode) {
|
|
63
|
+
const epicChoices = epics.map(e => ({ name: `${e.id} - ${e.title} (${e.status})`, value: e.id }));
|
|
64
|
+
outputPromptAsJson(buildPromptConfig('list', 'epicId', 'Select epic to move:', epicChoices), createMetadata('epic project', flags));
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
const { selected } = await inquirer.prompt([{
|
|
68
|
+
type: 'list',
|
|
69
|
+
name: 'selected',
|
|
70
|
+
message: 'Select epic to move:',
|
|
71
|
+
choices: epics.map(e => ({
|
|
72
|
+
name: `${e.id} - ${e.title} (${e.status})`,
|
|
73
|
+
value: e.id,
|
|
74
|
+
})),
|
|
75
|
+
}]);
|
|
76
|
+
epicId = selected;
|
|
77
|
+
}
|
|
78
|
+
// Get epic details
|
|
79
|
+
const epic = await this.storage.getEpic(epicId);
|
|
80
|
+
if (!epic) {
|
|
81
|
+
return handleError('EPIC_NOT_FOUND', `Epic not found: ${epicId}`);
|
|
82
|
+
}
|
|
83
|
+
// Get all projects
|
|
84
|
+
const projects = await this.storage.listProjects();
|
|
85
|
+
const otherProjects = projects.filter(p => p.id !== sourceProjectId);
|
|
86
|
+
if (otherProjects.length === 0) {
|
|
87
|
+
if (jsonMode) {
|
|
88
|
+
const actionChoices = [
|
|
89
|
+
{ name: 'Create a new project', value: 'create' },
|
|
90
|
+
{ name: 'Cancel', value: 'cancel' },
|
|
91
|
+
];
|
|
92
|
+
outputPromptAsJson(buildPromptConfig('list', 'action', 'No other projects to move to. What would you like to do?', actionChoices), createMetadata('epic project', flags));
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
this.log(styles.muted('\nNo other projects to move to.'));
|
|
96
|
+
const { action } = await inquirer.prompt([{
|
|
97
|
+
type: 'list',
|
|
98
|
+
name: 'action',
|
|
99
|
+
message: 'What would you like to do?',
|
|
100
|
+
choices: [
|
|
101
|
+
{ name: 'Create a new project', value: 'create' },
|
|
102
|
+
{ name: 'Cancel', value: 'cancel' },
|
|
103
|
+
],
|
|
104
|
+
}]);
|
|
105
|
+
if (action === 'create') {
|
|
106
|
+
await this.config.runCommand('project:create', []);
|
|
107
|
+
}
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
// Get target project
|
|
111
|
+
let targetProjectId = args.targetProject;
|
|
112
|
+
if (!targetProjectId) {
|
|
113
|
+
// In JSON mode, output project selection prompt
|
|
114
|
+
if (jsonMode) {
|
|
115
|
+
const projectChoices = otherProjects.map(p => ({ name: `${p.id} - ${p.name} (${p.status})`, value: p.id }));
|
|
116
|
+
outputPromptAsJson(buildPromptConfig('list', 'targetProject', 'Select target project:', projectChoices), createMetadata('epic project', flags));
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
const { selected } = await inquirer.prompt([{
|
|
120
|
+
type: 'list',
|
|
121
|
+
name: 'selected',
|
|
122
|
+
message: 'Select target project:',
|
|
123
|
+
choices: otherProjects.map(p => ({
|
|
124
|
+
name: `${p.id} - ${p.name} (${p.status})`,
|
|
125
|
+
value: p.id,
|
|
126
|
+
})),
|
|
127
|
+
}]);
|
|
128
|
+
targetProjectId = selected;
|
|
129
|
+
}
|
|
130
|
+
// Validate target project
|
|
131
|
+
const targetProject = projects.find(p => p.id === targetProjectId);
|
|
132
|
+
if (!targetProject) {
|
|
133
|
+
this.error(`Project not found: ${targetProjectId}`);
|
|
134
|
+
}
|
|
135
|
+
if (targetProjectId === sourceProjectId) {
|
|
136
|
+
this.log(styles.muted('\nEpic is already in this project.'));
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
// Get database for direct updates
|
|
140
|
+
const db = this.storage.db;
|
|
141
|
+
// Get tickets associated with this epic
|
|
142
|
+
const epicTickets = await this.storage.getTicketsForEpic(sourceProjectId, epicId);
|
|
143
|
+
// Handle tickets
|
|
144
|
+
let moveTickets = flags['with-tickets'];
|
|
145
|
+
if (epicTickets.length > 0 && !flags['with-tickets']) {
|
|
146
|
+
// In JSON mode, output ticket handling prompt
|
|
147
|
+
if (jsonMode) {
|
|
148
|
+
const ticketActionChoices = [
|
|
149
|
+
{ name: 'Move tickets with epic', value: 'move' },
|
|
150
|
+
{ name: 'Keep tickets in source project (unlink from epic)', value: 'unlink' },
|
|
151
|
+
{ name: 'Cancel', value: 'cancel' },
|
|
152
|
+
];
|
|
153
|
+
outputPromptAsJson(buildPromptConfig('list', 'ticketAction', `Epic has ${epicTickets.length} ticket(s) assigned. How to handle tickets?`, ticketActionChoices), createMetadata('epic project', flags));
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
this.log(styles.warning(`\nEpic has ${epicTickets.length} ticket(s) assigned.`));
|
|
157
|
+
const { action } = await inquirer.prompt([{
|
|
158
|
+
type: 'list',
|
|
159
|
+
name: 'action',
|
|
160
|
+
message: 'How to handle tickets?',
|
|
161
|
+
choices: [
|
|
162
|
+
{ name: 'Move tickets with epic', value: 'move' },
|
|
163
|
+
{ name: 'Keep tickets in source project (unlink from epic)', value: 'unlink' },
|
|
164
|
+
{ name: 'Cancel', value: 'cancel' },
|
|
165
|
+
],
|
|
166
|
+
}]);
|
|
167
|
+
if (action === 'cancel') {
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
moveTickets = action === 'move';
|
|
171
|
+
}
|
|
172
|
+
// Move epic to new project
|
|
173
|
+
db.prepare(`
|
|
174
|
+
UPDATE pmo_epics
|
|
175
|
+
SET project_id = ?, updated_at = ?
|
|
176
|
+
WHERE id = ?
|
|
177
|
+
`).run(targetProjectId, Date.now(), epicId);
|
|
178
|
+
// Handle tickets
|
|
179
|
+
const movedTicketIds = [];
|
|
180
|
+
if (epicTickets.length > 0) {
|
|
181
|
+
// Get target project's default status
|
|
182
|
+
const targetBoard = await this.storage.getProjectBoard(targetProjectId);
|
|
183
|
+
const targetStatusId = targetBoard?.columns[0]?.id;
|
|
184
|
+
for (const ticket of epicTickets) {
|
|
185
|
+
if (moveTickets) {
|
|
186
|
+
// Move ticket to target project with its default status
|
|
187
|
+
db.prepare(`
|
|
188
|
+
UPDATE pmo_tickets
|
|
189
|
+
SET project_id = ?, status_id = ?, updated_at = ?
|
|
190
|
+
WHERE id = ?
|
|
191
|
+
`).run(targetProjectId, targetStatusId, Date.now(), ticket.id);
|
|
192
|
+
movedTicketIds.push(ticket.id);
|
|
193
|
+
}
|
|
194
|
+
else {
|
|
195
|
+
// Unlink ticket from epic (keep in source project)
|
|
196
|
+
db.prepare(`
|
|
197
|
+
UPDATE pmo_tickets
|
|
198
|
+
SET epic_id = NULL, updated_at = ?
|
|
199
|
+
WHERE id = ?
|
|
200
|
+
`).run(Date.now(), ticket.id);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
await autoExportToBoard(this.pmoPath, this.storage, (msg) => this.log(styles.muted(msg)));
|
|
205
|
+
this.log(styles.success(`\n✅ Moved epic ${styles.emphasis(epicId)} to project ${styles.emphasis(targetProjectId)}`));
|
|
206
|
+
this.log(styles.muted(` From: ${sourceProjectId}`));
|
|
207
|
+
this.log(styles.muted(` To: ${targetProjectId}`));
|
|
208
|
+
if (movedTicketIds.length > 0) {
|
|
209
|
+
this.log(styles.muted(`\n Moved ${movedTicketIds.length} ticket(s) with epic:`));
|
|
210
|
+
for (const ticketId of movedTicketIds) {
|
|
211
|
+
this.log(styles.muted(` - ${ticketId}`));
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
else if (epicTickets.length > 0) {
|
|
215
|
+
this.log(styles.muted(`\n ${epicTickets.length} ticket(s) unlinked and kept in source project.`));
|
|
216
|
+
}
|
|
217
|
+
this.log(styles.muted(`\nView epic: prlt epic view ${epicId}`));
|
|
218
|
+
}
|
|
219
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { PMOCommand } from '../../lib/pmo/index.js';
|
|
2
|
+
export default class EpicReorder extends PMOCommand {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static args: {
|
|
6
|
+
id: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
7
|
+
position: import("@oclif/core/interfaces").Arg<number | undefined, {
|
|
8
|
+
max?: number;
|
|
9
|
+
min?: number;
|
|
10
|
+
}>;
|
|
11
|
+
};
|
|
12
|
+
static flags: {
|
|
13
|
+
first: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
14
|
+
last: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
15
|
+
after: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
16
|
+
before: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
17
|
+
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
18
|
+
project: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
19
|
+
};
|
|
20
|
+
execute(): Promise<void>;
|
|
21
|
+
}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { Args, Flags } from '@oclif/core';
|
|
2
|
+
import inquirer from 'inquirer';
|
|
3
|
+
import { PMOCommand, pmoBaseFlags } from '../../lib/pmo/index.js';
|
|
4
|
+
import { styles } from '../../lib/styles.js';
|
|
5
|
+
import { shouldOutputJson, outputPromptAsJson, outputErrorAsJson, createMetadata, buildPromptConfig, } from '../../lib/prompt-json.js';
|
|
6
|
+
export default class EpicReorder extends PMOCommand {
|
|
7
|
+
static description = 'Reorder epic priority/rank';
|
|
8
|
+
static examples = [
|
|
9
|
+
'<%= config.bin %> <%= command.id %> EPIC-001 1',
|
|
10
|
+
'<%= config.bin %> <%= command.id %> EPIC-003 --first',
|
|
11
|
+
'<%= config.bin %> <%= command.id %> EPIC-002 --after EPIC-001',
|
|
12
|
+
];
|
|
13
|
+
static args = {
|
|
14
|
+
id: Args.string({
|
|
15
|
+
description: 'Epic ID to reorder',
|
|
16
|
+
required: false,
|
|
17
|
+
}),
|
|
18
|
+
position: Args.integer({
|
|
19
|
+
description: 'New position (1-based rank)',
|
|
20
|
+
required: false,
|
|
21
|
+
}),
|
|
22
|
+
};
|
|
23
|
+
static flags = {
|
|
24
|
+
...pmoBaseFlags,
|
|
25
|
+
first: Flags.boolean({
|
|
26
|
+
description: 'Move to first position (highest priority)',
|
|
27
|
+
exclusive: ['last', 'after', 'before'],
|
|
28
|
+
}),
|
|
29
|
+
last: Flags.boolean({
|
|
30
|
+
description: 'Move to last position (lowest priority)',
|
|
31
|
+
exclusive: ['first', 'after', 'before'],
|
|
32
|
+
}),
|
|
33
|
+
after: Flags.string({
|
|
34
|
+
description: 'Move after this epic ID',
|
|
35
|
+
exclusive: ['first', 'last', 'before'],
|
|
36
|
+
}),
|
|
37
|
+
before: Flags.string({
|
|
38
|
+
description: 'Move before this epic ID',
|
|
39
|
+
exclusive: ['first', 'last', 'after'],
|
|
40
|
+
}),
|
|
41
|
+
json: Flags.boolean({
|
|
42
|
+
description: 'Output prompt configuration as JSON (for AI agents/scripts)',
|
|
43
|
+
default: false,
|
|
44
|
+
}),
|
|
45
|
+
};
|
|
46
|
+
async execute() {
|
|
47
|
+
const { args, flags } = await this.parse(EpicReorder);
|
|
48
|
+
// Check if JSON output mode is active
|
|
49
|
+
const jsonMode = shouldOutputJson(flags);
|
|
50
|
+
// Helper to handle errors in JSON mode
|
|
51
|
+
const handleError = (code, message) => {
|
|
52
|
+
if (jsonMode) {
|
|
53
|
+
outputErrorAsJson(code, message, createMetadata('epic reorder', flags));
|
|
54
|
+
this.exit(1);
|
|
55
|
+
}
|
|
56
|
+
this.error(message);
|
|
57
|
+
};
|
|
58
|
+
const projectId = await this.requireProject();
|
|
59
|
+
// Get all epics for context
|
|
60
|
+
const epics = await this.storage.listEpics(projectId, { status: 'active' });
|
|
61
|
+
if (epics.length === 0) {
|
|
62
|
+
if (jsonMode) {
|
|
63
|
+
outputErrorAsJson('NO_ACTIVE_EPICS', 'No active epics to reorder.', createMetadata('epic reorder', flags));
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
this.log(styles.muted('\nNo active epics to reorder.'));
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
let epicId = args.id;
|
|
70
|
+
// If no ID provided, prompt for selection
|
|
71
|
+
if (!epicId) {
|
|
72
|
+
const choices = epics.map((e, i) => ({
|
|
73
|
+
name: `#${i + 1} ${e.id} - ${e.title}`,
|
|
74
|
+
value: e.id,
|
|
75
|
+
}));
|
|
76
|
+
// In JSON mode, output epic selection prompt
|
|
77
|
+
if (jsonMode) {
|
|
78
|
+
outputPromptAsJson(buildPromptConfig('list', 'id', 'Select epic to reorder:', choices), createMetadata('epic reorder', flags));
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
const { selected } = await inquirer.prompt([{
|
|
82
|
+
type: 'list',
|
|
83
|
+
name: 'selected',
|
|
84
|
+
message: 'Select epic to reorder:',
|
|
85
|
+
choices,
|
|
86
|
+
}]);
|
|
87
|
+
epicId = selected;
|
|
88
|
+
}
|
|
89
|
+
const epic = await this.storage.getEpic(epicId);
|
|
90
|
+
if (!epic) {
|
|
91
|
+
return handleError('EPIC_NOT_FOUND', `Epic not found: ${epicId}`);
|
|
92
|
+
}
|
|
93
|
+
// Determine new position
|
|
94
|
+
let newPosition;
|
|
95
|
+
if (flags.first) {
|
|
96
|
+
newPosition = 0;
|
|
97
|
+
}
|
|
98
|
+
else if (flags.last) {
|
|
99
|
+
newPosition = epics.length - 1;
|
|
100
|
+
}
|
|
101
|
+
else if (flags.after) {
|
|
102
|
+
const afterEpic = epics.find(e => e.id === flags.after);
|
|
103
|
+
if (!afterEpic) {
|
|
104
|
+
this.error(`Epic not found: ${flags.after}`);
|
|
105
|
+
}
|
|
106
|
+
newPosition = afterEpic.position + 1;
|
|
107
|
+
}
|
|
108
|
+
else if (flags.before) {
|
|
109
|
+
const beforeEpic = epics.find(e => e.id === flags.before);
|
|
110
|
+
if (!beforeEpic) {
|
|
111
|
+
this.error(`Epic not found: ${flags.before}`);
|
|
112
|
+
}
|
|
113
|
+
newPosition = beforeEpic.position;
|
|
114
|
+
}
|
|
115
|
+
else if (args.position !== undefined) {
|
|
116
|
+
// Convert 1-based rank to 0-based position
|
|
117
|
+
newPosition = args.position - 1;
|
|
118
|
+
if (newPosition < 0)
|
|
119
|
+
newPosition = 0;
|
|
120
|
+
if (newPosition >= epics.length)
|
|
121
|
+
newPosition = epics.length - 1;
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
// In JSON mode, output rank input prompt
|
|
125
|
+
if (jsonMode) {
|
|
126
|
+
outputPromptAsJson(buildPromptConfig('input', 'rank', `New rank for ${epicId} (1-${epics.length}):`, undefined, String(epic.position + 1)), createMetadata('epic reorder', flags));
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
// Interactive: show current order and ask for new position
|
|
130
|
+
this.log(`\nCurrent order:`);
|
|
131
|
+
epics.forEach((e, i) => {
|
|
132
|
+
const marker = e.id === epicId ? ' ◀' : '';
|
|
133
|
+
this.log(` #${i + 1} ${e.id} - ${e.title}${marker}`);
|
|
134
|
+
});
|
|
135
|
+
const { rank } = await inquirer.prompt([{
|
|
136
|
+
type: 'number',
|
|
137
|
+
name: 'rank',
|
|
138
|
+
message: `New rank for ${epicId} (1-${epics.length}):`,
|
|
139
|
+
default: epic.position + 1,
|
|
140
|
+
validate: (input) => {
|
|
141
|
+
if (input < 1 || input > epics.length) {
|
|
142
|
+
return `Please enter a number between 1 and ${epics.length}`;
|
|
143
|
+
}
|
|
144
|
+
return true;
|
|
145
|
+
},
|
|
146
|
+
}]);
|
|
147
|
+
newPosition = rank - 1;
|
|
148
|
+
}
|
|
149
|
+
// Perform reorder
|
|
150
|
+
await this.storage.reorderEpic(projectId, epicId, newPosition);
|
|
151
|
+
// Show new order
|
|
152
|
+
const updatedEpics = await this.storage.listEpics(projectId, { status: 'active' });
|
|
153
|
+
this.log(styles.success(`\n✅ Reordered ${epicId}`));
|
|
154
|
+
this.log(`\nNew priority order:`);
|
|
155
|
+
updatedEpics.forEach((e, i) => {
|
|
156
|
+
const marker = e.id === epicId ? styles.emphasis(' ◀') : '';
|
|
157
|
+
this.log(` #${i + 1} ${e.id} - ${e.title}${marker}`);
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { PMOCommand } from '../../lib/pmo/index.js';
|
|
2
|
+
export default class EpicSpec extends PMOCommand {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static args: {
|
|
6
|
+
epicId: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
7
|
+
specId: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
8
|
+
};
|
|
9
|
+
static flags: {
|
|
10
|
+
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
11
|
+
unlink: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
12
|
+
project: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
+
};
|
|
14
|
+
execute(): Promise<void>;
|
|
15
|
+
}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import { Args, Flags } from '@oclif/core';
|
|
2
|
+
import inquirer from 'inquirer';
|
|
3
|
+
import { PMOCommand, pmoBaseFlags } from '../../lib/pmo/index.js';
|
|
4
|
+
import { styles } from '../../lib/styles.js';
|
|
5
|
+
import { shouldOutputJson, outputPromptAsJson, outputErrorAsJson, createMetadata, buildPromptConfig, } from '../../lib/prompt-json.js';
|
|
6
|
+
export default class EpicSpec extends PMOCommand {
|
|
7
|
+
static description = 'Assign a spec to an epic (design document)';
|
|
8
|
+
static examples = [
|
|
9
|
+
'<%= config.bin %> <%= command.id %> EPIC-001 SPEC-001',
|
|
10
|
+
'<%= config.bin %> <%= command.id %> EPIC-001',
|
|
11
|
+
'<%= config.bin %> <%= command.id %>',
|
|
12
|
+
'<%= config.bin %> <%= command.id %> EPIC-001 --unlink',
|
|
13
|
+
];
|
|
14
|
+
static args = {
|
|
15
|
+
epicId: Args.string({
|
|
16
|
+
description: 'Epic ID',
|
|
17
|
+
required: false,
|
|
18
|
+
}),
|
|
19
|
+
specId: Args.string({
|
|
20
|
+
description: 'Spec ID to link',
|
|
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 spec from epic instead of adding',
|
|
33
|
+
default: false,
|
|
34
|
+
}),
|
|
35
|
+
};
|
|
36
|
+
async execute() {
|
|
37
|
+
const { args, flags } = await this.parse(EpicSpec);
|
|
38
|
+
// Check if JSON output mode is active
|
|
39
|
+
const jsonMode = shouldOutputJson(flags);
|
|
40
|
+
// Helper to handle errors in JSON mode
|
|
41
|
+
const handleError = (code, message) => {
|
|
42
|
+
if (jsonMode) {
|
|
43
|
+
outputErrorAsJson(code, message, createMetadata('epic spec', flags));
|
|
44
|
+
this.exit(1);
|
|
45
|
+
}
|
|
46
|
+
this.error(message);
|
|
47
|
+
};
|
|
48
|
+
const projectId = await this.requireProject();
|
|
49
|
+
// Get all epics
|
|
50
|
+
const epics = await this.storage.listEpics(projectId);
|
|
51
|
+
if (epics.length === 0) {
|
|
52
|
+
if (jsonMode) {
|
|
53
|
+
outputErrorAsJson('NO_EPICS', 'No epics found.', createMetadata('epic spec', flags));
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
this.log(styles.muted('\nNo epics found. Create one with: prlt epic create'));
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
let epicId = args.epicId;
|
|
60
|
+
// If no epic ID provided, prompt for selection
|
|
61
|
+
if (!epicId) {
|
|
62
|
+
const epicChoices = epics.map(e => {
|
|
63
|
+
const specLabel = e.specId ? ` [spec: ${e.specId}]` : '';
|
|
64
|
+
return {
|
|
65
|
+
name: `${e.id} ${e.title} (${e.status})${specLabel}`,
|
|
66
|
+
value: e.id,
|
|
67
|
+
};
|
|
68
|
+
});
|
|
69
|
+
// In JSON mode, output epic selection prompt
|
|
70
|
+
if (jsonMode) {
|
|
71
|
+
outputPromptAsJson(buildPromptConfig('list', 'epicId', 'Select epic:', epicChoices), createMetadata('epic spec', flags));
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const { selected } = await inquirer.prompt([{
|
|
75
|
+
type: 'list',
|
|
76
|
+
name: 'selected',
|
|
77
|
+
message: 'Select epic:',
|
|
78
|
+
choices: epicChoices,
|
|
79
|
+
}]);
|
|
80
|
+
epicId = selected;
|
|
81
|
+
}
|
|
82
|
+
// Validate epic exists
|
|
83
|
+
const epic = epics.find(e => e.id === epicId);
|
|
84
|
+
if (!epic) {
|
|
85
|
+
return handleError('EPIC_NOT_FOUND', `Epic not found: ${epicId}`);
|
|
86
|
+
}
|
|
87
|
+
// Handle unlink
|
|
88
|
+
if (flags.unlink) {
|
|
89
|
+
if (!epic.specId) {
|
|
90
|
+
this.log(styles.muted(`\nEpic ${epicId} is not linked to any spec.`));
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
const oldSpecId = epic.specId;
|
|
94
|
+
await this.storage.updateEpic(epicId, { specId: undefined });
|
|
95
|
+
this.log(styles.success(`\n✅ Unlinked spec "${styles.emphasis(oldSpecId)}" from epic ${styles.emphasis(epicId)} "${epic.title}"`));
|
|
96
|
+
}
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
// Get all specs
|
|
100
|
+
const specs = await this.storage.listSpecs();
|
|
101
|
+
if (specs.length === 0) {
|
|
102
|
+
if (jsonMode) {
|
|
103
|
+
outputErrorAsJson('NO_SPECS', 'No specs found.', createMetadata('epic spec', flags));
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
this.log(styles.muted('\nNo specs found. Create one with: prlt spec create'));
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
let specId = args.specId;
|
|
110
|
+
// If no spec ID provided, prompt for selection
|
|
111
|
+
if (!specId) {
|
|
112
|
+
const specChoices = specs.map(s => ({
|
|
113
|
+
name: `${s.id} - ${s.title} (${s.status})`,
|
|
114
|
+
value: s.id,
|
|
115
|
+
}));
|
|
116
|
+
// In JSON mode, output spec selection prompt
|
|
117
|
+
if (jsonMode) {
|
|
118
|
+
outputPromptAsJson(buildPromptConfig('list', 'specId', `Select spec to link to ${epicId}:`, specChoices), createMetadata('epic spec', flags));
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
const { selected } = await inquirer.prompt([{
|
|
122
|
+
type: 'list',
|
|
123
|
+
name: 'selected',
|
|
124
|
+
message: `Select spec to link to ${epicId}:`,
|
|
125
|
+
choices: specChoices,
|
|
126
|
+
}]);
|
|
127
|
+
specId = selected;
|
|
128
|
+
}
|
|
129
|
+
// Validate spec exists
|
|
130
|
+
const spec = specs.find(s => s.id === specId);
|
|
131
|
+
if (!spec) {
|
|
132
|
+
this.error(`Spec not found: ${specId}`);
|
|
133
|
+
}
|
|
134
|
+
// Check if already linked
|
|
135
|
+
if (epic.specId === specId) {
|
|
136
|
+
this.log(styles.muted(`\nEpic "${epicId}" is already linked to spec "${specId}".`));
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
// Warn if epic has different spec
|
|
140
|
+
if (epic.specId) {
|
|
141
|
+
this.log(styles.warning(`Epic "${epicId}" is currently linked to spec "${epic.specId}"`));
|
|
142
|
+
this.log(styles.muted(`This will replace the existing spec link.`));
|
|
143
|
+
}
|
|
144
|
+
// Reconciliation: Check if epic's tickets have different specs
|
|
145
|
+
const epicTickets = await this.storage.getTicketsForEpic(projectId, epicId);
|
|
146
|
+
const ticketsWithDifferentSpec = epicTickets.filter(t => t.specId && t.specId !== specId);
|
|
147
|
+
if (ticketsWithDifferentSpec.length > 0) {
|
|
148
|
+
// In JSON mode, output spec mismatch handling prompt
|
|
149
|
+
if (jsonMode) {
|
|
150
|
+
const mismatchChoices = [
|
|
151
|
+
{ name: 'Update epic only (tickets keep their specs)', value: 'epic_only' },
|
|
152
|
+
{ name: `Update epic AND align all tickets to "${specId}"`, value: 'align_all' },
|
|
153
|
+
{ name: 'Cancel', value: 'cancel' },
|
|
154
|
+
];
|
|
155
|
+
outputPromptAsJson(buildPromptConfig('list', 'specMismatchAction', `${ticketsWithDifferentSpec.length} ticket(s) in this epic have different specs. How to handle spec mismatch?`, mismatchChoices), createMetadata('epic spec', flags));
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
this.log(styles.warning(`\n⚠️ ${ticketsWithDifferentSpec.length} ticket(s) in this epic have different specs:`));
|
|
159
|
+
for (const t of ticketsWithDifferentSpec.slice(0, 5)) {
|
|
160
|
+
this.log(styles.muted(` - ${t.id}: spec "${t.specId}"`));
|
|
161
|
+
}
|
|
162
|
+
if (ticketsWithDifferentSpec.length > 5) {
|
|
163
|
+
this.log(styles.muted(` ... and ${ticketsWithDifferentSpec.length - 5} more`));
|
|
164
|
+
}
|
|
165
|
+
const { action } = await inquirer.prompt([{
|
|
166
|
+
type: 'list',
|
|
167
|
+
name: 'action',
|
|
168
|
+
message: 'How to handle spec mismatch?',
|
|
169
|
+
choices: [
|
|
170
|
+
{ name: 'Update epic only (tickets keep their specs)', value: 'epic_only' },
|
|
171
|
+
{ name: `Update epic AND align all tickets to "${specId}"`, value: 'align_all' },
|
|
172
|
+
{ name: 'Cancel', value: 'cancel' },
|
|
173
|
+
],
|
|
174
|
+
}]);
|
|
175
|
+
if (action === 'cancel') {
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
if (action === 'align_all') {
|
|
179
|
+
for (const t of ticketsWithDifferentSpec) {
|
|
180
|
+
await this.storage.updateTicket(t.id, { specId });
|
|
181
|
+
this.log(styles.muted(` Updated ${t.id} to spec "${specId}"`));
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
// Link spec to epic
|
|
186
|
+
await this.storage.updateEpic(epicId, { specId });
|
|
187
|
+
this.log(styles.success(`\n✅ Linked epic ${styles.emphasis(epicId)} "${epic.title}" to spec ${styles.emphasis(specId)}`));
|
|
188
|
+
this.log(styles.muted(` Spec: ${spec.title}`));
|
|
189
|
+
this.log(styles.muted(`\nView epic: prlt epic view ${epicId}`));
|
|
190
|
+
}
|
|
191
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { PMOCommand } from '../../lib/pmo/index.js';
|
|
2
|
+
export default class EpicTicket extends PMOCommand {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static args: {
|
|
6
|
+
id: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
7
|
+
tickets: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
8
|
+
};
|
|
9
|
+
static strict: boolean;
|
|
10
|
+
static flags: {
|
|
11
|
+
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
12
|
+
unlink: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
13
|
+
spec: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
|
+
'unlink-spec': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
15
|
+
project: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
16
|
+
};
|
|
17
|
+
execute(): Promise<void>;
|
|
18
|
+
}
|