@proletariat/cli 0.1.4 → 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 +510 -255
- 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 +104 -52
- 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 -139
- 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 -173
- 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 -212
- 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 -140
- 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,341 @@
|
|
|
1
|
+
import { Command, Flags } from '@oclif/core';
|
|
2
|
+
import * as fs from 'node:fs';
|
|
3
|
+
import * as path from 'node:path';
|
|
4
|
+
import { execSync } from 'node:child_process';
|
|
5
|
+
import chalk from 'chalk';
|
|
6
|
+
import inquirer from 'inquirer';
|
|
7
|
+
import Database from 'better-sqlite3';
|
|
8
|
+
import { SQLiteStorage, getColumnsForTemplate, createPMO, promptForPMOLocation, promptForBoardTemplate, promptForBoardName, promptForCustomColumns, determinePMOPath, } from '../../lib/pmo/index.js';
|
|
9
|
+
import { styles } from '../../lib/styles.js';
|
|
10
|
+
import { isGHInstalled, isGHAuthenticated, getGHUsername, isGHTokenInEnv } from '../../lib/pr/index.js';
|
|
11
|
+
import { shouldOutputJson, outputPromptAsJson, createMetadata, buildPromptConfig, } from '../../lib/prompt-json.js';
|
|
12
|
+
export default class PMOInit extends Command {
|
|
13
|
+
static description = 'Initialize PMO (Project Management Office) in current directory or HQ';
|
|
14
|
+
static examples = [
|
|
15
|
+
'<%= config.bin %> <%= command.id %>',
|
|
16
|
+
'<%= config.bin %> <%= command.id %> --location repo:proletariat --template founder',
|
|
17
|
+
'<%= config.bin %> <%= command.id %> --location separate --template scrum',
|
|
18
|
+
];
|
|
19
|
+
static flags = {
|
|
20
|
+
location: Flags.string({
|
|
21
|
+
char: 'l',
|
|
22
|
+
description: 'PMO location (separate or repo:name)',
|
|
23
|
+
}),
|
|
24
|
+
template: Flags.string({
|
|
25
|
+
char: 't',
|
|
26
|
+
description: 'Board template',
|
|
27
|
+
options: ['kanban', 'scrum', 'founder', 'custom'],
|
|
28
|
+
}),
|
|
29
|
+
name: Flags.string({
|
|
30
|
+
char: 'n',
|
|
31
|
+
description: 'Board name',
|
|
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 { flags } = await this.parse(PMOInit);
|
|
40
|
+
// Check if JSON output mode is active
|
|
41
|
+
const jsonMode = shouldOutputJson(flags);
|
|
42
|
+
// Check if PMO already exists
|
|
43
|
+
const hqRoot = this.findHQRoot();
|
|
44
|
+
let existingPMO = false;
|
|
45
|
+
let projectCount = 0;
|
|
46
|
+
let ticketCount = 0;
|
|
47
|
+
if (hqRoot) {
|
|
48
|
+
const dbPath = path.join(hqRoot, '.proletariat', 'workspace.db');
|
|
49
|
+
if (fs.existsSync(dbPath)) {
|
|
50
|
+
try {
|
|
51
|
+
const db = new Database(dbPath);
|
|
52
|
+
const result = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='pmo_projects'").get();
|
|
53
|
+
if (result !== undefined) {
|
|
54
|
+
existingPMO = true;
|
|
55
|
+
// Get counts
|
|
56
|
+
const projectCountResult = db.prepare('SELECT COUNT(*) as count FROM pmo_projects').get();
|
|
57
|
+
const ticketCountResult = db.prepare('SELECT COUNT(*) as count FROM pmo_tickets').get();
|
|
58
|
+
projectCount = projectCountResult.count;
|
|
59
|
+
ticketCount = ticketCountResult.count;
|
|
60
|
+
}
|
|
61
|
+
db.close();
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
// Log error for debugging
|
|
65
|
+
console.error('PMO check error:', error);
|
|
66
|
+
// Ignore errors - database might not be initialized yet
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
// If PMO exists, prompt for reinitialize
|
|
71
|
+
if (existingPMO) {
|
|
72
|
+
const shouldReinitialize = await this.promptReinitialize(hqRoot, projectCount, ticketCount, jsonMode, flags);
|
|
73
|
+
if (shouldReinitialize === null) {
|
|
74
|
+
// JSON mode returned early
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
if (!shouldReinitialize) {
|
|
78
|
+
this.log(chalk.yellow('\nCancelled. Existing PMO preserved.'));
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
// Delete existing PMO
|
|
82
|
+
await this.deletePMO(hqRoot);
|
|
83
|
+
}
|
|
84
|
+
this.log(chalk.blue('🎯 Initializing PMO...\n'));
|
|
85
|
+
this.log(chalk.gray(' Creates board.md and specs/ for project planning'));
|
|
86
|
+
this.log(chalk.gray(' (Data stored in SQLite, synced to markdown files)\n'));
|
|
87
|
+
// Get PMO location using shared prompt (or from flag)
|
|
88
|
+
let location;
|
|
89
|
+
if (flags.location) {
|
|
90
|
+
location = flags.location;
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
location = await promptForPMOLocation(hqRoot);
|
|
94
|
+
}
|
|
95
|
+
// Get board template using shared prompt (or from flag)
|
|
96
|
+
let template;
|
|
97
|
+
if (flags.template) {
|
|
98
|
+
template = flags.template;
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
template = await promptForBoardTemplate();
|
|
102
|
+
}
|
|
103
|
+
// Get columns for template
|
|
104
|
+
let columns = getColumnsForTemplate(template);
|
|
105
|
+
if (template === 'custom') {
|
|
106
|
+
columns = await promptForCustomColumns();
|
|
107
|
+
}
|
|
108
|
+
// Get board name using shared prompt (or from flag)
|
|
109
|
+
// Default to {hqname}-kanban pattern
|
|
110
|
+
const hqName = hqRoot ? path.basename(hqRoot).replace(/-hq$/, '') : undefined;
|
|
111
|
+
const defaultBoardName = hqName ? `${hqName}-kanban` : undefined;
|
|
112
|
+
const boardName = flags.name || await promptForBoardName(defaultBoardName);
|
|
113
|
+
// For standalone PMO (no HQ), we need to create mini-HQ structure first
|
|
114
|
+
const isStandalone = !hqRoot;
|
|
115
|
+
let effectiveHqPath;
|
|
116
|
+
if (isStandalone) {
|
|
117
|
+
// Create mini-HQ structure
|
|
118
|
+
effectiveHqPath = path.join(process.cwd(), '.pmo');
|
|
119
|
+
await this.createStandaloneHQ(effectiveHqPath);
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
effectiveHqPath = hqRoot;
|
|
123
|
+
}
|
|
124
|
+
// Use shared createPMO function
|
|
125
|
+
await createPMO({
|
|
126
|
+
hqPath: effectiveHqPath,
|
|
127
|
+
location,
|
|
128
|
+
boardTemplate: template,
|
|
129
|
+
boardName,
|
|
130
|
+
columns,
|
|
131
|
+
storageType: 'sqlite',
|
|
132
|
+
});
|
|
133
|
+
// Initialize git for separate PMO (recommended for syncing across machines)
|
|
134
|
+
if (location === 'separate' && !isStandalone) {
|
|
135
|
+
const pmoPath = determinePMOPath(effectiveHqPath, location);
|
|
136
|
+
await this.initGitForPMO(pmoPath);
|
|
137
|
+
}
|
|
138
|
+
this.log(chalk.green('\n✅ PMO initialized successfully!'));
|
|
139
|
+
// Check GitHub CLI setup for PR workflow
|
|
140
|
+
this.checkGitHubCLI();
|
|
141
|
+
this.logNextSteps();
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Create standalone mini-HQ structure for PMO outside of an HQ
|
|
145
|
+
*/
|
|
146
|
+
async createStandaloneHQ(hqPath) {
|
|
147
|
+
const proletariatPath = path.join(hqPath, '.proletariat');
|
|
148
|
+
fs.mkdirSync(proletariatPath, { recursive: true });
|
|
149
|
+
// Create minimal config
|
|
150
|
+
const config = {
|
|
151
|
+
type: 'hq',
|
|
152
|
+
name: 'PMO',
|
|
153
|
+
created: new Date().toISOString(),
|
|
154
|
+
version: '2.0.0',
|
|
155
|
+
};
|
|
156
|
+
fs.writeFileSync(path.join(proletariatPath, 'config.json'), JSON.stringify(config, null, 2));
|
|
157
|
+
// Create workspace.db using SQLiteStorage (which creates tables)
|
|
158
|
+
const dbPath = path.join(proletariatPath, 'workspace.db');
|
|
159
|
+
const storage = new SQLiteStorage(dbPath);
|
|
160
|
+
await storage.close();
|
|
161
|
+
this.log(chalk.green(' ✓ Standalone PMO structure created'));
|
|
162
|
+
}
|
|
163
|
+
findHQRoot() {
|
|
164
|
+
let currentDir = process.cwd();
|
|
165
|
+
while (currentDir !== '/') {
|
|
166
|
+
const configPath = path.join(currentDir, '.proletariat', 'config.json');
|
|
167
|
+
if (fs.existsSync(configPath)) {
|
|
168
|
+
try {
|
|
169
|
+
const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
|
|
170
|
+
if (config.type === 'hq') {
|
|
171
|
+
return currentDir;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
catch {
|
|
175
|
+
// Ignore parse errors
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
currentDir = path.dirname(currentDir);
|
|
179
|
+
}
|
|
180
|
+
return null;
|
|
181
|
+
}
|
|
182
|
+
async promptReinitialize(hqRoot, projectCount, ticketCount, jsonMode = false, flags = {}) {
|
|
183
|
+
// Find PMO location from database
|
|
184
|
+
const dbPath = path.join(hqRoot, '.proletariat', 'workspace.db');
|
|
185
|
+
let pmoPath = path.join(hqRoot, 'pmo'); // Default fallback
|
|
186
|
+
try {
|
|
187
|
+
const db = new Database(dbPath);
|
|
188
|
+
const result = db.prepare('SELECT value FROM pmo_settings WHERE key = ?').get('pmo_path');
|
|
189
|
+
if (result) {
|
|
190
|
+
pmoPath = result.value;
|
|
191
|
+
}
|
|
192
|
+
db.close();
|
|
193
|
+
}
|
|
194
|
+
catch {
|
|
195
|
+
// Use default if table doesn't exist
|
|
196
|
+
}
|
|
197
|
+
// Define choices once, use for both JSON and interactive modes
|
|
198
|
+
const actionChoices = [
|
|
199
|
+
{ name: 'Cancel (keep existing PMO)', value: 'cancel' },
|
|
200
|
+
{ name: 'Reinitialize (DELETES all data)', value: 'reinitialize' },
|
|
201
|
+
];
|
|
202
|
+
const message = `PMO already exists at ${pmoPath} (${projectCount} projects, ${ticketCount} tickets). What would you like to do?`;
|
|
203
|
+
// In JSON mode, output reinitialize prompt and exit
|
|
204
|
+
if (jsonMode) {
|
|
205
|
+
outputPromptAsJson(buildPromptConfig('list', 'action', message, actionChoices), createMetadata('pmo init', flags));
|
|
206
|
+
}
|
|
207
|
+
this.log(chalk.yellow('\n⚠️ PMO already exists'));
|
|
208
|
+
this.log(chalk.gray(` Location: ${pmoPath}`));
|
|
209
|
+
this.log(chalk.gray(` Projects: ${projectCount}`));
|
|
210
|
+
this.log(chalk.gray(` Tickets: ${ticketCount}\n`));
|
|
211
|
+
const { action } = await inquirer.prompt([{
|
|
212
|
+
type: 'list',
|
|
213
|
+
name: 'action',
|
|
214
|
+
message: 'What would you like to do?',
|
|
215
|
+
choices: actionChoices,
|
|
216
|
+
default: 'cancel',
|
|
217
|
+
}]);
|
|
218
|
+
if (action === 'cancel') {
|
|
219
|
+
return false;
|
|
220
|
+
}
|
|
221
|
+
// Show warning and require typed confirmation
|
|
222
|
+
this.log(chalk.red('\n⚠️ WARNING: This will permanently delete:'));
|
|
223
|
+
this.log(chalk.red(' • All tickets and boards'));
|
|
224
|
+
this.log(chalk.red(' • All specs and documentation'));
|
|
225
|
+
this.log(chalk.red(' • Database tables (pmo_*)\n'));
|
|
226
|
+
const { confirmation } = await inquirer.prompt([{
|
|
227
|
+
type: 'input',
|
|
228
|
+
name: 'confirmation',
|
|
229
|
+
message: 'Type "delete pmo" to confirm:',
|
|
230
|
+
}]);
|
|
231
|
+
if (confirmation !== 'delete pmo') {
|
|
232
|
+
this.log(chalk.yellow('\nCancelled. Confirmation text did not match.'));
|
|
233
|
+
return false;
|
|
234
|
+
}
|
|
235
|
+
return true;
|
|
236
|
+
}
|
|
237
|
+
async deletePMO(hqRoot) {
|
|
238
|
+
this.log(chalk.blue('\n🗑️ Deleting existing PMO...\n'));
|
|
239
|
+
// Delete database tables and get PMO path before dropping settings
|
|
240
|
+
const dbPath = path.join(hqRoot, '.proletariat', 'workspace.db');
|
|
241
|
+
let pmoPath = path.join(hqRoot, 'pmo'); // Default fallback
|
|
242
|
+
if (fs.existsSync(dbPath)) {
|
|
243
|
+
const db = new Database(dbPath);
|
|
244
|
+
// Get PMO path from database before deleting
|
|
245
|
+
try {
|
|
246
|
+
const result = db.prepare('SELECT value FROM pmo_settings WHERE key = ?').get('pmo_path');
|
|
247
|
+
if (result) {
|
|
248
|
+
pmoPath = result.value;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
catch {
|
|
252
|
+
// Ignore - table might not exist, use default
|
|
253
|
+
}
|
|
254
|
+
// Drop all pmo_* tables
|
|
255
|
+
const tables = ['pmo_ticket_specs', 'pmo_ticket_metadata', 'pmo_subtasks', 'pmo_tickets',
|
|
256
|
+
'pmo_columns', 'pmo_specs', 'pmo_epics', 'pmo_projects',
|
|
257
|
+
'pmo_initiatives', 'pmo_ticket_assignments', 'pmo_cache_metadata', 'pmo_settings'];
|
|
258
|
+
for (const table of tables) {
|
|
259
|
+
try {
|
|
260
|
+
db.prepare(`DROP TABLE IF EXISTS ${table}`).run();
|
|
261
|
+
}
|
|
262
|
+
catch {
|
|
263
|
+
// Ignore errors - table might not exist
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
db.close();
|
|
267
|
+
this.log(chalk.green(' ✓ Dropped database tables'));
|
|
268
|
+
}
|
|
269
|
+
// Delete pmo/ directory (using path from database or default)
|
|
270
|
+
if (fs.existsSync(pmoPath)) {
|
|
271
|
+
fs.rmSync(pmoPath, { recursive: true, force: true });
|
|
272
|
+
this.log(chalk.green(' ✓ Removed pmo/ directory\n'));
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
async initGitForPMO(pmoPath) {
|
|
276
|
+
try {
|
|
277
|
+
// Create .gitignore
|
|
278
|
+
const gitignore = `# Proletariat PMO
|
|
279
|
+
.DS_Store
|
|
280
|
+
*.swp
|
|
281
|
+
*.swo
|
|
282
|
+
*~
|
|
283
|
+
.vscode/
|
|
284
|
+
.idea/
|
|
285
|
+
`;
|
|
286
|
+
fs.writeFileSync(path.join(pmoPath, '.gitignore'), gitignore);
|
|
287
|
+
// Initialize git repo
|
|
288
|
+
execSync('git init', { cwd: pmoPath, stdio: 'pipe' });
|
|
289
|
+
execSync('git add .', { cwd: pmoPath, stdio: 'pipe' });
|
|
290
|
+
execSync('git commit -m "Initialize PMO\n\nCreated with Proletariat CLI"', { cwd: pmoPath, stdio: 'pipe' });
|
|
291
|
+
this.log(chalk.green(' ✓ Git repository initialized'));
|
|
292
|
+
this.log(styles.muted(' Add remote: cd pmo && git remote add origin <url>'));
|
|
293
|
+
}
|
|
294
|
+
catch {
|
|
295
|
+
this.log(chalk.yellow(' ⚠ Git initialization failed (continuing without git)'));
|
|
296
|
+
this.log(styles.muted(' You can initialize git manually: cd pmo && git init'));
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
logNextSteps() {
|
|
300
|
+
this.log(styles.muted('\nNext steps:'));
|
|
301
|
+
this.log(styles.muted(' 1. Create your first ticket: prlt ticket create'));
|
|
302
|
+
this.log(styles.muted(' 2. Create a spec: prlt spec create'));
|
|
303
|
+
this.log(styles.muted(' 3. Open pmo/ in Obsidian for visual kanban'));
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Check GitHub CLI setup and provide guidance for PR workflow
|
|
307
|
+
*/
|
|
308
|
+
checkGitHubCLI() {
|
|
309
|
+
this.log(styles.muted('\nChecking GitHub CLI for PR workflow...'));
|
|
310
|
+
// Check if gh is installed
|
|
311
|
+
if (!isGHInstalled()) {
|
|
312
|
+
this.log(chalk.yellow(' ⚠ gh CLI not installed'));
|
|
313
|
+
this.log(styles.muted(' Install: brew install gh'));
|
|
314
|
+
this.log(styles.muted(' PR creation will be skipped without gh\n'));
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
this.log(chalk.green(' ✓ gh CLI installed'));
|
|
318
|
+
// Check if gh is authenticated
|
|
319
|
+
if (!isGHAuthenticated()) {
|
|
320
|
+
this.log(chalk.yellow(' ⚠ gh CLI not authenticated'));
|
|
321
|
+
this.log(styles.muted(' Run: gh auth login'));
|
|
322
|
+
this.log(styles.muted(' PR creation will be skipped without auth\n'));
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
325
|
+
const username = getGHUsername();
|
|
326
|
+
this.log(chalk.green(` ✓ gh authenticated${username ? ` as ${username}` : ''}`));
|
|
327
|
+
// Check if GH_TOKEN is available for devcontainers
|
|
328
|
+
if (isGHTokenInEnv()) {
|
|
329
|
+
this.log(chalk.green(' ✓ GH_TOKEN available for devcontainers'));
|
|
330
|
+
}
|
|
331
|
+
else {
|
|
332
|
+
this.log(chalk.yellow(' ⚠ GH_TOKEN not set (needed for PR creation in devcontainers)'));
|
|
333
|
+
this.log(styles.muted(''));
|
|
334
|
+
this.log(styles.muted(' To enable PR creation from devcontainers, add to your shell profile:'));
|
|
335
|
+
this.log(styles.muted(''));
|
|
336
|
+
this.log(chalk.cyan(" echo 'export GH_TOKEN=$(gh auth token 2>/dev/null)' >> ~/.zshrc"));
|
|
337
|
+
this.log(styles.muted(''));
|
|
338
|
+
this.log(styles.muted(' Then restart your terminal or run: source ~/.zshrc'));
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
export default class PRCreate 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
|
+
base: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
+
draft: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
11
|
+
'no-link': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
12
|
+
title: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
+
body: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
|
+
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
15
|
+
};
|
|
16
|
+
run(): Promise<void>;
|
|
17
|
+
}
|
|
@@ -0,0 +1,242 @@
|
|
|
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, getCurrentBranch, getDefaultBaseBranch, hasBranchBeenPushed, pushBranch, hasUnpushedCommits, getCommitLog, createPR, getPRForBranch, generatePRTitle, generatePRBody, } from '../../lib/pr/index.js';
|
|
9
|
+
import { shouldOutputJson, outputPromptAsJson, outputErrorAsJson, createMetadata, buildPromptConfig, } from '../../lib/prompt-json.js';
|
|
10
|
+
export default class PRCreate extends Command {
|
|
11
|
+
static description = 'Create a GitHub pull request from the current branch';
|
|
12
|
+
static examples = [
|
|
13
|
+
'<%= config.bin %> <%= command.id %>',
|
|
14
|
+
'<%= config.bin %> <%= command.id %> TKT-001',
|
|
15
|
+
'<%= config.bin %> <%= command.id %> --draft',
|
|
16
|
+
'<%= config.bin %> <%= command.id %> --base develop',
|
|
17
|
+
];
|
|
18
|
+
static args = {
|
|
19
|
+
ticketId: Args.string({
|
|
20
|
+
description: 'Ticket ID to link to PR - auto-detects from branch if not provided',
|
|
21
|
+
required: false,
|
|
22
|
+
}),
|
|
23
|
+
};
|
|
24
|
+
static flags = {
|
|
25
|
+
base: Flags.string({
|
|
26
|
+
char: 'b',
|
|
27
|
+
description: 'Base branch for the PR (defaults to main/master)',
|
|
28
|
+
}),
|
|
29
|
+
draft: Flags.boolean({
|
|
30
|
+
char: 'd',
|
|
31
|
+
description: 'Create as draft PR',
|
|
32
|
+
default: false,
|
|
33
|
+
}),
|
|
34
|
+
'no-link': Flags.boolean({
|
|
35
|
+
description: 'Skip linking PR to ticket',
|
|
36
|
+
default: false,
|
|
37
|
+
}),
|
|
38
|
+
title: Flags.string({
|
|
39
|
+
char: 't',
|
|
40
|
+
description: 'PR title (auto-generated from ticket if not provided)',
|
|
41
|
+
}),
|
|
42
|
+
body: Flags.string({
|
|
43
|
+
description: 'PR body/description',
|
|
44
|
+
}),
|
|
45
|
+
json: Flags.boolean({
|
|
46
|
+
description: 'Output prompt configuration as JSON (for AI agents/scripts)',
|
|
47
|
+
default: false,
|
|
48
|
+
}),
|
|
49
|
+
};
|
|
50
|
+
async run() {
|
|
51
|
+
const { args, flags } = await this.parse(PRCreate);
|
|
52
|
+
// Check if JSON output mode is active
|
|
53
|
+
const jsonMode = shouldOutputJson(flags);
|
|
54
|
+
// Helper to handle errors in JSON mode
|
|
55
|
+
const handleError = (code, message) => {
|
|
56
|
+
if (jsonMode) {
|
|
57
|
+
outputErrorAsJson(code, message, createMetadata('pr create', flags));
|
|
58
|
+
this.exit(1);
|
|
59
|
+
}
|
|
60
|
+
this.error(message);
|
|
61
|
+
};
|
|
62
|
+
// Check gh CLI
|
|
63
|
+
if (!isGHInstalled()) {
|
|
64
|
+
return handleError('GH_NOT_INSTALLED', 'GitHub CLI (gh) is not installed. Install it from https://cli.github.com/');
|
|
65
|
+
}
|
|
66
|
+
if (!isGHAuthenticated()) {
|
|
67
|
+
return handleError('GH_NOT_AUTHENTICATED', 'GitHub CLI is not authenticated. Run "gh auth login" first.');
|
|
68
|
+
}
|
|
69
|
+
// Get current branch
|
|
70
|
+
const currentBranch = getCurrentBranch();
|
|
71
|
+
if (!currentBranch) {
|
|
72
|
+
return handleError('NO_GIT_REPO', 'Not in a git repository or unable to determine current branch.');
|
|
73
|
+
}
|
|
74
|
+
// Check if on main/master
|
|
75
|
+
const baseBranch = flags.base || getDefaultBaseBranch();
|
|
76
|
+
if (currentBranch === baseBranch) {
|
|
77
|
+
return handleError('ON_BASE_BRANCH', `Cannot create PR from ${baseBranch} branch. Switch to a feature branch first.`);
|
|
78
|
+
}
|
|
79
|
+
// Check if PR already exists for this branch
|
|
80
|
+
const existingPR = getPRForBranch(currentBranch);
|
|
81
|
+
if (existingPR) {
|
|
82
|
+
this.log(styles.info(`PR already exists for branch "${currentBranch}":`));
|
|
83
|
+
this.log(styles.muted(` #${existingPR.number}: ${existingPR.title}`));
|
|
84
|
+
this.log(styles.muted(` URL: ${existingPR.url}`));
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
// Get workspace and PMO context (optional - PR creation works without it)
|
|
88
|
+
let workspaceInfo;
|
|
89
|
+
let storage = null;
|
|
90
|
+
let db = null;
|
|
91
|
+
try {
|
|
92
|
+
workspaceInfo = getWorkspaceInfo();
|
|
93
|
+
const pmoContext = await getPMOContext({
|
|
94
|
+
logger: (msg) => this.log(styles.muted(msg)),
|
|
95
|
+
});
|
|
96
|
+
storage = pmoContext.storage;
|
|
97
|
+
db = new Database(path.join(workspaceInfo.path, '.proletariat', 'workspace.db'));
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
// No workspace - that's fine, we can still create PRs
|
|
101
|
+
this.log(styles.muted(' No workspace found - creating PR without ticket linking'));
|
|
102
|
+
}
|
|
103
|
+
try {
|
|
104
|
+
// Determine ticket ID
|
|
105
|
+
let ticketId = args.ticketId;
|
|
106
|
+
if (!ticketId && !flags['no-link'] && storage) {
|
|
107
|
+
// Try to extract ticket ID from branch name (e.g., feat/agent/TKT-001-description)
|
|
108
|
+
const ticketMatch = currentBranch.match(/(TKT-\d+)/i);
|
|
109
|
+
if (ticketMatch) {
|
|
110
|
+
ticketId = ticketMatch[1].toUpperCase();
|
|
111
|
+
this.log(styles.muted(` Auto-detected ticket: ${ticketId}`));
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
// Get ticket info if available
|
|
115
|
+
let ticket = null;
|
|
116
|
+
if (ticketId && storage) {
|
|
117
|
+
ticket = await storage.getTicket(ticketId);
|
|
118
|
+
if (!ticket) {
|
|
119
|
+
this.warn(`Ticket "${ticketId}" not found. Continuing without ticket link.`);
|
|
120
|
+
ticketId = undefined;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
// If no ticket, prompt for selection (only if we have storage)
|
|
124
|
+
if (!ticketId && !flags['no-link'] && storage) {
|
|
125
|
+
const projectId = flags.project;
|
|
126
|
+
const allTickets = await storage.listTickets(projectId);
|
|
127
|
+
const inProgressTickets = allTickets.filter(t => t.statusName && t.statusName.toLowerCase().includes('progress'));
|
|
128
|
+
if (inProgressTickets.length > 0) {
|
|
129
|
+
// Build choices once, use for both JSON and interactive modes
|
|
130
|
+
const ticketChoices = [
|
|
131
|
+
...inProgressTickets.map(t => ({
|
|
132
|
+
name: `${t.id} - ${t.title}`,
|
|
133
|
+
value: t.id,
|
|
134
|
+
})),
|
|
135
|
+
{ name: 'Skip - create PR without linking', value: '__skip__' },
|
|
136
|
+
];
|
|
137
|
+
const message = 'Link PR to a ticket?';
|
|
138
|
+
// In JSON mode, output ticket selection prompt and exit
|
|
139
|
+
if (jsonMode) {
|
|
140
|
+
outputPromptAsJson(buildPromptConfig('list', 'ticketId', message, ticketChoices), createMetadata('pr create', flags));
|
|
141
|
+
}
|
|
142
|
+
const { selectedTicketId } = await inquirer.prompt([
|
|
143
|
+
{
|
|
144
|
+
type: 'list',
|
|
145
|
+
name: 'selectedTicketId',
|
|
146
|
+
message,
|
|
147
|
+
choices: [
|
|
148
|
+
...ticketChoices.slice(0, -1),
|
|
149
|
+
new inquirer.Separator(),
|
|
150
|
+
ticketChoices[ticketChoices.length - 1],
|
|
151
|
+
],
|
|
152
|
+
},
|
|
153
|
+
]);
|
|
154
|
+
if (selectedTicketId !== '__skip__') {
|
|
155
|
+
ticketId = selectedTicketId;
|
|
156
|
+
ticket = await storage.getTicket(ticketId);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
// Generate PR title and body
|
|
161
|
+
let prTitle = flags.title;
|
|
162
|
+
let prBody = flags.body;
|
|
163
|
+
if (!prTitle) {
|
|
164
|
+
if (ticket) {
|
|
165
|
+
prTitle = generatePRTitle(ticket.id, ticket.title);
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
// Use branch name as title
|
|
169
|
+
const branchParts = currentBranch.split('/');
|
|
170
|
+
prTitle = branchParts[branchParts.length - 1].replace(/-/g, ' ');
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
if (!prBody && ticket) {
|
|
174
|
+
const commits = getCommitLog(baseBranch);
|
|
175
|
+
prBody = generatePRBody({
|
|
176
|
+
ticketId: ticket.id,
|
|
177
|
+
ticketTitle: ticket.title,
|
|
178
|
+
ticketDescription: ticket.description,
|
|
179
|
+
commits: commits.slice(0, 10), // Limit to 10 commits
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
// Push branch if not pushed
|
|
183
|
+
if (!hasBranchBeenPushed(currentBranch)) {
|
|
184
|
+
this.log(styles.muted(` Pushing branch to origin...`));
|
|
185
|
+
if (!pushBranch(currentBranch)) {
|
|
186
|
+
this.error('Failed to push branch to origin.');
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
else if (hasUnpushedCommits(currentBranch)) {
|
|
190
|
+
this.log(styles.muted(` Pushing unpushed commits...`));
|
|
191
|
+
if (!pushBranch(currentBranch)) {
|
|
192
|
+
this.error('Failed to push commits to origin.');
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
// Create PR
|
|
196
|
+
this.log('');
|
|
197
|
+
this.log(styles.header('Creating Pull Request'));
|
|
198
|
+
this.log(styles.muted(` Branch: ${currentBranch}`));
|
|
199
|
+
this.log(styles.muted(` Base: ${baseBranch}`));
|
|
200
|
+
this.log(styles.muted(` Title: ${prTitle}`));
|
|
201
|
+
if (flags.draft) {
|
|
202
|
+
this.log(styles.muted(` Draft: yes`));
|
|
203
|
+
}
|
|
204
|
+
const result = createPR({
|
|
205
|
+
title: prTitle,
|
|
206
|
+
body: prBody,
|
|
207
|
+
base: baseBranch,
|
|
208
|
+
draft: flags.draft,
|
|
209
|
+
});
|
|
210
|
+
if (!result.success) {
|
|
211
|
+
this.error(`Failed to create PR: ${result.error}`);
|
|
212
|
+
}
|
|
213
|
+
// Store PR URL in ticket metadata
|
|
214
|
+
if (ticket && result.url && storage) {
|
|
215
|
+
await storage.updateTicket(ticket.id, {
|
|
216
|
+
metadata: {
|
|
217
|
+
pr_url: result.url,
|
|
218
|
+
pr_number: String(result.number),
|
|
219
|
+
},
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
if (storage)
|
|
223
|
+
await storage.close();
|
|
224
|
+
if (db)
|
|
225
|
+
db.close();
|
|
226
|
+
this.log('');
|
|
227
|
+
this.log(styles.success(`Pull request created!`));
|
|
228
|
+
this.log(styles.muted(` PR #${result.number}`));
|
|
229
|
+
this.log(styles.muted(` URL: ${result.url}`));
|
|
230
|
+
if (ticket) {
|
|
231
|
+
this.log(styles.muted(` Linked to: ${ticket.id}`));
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
catch (error) {
|
|
235
|
+
if (storage)
|
|
236
|
+
await storage.close();
|
|
237
|
+
if (db)
|
|
238
|
+
db.close();
|
|
239
|
+
throw error;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { Command, Flags } from '@oclif/core';
|
|
2
|
+
import inquirer from 'inquirer';
|
|
3
|
+
import { findPMO } from '../../lib/pmo/index.js';
|
|
4
|
+
import { shouldOutputJson, outputPromptAsJson, outputErrorAsJson, createMetadata, buildPromptConfig, } from '../../lib/prompt-json.js';
|
|
5
|
+
export default class PR extends Command {
|
|
6
|
+
static description = 'Interactive menu for pull request operations';
|
|
7
|
+
static examples = [
|
|
8
|
+
'<%= config.bin %> <%= command.id %>',
|
|
9
|
+
];
|
|
10
|
+
static flags = {
|
|
11
|
+
json: Flags.boolean({
|
|
12
|
+
description: 'Output prompt configuration as JSON (for AI agents/scripts)',
|
|
13
|
+
default: false,
|
|
14
|
+
}),
|
|
15
|
+
};
|
|
16
|
+
async run() {
|
|
17
|
+
const { flags } = await this.parse(PR);
|
|
18
|
+
// Check if JSON output mode is active
|
|
19
|
+
const jsonMode = shouldOutputJson(flags);
|
|
20
|
+
const pmoPath = findPMO();
|
|
21
|
+
if (!pmoPath) {
|
|
22
|
+
if (jsonMode) {
|
|
23
|
+
outputErrorAsJson('PMO_NOT_FOUND', 'PMO not found. Run "prlt pmo init" first.', createMetadata('pr', flags));
|
|
24
|
+
this.exit(1);
|
|
25
|
+
}
|
|
26
|
+
this.error('PMO not found. Run "prlt pmo init" first.');
|
|
27
|
+
}
|
|
28
|
+
// Define choices once, use for both JSON and interactive modes
|
|
29
|
+
const menuChoices = [
|
|
30
|
+
{ name: 'Create PR from current branch', value: 'create' },
|
|
31
|
+
{ name: 'Link existing PR to ticket', value: 'link' },
|
|
32
|
+
{ name: 'View PR status for ticket', value: 'status' },
|
|
33
|
+
{ name: 'Cancel', value: 'cancel' },
|
|
34
|
+
];
|
|
35
|
+
const message = 'Pull Request Operations - What would you like to do?';
|
|
36
|
+
// In JSON mode, output menu prompt
|
|
37
|
+
if (jsonMode) {
|
|
38
|
+
outputPromptAsJson(buildPromptConfig('list', 'action', message, menuChoices), createMetadata('pr', flags));
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
// Show interactive menu (with separator before Cancel)
|
|
42
|
+
const { action } = await inquirer.prompt([{
|
|
43
|
+
type: 'list',
|
|
44
|
+
name: 'action',
|
|
45
|
+
message,
|
|
46
|
+
choices: [
|
|
47
|
+
...menuChoices.slice(0, -1),
|
|
48
|
+
new inquirer.Separator('──────────────'),
|
|
49
|
+
menuChoices[menuChoices.length - 1],
|
|
50
|
+
],
|
|
51
|
+
}]);
|
|
52
|
+
if (action === 'cancel') {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
// Run the selected subcommand
|
|
56
|
+
switch (action) {
|
|
57
|
+
case 'create':
|
|
58
|
+
await this.config.runCommand('pr:create', []);
|
|
59
|
+
break;
|
|
60
|
+
case 'link':
|
|
61
|
+
await this.config.runCommand('pr:link', []);
|
|
62
|
+
break;
|
|
63
|
+
case 'status':
|
|
64
|
+
await this.config.runCommand('pr:status', []);
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|