@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,291 @@
|
|
|
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 EpicTicket extends PMOCommand {
|
|
7
|
+
static description = 'Assign tickets to an epic, or link epic to a spec (parent-child)';
|
|
8
|
+
static examples = [
|
|
9
|
+
'<%= config.bin %> <%= command.id %> EPIC-001 TKT-001 TKT-002',
|
|
10
|
+
'<%= config.bin %> <%= command.id %> EPIC-001',
|
|
11
|
+
'<%= config.bin %> <%= command.id %>',
|
|
12
|
+
'<%= config.bin %> <%= command.id %> EPIC-001 --unlink TKT-001',
|
|
13
|
+
'<%= config.bin %> <%= command.id %> EPIC-001 --spec SPEC-001',
|
|
14
|
+
];
|
|
15
|
+
static args = {
|
|
16
|
+
id: Args.string({
|
|
17
|
+
description: 'Epic ID',
|
|
18
|
+
required: false,
|
|
19
|
+
}),
|
|
20
|
+
tickets: Args.string({
|
|
21
|
+
description: 'Ticket IDs to link (space-separated)',
|
|
22
|
+
required: false,
|
|
23
|
+
multiple: true,
|
|
24
|
+
}),
|
|
25
|
+
};
|
|
26
|
+
static strict = false; // Allow multiple ticket arguments
|
|
27
|
+
static flags = {
|
|
28
|
+
...pmoBaseFlags,
|
|
29
|
+
json: Flags.boolean({
|
|
30
|
+
description: 'Output prompt configuration as JSON (for AI agents/scripts)',
|
|
31
|
+
default: false,
|
|
32
|
+
}),
|
|
33
|
+
unlink: Flags.boolean({
|
|
34
|
+
char: 'u',
|
|
35
|
+
description: 'Remove tickets from this epic instead of adding',
|
|
36
|
+
default: false,
|
|
37
|
+
}),
|
|
38
|
+
spec: Flags.string({
|
|
39
|
+
char: 's',
|
|
40
|
+
description: 'Link epic to a spec (design document)',
|
|
41
|
+
}),
|
|
42
|
+
'unlink-spec': Flags.boolean({
|
|
43
|
+
description: 'Remove spec link from epic',
|
|
44
|
+
default: false,
|
|
45
|
+
}),
|
|
46
|
+
};
|
|
47
|
+
async execute() {
|
|
48
|
+
const { args, flags, argv } = await this.parse(EpicTicket);
|
|
49
|
+
const filterProjectId = flags.project;
|
|
50
|
+
// Check if JSON output mode is active
|
|
51
|
+
const jsonMode = shouldOutputJson(flags);
|
|
52
|
+
// Helper to handle errors in JSON mode
|
|
53
|
+
const handleError = (code, message) => {
|
|
54
|
+
if (jsonMode) {
|
|
55
|
+
outputErrorAsJson(code, message, createMetadata('epic ticket', flags));
|
|
56
|
+
this.exit(1);
|
|
57
|
+
}
|
|
58
|
+
this.error(message);
|
|
59
|
+
};
|
|
60
|
+
const projectId = await this.requireProject();
|
|
61
|
+
// Get all epics
|
|
62
|
+
const epics = await this.storage.listEpics(projectId);
|
|
63
|
+
if (epics.length === 0) {
|
|
64
|
+
if (jsonMode) {
|
|
65
|
+
outputErrorAsJson('NO_EPICS', 'No epics found.', createMetadata('epic ticket', flags));
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
this.log(styles.muted('\nNo epics found. Create one with: prlt epic create'));
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
// Get all tickets
|
|
72
|
+
const allTickets = await this.storage.listTickets(filterProjectId);
|
|
73
|
+
if (allTickets.length === 0) {
|
|
74
|
+
if (jsonMode) {
|
|
75
|
+
outputErrorAsJson('NO_TICKETS', 'No tickets found.', createMetadata('epic ticket', flags));
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
this.log(styles.muted('\nNo tickets found.'));
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
// Get epic_id for each ticket via direct DB query
|
|
82
|
+
const db = this.storage.db;
|
|
83
|
+
const getTicketEpicId = (ticketId) => {
|
|
84
|
+
const row = db.prepare(`SELECT epic_id FROM pmo_tickets WHERE id = ?`).get(ticketId);
|
|
85
|
+
return row?.epic_id || null;
|
|
86
|
+
};
|
|
87
|
+
let epicId = args.id;
|
|
88
|
+
// If no epic ID provided, prompt for selection
|
|
89
|
+
if (!epicId) {
|
|
90
|
+
// Count tickets per epic
|
|
91
|
+
const ticketCounts = new Map();
|
|
92
|
+
for (const ticket of allTickets) {
|
|
93
|
+
const tid = getTicketEpicId(ticket.id);
|
|
94
|
+
if (tid) {
|
|
95
|
+
ticketCounts.set(tid, (ticketCounts.get(tid) || 0) + 1);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
const epicChoices = epics.map(e => ({
|
|
99
|
+
name: `${e.id} ${e.title} (${e.status}) [${ticketCounts.get(e.id) || 0} tickets]`,
|
|
100
|
+
value: e.id,
|
|
101
|
+
}));
|
|
102
|
+
// In JSON mode, output epic selection prompt
|
|
103
|
+
if (jsonMode) {
|
|
104
|
+
outputPromptAsJson(buildPromptConfig('list', 'id', 'Select epic to link tickets to:', epicChoices), createMetadata('epic ticket', flags));
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
const { selected } = await inquirer.prompt([{
|
|
108
|
+
type: 'list',
|
|
109
|
+
name: 'selected',
|
|
110
|
+
message: 'Select epic to link tickets to:',
|
|
111
|
+
choices: epicChoices,
|
|
112
|
+
}]);
|
|
113
|
+
epicId = selected;
|
|
114
|
+
}
|
|
115
|
+
// Validate epic exists
|
|
116
|
+
const epic = epics.find(e => e.id === epicId);
|
|
117
|
+
if (!epic) {
|
|
118
|
+
return handleError('EPIC_NOT_FOUND', `Epic not found: ${epicId}`);
|
|
119
|
+
}
|
|
120
|
+
// Handle spec linking if --spec or --unlink-spec provided
|
|
121
|
+
if (flags.spec || flags['unlink-spec']) {
|
|
122
|
+
if (flags['unlink-spec']) {
|
|
123
|
+
// Unlink spec from epic
|
|
124
|
+
if (!epic.specId) {
|
|
125
|
+
this.log(styles.muted(`\nEpic ${epicId} is not linked to any spec.`));
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
await this.storage.updateEpic(epicId, { specId: undefined });
|
|
129
|
+
this.log(styles.success(`\n✅ Unlinked spec from ${styles.emphasis(epicId)} "${epic.title}"`));
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
// Link spec to epic
|
|
134
|
+
const spec = await this.storage.getSpec(flags.spec);
|
|
135
|
+
if (!spec) {
|
|
136
|
+
this.error(`Spec not found: ${flags.spec}`);
|
|
137
|
+
}
|
|
138
|
+
await this.storage.updateEpic(epicId, { specId: flags.spec });
|
|
139
|
+
this.log(styles.success(`\n✅ Linked ${styles.emphasis(epicId)} "${epic.title}" to spec ${styles.emphasis(flags.spec)}`));
|
|
140
|
+
this.log(styles.muted(` Spec: ${spec.title}`));
|
|
141
|
+
}
|
|
142
|
+
// If only spec operation, exit here
|
|
143
|
+
const argvStrings = argv;
|
|
144
|
+
if (argvStrings.length <= 1 && !flags.unlink) {
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
// Get ticket IDs from remaining argv (after epic ID)
|
|
149
|
+
let ticketIds = [];
|
|
150
|
+
const argvStrings = argv;
|
|
151
|
+
if (argvStrings.length > 1) {
|
|
152
|
+
ticketIds = argvStrings.slice(1);
|
|
153
|
+
}
|
|
154
|
+
// If no ticket IDs provided, prompt with multi-select
|
|
155
|
+
if (ticketIds.length === 0) {
|
|
156
|
+
const choices = allTickets.map((t) => {
|
|
157
|
+
const currentEpicId = getTicketEpicId(t.id);
|
|
158
|
+
let epicLabel = 'No epic';
|
|
159
|
+
if (currentEpicId === epicId) {
|
|
160
|
+
epicLabel = `${epicId} ← current`;
|
|
161
|
+
}
|
|
162
|
+
else if (currentEpicId) {
|
|
163
|
+
const currentEpic = epics.find(e => e.id === currentEpicId);
|
|
164
|
+
epicLabel = currentEpic?.title || currentEpicId;
|
|
165
|
+
}
|
|
166
|
+
return {
|
|
167
|
+
name: `${t.id} - ${t.title} [${epicLabel}]`,
|
|
168
|
+
value: t.id,
|
|
169
|
+
checked: false,
|
|
170
|
+
};
|
|
171
|
+
});
|
|
172
|
+
// In JSON mode, output ticket selection prompt
|
|
173
|
+
if (jsonMode) {
|
|
174
|
+
outputPromptAsJson(buildPromptConfig('checkbox', 'tickets', `Select tickets to ${flags.unlink ? 'unlink from' : 'link to'} ${epicId}:`, choices), createMetadata('epic ticket', flags));
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
const { selected } = await inquirer.prompt([{
|
|
178
|
+
type: 'checkbox',
|
|
179
|
+
name: 'selected',
|
|
180
|
+
message: `Select tickets to ${flags.unlink ? 'unlink from' : 'link to'} ${epicId}:`,
|
|
181
|
+
choices,
|
|
182
|
+
}]);
|
|
183
|
+
ticketIds = selected;
|
|
184
|
+
}
|
|
185
|
+
if (ticketIds.length === 0) {
|
|
186
|
+
this.log(styles.muted('\nNo tickets selected.'));
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
// Validate all tickets exist
|
|
190
|
+
const invalidTickets = ticketIds.filter(id => !allTickets.find((t) => t.id === id));
|
|
191
|
+
if (invalidTickets.length > 0) {
|
|
192
|
+
this.error(`Tickets not found: ${invalidTickets.join(', ')}`);
|
|
193
|
+
}
|
|
194
|
+
// Process each ticket
|
|
195
|
+
let successCount = 0;
|
|
196
|
+
const linkedTickets = [];
|
|
197
|
+
for (const ticketId of ticketIds) {
|
|
198
|
+
const ticket = allTickets.find((t) => t.id === ticketId);
|
|
199
|
+
const currentEpicId = getTicketEpicId(ticketId);
|
|
200
|
+
if (flags.unlink) {
|
|
201
|
+
// Unlink: only if currently linked to this epic
|
|
202
|
+
if (currentEpicId !== epicId) {
|
|
203
|
+
this.log(styles.muted(` ${ticketId} is not linked to ${epicId}, skipping`));
|
|
204
|
+
continue;
|
|
205
|
+
}
|
|
206
|
+
db.prepare(`
|
|
207
|
+
UPDATE pmo_tickets
|
|
208
|
+
SET epic_id = NULL, updated_at = ?
|
|
209
|
+
WHERE id = ?
|
|
210
|
+
`).run(Date.now(), ticketId);
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
// Link: check if already linked to same epic
|
|
214
|
+
if (currentEpicId === epicId) {
|
|
215
|
+
this.log(styles.muted(` ${ticketId} already linked to ${epicId}, skipping`));
|
|
216
|
+
continue;
|
|
217
|
+
}
|
|
218
|
+
// Warn if linked to different epic
|
|
219
|
+
if (currentEpicId) {
|
|
220
|
+
const currentEpic = epics.find(e => e.id === currentEpicId);
|
|
221
|
+
this.log(styles.warning(` ${ticketId} was linked to ${currentEpic?.title || currentEpicId}, reassigning`));
|
|
222
|
+
}
|
|
223
|
+
// Reconciliation: Check spec consistency between ticket and epic
|
|
224
|
+
const ticketSpecId = ticket.specId;
|
|
225
|
+
const epicSpecId = epic.specId;
|
|
226
|
+
if (ticketSpecId && epicSpecId && ticketSpecId !== epicSpecId) {
|
|
227
|
+
// Both have specs but they differ - warn user
|
|
228
|
+
this.log(styles.warning(` ⚠️ Spec mismatch: ticket has "${ticketSpecId}", epic has "${epicSpecId}"`));
|
|
229
|
+
const { action } = await inquirer.prompt([{
|
|
230
|
+
type: 'list',
|
|
231
|
+
name: 'action',
|
|
232
|
+
message: `How to reconcile spec for ${ticketId}?`,
|
|
233
|
+
choices: [
|
|
234
|
+
{ name: `Keep ticket spec (${ticketSpecId})`, value: 'keep_ticket' },
|
|
235
|
+
{ name: `Use epic spec (${epicSpecId})`, value: 'use_epic' },
|
|
236
|
+
{ name: 'Skip this ticket', value: 'skip' },
|
|
237
|
+
],
|
|
238
|
+
}]);
|
|
239
|
+
if (action === 'skip') {
|
|
240
|
+
this.log(styles.muted(` Skipping ${ticketId}`));
|
|
241
|
+
continue;
|
|
242
|
+
}
|
|
243
|
+
if (action === 'use_epic') {
|
|
244
|
+
// Update ticket to use epic's spec
|
|
245
|
+
db.prepare(`
|
|
246
|
+
UPDATE pmo_tickets
|
|
247
|
+
SET spec_id = ?, updated_at = ?
|
|
248
|
+
WHERE id = ?
|
|
249
|
+
`).run(epicSpecId, Date.now(), ticketId);
|
|
250
|
+
this.log(styles.muted(` Updated ${ticketId} to use spec "${epicSpecId}"`));
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
else if (!ticketSpecId && epicSpecId) {
|
|
254
|
+
// Ticket has no spec but epic does - offer to inherit
|
|
255
|
+
const { inherit } = await inquirer.prompt([{
|
|
256
|
+
type: 'confirm',
|
|
257
|
+
name: 'inherit',
|
|
258
|
+
message: `${ticketId} has no spec. Inherit epic's spec "${epicSpecId}"?`,
|
|
259
|
+
default: true,
|
|
260
|
+
}]);
|
|
261
|
+
if (inherit) {
|
|
262
|
+
db.prepare(`
|
|
263
|
+
UPDATE pmo_tickets
|
|
264
|
+
SET spec_id = ?, updated_at = ?
|
|
265
|
+
WHERE id = ?
|
|
266
|
+
`).run(epicSpecId, Date.now(), ticketId);
|
|
267
|
+
this.log(styles.muted(` Assigned spec "${epicSpecId}" to ${ticketId}`));
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
db.prepare(`
|
|
271
|
+
UPDATE pmo_tickets
|
|
272
|
+
SET epic_id = ?, updated_at = ?
|
|
273
|
+
WHERE id = ?
|
|
274
|
+
`).run(epicId, Date.now(), ticketId);
|
|
275
|
+
}
|
|
276
|
+
linkedTickets.push(`${ticketId}: ${ticket.title}`);
|
|
277
|
+
successCount++;
|
|
278
|
+
}
|
|
279
|
+
await autoExportToBoard(this.pmoPath, this.storage, (msg) => this.log(styles.muted(msg)));
|
|
280
|
+
if (successCount === 0) {
|
|
281
|
+
this.log(styles.muted('\nNo changes made.'));
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
const action = flags.unlink ? 'Unlinked' : 'Linked';
|
|
285
|
+
this.log(styles.success(`\n✅ ${action} ${successCount} ticket${successCount === 1 ? '' : 's'} ${flags.unlink ? 'from' : 'to'} ${styles.emphasis(epicId)} "${epic.title}"`));
|
|
286
|
+
for (const t of linkedTickets) {
|
|
287
|
+
this.log(styles.muted(` ${t}`));
|
|
288
|
+
}
|
|
289
|
+
this.log(styles.muted(`\nView epic: prlt epic view ${epicId}`));
|
|
290
|
+
}
|
|
291
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { PMOCommand } from '../../lib/pmo/index.js';
|
|
2
|
+
export default class EpicView 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
|
+
};
|
|
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,117 @@
|
|
|
1
|
+
import { Args, Flags } from '@oclif/core';
|
|
2
|
+
import { PMOCommand, pmoBaseFlags } from '../../lib/pmo/index.js';
|
|
3
|
+
import { styles } from '../../lib/styles.js';
|
|
4
|
+
import { shouldOutputJson, outputErrorAsJson, createMetadata, } from '../../lib/prompt-json.js';
|
|
5
|
+
// Progress bar helper
|
|
6
|
+
function progressBar(percent, width = 20) {
|
|
7
|
+
const filled = Math.round((percent / 100) * width);
|
|
8
|
+
const empty = width - filled;
|
|
9
|
+
return '█'.repeat(filled) + '░'.repeat(empty);
|
|
10
|
+
}
|
|
11
|
+
export default class EpicView extends PMOCommand {
|
|
12
|
+
static description = 'View epic details and linked tickets';
|
|
13
|
+
static examples = [
|
|
14
|
+
'<%= config.bin %> <%= command.id %> EPIC-001',
|
|
15
|
+
'<%= config.bin %> <%= command.id %>',
|
|
16
|
+
];
|
|
17
|
+
static args = {
|
|
18
|
+
id: Args.string({
|
|
19
|
+
description: 'Epic ID',
|
|
20
|
+
required: false,
|
|
21
|
+
}),
|
|
22
|
+
};
|
|
23
|
+
static flags = {
|
|
24
|
+
...pmoBaseFlags,
|
|
25
|
+
json: Flags.boolean({
|
|
26
|
+
description: 'Output prompt configuration as JSON (for AI agents/scripts)',
|
|
27
|
+
default: false,
|
|
28
|
+
}),
|
|
29
|
+
};
|
|
30
|
+
async execute() {
|
|
31
|
+
const { args, flags } = await this.parse(EpicView);
|
|
32
|
+
// Check if JSON output mode is active
|
|
33
|
+
const jsonMode = shouldOutputJson(flags);
|
|
34
|
+
// Helper to handle errors in JSON mode
|
|
35
|
+
const handleError = (code, message) => {
|
|
36
|
+
if (jsonMode) {
|
|
37
|
+
outputErrorAsJson(code, message, createMetadata('epic view', flags));
|
|
38
|
+
this.exit(1);
|
|
39
|
+
}
|
|
40
|
+
this.error(message);
|
|
41
|
+
};
|
|
42
|
+
const projectId = await this.requireProject();
|
|
43
|
+
let epicId = args.id;
|
|
44
|
+
// If no ID provided, prompt for selection
|
|
45
|
+
if (!epicId) {
|
|
46
|
+
const epics = await this.storage.listEpics(projectId);
|
|
47
|
+
if (epics.length === 0) {
|
|
48
|
+
if (jsonMode) {
|
|
49
|
+
outputErrorAsJson('NO_EPICS', 'No epics found.', createMetadata('epic view', flags));
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
this.log(styles.muted('\nNo epics found.'));
|
|
53
|
+
this.log(styles.muted('Create one with: prlt epic create'));
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
const selected = await this.selectFromList({
|
|
57
|
+
message: 'Select epic to view:',
|
|
58
|
+
items: epics,
|
|
59
|
+
getName: (e) => `${e.id} ${e.title} (${e.status})`,
|
|
60
|
+
getValue: (e) => e.id,
|
|
61
|
+
getCommand: (e) => `prlt epic view ${e.id} --json`,
|
|
62
|
+
jsonMode: jsonMode ? { flags, commandName: 'epic view' } : null,
|
|
63
|
+
});
|
|
64
|
+
if (!selected) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
epicId = selected;
|
|
68
|
+
}
|
|
69
|
+
const epic = await this.storage.getEpic(epicId);
|
|
70
|
+
if (!epic) {
|
|
71
|
+
return handleError('EPIC_NOT_FOUND', `Epic not found: ${epicId}`);
|
|
72
|
+
}
|
|
73
|
+
const tickets = await this.storage.getTicketsForEpic(projectId, epicId);
|
|
74
|
+
const doneTickets = tickets.filter((t) => t.statusCategory === 'completed').length;
|
|
75
|
+
const percent = tickets.length > 0 ? Math.round((doneTickets / tickets.length) * 100) : 0;
|
|
76
|
+
// Get linked spec if any
|
|
77
|
+
let specTitle;
|
|
78
|
+
if (epic.specId) {
|
|
79
|
+
const spec = await this.storage.getSpec(epic.specId);
|
|
80
|
+
specTitle = spec?.title;
|
|
81
|
+
}
|
|
82
|
+
const projectName = await this.getProjectName(projectId);
|
|
83
|
+
this.log(`\n🎯 Epic: ${styles.emphasis(epic.id)} - ${epic.title}`);
|
|
84
|
+
this.log('═'.repeat(55));
|
|
85
|
+
this.log(`ID: ${epic.id}`);
|
|
86
|
+
this.log(`Title: ${epic.title}`);
|
|
87
|
+
this.log(`Project: ${projectName}`);
|
|
88
|
+
this.log(`Status: ${epic.status}`);
|
|
89
|
+
if (epic.specId) {
|
|
90
|
+
this.log(`Spec: ${epic.specId}${specTitle ? ` - ${specTitle}` : ''}`);
|
|
91
|
+
}
|
|
92
|
+
this.log(`Created: ${epic.createdAt.toLocaleDateString()}`);
|
|
93
|
+
if (epic.description) {
|
|
94
|
+
this.log(`\nDescription: ${epic.description}`);
|
|
95
|
+
}
|
|
96
|
+
this.log(`\nProgress: ${percent}% (${doneTickets}/${tickets.length} tickets complete)`);
|
|
97
|
+
this.log(progressBar(percent));
|
|
98
|
+
if (tickets.length > 0) {
|
|
99
|
+
this.log(`\n🎫 Tickets (${tickets.length}):`);
|
|
100
|
+
for (const ticket of tickets) {
|
|
101
|
+
const icon = ticket.statusCategory === 'completed' ? '✅' :
|
|
102
|
+
ticket.statusCategory === 'started' ? '🚧' :
|
|
103
|
+
ticket.statusCategory === 'unstarted' ? '📋' :
|
|
104
|
+
ticket.statusCategory === 'canceled' ? '🚫' : '📥';
|
|
105
|
+
const statusLabel = ticket.statusName || 'Unknown';
|
|
106
|
+
this.log(` ${icon} ${ticket.id}: ${ticket.title} [${statusLabel}]`);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
this.log(styles.muted('\n No tickets linked to this epic yet.'));
|
|
111
|
+
}
|
|
112
|
+
this.log('\n' + '═'.repeat(55));
|
|
113
|
+
this.log(styles.muted('Commands:'));
|
|
114
|
+
this.log(styles.muted(` prlt epic progress ${epic.id}`));
|
|
115
|
+
this.log(styles.muted(` prlt ticket create --epic ${epic.id} "New task"`));
|
|
116
|
+
}
|
|
117
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { PMOCommand } from '../../lib/pmo/index.js';
|
|
2
|
+
export default class Execution extends PMOCommand {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static flags: {
|
|
6
|
+
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
7
|
+
project: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
8
|
+
};
|
|
9
|
+
protected getPMOOptions(): {
|
|
10
|
+
promptIfMultiple: boolean;
|
|
11
|
+
};
|
|
12
|
+
execute(): Promise<void>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { Flags } from '@oclif/core';
|
|
2
|
+
import inquirer from 'inquirer';
|
|
3
|
+
import { PMOCommand, pmoBaseFlags } from '../../lib/pmo/index.js';
|
|
4
|
+
import { shouldOutputJson, outputPromptAsJson, createMetadata, buildPromptConfig, } from '../../lib/prompt-json.js';
|
|
5
|
+
export default class Execution extends PMOCommand {
|
|
6
|
+
static description = 'Single execution operations (logs, stop)';
|
|
7
|
+
static examples = [
|
|
8
|
+
'<%= config.bin %> <%= command.id %>',
|
|
9
|
+
'<%= config.bin %> <%= command.id %> logs WORK-001',
|
|
10
|
+
'<%= config.bin %> <%= command.id %> stop WORK-001',
|
|
11
|
+
];
|
|
12
|
+
static flags = {
|
|
13
|
+
...pmoBaseFlags,
|
|
14
|
+
json: Flags.boolean({
|
|
15
|
+
description: 'Output prompt configuration as JSON (for AI agents/scripts)',
|
|
16
|
+
default: false,
|
|
17
|
+
}),
|
|
18
|
+
};
|
|
19
|
+
getPMOOptions() {
|
|
20
|
+
return { promptIfMultiple: false };
|
|
21
|
+
}
|
|
22
|
+
async execute() {
|
|
23
|
+
const { flags } = await this.parse(Execution);
|
|
24
|
+
// Check if JSON output mode is active
|
|
25
|
+
const jsonMode = shouldOutputJson(flags);
|
|
26
|
+
// Define choices once, use for both JSON and interactive modes
|
|
27
|
+
const menuChoices = [
|
|
28
|
+
{ name: 'List all executions', value: 'list' },
|
|
29
|
+
{ name: 'View logs for an execution', value: 'logs' },
|
|
30
|
+
{ name: 'Stop an execution', value: 'stop' },
|
|
31
|
+
{ name: 'Stop all running', value: 'stop-all' },
|
|
32
|
+
{ name: 'Cancel', value: 'cancel' },
|
|
33
|
+
];
|
|
34
|
+
const message = 'What would you like to do?';
|
|
35
|
+
// In JSON mode, output menu prompt
|
|
36
|
+
if (jsonMode) {
|
|
37
|
+
outputPromptAsJson(buildPromptConfig('list', 'action', message, menuChoices), createMetadata('execution', flags));
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
const { action } = await inquirer.prompt([
|
|
41
|
+
{
|
|
42
|
+
type: 'list',
|
|
43
|
+
name: 'action',
|
|
44
|
+
message,
|
|
45
|
+
choices: [
|
|
46
|
+
{ name: '📋 ' + menuChoices[0].name, value: menuChoices[0].value },
|
|
47
|
+
{ name: '📜 ' + menuChoices[1].name, value: menuChoices[1].value },
|
|
48
|
+
{ name: '🛑 ' + menuChoices[2].name, value: menuChoices[2].value },
|
|
49
|
+
{ name: '🛑 ' + menuChoices[3].name, value: menuChoices[3].value },
|
|
50
|
+
new inquirer.Separator(),
|
|
51
|
+
{ name: '❌ ' + menuChoices[4].name, value: menuChoices[4].value },
|
|
52
|
+
],
|
|
53
|
+
},
|
|
54
|
+
]);
|
|
55
|
+
if (action === 'cancel') {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
// Run the selected subcommand
|
|
59
|
+
const commands = {
|
|
60
|
+
list: { cmd: 'execution:list', args: [] },
|
|
61
|
+
logs: { cmd: 'execution:logs', args: [] },
|
|
62
|
+
stop: { cmd: 'execution:stop', args: [] },
|
|
63
|
+
'stop-all': { cmd: 'execution:stop', args: ['--all'] },
|
|
64
|
+
};
|
|
65
|
+
const command = commands[action];
|
|
66
|
+
if (command) {
|
|
67
|
+
await this.config.runCommand(command.cmd, command.args);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { PMOCommand } from '../../lib/pmo/index.js';
|
|
2
|
+
export default class ExecutionList extends PMOCommand {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static flags: {
|
|
6
|
+
status: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
7
|
+
agent: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
8
|
+
limit: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
|
+
project: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
+
};
|
|
11
|
+
protected getPMOOptions(): {
|
|
12
|
+
promptIfMultiple: boolean;
|
|
13
|
+
};
|
|
14
|
+
execute(): Promise<void>;
|
|
15
|
+
}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { Flags } from '@oclif/core';
|
|
2
|
+
import * as path from 'node:path';
|
|
3
|
+
import Database from 'better-sqlite3';
|
|
4
|
+
import { styles } from '../../lib/styles.js';
|
|
5
|
+
import { getWorkspaceInfo } from '../../lib/agents/commands.js';
|
|
6
|
+
import { ExecutionStorage } from '../../lib/execution/storage.js';
|
|
7
|
+
import { PMOCommand, pmoBaseFlags } from '../../lib/pmo/index.js';
|
|
8
|
+
export default class ExecutionList extends PMOCommand {
|
|
9
|
+
static description = 'List running and recent executions';
|
|
10
|
+
static examples = [
|
|
11
|
+
'<%= config.bin %> <%= command.id %>',
|
|
12
|
+
'<%= config.bin %> <%= command.id %> --status running',
|
|
13
|
+
'<%= config.bin %> <%= command.id %> --agent alice',
|
|
14
|
+
'<%= config.bin %> <%= command.id %> --limit 50',
|
|
15
|
+
];
|
|
16
|
+
static flags = {
|
|
17
|
+
...pmoBaseFlags,
|
|
18
|
+
status: Flags.string({
|
|
19
|
+
char: 's',
|
|
20
|
+
description: 'Filter by status',
|
|
21
|
+
options: ['starting', 'running', 'completed', 'failed', 'stopped'],
|
|
22
|
+
}),
|
|
23
|
+
agent: Flags.string({
|
|
24
|
+
char: 'a',
|
|
25
|
+
description: 'Filter by agent name',
|
|
26
|
+
}),
|
|
27
|
+
limit: Flags.integer({
|
|
28
|
+
char: 'l',
|
|
29
|
+
description: 'Number of results',
|
|
30
|
+
default: 20,
|
|
31
|
+
}),
|
|
32
|
+
};
|
|
33
|
+
getPMOOptions() {
|
|
34
|
+
return { promptIfMultiple: false };
|
|
35
|
+
}
|
|
36
|
+
async execute() {
|
|
37
|
+
const { flags } = await this.parse(ExecutionList);
|
|
38
|
+
// Get workspace info
|
|
39
|
+
let workspaceInfo;
|
|
40
|
+
try {
|
|
41
|
+
workspaceInfo = getWorkspaceInfo();
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
this.error('Not in a workspace. Run "prlt init" first.');
|
|
45
|
+
}
|
|
46
|
+
// Open database
|
|
47
|
+
const dbPath = path.join(workspaceInfo.path, '.proletariat', 'workspace.db');
|
|
48
|
+
const db = new Database(dbPath);
|
|
49
|
+
const executionStorage = new ExecutionStorage(db);
|
|
50
|
+
try {
|
|
51
|
+
const executions = executionStorage.listExecutions({
|
|
52
|
+
status: flags.status,
|
|
53
|
+
agentName: flags.agent,
|
|
54
|
+
limit: flags.limit,
|
|
55
|
+
});
|
|
56
|
+
if (executions.length === 0) {
|
|
57
|
+
this.log(styles.muted('\nNo executions found.\n'));
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
// Display header
|
|
61
|
+
this.log('');
|
|
62
|
+
this.log(styles.header('🚀 Agent Work'));
|
|
63
|
+
this.log('═'.repeat(100));
|
|
64
|
+
this.log(styles.muted(padEnd('ID', 11) +
|
|
65
|
+
padEnd('Ticket', 9) +
|
|
66
|
+
padEnd('Agent', 10) +
|
|
67
|
+
padEnd('Env', 12) +
|
|
68
|
+
padEnd('Display', 11) +
|
|
69
|
+
padEnd('Perms', 8) +
|
|
70
|
+
padEnd('Status', 10) +
|
|
71
|
+
'Started'));
|
|
72
|
+
this.log('─'.repeat(100));
|
|
73
|
+
// Display executions
|
|
74
|
+
for (const exec of executions) {
|
|
75
|
+
const statusColor = getStatusColor(exec.status);
|
|
76
|
+
const timeAgo = formatTimeAgo(exec.startedAt);
|
|
77
|
+
const envIcon = exec.environment === 'devcontainer' ? '🐳' : (exec.environment === 'host' ? '💻' : '📦');
|
|
78
|
+
const envStr = `${envIcon} ${exec.environment}`;
|
|
79
|
+
const permsStr = exec.sandboxed ? 'safe' : 'danger';
|
|
80
|
+
const permsColor = exec.sandboxed ? styles.success : styles.warning;
|
|
81
|
+
this.log(padEnd(exec.id, 11) +
|
|
82
|
+
padEnd(exec.ticketId, 9) +
|
|
83
|
+
padEnd(exec.agentName, 10) +
|
|
84
|
+
padEnd(envStr, 12) +
|
|
85
|
+
padEnd(exec.displayMode, 11) +
|
|
86
|
+
permsColor(padEnd(permsStr, 8)) +
|
|
87
|
+
statusColor(padEnd(exec.status, 10)) +
|
|
88
|
+
styles.muted(timeAgo));
|
|
89
|
+
}
|
|
90
|
+
this.log('═'.repeat(100));
|
|
91
|
+
this.log('');
|
|
92
|
+
// Show commands
|
|
93
|
+
const runningExecs = executions.filter((e) => ['starting', 'running'].includes(e.status));
|
|
94
|
+
if (runningExecs.length > 0) {
|
|
95
|
+
this.log(styles.muted('Commands:'));
|
|
96
|
+
this.log(styles.muted(` prlt execution logs ${runningExecs[0].id} View logs`));
|
|
97
|
+
this.log(styles.muted(` prlt execution stop ${runningExecs[0].id} Stop execution`));
|
|
98
|
+
if (runningExecs.length > 1) {
|
|
99
|
+
this.log(styles.muted(` prlt execution stop --all Stop all running`));
|
|
100
|
+
}
|
|
101
|
+
this.log('');
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
finally {
|
|
105
|
+
db.close();
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
// =============================================================================
|
|
110
|
+
// Helper Functions
|
|
111
|
+
// =============================================================================
|
|
112
|
+
function padEnd(str, length) {
|
|
113
|
+
return str.padEnd(length);
|
|
114
|
+
}
|
|
115
|
+
function getStatusColor(status) {
|
|
116
|
+
switch (status) {
|
|
117
|
+
case 'running':
|
|
118
|
+
return styles.success;
|
|
119
|
+
case 'starting':
|
|
120
|
+
return styles.warning;
|
|
121
|
+
case 'completed':
|
|
122
|
+
return styles.muted;
|
|
123
|
+
case 'failed':
|
|
124
|
+
return styles.error;
|
|
125
|
+
case 'stopped':
|
|
126
|
+
return styles.muted;
|
|
127
|
+
default:
|
|
128
|
+
return (s) => s;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
function formatTimeAgo(date) {
|
|
132
|
+
const now = new Date();
|
|
133
|
+
const diffMs = now.getTime() - date.getTime();
|
|
134
|
+
const diffMins = Math.floor(diffMs / (1000 * 60));
|
|
135
|
+
const diffHours = Math.floor(diffMs / (1000 * 60 * 60));
|
|
136
|
+
const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));
|
|
137
|
+
if (diffMins < 1)
|
|
138
|
+
return 'just now';
|
|
139
|
+
if (diffMins < 60)
|
|
140
|
+
return `${diffMins} min ago`;
|
|
141
|
+
if (diffHours < 24)
|
|
142
|
+
return `${diffHours} hour${diffHours > 1 ? 's' : ''} ago`;
|
|
143
|
+
return `${diffDays} day${diffDays > 1 ? 's' : ''} ago`;
|
|
144
|
+
}
|