@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,728 @@
|
|
|
1
|
+
import { Flags } from '@oclif/core';
|
|
2
|
+
import * as path from 'node:path';
|
|
3
|
+
import inquirer from 'inquirer';
|
|
4
|
+
import Database from 'better-sqlite3';
|
|
5
|
+
import { PMOCommand, pmoBaseFlags, autoExportToBoard } from '../../lib/pmo/index.js';
|
|
6
|
+
import { styles } from '../../lib/styles.js';
|
|
7
|
+
import { getWorkspaceInfo, getTicketTmuxSession, killTmuxSession } from '../../lib/agents/commands.js';
|
|
8
|
+
import { ExecutionStorage } from '../../lib/execution/storage.js';
|
|
9
|
+
import { isDockerRunning } from '../../lib/execution/runners.js';
|
|
10
|
+
import { shouldOutputJson, outputPromptAsJson, outputSuccessAsJson, outputErrorAsJson, createMetadata, buildPromptConfig, } from '../../lib/prompt-json.js';
|
|
11
|
+
export default class WorkSpawn extends PMOCommand {
|
|
12
|
+
static description = 'Spawn work for multiple tickets by column (batch mode)';
|
|
13
|
+
static strict = false; // Allow multiple ticket ID args without defining them
|
|
14
|
+
static examples = [
|
|
15
|
+
'<%= config.bin %> <%= command.id %> # Interactive: All or Many',
|
|
16
|
+
'<%= config.bin %> <%= command.id %> --all # All tickets in selected column',
|
|
17
|
+
'<%= config.bin %> <%= command.id %> --column Backlog # All tickets in Backlog',
|
|
18
|
+
'<%= config.bin %> <%= command.id %> --many # Multi-select specific tickets',
|
|
19
|
+
'<%= config.bin %> <%= command.id %> TKT-001 TKT-002 # Spawn specific tickets by ID',
|
|
20
|
+
'<%= config.bin %> <%= command.id %> --dry-run # Preview without executing',
|
|
21
|
+
'<%= config.bin %> <%= command.id %> --many --json # Output ticket choices as JSON (for agents)',
|
|
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
|
+
all: Flags.boolean({
|
|
30
|
+
char: 'a',
|
|
31
|
+
description: 'Spawn all tickets tickets in a column',
|
|
32
|
+
default: false,
|
|
33
|
+
}),
|
|
34
|
+
many: Flags.boolean({
|
|
35
|
+
description: 'Multi-select specific tickets to spawn',
|
|
36
|
+
default: false,
|
|
37
|
+
}),
|
|
38
|
+
column: Flags.string({
|
|
39
|
+
char: 'c',
|
|
40
|
+
description: 'Column name to spawn tickets from (used with --all)',
|
|
41
|
+
}),
|
|
42
|
+
strategy: Flags.string({
|
|
43
|
+
char: 's',
|
|
44
|
+
description: 'Agent selection strategy',
|
|
45
|
+
options: ['round-robin', 'least-busy', 'random'],
|
|
46
|
+
default: 'round-robin',
|
|
47
|
+
}),
|
|
48
|
+
'dry-run': Flags.boolean({
|
|
49
|
+
description: 'Show what would be spawned without executing',
|
|
50
|
+
default: false,
|
|
51
|
+
}),
|
|
52
|
+
mode: Flags.string({
|
|
53
|
+
char: 'm',
|
|
54
|
+
description: 'Runtime mode for spawned agents',
|
|
55
|
+
options: ['foreground', 'background', 'tmux', 'terminal', 'devcontainer', 'docker', 'vm'],
|
|
56
|
+
}),
|
|
57
|
+
executor: Flags.string({
|
|
58
|
+
char: 'e',
|
|
59
|
+
description: 'Override executor',
|
|
60
|
+
options: ['claude-code', 'codex', 'aider', 'custom'],
|
|
61
|
+
}),
|
|
62
|
+
force: Flags.boolean({
|
|
63
|
+
char: 'f',
|
|
64
|
+
description: 'Start even if work already in progress',
|
|
65
|
+
default: false,
|
|
66
|
+
}),
|
|
67
|
+
'run-on-host': Flags.boolean({
|
|
68
|
+
description: 'Run on host even if devcontainer exists (bypasses sandbox)',
|
|
69
|
+
default: false,
|
|
70
|
+
}),
|
|
71
|
+
limit: Flags.integer({
|
|
72
|
+
char: 'l',
|
|
73
|
+
description: 'Maximum number of tickets to spawn',
|
|
74
|
+
}),
|
|
75
|
+
yes: Flags.boolean({
|
|
76
|
+
char: 'y',
|
|
77
|
+
description: 'Skip confirmation prompt',
|
|
78
|
+
default: false,
|
|
79
|
+
}),
|
|
80
|
+
'per-ticket': Flags.boolean({
|
|
81
|
+
description: 'Prompt for settings per ticket (default: batch mode with same settings for all)',
|
|
82
|
+
default: false,
|
|
83
|
+
}),
|
|
84
|
+
output: Flags.string({
|
|
85
|
+
char: 'o',
|
|
86
|
+
description: 'Output mode (batch mode only)',
|
|
87
|
+
options: ['interactive', 'print'],
|
|
88
|
+
}),
|
|
89
|
+
'skip-permissions': Flags.boolean({
|
|
90
|
+
description: 'Skip permission prompts - danger mode (batch mode only)',
|
|
91
|
+
default: false,
|
|
92
|
+
}),
|
|
93
|
+
'create-pr': Flags.boolean({
|
|
94
|
+
description: 'Create PR when work is ready (batch mode only)',
|
|
95
|
+
default: false,
|
|
96
|
+
}),
|
|
97
|
+
'no-pr': Flags.boolean({
|
|
98
|
+
description: 'Do not create PR when work is ready (batch mode only)',
|
|
99
|
+
default: false,
|
|
100
|
+
}),
|
|
101
|
+
action: Flags.string({
|
|
102
|
+
description: 'Action to perform (e.g., groom, implement, review). Prompts if not provided.',
|
|
103
|
+
}),
|
|
104
|
+
session: Flags.string({
|
|
105
|
+
description: 'Session manager inside container (tmux runs agent in tmux inside container)',
|
|
106
|
+
options: ['tmux', 'direct'],
|
|
107
|
+
default: 'tmux',
|
|
108
|
+
}),
|
|
109
|
+
};
|
|
110
|
+
async execute() {
|
|
111
|
+
const { flags, argv } = await this.parse(WorkSpawn);
|
|
112
|
+
// This command requires project context
|
|
113
|
+
const projectId = await this.requireProject();
|
|
114
|
+
// Check if JSON output mode is active
|
|
115
|
+
const jsonMode = shouldOutputJson(flags);
|
|
116
|
+
// Helper to handle errors in JSON mode
|
|
117
|
+
const handleError = (code, message) => {
|
|
118
|
+
if (jsonMode) {
|
|
119
|
+
outputErrorAsJson(code, message, createMetadata('work spawn', flags));
|
|
120
|
+
this.exit(1);
|
|
121
|
+
}
|
|
122
|
+
this.error(message);
|
|
123
|
+
};
|
|
124
|
+
// Parse ticket IDs from args (everything after flags)
|
|
125
|
+
const ticketIdArgs = argv;
|
|
126
|
+
// Note: Docker check is handled by work:start command when spawning each ticket
|
|
127
|
+
// This allows for the interactive devcontainer/host selection with retry loop
|
|
128
|
+
// Get workspace info (for agent worktree paths)
|
|
129
|
+
let workspaceInfo;
|
|
130
|
+
try {
|
|
131
|
+
workspaceInfo = getWorkspaceInfo();
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
return handleError('NOT_IN_WORKSPACE', 'Not in a workspace. Run "prlt init" first.');
|
|
135
|
+
}
|
|
136
|
+
// Open database for execution storage
|
|
137
|
+
const dbPath = path.join(workspaceInfo.path, '.proletariat', 'workspace.db');
|
|
138
|
+
const db = new Database(dbPath);
|
|
139
|
+
const executionStorage = new ExecutionStorage(db);
|
|
140
|
+
try {
|
|
141
|
+
// Get board to list available columns
|
|
142
|
+
const board = await this.storage.getBoard(projectId);
|
|
143
|
+
const columnNames = board.columns.map(col => col.name);
|
|
144
|
+
if (columnNames.length === 0) {
|
|
145
|
+
db.close();
|
|
146
|
+
return handleError('NO_COLUMNS', 'No columns found on the board.');
|
|
147
|
+
}
|
|
148
|
+
// Get all tickets (no assignee filter - show ALL tickets per ticket requirements)
|
|
149
|
+
const allTickets = await this.storage.listTickets(projectId);
|
|
150
|
+
if (allTickets.length === 0) {
|
|
151
|
+
db.close();
|
|
152
|
+
if (jsonMode) {
|
|
153
|
+
outputErrorAsJson('NO_TICKETS', 'No tickets found to spawn.', createMetadata('work spawn', flags));
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
this.log(styles.muted('No tickets found to spawn.'));
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
// Note: With ephemeral agents, we no longer need to check for available pre-registered agents
|
|
160
|
+
// Agents are created on-demand when spawning
|
|
161
|
+
// Determine spawn mode: All, Many, or Args (positional ticket IDs)
|
|
162
|
+
let spawnMode = 'all';
|
|
163
|
+
if (ticketIdArgs.length > 0) {
|
|
164
|
+
// Ticket IDs provided as positional args
|
|
165
|
+
spawnMode = 'args';
|
|
166
|
+
}
|
|
167
|
+
else if (flags.all) {
|
|
168
|
+
spawnMode = 'all';
|
|
169
|
+
}
|
|
170
|
+
else if (flags.many) {
|
|
171
|
+
spawnMode = 'many';
|
|
172
|
+
}
|
|
173
|
+
else if (!flags.column) {
|
|
174
|
+
// In JSON mode without explicit flags, output the mode selection prompt
|
|
175
|
+
if (jsonMode) {
|
|
176
|
+
outputPromptAsJson(buildPromptConfig('list', 'mode', 'How would you like to spawn work?', [
|
|
177
|
+
{ name: 'All - Spawn all tickets tickets in a column', value: 'all' },
|
|
178
|
+
{ name: 'Many - Select specific tickets to spawn', value: 'many' },
|
|
179
|
+
]), createMetadata('work spawn', flags));
|
|
180
|
+
db.close();
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
// Interactive: ask user
|
|
184
|
+
const { mode } = await inquirer.prompt([
|
|
185
|
+
{
|
|
186
|
+
type: 'list',
|
|
187
|
+
name: 'mode',
|
|
188
|
+
message: 'How would you like to spawn work?',
|
|
189
|
+
choices: [
|
|
190
|
+
{ name: '📦 All - Spawn all tickets tickets in a column', value: 'all' },
|
|
191
|
+
{ name: '✅ Many - Select specific tickets to spawn', value: 'many' },
|
|
192
|
+
],
|
|
193
|
+
},
|
|
194
|
+
]);
|
|
195
|
+
spawnMode = mode;
|
|
196
|
+
}
|
|
197
|
+
let ticketsToSpawn = [];
|
|
198
|
+
if (spawnMode === 'args') {
|
|
199
|
+
// ARGS MODE: Spawn specific tickets by ID
|
|
200
|
+
// Look up tickets by ID (don't filter by assignee - allow forcing assigned tickets)
|
|
201
|
+
for (const ticketId of ticketIdArgs) {
|
|
202
|
+
const ticket = allTickets.find(t => t.id.toLowerCase() === ticketId.toLowerCase());
|
|
203
|
+
if (ticket) {
|
|
204
|
+
ticketsToSpawn.push(ticket);
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
if (!jsonMode) {
|
|
208
|
+
this.warn(`Ticket "${ticketId}" not found, skipping.`);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
if (ticketsToSpawn.length === 0) {
|
|
213
|
+
db.close();
|
|
214
|
+
return handleError('NO_VALID_TICKETS', 'No valid tickets found from provided IDs.');
|
|
215
|
+
}
|
|
216
|
+
// In JSON mode with explicit tickets, output success
|
|
217
|
+
if (jsonMode) {
|
|
218
|
+
outputSuccessAsJson({
|
|
219
|
+
ticketsSelected: ticketsToSpawn.map(t => ({
|
|
220
|
+
id: t.id,
|
|
221
|
+
title: t.title,
|
|
222
|
+
status: t.statusName,
|
|
223
|
+
})),
|
|
224
|
+
count: ticketsToSpawn.length,
|
|
225
|
+
}, createMetadata('work spawn', flags));
|
|
226
|
+
db.close();
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
this.log('');
|
|
230
|
+
this.log(styles.header(`🚀 Spawn: ${ticketsToSpawn.length} ticket(s)`));
|
|
231
|
+
this.log(styles.muted(`Tickets: ${ticketsToSpawn.map(t => t.id).join(', ')}`));
|
|
232
|
+
}
|
|
233
|
+
else if (spawnMode === 'all') {
|
|
234
|
+
// ALL MODE: Column picker, then spawn all tickets in that column
|
|
235
|
+
let targetColumn = flags.column;
|
|
236
|
+
if (!targetColumn) {
|
|
237
|
+
// Show columns with ticket counts
|
|
238
|
+
const columnChoices = columnNames.map(name => {
|
|
239
|
+
const count = allTickets.filter(t => t.statusName === name).length;
|
|
240
|
+
return {
|
|
241
|
+
name: `${name} (${count} tickets)`,
|
|
242
|
+
value: name,
|
|
243
|
+
};
|
|
244
|
+
});
|
|
245
|
+
// In JSON mode, output the column selection prompt
|
|
246
|
+
if (jsonMode) {
|
|
247
|
+
outputPromptAsJson(buildPromptConfig('list', 'selectedColumn', 'Select column to spawn all tickets tickets from:', columnChoices), createMetadata('work spawn', flags));
|
|
248
|
+
db.close();
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
const { selectedColumn } = await inquirer.prompt([
|
|
252
|
+
{
|
|
253
|
+
type: 'list',
|
|
254
|
+
name: 'selectedColumn',
|
|
255
|
+
message: 'Select column to spawn all tickets tickets from:',
|
|
256
|
+
choices: columnChoices,
|
|
257
|
+
},
|
|
258
|
+
]);
|
|
259
|
+
targetColumn = selectedColumn;
|
|
260
|
+
}
|
|
261
|
+
// Verify column exists
|
|
262
|
+
const matchedColumn = columnNames.find(c => c.toLowerCase() === targetColumn.toLowerCase());
|
|
263
|
+
if (!matchedColumn) {
|
|
264
|
+
db.close();
|
|
265
|
+
return handleError('COLUMN_NOT_FOUND', `Column "${targetColumn}" not found.\nAvailable columns: ${columnNames.join(', ')}`);
|
|
266
|
+
}
|
|
267
|
+
ticketsToSpawn = allTickets.filter(t => t.statusName === matchedColumn);
|
|
268
|
+
if (ticketsToSpawn.length === 0) {
|
|
269
|
+
db.close();
|
|
270
|
+
if (jsonMode) {
|
|
271
|
+
outputErrorAsJson('NO_TICKETS_IN_COLUMN', `No tickets tickets in column "${matchedColumn}".`, createMetadata('work spawn', flags));
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
this.log(styles.muted(`No tickets tickets in column "${matchedColumn}".`));
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
this.log('');
|
|
278
|
+
this.log(styles.header(`🚀 Spawn All from: ${matchedColumn}`));
|
|
279
|
+
}
|
|
280
|
+
else {
|
|
281
|
+
// MANY MODE: First pick column (or all), then multi-select tickets
|
|
282
|
+
// In JSON mode with --many, output the ticket selection prompt directly
|
|
283
|
+
// (skip column selection for simplicity - show all tickets)
|
|
284
|
+
if (jsonMode) {
|
|
285
|
+
// Build choices from all tickets tickets
|
|
286
|
+
const ticketChoices = allTickets.map(ticket => {
|
|
287
|
+
const priority = ticket.priority ? `[${ticket.priority}] ` : '';
|
|
288
|
+
return {
|
|
289
|
+
name: `${priority}${ticket.id} - ${ticket.title} (${ticket.statusName || 'No Status'})`,
|
|
290
|
+
value: ticket.id,
|
|
291
|
+
};
|
|
292
|
+
});
|
|
293
|
+
outputPromptAsJson(buildPromptConfig('checkbox', 'selectedTickets', 'Select tickets to spawn (provide ticket IDs as positional args to execute):', ticketChoices), createMetadata('work spawn', flags));
|
|
294
|
+
db.close();
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
// Build column choices with counts - show ALL columns even if empty
|
|
298
|
+
const columnChoices = [
|
|
299
|
+
{ name: '🌐 All columns (select from anywhere)', value: '__ALL__' },
|
|
300
|
+
];
|
|
301
|
+
for (const name of columnNames) {
|
|
302
|
+
const count = allTickets.filter(t => t.statusName === name).length;
|
|
303
|
+
columnChoices.push({
|
|
304
|
+
name: count > 0 ? `${name} (${count} tickets)` : `${name} (0)`,
|
|
305
|
+
value: name,
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
const { manyColumn } = await inquirer.prompt([
|
|
309
|
+
{
|
|
310
|
+
type: 'list',
|
|
311
|
+
name: 'manyColumn',
|
|
312
|
+
message: 'Select from which column:',
|
|
313
|
+
choices: columnChoices,
|
|
314
|
+
},
|
|
315
|
+
]);
|
|
316
|
+
// Filter tickets based on column selection
|
|
317
|
+
const ticketsForSelection = manyColumn === '__ALL__'
|
|
318
|
+
? allTickets
|
|
319
|
+
: allTickets.filter(t => t.statusName === manyColumn);
|
|
320
|
+
if (ticketsForSelection.length === 0) {
|
|
321
|
+
db.close();
|
|
322
|
+
this.log(styles.muted('No tickets tickets in that column.'));
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
325
|
+
// Group tickets by priority for display
|
|
326
|
+
const PRIORITY_ORDER = ['P0', 'P1', 'P2', 'P3', 'None'];
|
|
327
|
+
const ticketsByPriority = new Map();
|
|
328
|
+
for (const priority of PRIORITY_ORDER) {
|
|
329
|
+
ticketsByPriority.set(priority, []);
|
|
330
|
+
}
|
|
331
|
+
for (const ticket of ticketsForSelection) {
|
|
332
|
+
const priority = ticket.priority || 'None';
|
|
333
|
+
if (!ticketsByPriority.has(priority)) {
|
|
334
|
+
ticketsByPriority.set(priority, []);
|
|
335
|
+
}
|
|
336
|
+
ticketsByPriority.get(priority).push(ticket);
|
|
337
|
+
}
|
|
338
|
+
// Build choices with priority separators
|
|
339
|
+
const choices = [];
|
|
340
|
+
for (const priority of PRIORITY_ORDER) {
|
|
341
|
+
const tickets = ticketsByPriority.get(priority) || [];
|
|
342
|
+
if (tickets.length === 0)
|
|
343
|
+
continue;
|
|
344
|
+
choices.push(new inquirer.Separator(`── ${priority} (${tickets.length}) ──`));
|
|
345
|
+
for (const ticket of tickets) {
|
|
346
|
+
const statusBadge = ticket.statusName ? ` [${ticket.statusName}]` : '';
|
|
347
|
+
choices.push({
|
|
348
|
+
name: `[${priority}] ${ticket.id} - ${ticket.title}${statusBadge}`,
|
|
349
|
+
value: ticket.id,
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
const { selectedTicketIds } = await inquirer.prompt([
|
|
354
|
+
{
|
|
355
|
+
type: 'checkbox',
|
|
356
|
+
name: 'selectedTicketIds',
|
|
357
|
+
message: 'Select tickets to spawn (space to toggle, enter to confirm):',
|
|
358
|
+
choices,
|
|
359
|
+
validate: (input) => {
|
|
360
|
+
if (input.length === 0) {
|
|
361
|
+
return 'Please select at least one ticket';
|
|
362
|
+
}
|
|
363
|
+
return true;
|
|
364
|
+
},
|
|
365
|
+
},
|
|
366
|
+
]);
|
|
367
|
+
ticketsToSpawn = allTickets.filter(t => selectedTicketIds.includes(t.id));
|
|
368
|
+
this.log('');
|
|
369
|
+
this.log(styles.header(`🚀 Spawn Many: ${ticketsToSpawn.length} tickets`));
|
|
370
|
+
}
|
|
371
|
+
// Apply limit if specified
|
|
372
|
+
if (flags.limit && flags.limit > 0) {
|
|
373
|
+
ticketsToSpawn = ticketsToSpawn.slice(0, flags.limit);
|
|
374
|
+
}
|
|
375
|
+
this.log('');
|
|
376
|
+
// Note: With ephemeral agents, we don't need to check availability
|
|
377
|
+
// Each ticket will get its own ephemeral agent created on-demand
|
|
378
|
+
// Check for tickets with existing tmux sessions (active work)
|
|
379
|
+
const ticketsWithActiveSessions = [];
|
|
380
|
+
const ticketsToProcess = [];
|
|
381
|
+
for (const ticket of ticketsToSpawn) {
|
|
382
|
+
const session = getTicketTmuxSession(ticket.id);
|
|
383
|
+
if (session) {
|
|
384
|
+
ticketsWithActiveSessions.push({
|
|
385
|
+
ticketId: ticket.id,
|
|
386
|
+
sessionName: session.sessionName,
|
|
387
|
+
agent: session.agent
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
else {
|
|
391
|
+
ticketsToProcess.push(ticket);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
// Handle tickets with active sessions
|
|
395
|
+
if (ticketsWithActiveSessions.length > 0 && !jsonMode) {
|
|
396
|
+
this.log(styles.warning(`Found ${ticketsWithActiveSessions.length} ticket(s) with active tmux sessions:`));
|
|
397
|
+
for (const { ticketId, agent } of ticketsWithActiveSessions) {
|
|
398
|
+
this.log(styles.muted(` ${ticketId} → ${agent}`));
|
|
399
|
+
}
|
|
400
|
+
this.log('');
|
|
401
|
+
const { sessionAction } = await inquirer.prompt([
|
|
402
|
+
{
|
|
403
|
+
type: 'list',
|
|
404
|
+
name: 'sessionAction',
|
|
405
|
+
message: 'What would you like to do with these tickets?',
|
|
406
|
+
choices: [
|
|
407
|
+
{ name: 'Skip them (only spawn tickets without active sessions)', value: 'skip' },
|
|
408
|
+
{ name: 'Kill sessions and respawn with new agents', value: 'kill' },
|
|
409
|
+
{ name: 'Cancel', value: 'cancel' },
|
|
410
|
+
],
|
|
411
|
+
},
|
|
412
|
+
]);
|
|
413
|
+
if (sessionAction === 'cancel') {
|
|
414
|
+
db.close();
|
|
415
|
+
this.log(styles.muted('Cancelled.'));
|
|
416
|
+
return;
|
|
417
|
+
}
|
|
418
|
+
if (sessionAction === 'kill') {
|
|
419
|
+
// Kill existing sessions and add those tickets back to process list
|
|
420
|
+
for (const { ticketId, sessionName } of ticketsWithActiveSessions) {
|
|
421
|
+
killTmuxSession(sessionName);
|
|
422
|
+
const ticket = ticketsToSpawn.find(t => t.id === ticketId);
|
|
423
|
+
if (ticket) {
|
|
424
|
+
ticketsToProcess.push(ticket);
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
this.log(styles.success(`Killed ${ticketsWithActiveSessions.length} session(s)`));
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
// Update ticketsToSpawn to only include tickets we'll process
|
|
431
|
+
ticketsToSpawn = ticketsToProcess;
|
|
432
|
+
if (ticketsToSpawn.length === 0) {
|
|
433
|
+
db.close();
|
|
434
|
+
this.log(styles.muted('No tickets to spawn (all have active sessions).'));
|
|
435
|
+
return;
|
|
436
|
+
}
|
|
437
|
+
this.log(styles.muted(`Tickets: ${ticketsToSpawn.map(t => t.id).join(', ')}`));
|
|
438
|
+
this.log(styles.muted(`Agents: Ephemeral (unique per ticket)`));
|
|
439
|
+
this.log('');
|
|
440
|
+
// Note: Removed redundant confirmation - user already selected tickets
|
|
441
|
+
// Use --dry-run to preview without executing
|
|
442
|
+
// Dry run - just show what would happen
|
|
443
|
+
if (flags['dry-run']) {
|
|
444
|
+
db.close();
|
|
445
|
+
this.log(styles.success(`Dry run complete: would spawn ${ticketsToSpawn.length} tickets with ephemeral agents`));
|
|
446
|
+
return;
|
|
447
|
+
}
|
|
448
|
+
// Batch mode settings - prompt once for all tickets
|
|
449
|
+
let batchMode = flags.mode;
|
|
450
|
+
let batchOutput = flags.output;
|
|
451
|
+
let batchSkipPermissions = flags['skip-permissions'];
|
|
452
|
+
let batchCreatePr = flags['create-pr'];
|
|
453
|
+
let batchNoPr = flags['no-pr'];
|
|
454
|
+
let batchRunOnHost = flags['run-on-host'];
|
|
455
|
+
let batchAction = flags.action;
|
|
456
|
+
// Track display mode separately for devcontainer (needs to be outside the if block)
|
|
457
|
+
let batchDisplayMode;
|
|
458
|
+
// For ephemeral agents, we'll create devcontainers on-demand
|
|
459
|
+
// Default to devcontainer support (can be overridden by --run-on-host)
|
|
460
|
+
const hasDevcontainer = true; // Ephemeral agents always get devcontainer config
|
|
461
|
+
// Will be populated after action is selected/confirmed
|
|
462
|
+
let selectedActionDetails = null;
|
|
463
|
+
if (!flags['per-ticket']) {
|
|
464
|
+
this.log(styles.header('Batch Settings (applies to all tickets)'));
|
|
465
|
+
this.log('');
|
|
466
|
+
// Prompt for action selection first (unless explicitly provided via --action flag)
|
|
467
|
+
if (!flags.action) {
|
|
468
|
+
// Get available actions from database
|
|
469
|
+
const actions = await this.storage.listActions();
|
|
470
|
+
const actionChoices = actions
|
|
471
|
+
.filter(a => a.isBuiltin)
|
|
472
|
+
.map(a => ({
|
|
473
|
+
name: `${a.id.padEnd(12)} - ${a.description || a.name}`,
|
|
474
|
+
value: a.id,
|
|
475
|
+
}));
|
|
476
|
+
const { selectedAction } = await inquirer.prompt([
|
|
477
|
+
{
|
|
478
|
+
type: 'list',
|
|
479
|
+
name: 'selectedAction',
|
|
480
|
+
message: 'What action should agents perform?',
|
|
481
|
+
choices: actionChoices,
|
|
482
|
+
default: 'implement',
|
|
483
|
+
},
|
|
484
|
+
]);
|
|
485
|
+
batchAction = selectedAction;
|
|
486
|
+
}
|
|
487
|
+
// Now fetch action details after selection is made
|
|
488
|
+
selectedActionDetails = await this.storage.getAction(batchAction || 'implement');
|
|
489
|
+
// Check if any explicit settings were provided via flags
|
|
490
|
+
const hasExplicitSettings = flags.mode || flags.output || flags['skip-permissions'] ||
|
|
491
|
+
flags['create-pr'] || flags['no-pr'] || flags['run-on-host'];
|
|
492
|
+
// Offer to use default settings if no explicit flags provided
|
|
493
|
+
if (!hasExplicitSettings) {
|
|
494
|
+
const actionName = batchAction || 'implement';
|
|
495
|
+
const modifiesCode = selectedActionDetails?.modifiesCode ?? true;
|
|
496
|
+
const defaultsDescription = modifiesCode
|
|
497
|
+
? 'devcontainer, terminal, interactive, safe permissions, create PRs'
|
|
498
|
+
: 'devcontainer, terminal, interactive, safe permissions, no PRs';
|
|
499
|
+
const { useDefaults } = await inquirer.prompt([
|
|
500
|
+
{
|
|
501
|
+
type: 'list',
|
|
502
|
+
name: 'useDefaults',
|
|
503
|
+
message: `Use default settings for "${actionName}"?`,
|
|
504
|
+
choices: [
|
|
505
|
+
{ name: `✓ Yes - Use defaults (${defaultsDescription})`, value: true },
|
|
506
|
+
{ name: '✗ No - Configure each setting', value: false },
|
|
507
|
+
],
|
|
508
|
+
default: true,
|
|
509
|
+
},
|
|
510
|
+
]);
|
|
511
|
+
if (useDefaults) {
|
|
512
|
+
// Apply defaults
|
|
513
|
+
if (hasDevcontainer) {
|
|
514
|
+
batchMode = 'devcontainer';
|
|
515
|
+
batchDisplayMode = 'terminal';
|
|
516
|
+
}
|
|
517
|
+
else {
|
|
518
|
+
batchMode = 'terminal';
|
|
519
|
+
}
|
|
520
|
+
batchOutput = 'interactive';
|
|
521
|
+
batchSkipPermissions = false;
|
|
522
|
+
// For non-code-modifying actions, don't create PRs
|
|
523
|
+
if (modifiesCode) {
|
|
524
|
+
batchCreatePr = true;
|
|
525
|
+
batchNoPr = false;
|
|
526
|
+
}
|
|
527
|
+
else {
|
|
528
|
+
batchCreatePr = false;
|
|
529
|
+
batchNoPr = true;
|
|
530
|
+
}
|
|
531
|
+
this.log('');
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
// Prompt for environment (devcontainer vs host) if devcontainer available and not already set
|
|
535
|
+
if (hasDevcontainer && !batchRunOnHost && !batchMode) {
|
|
536
|
+
let environmentSelected = false;
|
|
537
|
+
while (!environmentSelected) {
|
|
538
|
+
const { selectedEnvironment } = await inquirer.prompt([
|
|
539
|
+
{
|
|
540
|
+
type: 'list',
|
|
541
|
+
name: 'selectedEnvironment',
|
|
542
|
+
message: 'Where should agents run?',
|
|
543
|
+
choices: [
|
|
544
|
+
{ name: '🐳 devcontainer (sandboxed, recommended)', value: 'devcontainer' },
|
|
545
|
+
{ name: '💻 host (runs directly on your machine)', value: 'host' },
|
|
546
|
+
{ name: '✗ cancel', value: 'cancel' },
|
|
547
|
+
],
|
|
548
|
+
default: 'devcontainer',
|
|
549
|
+
},
|
|
550
|
+
]);
|
|
551
|
+
if (selectedEnvironment === 'cancel') {
|
|
552
|
+
db.close();
|
|
553
|
+
this.log(styles.muted('Cancelled.'));
|
|
554
|
+
return;
|
|
555
|
+
}
|
|
556
|
+
if (selectedEnvironment === 'devcontainer') {
|
|
557
|
+
if (!isDockerRunning()) {
|
|
558
|
+
this.log('');
|
|
559
|
+
this.warn('Docker is not running.\n' +
|
|
560
|
+
'Docker is required for devcontainer execution.\n' +
|
|
561
|
+
'Please start Docker Desktop or select "host" to run directly on your machine.');
|
|
562
|
+
this.log('');
|
|
563
|
+
continue;
|
|
564
|
+
}
|
|
565
|
+
batchMode = 'devcontainer';
|
|
566
|
+
environmentSelected = true;
|
|
567
|
+
// For devcontainer, prompt for display mode
|
|
568
|
+
// Simplified: tmux is always used inside container for session persistence
|
|
569
|
+
const { selectedDisplay } = await inquirer.prompt([
|
|
570
|
+
{
|
|
571
|
+
type: 'list',
|
|
572
|
+
name: 'selectedDisplay',
|
|
573
|
+
message: 'How should agent output be displayed?',
|
|
574
|
+
choices: [
|
|
575
|
+
{ name: '🖥️ New tab - Opens in new terminal tab (recommended)', value: 'terminal' },
|
|
576
|
+
{ name: '📦 Background - Runs detached, reattach with: prlt session attach', value: 'background' },
|
|
577
|
+
],
|
|
578
|
+
default: 'terminal',
|
|
579
|
+
},
|
|
580
|
+
]);
|
|
581
|
+
batchDisplayMode = selectedDisplay;
|
|
582
|
+
// Always use tmux inside container for session persistence
|
|
583
|
+
flags.session = 'tmux';
|
|
584
|
+
}
|
|
585
|
+
else {
|
|
586
|
+
batchRunOnHost = true;
|
|
587
|
+
environmentSelected = true;
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
// Prompt for display mode if not already set (for host mode without devcontainer)
|
|
592
|
+
if (!batchMode) {
|
|
593
|
+
const { selectedMode } = await inquirer.prompt([
|
|
594
|
+
{
|
|
595
|
+
type: 'list',
|
|
596
|
+
name: 'selectedMode',
|
|
597
|
+
message: 'How should agent output be displayed?',
|
|
598
|
+
choices: [
|
|
599
|
+
{ name: '🖥️ New tab - Opens in new terminal tab (recommended)', value: 'terminal' },
|
|
600
|
+
{ name: '📦 Background - Runs detached, reattach with: prlt session attach', value: 'background' },
|
|
601
|
+
],
|
|
602
|
+
},
|
|
603
|
+
]);
|
|
604
|
+
batchMode = selectedMode;
|
|
605
|
+
}
|
|
606
|
+
// Default to interactive output mode (streaming UI)
|
|
607
|
+
// Can be overridden via --output flag if needed
|
|
608
|
+
if (!batchOutput) {
|
|
609
|
+
batchOutput = 'interactive';
|
|
610
|
+
}
|
|
611
|
+
// Prompt for permissions mode if not provided
|
|
612
|
+
if (!batchSkipPermissions) {
|
|
613
|
+
const { permissionMode } = await inquirer.prompt([
|
|
614
|
+
{
|
|
615
|
+
type: 'list',
|
|
616
|
+
name: 'permissionMode',
|
|
617
|
+
message: 'Permission mode for Claude Code:',
|
|
618
|
+
choices: [
|
|
619
|
+
{ name: '⚠️ danger - Skip permission checks (faster, container provides isolation)', value: 'danger' },
|
|
620
|
+
{ name: '🔒 safe - Requires approval for dangerous operations', value: 'safe' },
|
|
621
|
+
],
|
|
622
|
+
default: 'danger',
|
|
623
|
+
},
|
|
624
|
+
]);
|
|
625
|
+
batchSkipPermissions = permissionMode === 'danger';
|
|
626
|
+
}
|
|
627
|
+
// Prompt for PR creation if not provided AND action modifies code
|
|
628
|
+
// Skip this prompt entirely for non-code-modifying actions (like groom)
|
|
629
|
+
const actionModifiesCode = selectedActionDetails?.modifiesCode ?? true;
|
|
630
|
+
if (!batchCreatePr && !batchNoPr) {
|
|
631
|
+
if (actionModifiesCode) {
|
|
632
|
+
const { prChoice } = await inquirer.prompt([
|
|
633
|
+
{
|
|
634
|
+
type: 'list',
|
|
635
|
+
name: 'prChoice',
|
|
636
|
+
message: 'Create pull requests when work is ready?',
|
|
637
|
+
choices: [
|
|
638
|
+
{ name: '✓ Yes - Create PR for each ticket', value: 'yes' },
|
|
639
|
+
{ name: '✗ No - Just move tickets to review', value: 'no' },
|
|
640
|
+
],
|
|
641
|
+
default: 'yes',
|
|
642
|
+
},
|
|
643
|
+
]);
|
|
644
|
+
batchCreatePr = prChoice === 'yes';
|
|
645
|
+
batchNoPr = prChoice === 'no';
|
|
646
|
+
}
|
|
647
|
+
else {
|
|
648
|
+
// Non-code-modifying action - no PR needed
|
|
649
|
+
batchCreatePr = false;
|
|
650
|
+
batchNoPr = true;
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
this.log('');
|
|
654
|
+
}
|
|
655
|
+
else {
|
|
656
|
+
// Per-ticket mode - still need to get action details if action flag was provided
|
|
657
|
+
if (batchAction) {
|
|
658
|
+
selectedActionDetails = await this.storage.getAction(batchAction);
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
// Spawn each ticket - work:start will create ephemeral agents on-demand
|
|
662
|
+
let successCount = 0;
|
|
663
|
+
let failCount = 0;
|
|
664
|
+
for (const ticket of ticketsToSpawn) {
|
|
665
|
+
try {
|
|
666
|
+
this.log(styles.muted(`Starting ${ticket.id} with ephemeral agent...`));
|
|
667
|
+
// Build args for work:start
|
|
668
|
+
// IMPORTANT: Pass --project to avoid re-prompting for project selection
|
|
669
|
+
// Pass --ephemeral to signal work:start should create an ephemeral agent
|
|
670
|
+
const startArgs = [ticket.id, '--project', projectId, '--ephemeral'];
|
|
671
|
+
if (flags['per-ticket']) {
|
|
672
|
+
// Per-ticket mode: only pass mode flag, let start prompt for the rest
|
|
673
|
+
if (batchMode)
|
|
674
|
+
startArgs.push('--mode', batchMode);
|
|
675
|
+
if (batchDisplayMode)
|
|
676
|
+
startArgs.push('--display', batchDisplayMode);
|
|
677
|
+
if (flags.executor)
|
|
678
|
+
startArgs.push('--executor', flags.executor);
|
|
679
|
+
if (batchRunOnHost)
|
|
680
|
+
startArgs.push('--run-on-host');
|
|
681
|
+
if (flags.force)
|
|
682
|
+
startArgs.push('--force');
|
|
683
|
+
}
|
|
684
|
+
else {
|
|
685
|
+
// Batch mode: pass all settings to skip prompts
|
|
686
|
+
if (batchMode)
|
|
687
|
+
startArgs.push('--mode', batchMode);
|
|
688
|
+
if (batchDisplayMode)
|
|
689
|
+
startArgs.push('--display', batchDisplayMode);
|
|
690
|
+
if (flags.executor)
|
|
691
|
+
startArgs.push('--executor', flags.executor);
|
|
692
|
+
if (batchRunOnHost)
|
|
693
|
+
startArgs.push('--run-on-host');
|
|
694
|
+
if (flags.force)
|
|
695
|
+
startArgs.push('--force');
|
|
696
|
+
if (batchOutput)
|
|
697
|
+
startArgs.push('--output', batchOutput);
|
|
698
|
+
if (batchSkipPermissions)
|
|
699
|
+
startArgs.push('--skip-permissions');
|
|
700
|
+
if (batchCreatePr)
|
|
701
|
+
startArgs.push('--create-pr');
|
|
702
|
+
if (batchNoPr)
|
|
703
|
+
startArgs.push('--no-pr');
|
|
704
|
+
// Pass action flag (from prompt or flag)
|
|
705
|
+
startArgs.push('--action', batchAction || 'implement');
|
|
706
|
+
// Pass session manager (tmux inside container by default)
|
|
707
|
+
if (flags.session)
|
|
708
|
+
startArgs.push('--session', flags.session);
|
|
709
|
+
}
|
|
710
|
+
await this.config.runCommand('work:start', startArgs);
|
|
711
|
+
successCount++;
|
|
712
|
+
}
|
|
713
|
+
catch (error) {
|
|
714
|
+
failCount++;
|
|
715
|
+
this.log(styles.error(`Failed to start ${ticket.id}: ${error instanceof Error ? error.message : error}`));
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
await autoExportToBoard(this.pmoPath, this.storage, (msg) => this.log(styles.muted(msg)));
|
|
719
|
+
db.close();
|
|
720
|
+
this.log('');
|
|
721
|
+
this.log(styles.success(`✓ Spawn results: ${successCount} started, ${failCount} failed`));
|
|
722
|
+
}
|
|
723
|
+
catch (error) {
|
|
724
|
+
db.close();
|
|
725
|
+
throw error;
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
}
|