@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,112 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
import { execSync } from 'child_process';
|
|
3
|
+
import * as path from 'path';
|
|
4
|
+
import Database from 'better-sqlite3';
|
|
5
|
+
import { styles } from '../../lib/styles.js';
|
|
6
|
+
import { getWorkspaceInfo } from '../../lib/agents/commands.js';
|
|
7
|
+
import { ContainerStorage } from '../../lib/execution/storage.js';
|
|
8
|
+
import { isDockerRunning } from '../../lib/execution/runners.js';
|
|
9
|
+
export default class DockerSync extends Command {
|
|
10
|
+
static description = 'Sync container status from Docker into the database';
|
|
11
|
+
static examples = [
|
|
12
|
+
'<%= config.bin %> <%= command.id %>',
|
|
13
|
+
];
|
|
14
|
+
async run() {
|
|
15
|
+
if (!isDockerRunning()) {
|
|
16
|
+
this.error('Docker is not running. Start Docker Desktop or the Docker daemon first.');
|
|
17
|
+
}
|
|
18
|
+
// Get workspace info
|
|
19
|
+
let workspaceInfo;
|
|
20
|
+
try {
|
|
21
|
+
workspaceInfo = getWorkspaceInfo();
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
this.error('Not in a workspace. Run "prlt init" first.');
|
|
25
|
+
}
|
|
26
|
+
// Open database
|
|
27
|
+
const dbPath = path.join(workspaceInfo.path, '.proletariat', 'workspace.db');
|
|
28
|
+
let db;
|
|
29
|
+
try {
|
|
30
|
+
db = new Database(dbPath);
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
this.error('Could not open workspace database.');
|
|
34
|
+
}
|
|
35
|
+
try {
|
|
36
|
+
const containerStorage = new ContainerStorage(db);
|
|
37
|
+
// Get devcontainers from Docker
|
|
38
|
+
const dockerContainers = this.getDockerContainers();
|
|
39
|
+
this.log(`\n${styles.header('Syncing Containers')}`);
|
|
40
|
+
this.log(styles.muted(`Found ${dockerContainers.length} devcontainers in Docker\n`));
|
|
41
|
+
// Add agent name from image (only used for new containers)
|
|
42
|
+
const containersWithAgent = dockerContainers.map(c => ({
|
|
43
|
+
...c,
|
|
44
|
+
agentName: this.extractAgentFromImage(c.image),
|
|
45
|
+
}));
|
|
46
|
+
// Sync with database
|
|
47
|
+
const result = containerStorage.syncFromDocker(containersWithAgent);
|
|
48
|
+
this.log(styles.success('✓ Sync complete'));
|
|
49
|
+
this.log(styles.muted(` Added: ${result.added}`));
|
|
50
|
+
this.log(styles.muted(` Updated: ${result.updated}`));
|
|
51
|
+
this.log(styles.muted(` Marked removed: ${result.removed}\n`));
|
|
52
|
+
// Show current containers
|
|
53
|
+
const containers = containerStorage.listContainers({ limit: 20 });
|
|
54
|
+
if (containers.length > 0) {
|
|
55
|
+
this.log(styles.subheader('Tracked Containers:'));
|
|
56
|
+
this.log(styles.muted(' ' +
|
|
57
|
+
'ID'.padEnd(18) +
|
|
58
|
+
'Agent'.padEnd(15) +
|
|
59
|
+
'Status'.padEnd(12) +
|
|
60
|
+
'Docker ID'));
|
|
61
|
+
this.log(styles.muted(' ' + '-'.repeat(65)));
|
|
62
|
+
for (const container of containers) {
|
|
63
|
+
const statusColor = container.status === 'running' ? styles.success :
|
|
64
|
+
container.status === 'exited' ? styles.muted :
|
|
65
|
+
container.status === 'removed' ? styles.error : styles.warning;
|
|
66
|
+
this.log(' ' +
|
|
67
|
+
container.id.padEnd(18) +
|
|
68
|
+
container.agentName.padEnd(15) +
|
|
69
|
+
statusColor(container.status.padEnd(12)) +
|
|
70
|
+
styles.muted(container.dockerId.substring(0, 12)));
|
|
71
|
+
}
|
|
72
|
+
this.log('');
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
this.log('');
|
|
76
|
+
}
|
|
77
|
+
db.close();
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
db.close();
|
|
81
|
+
throw error;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Get raw container info from Docker
|
|
86
|
+
*/
|
|
87
|
+
getDockerContainers() {
|
|
88
|
+
try {
|
|
89
|
+
const output = execSync('docker ps -a --format "{{.ID}}|{{.Names}}|{{.Image}}|{{.Status}}"', {
|
|
90
|
+
encoding: 'utf-8',
|
|
91
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
92
|
+
}).trim();
|
|
93
|
+
if (!output)
|
|
94
|
+
return [];
|
|
95
|
+
return output.split('\n').filter(Boolean).map(line => {
|
|
96
|
+
const [id, name, image, status] = line.split('|');
|
|
97
|
+
return { id, name, image, status };
|
|
98
|
+
}).filter(c => c.image.startsWith('vsc-')); // Only devcontainers
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
return [];
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Extract agent name from devcontainer image name.
|
|
106
|
+
* Only used for initial sync - DB is source of truth after that.
|
|
107
|
+
*/
|
|
108
|
+
extractAgentFromImage(image) {
|
|
109
|
+
const match = image.match(/^vsc-([^-]+)-/);
|
|
110
|
+
return match ? match[1] : 'unknown';
|
|
111
|
+
}
|
|
112
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { PMOCommand } from '../../lib/pmo/index.js';
|
|
2
|
+
export default class EpicActivate 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,118 @@
|
|
|
1
|
+
import { Args, Flags } from '@oclif/core';
|
|
2
|
+
import inquirer from 'inquirer';
|
|
3
|
+
import { PMOCommand, pmoBaseFlags } from '../../lib/pmo/index.js';
|
|
4
|
+
import { styles } from '../../lib/styles.js';
|
|
5
|
+
import { moveEpicFile, getRelativeEpicPath } from '../../lib/pmo/epic-files.js';
|
|
6
|
+
import { shouldOutputJson, outputPromptAsJson, outputErrorAsJson, createMetadata, buildPromptConfig, } from '../../lib/prompt-json.js';
|
|
7
|
+
export default class EpicActivate extends PMOCommand {
|
|
8
|
+
static description = 'Activate a draft or archived epic';
|
|
9
|
+
static examples = [
|
|
10
|
+
'<%= config.bin %> <%= command.id %> EPIC-004',
|
|
11
|
+
'<%= config.bin %> <%= command.id %>',
|
|
12
|
+
];
|
|
13
|
+
static args = {
|
|
14
|
+
id: Args.string({
|
|
15
|
+
description: 'Epic ID',
|
|
16
|
+
required: false,
|
|
17
|
+
}),
|
|
18
|
+
};
|
|
19
|
+
static flags = {
|
|
20
|
+
...pmoBaseFlags,
|
|
21
|
+
json: Flags.boolean({
|
|
22
|
+
description: 'Output prompt configuration as JSON (for AI agents/scripts)',
|
|
23
|
+
default: false,
|
|
24
|
+
}),
|
|
25
|
+
};
|
|
26
|
+
async execute() {
|
|
27
|
+
const { args, flags } = await this.parse(EpicActivate);
|
|
28
|
+
const projectId = await this.requireProject();
|
|
29
|
+
// Check if JSON output mode is active
|
|
30
|
+
const jsonMode = shouldOutputJson(flags);
|
|
31
|
+
// Helper to handle errors in JSON mode
|
|
32
|
+
const handleError = (code, message) => {
|
|
33
|
+
if (jsonMode) {
|
|
34
|
+
outputErrorAsJson(code, message, createMetadata('epic activate', flags));
|
|
35
|
+
this.exit(1);
|
|
36
|
+
}
|
|
37
|
+
this.error(message);
|
|
38
|
+
};
|
|
39
|
+
let epicId = args.id;
|
|
40
|
+
// If no ID provided, prompt for selection (show only non-active epics)
|
|
41
|
+
if (!epicId) {
|
|
42
|
+
const epics = await this.storage.listEpics(projectId);
|
|
43
|
+
const activatable = epics.filter(e => e.status !== 'active');
|
|
44
|
+
if (activatable.length === 0) {
|
|
45
|
+
if (jsonMode) {
|
|
46
|
+
outputErrorAsJson('NO_EPICS_TO_ACTIVATE', 'No epics available to activate.', createMetadata('epic activate', flags));
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
this.log(styles.muted('\nNo epics available to activate.'));
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
const selected = await this.selectFromList({
|
|
53
|
+
message: 'Select epic to activate:',
|
|
54
|
+
items: activatable,
|
|
55
|
+
getName: (e) => `${e.id} ${e.title} (${e.status})`,
|
|
56
|
+
getValue: (e) => e.id,
|
|
57
|
+
getCommand: (e) => `prlt epic activate ${e.id} --json`,
|
|
58
|
+
jsonMode: jsonMode ? { flags, commandName: 'epic activate' } : null,
|
|
59
|
+
});
|
|
60
|
+
if (!selected) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
epicId = selected;
|
|
64
|
+
}
|
|
65
|
+
const epic = await this.storage.getEpic(epicId);
|
|
66
|
+
if (!epic) {
|
|
67
|
+
return handleError('EPIC_NOT_FOUND', `Epic not found: ${epicId}`);
|
|
68
|
+
}
|
|
69
|
+
if (epic.status === 'active') {
|
|
70
|
+
this.log(styles.muted(`Epic ${epicId} is already active.`));
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
// Warn if reactivating a complete epic
|
|
74
|
+
if (epic.status === 'complete') {
|
|
75
|
+
const tickets = await this.storage.getTicketsForEpic(projectId, epicId);
|
|
76
|
+
const doneTickets = tickets.filter((t) => t.status === 'done').length;
|
|
77
|
+
// In JSON mode, output confirmation prompt
|
|
78
|
+
if (jsonMode) {
|
|
79
|
+
const confirmChoices = [
|
|
80
|
+
{ name: 'No', value: 'false' },
|
|
81
|
+
{ name: 'Yes', value: 'true' },
|
|
82
|
+
];
|
|
83
|
+
outputPromptAsJson(buildPromptConfig('list', 'confirm', `This epic was previously completed (${doneTickets}/${tickets.length} tickets done). Reactivate this epic?`, confirmChoices), createMetadata('epic activate', flags));
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
this.log(styles.warning(`\n⚠️ This epic was previously completed (${doneTickets}/${tickets.length} tickets done)`));
|
|
87
|
+
const { confirm } = await inquirer.prompt([{
|
|
88
|
+
type: 'list',
|
|
89
|
+
name: 'confirm',
|
|
90
|
+
message: 'Reactivate this epic?',
|
|
91
|
+
choices: [
|
|
92
|
+
{ name: 'No', value: false },
|
|
93
|
+
{ name: 'Yes', value: true },
|
|
94
|
+
],
|
|
95
|
+
default: false,
|
|
96
|
+
}]);
|
|
97
|
+
if (!confirm) {
|
|
98
|
+
this.log(styles.muted('Cancelled.'));
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
this.log(`\nActivating: ${epicId} "${epic.title}"`);
|
|
103
|
+
this.log(`Current status: ${epic.status}`);
|
|
104
|
+
const previousStatus = epic.status;
|
|
105
|
+
// Move the epic file to active status directory
|
|
106
|
+
const moveResult = moveEpicFile(this.pmoPath, epicId, previousStatus, 'active', projectId);
|
|
107
|
+
await this.storage.updateEpic(epicId, { status: 'active' });
|
|
108
|
+
this.log(styles.success(`\n✅ Activated epic ${styles.emphasis(epicId)} "${epic.title}"`));
|
|
109
|
+
this.log(styles.muted(` Status: ${previousStatus} → active`));
|
|
110
|
+
if (moveResult) {
|
|
111
|
+
const relativePath = getRelativeEpicPath(this.pmoPath, epicId, 'active', projectId);
|
|
112
|
+
this.log(styles.muted(` File: ${relativePath}`));
|
|
113
|
+
}
|
|
114
|
+
this.log(styles.muted('\nNext steps:'));
|
|
115
|
+
this.log(styles.muted(` prlt epic view ${epicId}`));
|
|
116
|
+
this.log(styles.muted(` prlt ticket create --epic ${epicId} "First task"`));
|
|
117
|
+
}
|
|
118
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { PMOCommand } from '../../lib/pmo/index.js';
|
|
2
|
+
export default class EpicArchive 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
|
+
force: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
11
|
+
project: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
};
|
|
13
|
+
execute(): Promise<void>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { Args, Flags } from '@oclif/core';
|
|
2
|
+
import inquirer from 'inquirer';
|
|
3
|
+
import { PMOCommand, pmoBaseFlags } from '../../lib/pmo/index.js';
|
|
4
|
+
import { styles } from '../../lib/styles.js';
|
|
5
|
+
import { moveEpicFile, getRelativeEpicPath } from '../../lib/pmo/epic-files.js';
|
|
6
|
+
import { shouldOutputJson, outputPromptAsJson, outputErrorAsJson, createMetadata, buildPromptConfig, } from '../../lib/prompt-json.js';
|
|
7
|
+
export default class EpicArchive extends PMOCommand {
|
|
8
|
+
static description = 'Archive a completed epic';
|
|
9
|
+
static examples = [
|
|
10
|
+
'<%= config.bin %> <%= command.id %> EPIC-002',
|
|
11
|
+
'<%= config.bin %> <%= command.id %> --force',
|
|
12
|
+
];
|
|
13
|
+
static args = {
|
|
14
|
+
id: Args.string({
|
|
15
|
+
description: 'Epic ID',
|
|
16
|
+
required: false,
|
|
17
|
+
}),
|
|
18
|
+
};
|
|
19
|
+
static flags = {
|
|
20
|
+
...pmoBaseFlags,
|
|
21
|
+
json: Flags.boolean({
|
|
22
|
+
description: 'Output prompt configuration as JSON (for AI agents/scripts)',
|
|
23
|
+
default: false,
|
|
24
|
+
}),
|
|
25
|
+
force: Flags.boolean({
|
|
26
|
+
char: 'f',
|
|
27
|
+
description: 'Skip ticket completion check',
|
|
28
|
+
default: false,
|
|
29
|
+
}),
|
|
30
|
+
};
|
|
31
|
+
async execute() {
|
|
32
|
+
const { args, flags } = await this.parse(EpicArchive);
|
|
33
|
+
const projectId = await this.requireProject();
|
|
34
|
+
// Check if JSON output mode is active
|
|
35
|
+
const jsonMode = shouldOutputJson(flags);
|
|
36
|
+
// Helper to handle errors in JSON mode
|
|
37
|
+
const handleError = (code, message) => {
|
|
38
|
+
if (jsonMode) {
|
|
39
|
+
outputErrorAsJson(code, message, createMetadata('epic archive', flags));
|
|
40
|
+
this.exit(1);
|
|
41
|
+
}
|
|
42
|
+
this.error(message);
|
|
43
|
+
};
|
|
44
|
+
let epicId = args.id;
|
|
45
|
+
// If no ID provided, prompt for selection (show only non-complete epics)
|
|
46
|
+
if (!epicId) {
|
|
47
|
+
const epics = await this.storage.listEpics(projectId);
|
|
48
|
+
const archivable = epics.filter(e => e.status !== 'complete' && e.status !== 'dropped');
|
|
49
|
+
if (archivable.length === 0) {
|
|
50
|
+
if (jsonMode) {
|
|
51
|
+
outputErrorAsJson('NO_EPICS_TO_ARCHIVE', 'No epics available to archive.', createMetadata('epic archive', flags));
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
this.log(styles.muted('\nNo epics available to archive.'));
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
// Get ticket counts
|
|
58
|
+
const choices = await Promise.all(archivable.map(async (e) => {
|
|
59
|
+
const tickets = await this.storage.getTicketsForEpic(projectId, e.id);
|
|
60
|
+
const done = tickets.filter((t) => t.status === 'done').length;
|
|
61
|
+
const complete = done === tickets.length && tickets.length > 0;
|
|
62
|
+
return {
|
|
63
|
+
name: `${e.id} ${e.title} (${e.status}) [${done}/${tickets.length} tickets complete]${complete ? ' ✅' : ''}`,
|
|
64
|
+
value: e.id,
|
|
65
|
+
};
|
|
66
|
+
}));
|
|
67
|
+
// In JSON mode, output epic selection prompt
|
|
68
|
+
if (jsonMode) {
|
|
69
|
+
outputPromptAsJson(buildPromptConfig('list', 'id', 'Select epic to archive:', choices), createMetadata('epic archive', flags));
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
const { selected } = await inquirer.prompt([{
|
|
73
|
+
type: 'list',
|
|
74
|
+
name: 'selected',
|
|
75
|
+
message: 'Select epic to archive:',
|
|
76
|
+
choices,
|
|
77
|
+
}]);
|
|
78
|
+
epicId = selected;
|
|
79
|
+
}
|
|
80
|
+
const epic = await this.storage.getEpic(epicId);
|
|
81
|
+
if (!epic) {
|
|
82
|
+
return handleError('EPIC_NOT_FOUND', `Epic not found: ${epicId}`);
|
|
83
|
+
}
|
|
84
|
+
if (epic.status === 'complete') {
|
|
85
|
+
this.log(styles.muted(`Epic ${epicId} is already archived.`));
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
// Check ticket completion
|
|
89
|
+
const tickets = await this.storage.getTicketsForEpic(projectId, epicId);
|
|
90
|
+
const doneTickets = tickets.filter((t) => t.status === 'done').length;
|
|
91
|
+
const allComplete = doneTickets === tickets.length;
|
|
92
|
+
if (!allComplete && !flags.force) {
|
|
93
|
+
// In JSON mode, output confirmation prompt
|
|
94
|
+
if (jsonMode) {
|
|
95
|
+
const confirmChoices = [
|
|
96
|
+
{ name: 'No', value: 'false' },
|
|
97
|
+
{ name: 'Yes', value: 'true' },
|
|
98
|
+
];
|
|
99
|
+
outputPromptAsJson(buildPromptConfig('list', 'confirm', `Not all tickets are complete (${doneTickets}/${tickets.length} done). Continue archiving anyway?`, confirmChoices), createMetadata('epic archive', flags));
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
this.log(styles.warning(`\n⚠️ Not all tickets are complete (${doneTickets}/${tickets.length} done)`));
|
|
103
|
+
const { confirm } = await inquirer.prompt([{
|
|
104
|
+
type: 'list',
|
|
105
|
+
name: 'confirm',
|
|
106
|
+
message: 'Continue archiving anyway?',
|
|
107
|
+
choices: [
|
|
108
|
+
{ name: 'No', value: false },
|
|
109
|
+
{ name: 'Yes', value: true },
|
|
110
|
+
],
|
|
111
|
+
default: false,
|
|
112
|
+
}]);
|
|
113
|
+
if (!confirm) {
|
|
114
|
+
this.log(styles.muted('Cancelled.'));
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
this.log(`\nArchiving: ${epicId} "${epic.title}"`);
|
|
119
|
+
this.log(`Status: ${doneTickets}/${tickets.length} tickets complete${allComplete ? ' ✅' : ''}`);
|
|
120
|
+
// Move the epic file to complete status directory
|
|
121
|
+
const moveResult = moveEpicFile(this.pmoPath, epicId, epic.status, 'complete', projectId);
|
|
122
|
+
await this.storage.updateEpic(epicId, { status: 'complete' });
|
|
123
|
+
this.log(styles.success(`\n✅ Archived epic ${styles.emphasis(epicId)} "${epic.title}"`));
|
|
124
|
+
this.log(styles.muted(` Status: ${epic.status} → complete`));
|
|
125
|
+
if (moveResult) {
|
|
126
|
+
const relativePath = getRelativeEpicPath(this.pmoPath, epicId, 'complete', projectId);
|
|
127
|
+
this.log(styles.muted(` File: ${relativePath}`));
|
|
128
|
+
}
|
|
129
|
+
this.log(styles.muted('\nView archived epics:'));
|
|
130
|
+
this.log(styles.muted(' prlt epic list --status complete'));
|
|
131
|
+
}
|
|
132
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { PMOCommand } from '../../lib/pmo/index.js';
|
|
2
|
+
export default class EpicCreate extends PMOCommand {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static flags: {
|
|
6
|
+
title: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
7
|
+
status: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
8
|
+
description: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
|
+
spec: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
+
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
11
|
+
project: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
};
|
|
13
|
+
execute(): Promise<void>;
|
|
14
|
+
private promptEpicData;
|
|
15
|
+
}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { Flags } from '@oclif/core';
|
|
2
|
+
import inquirer from 'inquirer';
|
|
3
|
+
import { PMOCommand, pmoBaseFlags } from '../../lib/pmo/index.js';
|
|
4
|
+
import { styles } from '../../lib/styles.js';
|
|
5
|
+
import { createEpicFile, getRelativeEpicPath } from '../../lib/pmo/epic-files.js';
|
|
6
|
+
import { shouldOutputJson, outputPromptAsJson, createMetadata, buildFormPromptConfig, } from '../../lib/prompt-json.js';
|
|
7
|
+
export default class EpicCreate extends PMOCommand {
|
|
8
|
+
static description = 'Create a new epic';
|
|
9
|
+
static examples = [
|
|
10
|
+
'<%= config.bin %> <%= command.id %>',
|
|
11
|
+
'<%= config.bin %> <%= command.id %> --title "User Authentication System"',
|
|
12
|
+
'<%= config.bin %> <%= command.id %> -t "API Design" --status draft',
|
|
13
|
+
'<%= config.bin %> <%= command.id %> -t "Implement Auth" --spec SPEC-001',
|
|
14
|
+
];
|
|
15
|
+
static flags = {
|
|
16
|
+
...pmoBaseFlags,
|
|
17
|
+
title: Flags.string({
|
|
18
|
+
char: 't',
|
|
19
|
+
description: 'Epic title',
|
|
20
|
+
}),
|
|
21
|
+
status: Flags.string({
|
|
22
|
+
char: 's',
|
|
23
|
+
description: 'Initial status',
|
|
24
|
+
options: ['active', 'draft'],
|
|
25
|
+
default: 'active',
|
|
26
|
+
}),
|
|
27
|
+
description: Flags.string({
|
|
28
|
+
char: 'd',
|
|
29
|
+
description: 'Epic description',
|
|
30
|
+
}),
|
|
31
|
+
spec: Flags.string({
|
|
32
|
+
description: 'Link to spec ID (the design spec that describes this epic)',
|
|
33
|
+
}),
|
|
34
|
+
json: Flags.boolean({
|
|
35
|
+
description: 'Output prompt configuration as JSON (for AI agents/scripts)',
|
|
36
|
+
default: false,
|
|
37
|
+
}),
|
|
38
|
+
};
|
|
39
|
+
async execute() {
|
|
40
|
+
const { flags } = await this.parse(EpicCreate);
|
|
41
|
+
const projectId = await this.requireProject();
|
|
42
|
+
// Check if JSON output mode is active
|
|
43
|
+
const jsonMode = shouldOutputJson(flags);
|
|
44
|
+
// Build choices once, use for both JSON and interactive modes
|
|
45
|
+
const statusChoices = [
|
|
46
|
+
{ name: 'Active (currently working on)', value: 'active' },
|
|
47
|
+
{ name: 'Draft (planning phase)', value: 'draft' },
|
|
48
|
+
];
|
|
49
|
+
// Get epic data
|
|
50
|
+
let epicData;
|
|
51
|
+
if (!flags.title) {
|
|
52
|
+
// Get specs once, use for both modes
|
|
53
|
+
const specs = await this.storage.listSpecs();
|
|
54
|
+
const specChoices = [
|
|
55
|
+
{ name: 'None (no spec linked)', value: '' },
|
|
56
|
+
...specs.map(s => ({
|
|
57
|
+
name: `${s.id} - ${s.title}`,
|
|
58
|
+
value: s.id,
|
|
59
|
+
})),
|
|
60
|
+
];
|
|
61
|
+
// Define fields once - single source of truth for both JSON and interactive modes
|
|
62
|
+
const fields = [
|
|
63
|
+
{ type: 'input', name: 'title', message: 'Epic title:', default: flags.title },
|
|
64
|
+
{ type: 'list', name: 'status', message: 'Initial status:', choices: statusChoices, default: flags.status || 'active' },
|
|
65
|
+
{ type: 'input', name: 'description', message: 'Description (optional):', default: flags.description },
|
|
66
|
+
];
|
|
67
|
+
if (specs.length > 0) {
|
|
68
|
+
fields.push({
|
|
69
|
+
type: 'list', name: 'specId', message: 'Link to spec (design document):',
|
|
70
|
+
choices: specChoices, default: flags.spec || ''
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
// In JSON mode, output form prompt for epic creation
|
|
74
|
+
if (jsonMode) {
|
|
75
|
+
outputPromptAsJson(buildFormPromptConfig(fields), createMetadata('epic create', flags));
|
|
76
|
+
}
|
|
77
|
+
epicData = await this.promptEpicData(fields, specChoices.length > 1);
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
epicData = {
|
|
81
|
+
title: flags.title,
|
|
82
|
+
status: (flags.status || 'active'),
|
|
83
|
+
description: flags.description,
|
|
84
|
+
specId: flags.spec,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
// Validate spec exists if provided
|
|
88
|
+
if (epicData.specId) {
|
|
89
|
+
const spec = await this.storage.getSpec(epicData.specId);
|
|
90
|
+
if (!spec) {
|
|
91
|
+
this.error(`Spec not found: ${epicData.specId}`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
const epic = await this.storage.createEpic(projectId, {
|
|
95
|
+
title: epicData.title,
|
|
96
|
+
status: epicData.status,
|
|
97
|
+
description: epicData.description,
|
|
98
|
+
specId: epicData.specId,
|
|
99
|
+
});
|
|
100
|
+
// Create markdown file for the epic
|
|
101
|
+
const filePath = createEpicFile(this.pmoPath, epic, projectId);
|
|
102
|
+
const relativePath = getRelativeEpicPath(this.pmoPath, epic.id, epic.status, projectId);
|
|
103
|
+
// Update epic with file path
|
|
104
|
+
await this.storage.updateEpic(epic.id, { filePath });
|
|
105
|
+
const projectName = await this.getProjectName(projectId);
|
|
106
|
+
this.log(styles.success(`\n✅ Created epic ${styles.emphasis(epic.id)} "${epic.title}"`));
|
|
107
|
+
this.log(styles.muted(` Project: ${projectName}`));
|
|
108
|
+
this.log(styles.muted(` Status: ${epic.status}`));
|
|
109
|
+
if (epic.specId) {
|
|
110
|
+
this.log(styles.muted(` Spec: ${epic.specId}`));
|
|
111
|
+
}
|
|
112
|
+
this.log(styles.muted(` File: ${relativePath}`));
|
|
113
|
+
this.log('');
|
|
114
|
+
this.log(styles.muted('Next steps:'));
|
|
115
|
+
this.log(styles.muted(` 1. Edit the epic file to add details:`));
|
|
116
|
+
this.log(styles.muted(` ${relativePath}`));
|
|
117
|
+
this.log(styles.muted(` 2. Create tickets linked to this epic:`));
|
|
118
|
+
this.log(styles.muted(` prlt ticket create --epic ${epic.id} "Design auth flow"`));
|
|
119
|
+
this.log(styles.muted(` 3. View progress: prlt epic progress ${epic.id}`));
|
|
120
|
+
}
|
|
121
|
+
async promptEpicData(fields, hasSpecs) {
|
|
122
|
+
// Build inquirer prompts from fields, adding validators and conditionals
|
|
123
|
+
const answers = await inquirer.prompt(fields.map(field => ({
|
|
124
|
+
...field,
|
|
125
|
+
validate: field.name === 'title'
|
|
126
|
+
? ((input) => input.length > 0 || 'Title is required')
|
|
127
|
+
: undefined,
|
|
128
|
+
when: field.name === 'specId' ? () => hasSpecs : undefined,
|
|
129
|
+
})));
|
|
130
|
+
return {
|
|
131
|
+
title: answers.title,
|
|
132
|
+
status: answers.status,
|
|
133
|
+
description: answers.description || undefined,
|
|
134
|
+
specId: answers.specId || undefined,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { PMOCommand } from '../../lib/pmo/index.js';
|
|
2
|
+
export default class Epic 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,88 @@
|
|
|
1
|
+
import { Flags } from '@oclif/core';
|
|
2
|
+
import { PMOCommand, pmoBaseFlags } from '../../lib/pmo/index.js';
|
|
3
|
+
import { shouldOutputJson, } from '../../lib/prompt-json.js';
|
|
4
|
+
export default class Epic extends PMOCommand {
|
|
5
|
+
static description = 'Interactive menu for epic operations';
|
|
6
|
+
static examples = [
|
|
7
|
+
'<%= config.bin %> <%= command.id %>',
|
|
8
|
+
];
|
|
9
|
+
static flags = {
|
|
10
|
+
...pmoBaseFlags,
|
|
11
|
+
json: Flags.boolean({
|
|
12
|
+
description: 'Output prompt configuration as JSON (for AI agents/scripts)',
|
|
13
|
+
default: false,
|
|
14
|
+
}),
|
|
15
|
+
};
|
|
16
|
+
getPMOOptions() {
|
|
17
|
+
return { promptIfMultiple: false };
|
|
18
|
+
}
|
|
19
|
+
async execute() {
|
|
20
|
+
const { flags } = await this.parse(Epic);
|
|
21
|
+
// Check if JSON output mode is active
|
|
22
|
+
const jsonMode = shouldOutputJson(flags);
|
|
23
|
+
// Define choices once, use for both JSON and interactive modes
|
|
24
|
+
// Each choice includes the full command for AI agents to execute
|
|
25
|
+
const menuChoices = [
|
|
26
|
+
{ id: 'create', name: 'Create new epic', command: 'prlt epic create --json' },
|
|
27
|
+
{ id: 'list', name: 'List all epics', command: 'prlt epic list --format json' },
|
|
28
|
+
{ id: 'view', name: 'View epic', command: 'prlt epic view --json' },
|
|
29
|
+
{ id: 'progress', name: 'Show progress', command: 'prlt epic progress --json' },
|
|
30
|
+
{ id: 'ticket', name: 'Assign tickets to epic', command: 'prlt epic ticket --json' },
|
|
31
|
+
{ id: 'spec', name: 'Assign spec to epic', command: 'prlt epic spec --json' },
|
|
32
|
+
{ id: 'link', name: 'Manage dependencies', command: 'prlt epic link --json' },
|
|
33
|
+
{ id: 'archive', name: 'Archive epic (complete)', command: 'prlt epic archive --json' },
|
|
34
|
+
{ id: 'activate', name: 'Activate epic', command: 'prlt epic activate --json' },
|
|
35
|
+
{ id: 'move', name: 'Reorder epic', command: 'prlt epic move --json' },
|
|
36
|
+
{ id: 'project', name: 'Move to different project', command: 'prlt epic project --json' },
|
|
37
|
+
{ id: 'cancel', name: 'Cancel', command: '' },
|
|
38
|
+
];
|
|
39
|
+
const message = 'Epic Operations - What would you like to do?';
|
|
40
|
+
const action = await this.selectFromList({
|
|
41
|
+
message: '🎯 ' + message,
|
|
42
|
+
items: menuChoices,
|
|
43
|
+
getName: (c) => c.name,
|
|
44
|
+
getValue: (c) => c.id,
|
|
45
|
+
getCommand: (c) => c.command,
|
|
46
|
+
jsonMode: jsonMode ? { flags, commandName: 'epic' } : null,
|
|
47
|
+
});
|
|
48
|
+
if (action === 'cancel' || !action) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
// Run the selected subcommand
|
|
52
|
+
switch (action) {
|
|
53
|
+
case 'create':
|
|
54
|
+
await this.config.runCommand('epic:create', []);
|
|
55
|
+
break;
|
|
56
|
+
case 'list':
|
|
57
|
+
await this.config.runCommand('epic:list', []);
|
|
58
|
+
break;
|
|
59
|
+
case 'view':
|
|
60
|
+
await this.config.runCommand('epic:view', []);
|
|
61
|
+
break;
|
|
62
|
+
case 'progress':
|
|
63
|
+
await this.config.runCommand('epic:progress', []);
|
|
64
|
+
break;
|
|
65
|
+
case 'ticket':
|
|
66
|
+
await this.config.runCommand('epic:ticket', []);
|
|
67
|
+
break;
|
|
68
|
+
case 'spec':
|
|
69
|
+
await this.config.runCommand('epic:spec', []);
|
|
70
|
+
break;
|
|
71
|
+
case 'link':
|
|
72
|
+
await this.config.runCommand('epic:link', []);
|
|
73
|
+
break;
|
|
74
|
+
case 'archive':
|
|
75
|
+
await this.config.runCommand('epic:archive', []);
|
|
76
|
+
break;
|
|
77
|
+
case 'activate':
|
|
78
|
+
await this.config.runCommand('epic:activate', []);
|
|
79
|
+
break;
|
|
80
|
+
case 'move':
|
|
81
|
+
await this.config.runCommand('epic:move', []);
|
|
82
|
+
break;
|
|
83
|
+
case 'project':
|
|
84
|
+
await this.config.runCommand('epic:project', []);
|
|
85
|
+
break;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { PMOCommand } from '../../../lib/pmo/index.js';
|
|
2
|
+
export default class EpicLinkBlock extends PMOCommand {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static args: {
|
|
6
|
+
id: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
7
|
+
blocker: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
8
|
+
};
|
|
9
|
+
static flags: {
|
|
10
|
+
project: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
12
|
+
};
|
|
13
|
+
execute(): Promise<void>;
|
|
14
|
+
}
|