@proletariat/cli 0.2.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +561 -251
- package/bin/dev.cmd +3 -0
- package/bin/dev.js +5 -0
- package/bin/run.cmd +3 -0
- package/bin/run.js +23 -0
- package/dist/commands/action/create.d.ts +21 -0
- package/dist/commands/action/create.js +126 -0
- package/dist/commands/action/delete.d.ts +17 -0
- package/dist/commands/action/delete.js +78 -0
- package/dist/commands/action/index.d.ts +15 -0
- package/dist/commands/action/index.js +107 -0
- package/dist/commands/action/list.d.ts +14 -0
- package/dist/commands/action/list.js +89 -0
- package/dist/commands/action/run.d.ts +19 -0
- package/dist/commands/action/run.js +179 -0
- package/dist/commands/action/show.d.ts +15 -0
- package/dist/commands/action/show.js +47 -0
- package/dist/commands/action/update.d.ts +22 -0
- package/dist/commands/action/update.js +168 -0
- package/dist/commands/agent/index.d.ts +13 -0
- package/dist/commands/agent/index.js +131 -0
- package/dist/commands/agent/list.d.ts +7 -0
- package/dist/commands/agent/list.js +126 -0
- package/dist/commands/agent/login.d.ts +16 -0
- package/dist/commands/agent/login.js +146 -0
- package/dist/commands/agent/rebuild.d.ts +18 -0
- package/dist/commands/agent/rebuild.js +133 -0
- package/dist/commands/agent/restart.d.ts +17 -0
- package/dist/commands/agent/restart.js +116 -0
- package/dist/commands/agent/shell.d.ts +23 -0
- package/dist/commands/agent/shell.js +378 -0
- package/dist/commands/agent/staff/add.d.ts +15 -0
- package/dist/commands/agent/staff/add.js +281 -0
- package/dist/commands/agent/staff/index.d.ts +14 -0
- package/dist/commands/agent/staff/index.js +90 -0
- package/dist/commands/agent/staff/list.d.ts +7 -0
- package/dist/commands/agent/staff/list.js +90 -0
- package/dist/commands/agent/staff/remove.d.ts +16 -0
- package/dist/commands/agent/staff/remove.js +137 -0
- package/dist/commands/agent/status.d.ts +17 -0
- package/dist/commands/agent/status.js +139 -0
- package/dist/commands/agent/temp/cleanup.d.ts +23 -0
- package/dist/commands/agent/temp/cleanup.js +388 -0
- package/dist/commands/agent/temp/index.d.ts +14 -0
- package/dist/commands/agent/temp/index.js +82 -0
- package/dist/commands/agent/temp/list.d.ts +7 -0
- package/dist/commands/agent/temp/list.js +108 -0
- package/dist/commands/agent/themes/add-names.d.ts +10 -0
- package/dist/commands/agent/themes/add-names.js +67 -0
- package/dist/commands/agent/themes/create.d.ts +13 -0
- package/dist/commands/agent/themes/create.js +66 -0
- package/dist/commands/agent/themes/index.d.ts +9 -0
- package/dist/commands/agent/themes/index.js +194 -0
- package/dist/commands/agent/themes/list.d.ts +6 -0
- package/dist/commands/agent/themes/list.js +41 -0
- package/dist/commands/agent/themes/set.d.ts +12 -0
- package/dist/commands/agent/themes/set.js +77 -0
- package/dist/commands/agent/visit.d.ts +16 -0
- package/dist/commands/agent/visit.js +88 -0
- package/dist/commands/autocomplete/setup.d.ts +14 -0
- package/dist/commands/autocomplete/setup.js +154 -0
- package/dist/commands/board/index.d.ts +17 -0
- package/dist/commands/board/index.js +255 -0
- package/dist/commands/board/watch.d.ts +13 -0
- package/dist/commands/board/watch.js +52 -0
- package/dist/commands/branch/create.d.ts +50 -0
- package/dist/commands/branch/create.js +624 -0
- package/dist/commands/branch/index.d.ts +13 -0
- package/dist/commands/branch/index.js +50 -0
- package/dist/commands/branch/list.d.ts +17 -0
- package/dist/commands/branch/list.js +120 -0
- package/dist/commands/branch/validate.d.ts +15 -0
- package/dist/commands/branch/validate.js +73 -0
- package/dist/commands/commit.d.ts +71 -0
- package/dist/commands/commit.js +499 -0
- package/dist/commands/docker/clean.d.ts +13 -0
- package/dist/commands/docker/clean.js +224 -0
- package/dist/commands/docker/index.d.ts +19 -0
- package/dist/commands/docker/index.js +274 -0
- package/dist/commands/docker/list.d.ts +16 -0
- package/dist/commands/docker/list.js +200 -0
- package/dist/commands/docker/logs.d.ts +14 -0
- package/dist/commands/docker/logs.js +118 -0
- package/dist/commands/docker/prune.d.ts +14 -0
- package/dist/commands/docker/prune.js +211 -0
- package/dist/commands/docker/restart.d.ts +14 -0
- package/dist/commands/docker/restart.js +129 -0
- package/dist/commands/docker/shell.d.ts +14 -0
- package/dist/commands/docker/shell.js +103 -0
- package/dist/commands/docker/start.d.ts +12 -0
- package/dist/commands/docker/start.js +92 -0
- package/dist/commands/docker/status.d.ts +7 -0
- package/dist/commands/docker/status.js +40 -0
- package/dist/commands/docker/stop.d.ts +14 -0
- package/dist/commands/docker/stop.js +134 -0
- package/dist/commands/docker/sync.d.ts +15 -0
- package/dist/commands/docker/sync.js +112 -0
- package/dist/commands/epic/activate.d.ts +13 -0
- package/dist/commands/epic/activate.js +118 -0
- package/dist/commands/epic/archive.d.ts +14 -0
- package/dist/commands/epic/archive.js +132 -0
- package/dist/commands/epic/create.d.ts +15 -0
- package/dist/commands/epic/create.js +137 -0
- package/dist/commands/epic/index.d.ts +13 -0
- package/dist/commands/epic/index.js +88 -0
- package/dist/commands/epic/link/block.d.ts +14 -0
- package/dist/commands/epic/link/block.js +79 -0
- package/dist/commands/epic/link/duplicates.d.ts +14 -0
- package/dist/commands/epic/link/duplicates.js +66 -0
- package/dist/commands/epic/link/index.d.ts +19 -0
- package/dist/commands/epic/link/index.js +242 -0
- package/dist/commands/epic/link/relates.d.ts +14 -0
- package/dist/commands/epic/link/relates.js +66 -0
- package/dist/commands/epic/link/remove.d.ts +16 -0
- package/dist/commands/epic/link/remove.js +89 -0
- package/dist/commands/epic/list.d.ts +11 -0
- package/dist/commands/epic/list.js +87 -0
- package/dist/commands/epic/move.d.ts +15 -0
- package/dist/commands/epic/move.js +184 -0
- package/dist/commands/epic/progress.d.ts +16 -0
- package/dist/commands/epic/progress.js +166 -0
- package/dist/commands/epic/project.d.ts +15 -0
- package/dist/commands/epic/project.js +219 -0
- package/dist/commands/epic/reorder.d.ts +21 -0
- package/dist/commands/epic/reorder.js +160 -0
- package/dist/commands/epic/spec.d.ts +15 -0
- package/dist/commands/epic/spec.js +191 -0
- package/dist/commands/epic/ticket.d.ts +18 -0
- package/dist/commands/epic/ticket.js +291 -0
- package/dist/commands/epic/view.d.ts +13 -0
- package/dist/commands/epic/view.js +117 -0
- package/dist/commands/execution/index.d.ts +13 -0
- package/dist/commands/execution/index.js +70 -0
- package/dist/commands/execution/list.d.ts +15 -0
- package/dist/commands/execution/list.js +144 -0
- package/dist/commands/execution/logs.d.ts +18 -0
- package/dist/commands/execution/logs.js +161 -0
- package/dist/commands/execution/stop.d.ts +22 -0
- package/dist/commands/execution/stop.js +248 -0
- package/dist/commands/gh/index.d.ts +9 -0
- package/dist/commands/gh/index.js +53 -0
- package/dist/commands/gh/login.d.ts +6 -0
- package/dist/commands/gh/login.js +57 -0
- package/dist/commands/gh/status.d.ts +6 -0
- package/dist/commands/gh/status.js +48 -0
- package/dist/commands/gh/token.d.ts +6 -0
- package/dist/commands/gh/token.js +59 -0
- package/dist/commands/init.d.ts +26 -0
- package/dist/commands/init.js +200 -0
- package/dist/commands/phase/create.d.ts +22 -0
- package/dist/commands/phase/create.js +123 -0
- package/dist/commands/phase/delete.d.ts +17 -0
- package/dist/commands/phase/delete.js +73 -0
- package/dist/commands/phase/list.d.ts +12 -0
- package/dist/commands/phase/list.js +76 -0
- package/dist/commands/phase/move.d.ts +17 -0
- package/dist/commands/phase/move.js +115 -0
- package/dist/commands/phase/template/apply.d.ts +17 -0
- package/dist/commands/phase/template/apply.js +106 -0
- package/dist/commands/phase/template/create.d.ts +16 -0
- package/dist/commands/phase/template/create.js +58 -0
- package/dist/commands/phase/template/delete.d.ts +17 -0
- package/dist/commands/phase/template/delete.js +98 -0
- package/dist/commands/phase/template/index.d.ts +15 -0
- package/dist/commands/phase/template/index.js +128 -0
- package/dist/commands/phase/template/list.d.ts +16 -0
- package/dist/commands/phase/template/list.js +95 -0
- package/dist/commands/phase/template/update.d.ts +17 -0
- package/dist/commands/phase/template/update.js +89 -0
- package/dist/commands/phase/update.d.ts +23 -0
- package/dist/commands/phase/update.js +174 -0
- package/dist/commands/pmo/init.d.ts +25 -0
- package/dist/commands/pmo/init.js +341 -0
- package/dist/commands/pr/create.d.ts +17 -0
- package/dist/commands/pr/create.js +242 -0
- package/dist/commands/pr/index.d.ts +9 -0
- package/dist/commands/pr/index.js +68 -0
- package/dist/commands/pr/link.d.ts +14 -0
- package/dist/commands/pr/link.js +212 -0
- package/dist/commands/pr/status.d.ts +12 -0
- package/dist/commands/pr/status.js +161 -0
- package/dist/commands/project/archive.d.ts +17 -0
- package/dist/commands/project/archive.js +83 -0
- package/dist/commands/project/create.d.ts +22 -0
- package/dist/commands/project/create.js +143 -0
- package/dist/commands/project/delete.d.ts +17 -0
- package/dist/commands/project/delete.js +128 -0
- package/dist/commands/project/index.d.ts +13 -0
- package/dist/commands/project/index.js +64 -0
- package/dist/commands/project/list.d.ts +14 -0
- package/dist/commands/project/list.js +96 -0
- package/dist/commands/project/spec.d.ts +18 -0
- package/dist/commands/project/spec.js +216 -0
- package/dist/commands/project/unarchive.d.ts +15 -0
- package/dist/commands/project/unarchive.js +35 -0
- package/dist/commands/project/view.d.ts +16 -0
- package/dist/commands/project/view.js +94 -0
- package/dist/commands/repo/add.d.ts +21 -0
- package/dist/commands/repo/add.js +118 -0
- package/dist/commands/repo/index.d.ts +13 -0
- package/dist/commands/repo/index.js +114 -0
- package/dist/commands/repo/list.d.ts +13 -0
- package/dist/commands/repo/list.js +96 -0
- package/dist/commands/repo/remove.d.ts +23 -0
- package/dist/commands/repo/remove.js +217 -0
- package/dist/commands/repo/view.d.ts +15 -0
- package/dist/commands/repo/view.js +99 -0
- package/dist/commands/session/attach.d.ts +40 -0
- package/dist/commands/session/attach.js +307 -0
- package/dist/commands/session/index.d.ts +13 -0
- package/dist/commands/session/index.js +64 -0
- package/dist/commands/session/list.d.ts +21 -0
- package/dist/commands/session/list.js +181 -0
- package/dist/commands/spec/create.d.ts +19 -0
- package/dist/commands/spec/create.js +130 -0
- package/dist/commands/spec/index.d.ts +13 -0
- package/dist/commands/spec/index.js +68 -0
- package/dist/commands/spec/link/depends.d.ts +14 -0
- package/dist/commands/spec/link/depends.js +64 -0
- package/dist/commands/spec/link/duplicates.d.ts +14 -0
- package/dist/commands/spec/link/duplicates.js +63 -0
- package/dist/commands/spec/link/index.d.ts +19 -0
- package/dist/commands/spec/link/index.js +200 -0
- package/dist/commands/spec/link/relates.d.ts +14 -0
- package/dist/commands/spec/link/relates.js +63 -0
- package/dist/commands/spec/link/remove.d.ts +16 -0
- package/dist/commands/spec/link/remove.js +94 -0
- package/dist/commands/spec/list.d.ts +12 -0
- package/dist/commands/spec/list.js +75 -0
- package/dist/commands/spec/plan.d.ts +15 -0
- package/dist/commands/spec/plan.js +108 -0
- package/dist/commands/spec/ticket.d.ts +18 -0
- package/dist/commands/spec/ticket.js +160 -0
- package/dist/commands/spec/view.d.ts +15 -0
- package/dist/commands/spec/view.js +163 -0
- package/dist/commands/status/create.d.ts +21 -0
- package/dist/commands/status/create.js +140 -0
- package/dist/commands/status/delete.d.ts +13 -0
- package/dist/commands/status/delete.js +77 -0
- package/dist/commands/status/index.d.ts +14 -0
- package/dist/commands/status/index.js +91 -0
- package/dist/commands/status/list.d.ts +12 -0
- package/dist/commands/status/list.js +93 -0
- package/dist/commands/status/move.d.ts +14 -0
- package/dist/commands/status/move.js +120 -0
- package/dist/commands/status/update.d.ts +20 -0
- package/dist/commands/status/update.js +180 -0
- package/dist/commands/template/delete.d.ts +15 -0
- package/dist/commands/template/delete.js +142 -0
- package/dist/commands/template/index.d.ts +10 -0
- package/dist/commands/template/index.js +64 -0
- package/dist/commands/template/list.d.ts +18 -0
- package/dist/commands/template/list.js +157 -0
- package/dist/commands/template/phase/apply.d.ts +14 -0
- package/dist/commands/template/phase/apply.js +41 -0
- package/dist/commands/template/phase/create.d.ts +12 -0
- package/dist/commands/template/phase/create.js +29 -0
- package/dist/commands/template/phase/delete.d.ts +13 -0
- package/dist/commands/template/phase/delete.js +34 -0
- package/dist/commands/template/phase/index.d.ts +10 -0
- package/dist/commands/template/phase/index.js +62 -0
- package/dist/commands/template/phase/list.d.ts +11 -0
- package/dist/commands/template/phase/list.js +34 -0
- package/dist/commands/template/phase/update.d.ts +13 -0
- package/dist/commands/template/phase/update.js +35 -0
- package/dist/commands/template/ticket/apply.d.ts +17 -0
- package/dist/commands/template/ticket/apply.js +58 -0
- package/dist/commands/template/ticket/delete.d.ts +13 -0
- package/dist/commands/template/ticket/delete.js +34 -0
- package/dist/commands/template/ticket/index.d.ts +10 -0
- package/dist/commands/template/ticket/index.js +62 -0
- package/dist/commands/template/ticket/list.d.ts +11 -0
- package/dist/commands/template/ticket/list.js +34 -0
- package/dist/commands/template/ticket/save.d.ts +13 -0
- package/dist/commands/template/ticket/save.js +35 -0
- package/dist/commands/ticket/bulk.d.ts +13 -0
- package/dist/commands/ticket/bulk.js +145 -0
- package/dist/commands/ticket/complete.d.ts +16 -0
- package/dist/commands/ticket/complete.js +170 -0
- package/dist/commands/ticket/create.d.ts +22 -0
- package/dist/commands/ticket/create.js +390 -0
- package/dist/commands/ticket/delete.d.ts +16 -0
- package/dist/commands/ticket/delete.js +178 -0
- package/dist/commands/ticket/edit.d.ts +27 -0
- package/dist/commands/ticket/edit.js +322 -0
- package/dist/commands/ticket/epic.d.ts +20 -0
- package/dist/commands/ticket/epic.js +333 -0
- package/dist/commands/ticket/index.d.ts +13 -0
- package/dist/commands/ticket/index.js +103 -0
- package/dist/commands/ticket/link/block.d.ts +14 -0
- package/dist/commands/ticket/link/block.js +94 -0
- package/dist/commands/ticket/link/duplicates.d.ts +14 -0
- package/dist/commands/ticket/link/duplicates.js +93 -0
- package/dist/commands/ticket/link/index.d.ts +19 -0
- package/dist/commands/ticket/link/index.js +239 -0
- package/dist/commands/ticket/link/relates.d.ts +14 -0
- package/dist/commands/ticket/link/relates.js +93 -0
- package/dist/commands/ticket/link/remove.d.ts +16 -0
- package/dist/commands/ticket/link/remove.js +128 -0
- package/dist/commands/ticket/list.d.ts +24 -0
- package/dist/commands/ticket/list.js +431 -0
- package/dist/commands/ticket/move.d.ts +18 -0
- package/dist/commands/ticket/move.js +212 -0
- package/dist/commands/ticket/project.d.ts +18 -0
- package/dist/commands/ticket/project.js +254 -0
- package/dist/commands/ticket/reassign.d.ts +19 -0
- package/dist/commands/ticket/reassign.js +279 -0
- package/dist/commands/ticket/spec.d.ts +18 -0
- package/dist/commands/ticket/spec.js +259 -0
- package/dist/commands/ticket/status.d.ts +13 -0
- package/dist/commands/ticket/status.js +87 -0
- package/dist/commands/ticket/template/apply.d.ts +25 -0
- package/dist/commands/ticket/template/apply.js +249 -0
- package/dist/commands/ticket/template/create.d.ts +19 -0
- package/dist/commands/ticket/template/create.js +210 -0
- package/dist/commands/ticket/template/delete.d.ts +17 -0
- package/dist/commands/ticket/template/delete.js +92 -0
- package/dist/commands/ticket/template/index.d.ts +15 -0
- package/dist/commands/ticket/template/index.js +118 -0
- package/dist/commands/ticket/template/list.d.ts +16 -0
- package/dist/commands/ticket/template/list.js +110 -0
- package/dist/commands/ticket/template/save.d.ts +14 -0
- package/dist/commands/ticket/template/save.js +110 -0
- package/dist/commands/ticket/update.d.ts +18 -0
- package/dist/commands/ticket/update.js +325 -0
- package/dist/commands/ticket/view.d.ts +13 -0
- package/dist/commands/ticket/view.js +80 -0
- package/dist/commands/whoami.d.ts +9 -0
- package/dist/commands/whoami.js +103 -0
- package/dist/commands/work/complete.d.ts +13 -0
- package/dist/commands/work/complete.js +121 -0
- package/dist/commands/work/index.d.ts +13 -0
- package/dist/commands/work/index.js +70 -0
- package/dist/commands/work/ready.d.ts +24 -0
- package/dist/commands/work/ready.js +290 -0
- package/dist/commands/work/revise.d.ts +19 -0
- package/dist/commands/work/revise.js +377 -0
- package/dist/commands/work/spawn-all.d.ts +17 -0
- package/dist/commands/work/spawn-all.js +58 -0
- package/dist/commands/work/spawn.d.ts +29 -0
- package/dist/commands/work/spawn.js +728 -0
- package/dist/commands/work/start.d.ts +39 -0
- package/dist/commands/work/start.js +1393 -0
- package/dist/commands/work/watch.d.ts +31 -0
- package/dist/commands/work/watch.js +359 -0
- package/dist/commands/workflow/create.d.ts +18 -0
- package/dist/commands/workflow/create.js +119 -0
- package/dist/commands/workflow/delete.d.ts +17 -0
- package/dist/commands/workflow/delete.js +119 -0
- package/dist/commands/workflow/index.d.ts +15 -0
- package/dist/commands/workflow/index.js +75 -0
- package/dist/commands/workflow/list.d.ts +15 -0
- package/dist/commands/workflow/list.js +75 -0
- package/dist/commands/workflow/switch.d.ts +13 -0
- package/dist/commands/workflow/switch.js +117 -0
- package/dist/commands/workflow/view.d.ts +16 -0
- package/dist/commands/workflow/view.js +114 -0
- package/dist/commands/workspace/add.d.ts +12 -0
- package/dist/commands/workspace/add.js +74 -0
- package/dist/commands/workspace/list.d.ts +9 -0
- package/dist/commands/workspace/list.js +153 -0
- package/dist/commands/workspace/remove.d.ts +13 -0
- package/dist/commands/workspace/remove.js +98 -0
- package/dist/commands/workspace/use.d.ts +12 -0
- package/dist/commands/workspace/use.js +111 -0
- package/dist/hooks/init.d.ts +11 -0
- package/dist/hooks/init.js +57 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/lib/agents/commands.d.ts +189 -0
- package/dist/lib/agents/commands.js +893 -0
- package/dist/lib/agents/index.d.ts +54 -0
- package/dist/lib/agents/index.js +382 -0
- package/dist/lib/branch/index.d.ts +120 -0
- package/dist/lib/branch/index.js +334 -0
- package/dist/lib/colors.d.ts +94 -0
- package/dist/lib/colors.js +68 -0
- package/dist/lib/commands/docker-command.d.ts +21 -0
- package/dist/lib/commands/docker-command.js +27 -0
- package/dist/lib/database/index.d.ts +176 -0
- package/dist/lib/database/index.js +581 -0
- package/dist/lib/docker/resolve.d.ts +38 -0
- package/dist/lib/docker/resolve.js +175 -0
- package/dist/lib/execution/config.d.ts +150 -0
- package/dist/lib/execution/config.js +541 -0
- package/dist/lib/execution/devcontainer.d.ts +85 -0
- package/dist/lib/execution/devcontainer.js +594 -0
- package/dist/lib/execution/index.d.ts +10 -0
- package/dist/lib/execution/index.js +10 -0
- package/dist/lib/execution/runners.d.ts +53 -0
- package/dist/lib/execution/runners.js +1182 -0
- package/dist/lib/execution/spawner.d.ts +85 -0
- package/dist/lib/execution/spawner.js +548 -0
- package/dist/lib/execution/storage.d.ts +159 -0
- package/dist/lib/execution/storage.js +425 -0
- package/dist/lib/execution/types.d.ts +145 -0
- package/dist/lib/execution/types.js +157 -0
- package/dist/lib/init/index.d.ts +75 -0
- package/dist/lib/init/index.js +355 -0
- package/dist/lib/machine-config.d.ts +170 -0
- package/dist/lib/machine-config.js +386 -0
- package/dist/lib/pmo/base-command.d.ts +195 -0
- package/dist/lib/pmo/base-command.js +319 -0
- package/dist/lib/pmo/create-spec-folders.d.ts +43 -0
- package/dist/lib/pmo/create-spec-folders.js +64 -0
- package/dist/lib/pmo/epic-files.d.ts +56 -0
- package/dist/lib/pmo/epic-files.js +195 -0
- package/dist/lib/pmo/find-pmo.d.ts +14 -0
- package/dist/lib/pmo/find-pmo.js +172 -0
- package/dist/lib/pmo/index.d.ts +109 -0
- package/dist/lib/pmo/index.js +501 -0
- package/dist/lib/pmo/markdown.d.ts +31 -0
- package/dist/lib/pmo/markdown.js +245 -0
- package/dist/lib/pmo/pmo-context.d.ts +27 -0
- package/dist/lib/pmo/pmo-context.js +44 -0
- package/dist/lib/pmo/schema.d.ts +82 -0
- package/dist/lib/pmo/schema.js +531 -0
- package/dist/lib/pmo/spec-parser.d.ts +25 -0
- package/dist/lib/pmo/spec-parser.js +205 -0
- package/dist/lib/pmo/spec-types.d.ts +43 -0
- package/dist/lib/pmo/spec-types.js +7 -0
- package/dist/lib/pmo/storage/actions.d.ts +34 -0
- package/dist/lib/pmo/storage/actions.js +177 -0
- package/dist/lib/pmo/storage/base.d.ts +47 -0
- package/dist/lib/pmo/storage/base.js +858 -0
- package/dist/lib/pmo/storage/dependencies.d.ts +61 -0
- package/dist/lib/pmo/storage/dependencies.js +267 -0
- package/dist/lib/pmo/storage/epics.d.ts +46 -0
- package/dist/lib/pmo/storage/epics.js +243 -0
- package/dist/lib/pmo/storage/helpers.d.ts +33 -0
- package/dist/lib/pmo/storage/helpers.js +148 -0
- package/dist/lib/pmo/storage/index.d.ts +186 -0
- package/dist/lib/pmo/storage/index.js +689 -0
- package/dist/lib/pmo/storage/phases.d.ts +65 -0
- package/dist/lib/pmo/storage/phases.js +392 -0
- package/dist/lib/pmo/storage/projects.d.ts +79 -0
- package/dist/lib/pmo/storage/projects.js +303 -0
- package/dist/lib/pmo/storage/specs.d.ts +77 -0
- package/dist/lib/pmo/storage/specs.js +389 -0
- package/dist/lib/pmo/storage/statuses.d.ts +63 -0
- package/dist/lib/pmo/storage/statuses.js +404 -0
- package/dist/lib/pmo/storage/subtasks.d.ts +37 -0
- package/dist/lib/pmo/storage/subtasks.js +184 -0
- package/dist/lib/pmo/storage/templates.d.ts +40 -0
- package/dist/lib/pmo/storage/templates.js +210 -0
- package/dist/lib/pmo/storage/tickets.d.ts +57 -0
- package/dist/lib/pmo/storage/tickets.js +453 -0
- package/dist/lib/pmo/storage/types.d.ts +200 -0
- package/dist/lib/pmo/storage/types.js +5 -0
- package/dist/lib/pmo/storage/views.d.ts +44 -0
- package/dist/lib/pmo/storage/views.js +355 -0
- package/dist/lib/pmo/storage-sqlite.d.ts +7 -0
- package/dist/lib/pmo/storage-sqlite.js +7 -0
- package/dist/lib/pmo/sync-manager.d.ts +92 -0
- package/dist/lib/pmo/sync-manager.js +229 -0
- package/dist/lib/pmo/types.d.ts +710 -0
- package/dist/lib/pmo/types.js +108 -0
- package/dist/lib/pmo/utils.d.ts +122 -0
- package/dist/lib/pmo/utils.js +174 -0
- package/dist/lib/pmo/watcher.d.ts +43 -0
- package/dist/lib/pmo/watcher.js +208 -0
- package/dist/lib/pr/index.d.ts +150 -0
- package/dist/lib/pr/index.js +483 -0
- package/dist/lib/prompt-json.d.ts +231 -0
- package/dist/lib/prompt-json.js +213 -0
- package/dist/lib/repos/index.d.ts +81 -0
- package/dist/lib/repos/index.js +679 -0
- package/dist/lib/styles.d.ts +98 -0
- package/dist/lib/styles.js +195 -0
- package/dist/lib/themes.d.ts +128 -0
- package/dist/lib/themes.js +301 -0
- package/dist/lib/ui/BoardUI.d.ts +21 -0
- package/dist/lib/ui/BoardUI.js +85 -0
- package/dist/lib/ui/ClaimTicketUI.d.ts +17 -0
- package/dist/lib/ui/ClaimTicketUI.js +64 -0
- package/dist/lib/ui/CreateTicketUI.d.ts +13 -0
- package/dist/lib/ui/CreateTicketUI.js +101 -0
- package/dist/lib/workspace.d.ts +66 -0
- package/dist/lib/workspace.js +204 -0
- package/oclif.manifest.json +10593 -0
- package/package.json +103 -56
- package/LICENSE +0 -21
- package/dist/bin/prlt.d.ts +0 -11
- package/dist/bin/prlt.d.ts.map +0 -1
- package/dist/bin/prlt.js +0 -144
- package/dist/bin/prlt.js.map +0 -1
- package/dist/lib/config/index.d.ts +0 -14
- package/dist/lib/config/index.d.ts.map +0 -1
- package/dist/lib/config/index.js +0 -142
- package/dist/lib/config/index.js.map +0 -1
- package/dist/lib/config/upgrade.d.ts +0 -2
- package/dist/lib/config/upgrade.d.ts.map +0 -1
- package/dist/lib/config/upgrade.js +0 -248
- package/dist/lib/config/upgrade.js.map +0 -1
- package/dist/lib/themes/index.d.ts +0 -8
- package/dist/lib/themes/index.d.ts.map +0 -1
- package/dist/lib/themes/index.js +0 -80
- package/dist/lib/themes/index.js.map +0 -1
- package/dist/lib/utils/helpers.d.ts +0 -4
- package/dist/lib/utils/helpers.d.ts.map +0 -1
- package/dist/lib/utils/helpers.js +0 -39
- package/dist/lib/utils/helpers.js.map +0 -1
- package/dist/lib/utils/logger.d.ts +0 -4
- package/dist/lib/utils/logger.d.ts.map +0 -1
- package/dist/lib/utils/logger.js +0 -28
- package/dist/lib/utils/logger.js.map +0 -1
- package/dist/lib/workspace/index.d.ts +0 -13
- package/dist/lib/workspace/index.d.ts.map +0 -1
- package/dist/lib/workspace/index.js +0 -116
- package/dist/lib/workspace/index.js.map +0 -1
- package/dist/lib/worktree/index.d.ts +0 -7
- package/dist/lib/worktree/index.d.ts.map +0 -1
- package/dist/lib/worktree/index.js +0 -362
- package/dist/lib/worktree/index.js.map +0 -1
- package/dist/lib/worktree/migrate.d.ts +0 -2
- package/dist/lib/worktree/migrate.d.ts.map +0 -1
- package/dist/lib/worktree/migrate.js +0 -214
- package/dist/lib/worktree/migrate.js.map +0 -1
- package/dist/lib/worktree/repair.d.ts +0 -3
- package/dist/lib/worktree/repair.d.ts.map +0 -1
- package/dist/lib/worktree/repair.js +0 -320
- package/dist/lib/worktree/repair.js.map +0 -1
- package/dist/types/index.d.ts +0 -57
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/index.js +0 -3
- package/dist/types/index.js.map +0 -1
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
export default class PRLink extends Command {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static args: {
|
|
6
|
+
ticketId: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
7
|
+
};
|
|
8
|
+
static flags: {
|
|
9
|
+
pr: import("@oclif/core/interfaces").OptionFlag<number | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
+
url: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
12
|
+
};
|
|
13
|
+
run(): Promise<void>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import { Command, Args, Flags } from '@oclif/core';
|
|
2
|
+
import * as path from 'node:path';
|
|
3
|
+
import Database from 'better-sqlite3';
|
|
4
|
+
import inquirer from 'inquirer';
|
|
5
|
+
import { getPMOContext } from '../../lib/pmo/index.js';
|
|
6
|
+
import { styles } from '../../lib/styles.js';
|
|
7
|
+
import { getWorkspaceInfo } from '../../lib/agents/commands.js';
|
|
8
|
+
import { isGHInstalled, isGHAuthenticated, getPRByNumber, listOpenPRs, } from '../../lib/pr/index.js';
|
|
9
|
+
import { shouldOutputJson, outputPromptAsJson, outputErrorAsJson, createMetadata, buildPromptConfig, } from '../../lib/prompt-json.js';
|
|
10
|
+
export default class PRLink extends Command {
|
|
11
|
+
static description = 'Link an existing GitHub pull request to a ticket';
|
|
12
|
+
static examples = [
|
|
13
|
+
'<%= config.bin %> <%= command.id %>',
|
|
14
|
+
'<%= config.bin %> <%= command.id %> TKT-001',
|
|
15
|
+
'<%= config.bin %> <%= command.id %> TKT-001 --pr 123',
|
|
16
|
+
'<%= config.bin %> <%= command.id %> TKT-001 --url https://github.com/owner/repo/pull/123',
|
|
17
|
+
];
|
|
18
|
+
static args = {
|
|
19
|
+
ticketId: Args.string({
|
|
20
|
+
description: 'Ticket ID to link PR to',
|
|
21
|
+
required: false,
|
|
22
|
+
}),
|
|
23
|
+
};
|
|
24
|
+
static flags = {
|
|
25
|
+
pr: Flags.integer({
|
|
26
|
+
char: 'p',
|
|
27
|
+
description: 'PR number to link',
|
|
28
|
+
}),
|
|
29
|
+
url: Flags.string({
|
|
30
|
+
char: 'u',
|
|
31
|
+
description: 'PR URL to link',
|
|
32
|
+
}),
|
|
33
|
+
json: Flags.boolean({
|
|
34
|
+
description: 'Output prompt configuration as JSON (for AI agents/scripts)',
|
|
35
|
+
default: false,
|
|
36
|
+
}),
|
|
37
|
+
};
|
|
38
|
+
async run() {
|
|
39
|
+
const { args, flags } = await this.parse(PRLink);
|
|
40
|
+
// Check if JSON output mode is active
|
|
41
|
+
const jsonMode = shouldOutputJson(flags);
|
|
42
|
+
// Helper to handle errors in JSON mode
|
|
43
|
+
const handleError = (code, message) => {
|
|
44
|
+
if (jsonMode) {
|
|
45
|
+
outputErrorAsJson(code, message, createMetadata('pr link', flags));
|
|
46
|
+
this.exit(1);
|
|
47
|
+
}
|
|
48
|
+
this.error(message);
|
|
49
|
+
};
|
|
50
|
+
// Check gh CLI
|
|
51
|
+
if (!isGHInstalled()) {
|
|
52
|
+
return handleError('GH_NOT_INSTALLED', 'GitHub CLI (gh) is not installed. Install it from https://cli.github.com/');
|
|
53
|
+
}
|
|
54
|
+
if (!isGHAuthenticated()) {
|
|
55
|
+
return handleError('GH_NOT_AUTHENTICATED', 'GitHub CLI is not authenticated. Run "gh auth login" first.');
|
|
56
|
+
}
|
|
57
|
+
// Get workspace and PMO context
|
|
58
|
+
let workspaceInfo;
|
|
59
|
+
try {
|
|
60
|
+
workspaceInfo = getWorkspaceInfo();
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return handleError('NOT_IN_WORKSPACE', 'Not in a workspace. Run "prlt init" first.');
|
|
64
|
+
}
|
|
65
|
+
const { storage } = await getPMOContext({
|
|
66
|
+
logger: (msg) => this.log(styles.muted(msg)),
|
|
67
|
+
});
|
|
68
|
+
const dbPath = path.join(workspaceInfo.path, '.proletariat', 'workspace.db');
|
|
69
|
+
const db = new Database(dbPath);
|
|
70
|
+
try {
|
|
71
|
+
// Get ticket ID
|
|
72
|
+
let ticketId = args.ticketId;
|
|
73
|
+
if (!ticketId) {
|
|
74
|
+
const projectId = flags.project;
|
|
75
|
+
const allTickets = await storage.listTickets(projectId);
|
|
76
|
+
const activeTickets = allTickets.filter(t => t.statusName && !t.statusName.toLowerCase().includes('done') && !t.statusName.toLowerCase().includes('archive'));
|
|
77
|
+
if (activeTickets.length === 0) {
|
|
78
|
+
await storage.close();
|
|
79
|
+
db.close();
|
|
80
|
+
if (jsonMode) {
|
|
81
|
+
outputErrorAsJson('NO_ACTIVE_TICKETS', 'No active tickets found.', createMetadata('pr link', flags));
|
|
82
|
+
this.exit(1);
|
|
83
|
+
}
|
|
84
|
+
this.log(styles.info('No active tickets found.'));
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
// Build choices once, use for both JSON and interactive modes
|
|
88
|
+
const ticketChoices = activeTickets.map(t => ({
|
|
89
|
+
name: `${t.id} - ${t.title} (${t.statusName})`,
|
|
90
|
+
value: t.id,
|
|
91
|
+
}));
|
|
92
|
+
const ticketMessage = 'Select ticket to link PR to:';
|
|
93
|
+
// In JSON mode, output ticket selection prompt and exit
|
|
94
|
+
if (jsonMode) {
|
|
95
|
+
outputPromptAsJson(buildPromptConfig('list', 'ticketId', ticketMessage, ticketChoices), createMetadata('pr link', flags));
|
|
96
|
+
}
|
|
97
|
+
const { selectedTicketId } = await inquirer.prompt([{
|
|
98
|
+
type: 'list',
|
|
99
|
+
name: 'selectedTicketId',
|
|
100
|
+
message: ticketMessage,
|
|
101
|
+
choices: ticketChoices,
|
|
102
|
+
}]);
|
|
103
|
+
ticketId = selectedTicketId;
|
|
104
|
+
}
|
|
105
|
+
// Get ticket
|
|
106
|
+
const ticket = await storage.getTicket(ticketId);
|
|
107
|
+
if (!ticket) {
|
|
108
|
+
await storage.close();
|
|
109
|
+
db.close();
|
|
110
|
+
this.error(`Ticket "${ticketId}" not found.`);
|
|
111
|
+
}
|
|
112
|
+
// Check if ticket already has a PR linked
|
|
113
|
+
if (ticket.metadata?.pr_url) {
|
|
114
|
+
// Build choices once, use for both JSON and interactive modes
|
|
115
|
+
const confirmChoices = [
|
|
116
|
+
{ name: 'No', value: 'false' },
|
|
117
|
+
{ name: 'Yes', value: 'true' },
|
|
118
|
+
];
|
|
119
|
+
const confirmMessage = `Ticket ${ticketId} already has a linked PR (${ticket.metadata.pr_url}). Replace with a different PR?`;
|
|
120
|
+
// In JSON mode, output overwrite confirmation prompt and exit
|
|
121
|
+
if (jsonMode) {
|
|
122
|
+
outputPromptAsJson(buildPromptConfig('list', 'overwrite', confirmMessage, confirmChoices), createMetadata('pr link', flags));
|
|
123
|
+
}
|
|
124
|
+
this.log(styles.info(`Ticket ${ticketId} already has a linked PR:`));
|
|
125
|
+
this.log(styles.muted(` URL: ${ticket.metadata.pr_url}`));
|
|
126
|
+
const { overwrite } = await inquirer.prompt([{
|
|
127
|
+
type: 'list',
|
|
128
|
+
name: 'overwrite',
|
|
129
|
+
message: 'Replace with a different PR?',
|
|
130
|
+
choices: confirmChoices.map(c => ({ name: c.name, value: c.value === 'true' })),
|
|
131
|
+
default: false,
|
|
132
|
+
}]);
|
|
133
|
+
if (!overwrite) {
|
|
134
|
+
await storage.close();
|
|
135
|
+
db.close();
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
// Get PR number
|
|
140
|
+
let prNumber = flags.pr;
|
|
141
|
+
const prUrl = flags.url;
|
|
142
|
+
if (prUrl) {
|
|
143
|
+
// Extract PR number from URL
|
|
144
|
+
const urlMatch = prUrl.match(/\/pull\/(\d+)/);
|
|
145
|
+
if (urlMatch) {
|
|
146
|
+
prNumber = parseInt(urlMatch[1], 10);
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
this.error('Invalid PR URL format. Expected: https://github.com/owner/repo/pull/123');
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
if (!prNumber) {
|
|
153
|
+
// List open PRs for selection
|
|
154
|
+
const openPRs = listOpenPRs();
|
|
155
|
+
if (openPRs.length === 0) {
|
|
156
|
+
await storage.close();
|
|
157
|
+
db.close();
|
|
158
|
+
if (jsonMode) {
|
|
159
|
+
outputErrorAsJson('NO_OPEN_PRS', 'No open PRs found. Create one first with "prlt pr create".', createMetadata('pr link', flags));
|
|
160
|
+
this.exit(1);
|
|
161
|
+
}
|
|
162
|
+
this.error('No open PRs found. Create one first with "prlt pr create".');
|
|
163
|
+
}
|
|
164
|
+
// Build choices once, use for both JSON and interactive modes
|
|
165
|
+
const prChoices = openPRs.map(pr => ({
|
|
166
|
+
name: `#${pr.number} - ${pr.title} (${pr.headBranch})`,
|
|
167
|
+
value: String(pr.number),
|
|
168
|
+
}));
|
|
169
|
+
const prMessage = 'Select PR to link:';
|
|
170
|
+
// In JSON mode, output PR selection prompt and exit
|
|
171
|
+
if (jsonMode) {
|
|
172
|
+
outputPromptAsJson(buildPromptConfig('list', 'prNumber', prMessage, prChoices), createMetadata('pr link', flags));
|
|
173
|
+
}
|
|
174
|
+
const { selectedPR } = await inquirer.prompt([{
|
|
175
|
+
type: 'list',
|
|
176
|
+
name: 'selectedPR',
|
|
177
|
+
message: prMessage,
|
|
178
|
+
choices: prChoices.map(c => ({ name: c.name, value: parseInt(c.value, 10) })),
|
|
179
|
+
}]);
|
|
180
|
+
prNumber = selectedPR;
|
|
181
|
+
}
|
|
182
|
+
// Get PR info
|
|
183
|
+
const prInfo = getPRByNumber(prNumber);
|
|
184
|
+
if (!prInfo) {
|
|
185
|
+
await storage.close();
|
|
186
|
+
db.close();
|
|
187
|
+
this.error(`PR #${prNumber} not found.`);
|
|
188
|
+
}
|
|
189
|
+
// Link PR to ticket
|
|
190
|
+
await storage.updateTicket(ticketId, {
|
|
191
|
+
metadata: {
|
|
192
|
+
...ticket.metadata,
|
|
193
|
+
pr_url: prInfo.url,
|
|
194
|
+
pr_number: String(prInfo.number),
|
|
195
|
+
pr_branch: prInfo.headBranch,
|
|
196
|
+
},
|
|
197
|
+
});
|
|
198
|
+
await storage.close();
|
|
199
|
+
db.close();
|
|
200
|
+
this.log('');
|
|
201
|
+
this.log(styles.success(`PR linked to ticket!`));
|
|
202
|
+
this.log(styles.muted(` Ticket: ${ticketId}`));
|
|
203
|
+
this.log(styles.muted(` PR: #${prInfo.number} - ${prInfo.title}`));
|
|
204
|
+
this.log(styles.muted(` URL: ${prInfo.url}`));
|
|
205
|
+
}
|
|
206
|
+
catch (error) {
|
|
207
|
+
await storage.close();
|
|
208
|
+
db.close();
|
|
209
|
+
throw error;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
export default class PRStatus extends Command {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static args: {
|
|
6
|
+
ticketId: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
7
|
+
};
|
|
8
|
+
static flags: {
|
|
9
|
+
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
10
|
+
};
|
|
11
|
+
run(): Promise<void>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { Command, Args, Flags } from '@oclif/core';
|
|
2
|
+
import * as path from 'node:path';
|
|
3
|
+
import Database from 'better-sqlite3';
|
|
4
|
+
import inquirer from 'inquirer';
|
|
5
|
+
import { getPMOContext } from '../../lib/pmo/index.js';
|
|
6
|
+
import { styles } from '../../lib/styles.js';
|
|
7
|
+
import { getWorkspaceInfo } from '../../lib/agents/commands.js';
|
|
8
|
+
import { isGHInstalled, isGHAuthenticated, getPRByNumber, } from '../../lib/pr/index.js';
|
|
9
|
+
import { shouldOutputJson, outputPromptAsJson, outputErrorAsJson, createMetadata, buildPromptConfig, } from '../../lib/prompt-json.js';
|
|
10
|
+
export default class PRStatus extends Command {
|
|
11
|
+
static description = 'View PR status for a ticket';
|
|
12
|
+
static examples = [
|
|
13
|
+
'<%= config.bin %> <%= command.id %>',
|
|
14
|
+
'<%= config.bin %> <%= command.id %> TKT-001',
|
|
15
|
+
];
|
|
16
|
+
static args = {
|
|
17
|
+
ticketId: Args.string({
|
|
18
|
+
description: 'Ticket ID to check PR status for',
|
|
19
|
+
required: false,
|
|
20
|
+
}),
|
|
21
|
+
};
|
|
22
|
+
static flags = {
|
|
23
|
+
json: Flags.boolean({
|
|
24
|
+
description: 'Output prompt configuration as JSON (for AI agents/scripts)',
|
|
25
|
+
default: false,
|
|
26
|
+
}),
|
|
27
|
+
};
|
|
28
|
+
async run() {
|
|
29
|
+
const { args, flags } = await this.parse(PRStatus);
|
|
30
|
+
// Check if JSON output mode is active
|
|
31
|
+
const jsonMode = shouldOutputJson(flags);
|
|
32
|
+
// Helper to handle errors in JSON mode
|
|
33
|
+
const handleError = (code, message) => {
|
|
34
|
+
if (jsonMode) {
|
|
35
|
+
outputErrorAsJson(code, message, createMetadata('pr status', flags));
|
|
36
|
+
this.exit(1);
|
|
37
|
+
}
|
|
38
|
+
this.error(message);
|
|
39
|
+
};
|
|
40
|
+
// Get workspace and PMO context
|
|
41
|
+
let workspaceInfo;
|
|
42
|
+
try {
|
|
43
|
+
workspaceInfo = getWorkspaceInfo();
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return handleError('NOT_IN_WORKSPACE', 'Not in a workspace. Run "prlt init" first.');
|
|
47
|
+
}
|
|
48
|
+
const { storage } = await getPMOContext({
|
|
49
|
+
logger: (msg) => this.log(styles.muted(msg)),
|
|
50
|
+
});
|
|
51
|
+
const dbPath = path.join(workspaceInfo.path, '.proletariat', 'workspace.db');
|
|
52
|
+
const db = new Database(dbPath);
|
|
53
|
+
try {
|
|
54
|
+
// Get ticket ID
|
|
55
|
+
let ticketId = args.ticketId;
|
|
56
|
+
if (!ticketId) {
|
|
57
|
+
const projectId = flags.project;
|
|
58
|
+
const allTickets = await storage.listTickets(projectId);
|
|
59
|
+
// Filter to tickets that have a PR linked
|
|
60
|
+
const ticketsWithPR = allTickets.filter(t => t.metadata?.pr_url);
|
|
61
|
+
const ticketsWithoutPR = allTickets.filter(t => !t.metadata?.pr_url && t.statusName && !t.statusName.toLowerCase().includes('done'));
|
|
62
|
+
if (ticketsWithPR.length === 0 && ticketsWithoutPR.length === 0) {
|
|
63
|
+
await storage.close();
|
|
64
|
+
db.close();
|
|
65
|
+
this.log(styles.info('No tickets found.'));
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
// Build choices once, use for both JSON and interactive modes
|
|
69
|
+
const ticketsWithPRChoices = ticketsWithPR.map(t => ({
|
|
70
|
+
name: `${t.id} - ${t.title} [PR linked]`,
|
|
71
|
+
value: t.id,
|
|
72
|
+
}));
|
|
73
|
+
const ticketsWithoutPRChoices = ticketsWithoutPR.slice(0, 10).map(t => ({
|
|
74
|
+
name: `${t.id} - ${t.title} (${t.statusName})`,
|
|
75
|
+
value: t.id,
|
|
76
|
+
}));
|
|
77
|
+
const ticketChoices = [...ticketsWithPRChoices, ...ticketsWithoutPRChoices];
|
|
78
|
+
const message = 'Select ticket to check PR status:';
|
|
79
|
+
// In JSON mode, output ticket selection prompt and exit
|
|
80
|
+
if (jsonMode) {
|
|
81
|
+
outputPromptAsJson(buildPromptConfig('list', 'ticketId', message, ticketChoices), createMetadata('pr status', flags));
|
|
82
|
+
}
|
|
83
|
+
// Build interactive choices with separator
|
|
84
|
+
const interactiveChoices = [...ticketsWithPRChoices];
|
|
85
|
+
if (ticketsWithoutPRChoices.length > 0) {
|
|
86
|
+
interactiveChoices.push(new inquirer.Separator('── No PR Linked ──'));
|
|
87
|
+
interactiveChoices.push(...ticketsWithoutPRChoices);
|
|
88
|
+
}
|
|
89
|
+
const { selectedTicketId } = await inquirer.prompt([{
|
|
90
|
+
type: 'list',
|
|
91
|
+
name: 'selectedTicketId',
|
|
92
|
+
message,
|
|
93
|
+
choices: interactiveChoices,
|
|
94
|
+
}]);
|
|
95
|
+
ticketId = selectedTicketId;
|
|
96
|
+
}
|
|
97
|
+
// Get ticket
|
|
98
|
+
const ticket = await storage.getTicket(ticketId);
|
|
99
|
+
if (!ticket) {
|
|
100
|
+
await storage.close();
|
|
101
|
+
db.close();
|
|
102
|
+
this.error(`Ticket "${ticketId}" not found.`);
|
|
103
|
+
}
|
|
104
|
+
this.log('');
|
|
105
|
+
this.log(styles.header(`PR Status: ${ticket.id}`));
|
|
106
|
+
this.log(styles.muted(` Title: ${ticket.title}`));
|
|
107
|
+
this.log(styles.muted(` Status: ${ticket.statusName}`));
|
|
108
|
+
this.log('');
|
|
109
|
+
if (!ticket.metadata?.pr_url) {
|
|
110
|
+
this.log(styles.info('No PR linked to this ticket.'));
|
|
111
|
+
this.log(styles.muted(' Use "prlt pr create" or "prlt pr link" to link a PR.'));
|
|
112
|
+
await storage.close();
|
|
113
|
+
db.close();
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
// Check gh CLI for live status
|
|
117
|
+
if (!isGHInstalled() || !isGHAuthenticated()) {
|
|
118
|
+
this.log(styles.muted(' PR URL:'), ticket.metadata.pr_url);
|
|
119
|
+
this.log(styles.muted(' (Install and authenticate `gh` CLI for live status)'));
|
|
120
|
+
await storage.close();
|
|
121
|
+
db.close();
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
const prNumber = parseInt(ticket.metadata.pr_number || '0', 10);
|
|
125
|
+
if (!prNumber) {
|
|
126
|
+
this.log(styles.muted(' PR URL:'), ticket.metadata.pr_url);
|
|
127
|
+
await storage.close();
|
|
128
|
+
db.close();
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
const prInfo = getPRByNumber(prNumber);
|
|
132
|
+
if (!prInfo) {
|
|
133
|
+
this.log(styles.warning('Unable to fetch PR status (PR may have been deleted).'));
|
|
134
|
+
this.log(styles.muted(' Stored URL:'), ticket.metadata.pr_url);
|
|
135
|
+
await storage.close();
|
|
136
|
+
db.close();
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
// Display PR status
|
|
140
|
+
const stateEmoji = {
|
|
141
|
+
OPEN: '🟢',
|
|
142
|
+
CLOSED: '🔴',
|
|
143
|
+
MERGED: '🟣',
|
|
144
|
+
};
|
|
145
|
+
this.log(styles.success(`${stateEmoji[prInfo.state]} PR #${prInfo.number}: ${prInfo.title}`));
|
|
146
|
+
this.log('');
|
|
147
|
+
this.log(styles.muted(` State: ${prInfo.state}${prInfo.isDraft ? ' (Draft)' : ''}`));
|
|
148
|
+
this.log(styles.muted(` Branch: ${prInfo.headBranch} → ${prInfo.baseBranch}`));
|
|
149
|
+
this.log(styles.muted(` URL: ${prInfo.url}`));
|
|
150
|
+
this.log(styles.muted(` Created: ${new Date(prInfo.createdAt).toLocaleDateString()}`));
|
|
151
|
+
this.log(styles.muted(` Updated: ${new Date(prInfo.updatedAt).toLocaleDateString()}`));
|
|
152
|
+
await storage.close();
|
|
153
|
+
db.close();
|
|
154
|
+
}
|
|
155
|
+
catch (error) {
|
|
156
|
+
await storage.close();
|
|
157
|
+
db.close();
|
|
158
|
+
throw error;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { PMOCommand } from '../../lib/pmo/index.js';
|
|
2
|
+
export default class ProjectArchive 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
|
+
};
|
|
8
|
+
static flags: {
|
|
9
|
+
force: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
10
|
+
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
11
|
+
project: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
};
|
|
13
|
+
protected getPMOOptions(): {
|
|
14
|
+
promptIfMultiple: boolean;
|
|
15
|
+
};
|
|
16
|
+
execute(): Promise<void>;
|
|
17
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { Args, Flags } from '@oclif/core';
|
|
2
|
+
import inquirer from 'inquirer';
|
|
3
|
+
import { PMOCommand, pmoBaseFlags } from '../../lib/pmo/index.js';
|
|
4
|
+
import { styles } from '../../lib/styles.js';
|
|
5
|
+
import { shouldOutputJson, outputPromptAsJson, outputErrorAsJson, createMetadata, buildPromptConfig, } from '../../lib/prompt-json.js';
|
|
6
|
+
export default class ProjectArchive extends PMOCommand {
|
|
7
|
+
static description = 'Archive a project (hide from default views)';
|
|
8
|
+
static examples = [
|
|
9
|
+
'<%= config.bin %> <%= command.id %> old-project',
|
|
10
|
+
'<%= config.bin %> <%= command.id %> old-project --force',
|
|
11
|
+
];
|
|
12
|
+
static args = {
|
|
13
|
+
id: Args.string({
|
|
14
|
+
description: 'Project ID',
|
|
15
|
+
required: true,
|
|
16
|
+
}),
|
|
17
|
+
};
|
|
18
|
+
static flags = {
|
|
19
|
+
...pmoBaseFlags,
|
|
20
|
+
force: Flags.boolean({
|
|
21
|
+
char: 'f',
|
|
22
|
+
description: 'Skip confirmation',
|
|
23
|
+
default: false,
|
|
24
|
+
}),
|
|
25
|
+
json: Flags.boolean({
|
|
26
|
+
description: 'Output prompt configuration as JSON (for AI agents/scripts)',
|
|
27
|
+
default: false,
|
|
28
|
+
}),
|
|
29
|
+
};
|
|
30
|
+
getPMOOptions() {
|
|
31
|
+
return { promptIfMultiple: false };
|
|
32
|
+
}
|
|
33
|
+
async execute() {
|
|
34
|
+
const { args, flags } = await this.parse(ProjectArchive);
|
|
35
|
+
// Check if JSON output mode is active
|
|
36
|
+
const jsonMode = shouldOutputJson(flags);
|
|
37
|
+
// Helper to handle errors in JSON mode
|
|
38
|
+
const handleError = (code, message) => {
|
|
39
|
+
if (jsonMode) {
|
|
40
|
+
outputErrorAsJson(code, message, createMetadata('project archive', flags));
|
|
41
|
+
this.exit(1);
|
|
42
|
+
}
|
|
43
|
+
this.error(message);
|
|
44
|
+
};
|
|
45
|
+
const project = await this.storage.getProject(args.id);
|
|
46
|
+
if (!project) {
|
|
47
|
+
return handleError('PROJECT_NOT_FOUND', `Project "${args.id}" not found.`);
|
|
48
|
+
}
|
|
49
|
+
if (project.isArchived) {
|
|
50
|
+
if (jsonMode) {
|
|
51
|
+
outputErrorAsJson('ALREADY_ARCHIVED', `Project "${project.name}" is already archived.`, createMetadata('project archive', flags));
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
this.log(styles.muted(`Project "${project.name}" is already archived.`));
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
if (!flags.force) {
|
|
58
|
+
// In JSON mode, output confirmation prompt
|
|
59
|
+
if (jsonMode) {
|
|
60
|
+
const confirmChoices = [
|
|
61
|
+
{ name: 'No', value: 'false' },
|
|
62
|
+
{ name: 'Yes', value: 'true' },
|
|
63
|
+
];
|
|
64
|
+
outputPromptAsJson(buildPromptConfig('list', 'confirmed', `Archive project "${project.name}"? It will be hidden from default views.`, confirmChoices), createMetadata('project archive', flags));
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
const { confirm } = await inquirer.prompt([{
|
|
68
|
+
type: 'confirm',
|
|
69
|
+
name: 'confirm',
|
|
70
|
+
message: `Archive project "${project.name}"? It will be hidden from default views.`,
|
|
71
|
+
default: false,
|
|
72
|
+
}]);
|
|
73
|
+
if (!confirm) {
|
|
74
|
+
this.log(styles.muted('Cancelled.'));
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
await this.storage.archiveProject(args.id);
|
|
79
|
+
this.log(styles.success(`\nArchived project "${project.name}"`));
|
|
80
|
+
this.log(styles.muted('View archived projects: prlt project list --archived'));
|
|
81
|
+
this.log(styles.muted('Unarchive: prlt project unarchive ' + args.id));
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { PMOCommand } from '../../lib/pmo/index.js';
|
|
2
|
+
export default class ProjectCreate extends PMOCommand {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static args: {
|
|
6
|
+
name: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
7
|
+
};
|
|
8
|
+
static flags: {
|
|
9
|
+
name: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
+
id: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
description: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
template: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
+
interactive: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
14
|
+
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
15
|
+
project: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
16
|
+
};
|
|
17
|
+
protected getPMOOptions(): {
|
|
18
|
+
promptIfMultiple: boolean;
|
|
19
|
+
};
|
|
20
|
+
execute(): Promise<void>;
|
|
21
|
+
private promptProjectData;
|
|
22
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { Flags, Args } from '@oclif/core';
|
|
2
|
+
import * as fs from 'node:fs';
|
|
3
|
+
import * as path from 'node:path';
|
|
4
|
+
import inquirer from 'inquirer';
|
|
5
|
+
import { createBoardContent, createSpecFolders, PMOCommand, pmoBaseFlags } from '../../lib/pmo/index.js';
|
|
6
|
+
import { styles } from '../../lib/styles.js';
|
|
7
|
+
import { slugify } from '../../lib/pmo/utils.js';
|
|
8
|
+
import { shouldOutputJson, outputPromptAsJson, createMetadata, buildFormPromptConfig, } from '../../lib/prompt-json.js';
|
|
9
|
+
export default class ProjectCreate extends PMOCommand {
|
|
10
|
+
static description = 'Create a new project in the PMO';
|
|
11
|
+
static examples = [
|
|
12
|
+
'<%= config.bin %> <%= command.id %> "My New Project"',
|
|
13
|
+
'<%= config.bin %> <%= command.id %> --name "Mobile App" --description "iOS and Android app"',
|
|
14
|
+
'<%= config.bin %> <%= command.id %> -i # Interactive mode',
|
|
15
|
+
];
|
|
16
|
+
static args = {
|
|
17
|
+
name: Args.string({
|
|
18
|
+
description: 'Project name',
|
|
19
|
+
required: false,
|
|
20
|
+
}),
|
|
21
|
+
};
|
|
22
|
+
static flags = {
|
|
23
|
+
...pmoBaseFlags,
|
|
24
|
+
name: Flags.string({
|
|
25
|
+
char: 'n',
|
|
26
|
+
description: 'Project name',
|
|
27
|
+
}),
|
|
28
|
+
id: Flags.string({
|
|
29
|
+
description: 'Custom project ID (auto-generated from name if not provided)',
|
|
30
|
+
}),
|
|
31
|
+
description: Flags.string({
|
|
32
|
+
char: 'd',
|
|
33
|
+
description: 'Project description',
|
|
34
|
+
}),
|
|
35
|
+
template: Flags.string({
|
|
36
|
+
char: 't',
|
|
37
|
+
description: 'Workflow template',
|
|
38
|
+
options: ['kanban', 'linear', 'bug-smash', '5-tool-founder', 'gtm'],
|
|
39
|
+
default: 'kanban',
|
|
40
|
+
}),
|
|
41
|
+
interactive: Flags.boolean({
|
|
42
|
+
char: 'i',
|
|
43
|
+
description: 'Interactive mode',
|
|
44
|
+
default: false,
|
|
45
|
+
}),
|
|
46
|
+
json: Flags.boolean({
|
|
47
|
+
description: 'Output prompt configuration as JSON (for AI agents/scripts)',
|
|
48
|
+
default: false,
|
|
49
|
+
}),
|
|
50
|
+
};
|
|
51
|
+
getPMOOptions() {
|
|
52
|
+
return { promptIfMultiple: false };
|
|
53
|
+
}
|
|
54
|
+
async execute() {
|
|
55
|
+
const { args, flags } = await this.parse(ProjectCreate);
|
|
56
|
+
// Check if JSON output mode is active
|
|
57
|
+
const jsonMode = shouldOutputJson(flags);
|
|
58
|
+
// Get project data first (before storage so prompts work)
|
|
59
|
+
let projectData;
|
|
60
|
+
if (flags.interactive || (!args.name && !flags.name)) {
|
|
61
|
+
// Build choices once - single source of truth
|
|
62
|
+
const templateChoices = [
|
|
63
|
+
{ name: 'Kanban - Backlog → To Do → In Progress → Done', value: 'kanban' },
|
|
64
|
+
{ name: 'Linear - Backlog, Triage, Todo, In Progress, In Review, Done', value: 'linear' },
|
|
65
|
+
{ name: 'Bug Smash - Reported → Confirmed → Fixing → Verifying → Fixed', value: 'bug-smash' },
|
|
66
|
+
{ name: '5-Tool Founder - Ship, Grow, Support, Strategy, BizOps → In Progress → Review → Done', value: '5-tool-founder' },
|
|
67
|
+
{ name: 'GTM - Ideation → Planning → In Development → Ready to Launch → Launched', value: 'gtm' },
|
|
68
|
+
];
|
|
69
|
+
// Define fields once - single source of truth for both JSON and interactive modes
|
|
70
|
+
const fields = [
|
|
71
|
+
{ type: 'input', name: 'name', message: 'Project name:', default: flags.name },
|
|
72
|
+
{ type: 'input', name: 'id', message: 'Project ID (leave blank to auto-generate):' },
|
|
73
|
+
{ type: 'input', name: 'description', message: 'Description (optional):', default: flags.description },
|
|
74
|
+
{ type: 'list', name: 'template', message: 'Workflow template:', choices: templateChoices, default: flags.template || 'kanban' },
|
|
75
|
+
];
|
|
76
|
+
// In JSON mode, output form prompt for project creation
|
|
77
|
+
if (jsonMode) {
|
|
78
|
+
outputPromptAsJson(buildFormPromptConfig(fields), createMetadata('project create', flags));
|
|
79
|
+
}
|
|
80
|
+
projectData = await this.promptProjectData(fields);
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
projectData = {
|
|
84
|
+
name: args.name || flags.name,
|
|
85
|
+
id: flags.id,
|
|
86
|
+
description: flags.description,
|
|
87
|
+
template: flags.template || 'kanban',
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
const projectId = projectData.id || slugify(projectData.name);
|
|
91
|
+
// Check if project already exists
|
|
92
|
+
const existing = await this.storage.getProject(projectId);
|
|
93
|
+
if (existing) {
|
|
94
|
+
this.error(`Project "${projectId}" already exists.`);
|
|
95
|
+
}
|
|
96
|
+
// Create project in database
|
|
97
|
+
const project = await this.storage.createProject({
|
|
98
|
+
id: projectId,
|
|
99
|
+
name: projectData.name,
|
|
100
|
+
description: projectData.description,
|
|
101
|
+
template: projectData.template,
|
|
102
|
+
});
|
|
103
|
+
// Create project folder structure: pmo/projects/{projectId}/
|
|
104
|
+
const projectPath = path.join(this.pmoPath, 'projects', projectId);
|
|
105
|
+
fs.mkdirSync(projectPath, { recursive: true });
|
|
106
|
+
// Create kanban.md in project directory with project name as board name
|
|
107
|
+
const boardContent = createBoardContent(projectData.template, projectData.name);
|
|
108
|
+
const boardPath = path.join(projectPath, 'kanban.md');
|
|
109
|
+
fs.writeFileSync(boardPath, boardContent);
|
|
110
|
+
// Create spec folders in project directory
|
|
111
|
+
const specsPath = createSpecFolders(this.pmoPath, projectId);
|
|
112
|
+
// Get the statuses from the workflow (template name = workflow ID for built-in templates)
|
|
113
|
+
const statuses = await this.storage.listStatuses(projectData.template);
|
|
114
|
+
this.log(styles.success(`\nCreated project "${styles.emphasis(project.name)}"`));
|
|
115
|
+
this.log(styles.muted(` ID: ${project.id}`));
|
|
116
|
+
this.log(styles.muted(` Template: ${projectData.template}`));
|
|
117
|
+
this.log(styles.muted(` Statuses: ${statuses.map(s => s.name).join(' → ')}`));
|
|
118
|
+
this.log(styles.muted(` Board: ${path.relative(process.cwd(), boardPath)}`));
|
|
119
|
+
this.log(styles.muted(` Specs: ${path.relative(process.cwd(), specsPath)}/`));
|
|
120
|
+
this.log(styles.muted(`\nSwitch to this project:`));
|
|
121
|
+
this.log(styles.muted(` prlt ticket list --project ${project.id}`));
|
|
122
|
+
this.log(styles.muted(` prlt project view ${project.id}`));
|
|
123
|
+
}
|
|
124
|
+
async promptProjectData(fields) {
|
|
125
|
+
// Build inquirer prompts from fields, adding validators and dynamic defaults
|
|
126
|
+
const answers = await inquirer.prompt(fields.map(field => ({
|
|
127
|
+
...field,
|
|
128
|
+
validate: field.name === 'name'
|
|
129
|
+
? ((input) => input.length > 0 || 'Name is required')
|
|
130
|
+
: undefined,
|
|
131
|
+
// Dynamic default for id based on name
|
|
132
|
+
default: field.name === 'id'
|
|
133
|
+
? ((answers) => slugify(answers.name))
|
|
134
|
+
: field.default,
|
|
135
|
+
})));
|
|
136
|
+
return {
|
|
137
|
+
name: answers.name,
|
|
138
|
+
id: answers.id || undefined,
|
|
139
|
+
description: answers.description || undefined,
|
|
140
|
+
template: answers.template,
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
}
|