@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,319 @@
|
|
|
1
|
+
import { Command, Flags } from '@oclif/core';
|
|
2
|
+
import inquirer from 'inquirer';
|
|
3
|
+
import { getPMOContext } from './pmo-context.js';
|
|
4
|
+
import { styles } from '../styles.js';
|
|
5
|
+
import { shouldOutputJson, outputPromptAsJson, createMetadata, } from '../prompt-json.js';
|
|
6
|
+
/**
|
|
7
|
+
* Base flags shared by all PMO commands
|
|
8
|
+
* Include these in your command's flags by spreading: ...PMOCommand.baseFlags
|
|
9
|
+
*/
|
|
10
|
+
export const pmoBaseFlags = {
|
|
11
|
+
project: Flags.string({
|
|
12
|
+
char: 'P',
|
|
13
|
+
description: 'Project ID (uses first project if only one exists)',
|
|
14
|
+
}),
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Base command class for PMO commands
|
|
18
|
+
*
|
|
19
|
+
* Provides automatic PMO context initialization and cleanup:
|
|
20
|
+
* - Initializes storage before run() executes
|
|
21
|
+
* - Ensures storage.close() is called even if errors occur
|
|
22
|
+
* - Provides common PMO flags (--project)
|
|
23
|
+
*
|
|
24
|
+
* Storage is project-agnostic - projectId is passed explicitly to operations.
|
|
25
|
+
*
|
|
26
|
+
* Usage:
|
|
27
|
+
* ```typescript
|
|
28
|
+
* import { PMOCommand, pmoBaseFlags } from '../../lib/pmo/base-command.js';
|
|
29
|
+
*
|
|
30
|
+
* export default class MyCommand extends PMOCommand {
|
|
31
|
+
* static flags = {
|
|
32
|
+
* ...pmoBaseFlags,
|
|
33
|
+
* // additional flags...
|
|
34
|
+
* };
|
|
35
|
+
*
|
|
36
|
+
* async execute(): Promise<void> {
|
|
37
|
+
* // For project-agnostic operations (e.g., get ticket by ID):
|
|
38
|
+
* const ticket = await this.storage.getTicketById('TKT-123');
|
|
39
|
+
*
|
|
40
|
+
* // For project-scoped operations, get projectId first:
|
|
41
|
+
* const projectId = await this.requireProject();
|
|
42
|
+
* const board = await this.storage.getBoard(projectId);
|
|
43
|
+
*
|
|
44
|
+
* // Or derive from an entity:
|
|
45
|
+
* const projectId = ticket.projectId;
|
|
46
|
+
* await this.storage.moveTicket(projectId, ticket.id, 'Done');
|
|
47
|
+
* }
|
|
48
|
+
* }
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
export class PMOCommand extends Command {
|
|
52
|
+
/**
|
|
53
|
+
* PMO context with storage, pmoPath, etc.
|
|
54
|
+
* Available after init() runs (before execute())
|
|
55
|
+
*/
|
|
56
|
+
pmoContext;
|
|
57
|
+
/**
|
|
58
|
+
* Flag to track if context was successfully initialized
|
|
59
|
+
*/
|
|
60
|
+
contextInitialized = false;
|
|
61
|
+
/**
|
|
62
|
+
* Cached project ID from -P flag
|
|
63
|
+
*/
|
|
64
|
+
projectFlag;
|
|
65
|
+
/**
|
|
66
|
+
* Logger function for PMO context
|
|
67
|
+
* Can be overridden to customize logging behavior
|
|
68
|
+
*/
|
|
69
|
+
pmoLogger(msg) {
|
|
70
|
+
this.log(styles.muted(msg));
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* oclif init hook - runs before the command executes
|
|
74
|
+
* Initializes PMO context with storage access
|
|
75
|
+
*/
|
|
76
|
+
async init() {
|
|
77
|
+
await super.init();
|
|
78
|
+
// Parse flags to get project ID if provided
|
|
79
|
+
const { flags } = await this.parse(this.constructor);
|
|
80
|
+
this.projectFlag = flags.project;
|
|
81
|
+
try {
|
|
82
|
+
this.pmoContext = await getPMOContext({
|
|
83
|
+
logger: (msg) => this.pmoLogger(msg),
|
|
84
|
+
});
|
|
85
|
+
this.contextInitialized = true;
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
throw error;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Require a project to be selected.
|
|
93
|
+
* Returns projectId that should be passed to storage operations.
|
|
94
|
+
*
|
|
95
|
+
* Priority:
|
|
96
|
+
* 1. If -P flag was provided, uses that
|
|
97
|
+
* 2. If only one project exists, uses that
|
|
98
|
+
* 3. If multiple projects exist, prompts user to select one (or outputs JSON if jsonMode)
|
|
99
|
+
*
|
|
100
|
+
* @param options.filterEmptyProjects - Only show projects with tickets
|
|
101
|
+
* @param options.jsonMode - JSON mode configuration for AI agents
|
|
102
|
+
* @returns The selected project ID - pass this to storage operations
|
|
103
|
+
*/
|
|
104
|
+
async requireProject(options) {
|
|
105
|
+
// If -P flag was provided, use it
|
|
106
|
+
if (this.projectFlag) {
|
|
107
|
+
return this.projectFlag;
|
|
108
|
+
}
|
|
109
|
+
// Get all projects
|
|
110
|
+
const projects = await this.storage.listProjects();
|
|
111
|
+
if (projects.length === 0) {
|
|
112
|
+
throw new Error('No projects found. Run "prlt pmo init" first.');
|
|
113
|
+
}
|
|
114
|
+
// Filter to projects with tickets if requested
|
|
115
|
+
let filteredProjects = projects;
|
|
116
|
+
if (options?.filterEmptyProjects) {
|
|
117
|
+
const projectsWithTickets = [];
|
|
118
|
+
for (const p of projects) {
|
|
119
|
+
const tickets = await this.storage.listTickets(p.id);
|
|
120
|
+
if (tickets.length > 0) {
|
|
121
|
+
projectsWithTickets.push(p);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
filteredProjects = projectsWithTickets;
|
|
125
|
+
if (filteredProjects.length === 0) {
|
|
126
|
+
throw new Error('No projects with tickets found. Create a ticket first.');
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
// If only one project, use it
|
|
130
|
+
if (filteredProjects.length === 1) {
|
|
131
|
+
return filteredProjects[0].id;
|
|
132
|
+
}
|
|
133
|
+
// Multiple projects - check for JSON mode
|
|
134
|
+
// Sort projects by leading number in name (e.g., "1. MVP" before "10. Infra")
|
|
135
|
+
const sortedProjects = [...filteredProjects].sort((a, b) => {
|
|
136
|
+
const numA = parseInt(a.name.match(/^(\d+)/)?.[1] || '999', 10);
|
|
137
|
+
const numB = parseInt(b.name.match(/^(\d+)/)?.[1] || '999', 10);
|
|
138
|
+
return numA - numB;
|
|
139
|
+
});
|
|
140
|
+
// If JSON mode is active, output project choices as JSON
|
|
141
|
+
if (options?.jsonMode && shouldOutputJson(options.jsonMode.flags)) {
|
|
142
|
+
const choices = sortedProjects.map(p => ({
|
|
143
|
+
name: `${p.name} (${p.id})`,
|
|
144
|
+
value: p.id,
|
|
145
|
+
command: `${options.jsonMode.baseCommand} -P ${p.id} --json`,
|
|
146
|
+
}));
|
|
147
|
+
outputPromptAsJson({
|
|
148
|
+
type: 'list',
|
|
149
|
+
name: 'project',
|
|
150
|
+
message: 'Select project:',
|
|
151
|
+
choices,
|
|
152
|
+
}, createMetadata(options.jsonMode.commandName, options.jsonMode.flags));
|
|
153
|
+
// outputPromptAsJson calls process.exit, so this is unreachable
|
|
154
|
+
return '';
|
|
155
|
+
}
|
|
156
|
+
// Interactive mode - prompt for selection
|
|
157
|
+
const { selectedProjectId } = await inquirer.prompt([{
|
|
158
|
+
type: 'list',
|
|
159
|
+
name: 'selectedProjectId',
|
|
160
|
+
message: 'Select project:',
|
|
161
|
+
choices: sortedProjects.map(p => ({
|
|
162
|
+
name: `${p.name} (${p.id})`,
|
|
163
|
+
value: p.id,
|
|
164
|
+
})),
|
|
165
|
+
}]);
|
|
166
|
+
return selectedProjectId;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Get project name by ID
|
|
170
|
+
*/
|
|
171
|
+
async getProjectName(projectId) {
|
|
172
|
+
const project = await this.storage.getProject(projectId);
|
|
173
|
+
return project?.name || projectId;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Select from a list of items with JSON mode support for AI agents.
|
|
177
|
+
*
|
|
178
|
+
* In JSON mode: outputs choices as JSON with command field and exits
|
|
179
|
+
* In interactive mode: shows prompt and returns selected value
|
|
180
|
+
*
|
|
181
|
+
* @param options Configuration for the selection
|
|
182
|
+
* @returns The selected value (only in interactive mode)
|
|
183
|
+
*
|
|
184
|
+
* @example
|
|
185
|
+
* ```typescript
|
|
186
|
+
* const ticketId = await this.selectFromList({
|
|
187
|
+
* message: 'Select ticket:',
|
|
188
|
+
* items: tickets,
|
|
189
|
+
* getName: (t) => `${t.id}: ${t.title}`,
|
|
190
|
+
* getValue: (t) => t.id,
|
|
191
|
+
* getCommand: (t) => `prlt ticket view ${t.id} --json`,
|
|
192
|
+
* jsonMode: { flags, commandName: 'ticket view' },
|
|
193
|
+
* });
|
|
194
|
+
* ```
|
|
195
|
+
*/
|
|
196
|
+
async selectFromList(options) {
|
|
197
|
+
const { message, items, getName, getValue, getCommand, jsonMode, allowCancel = false, cancelValue, } = options;
|
|
198
|
+
// Build choices with command field
|
|
199
|
+
const choices = items.map(item => ({
|
|
200
|
+
name: getName(item),
|
|
201
|
+
value: getValue(item),
|
|
202
|
+
command: getCommand(item),
|
|
203
|
+
}));
|
|
204
|
+
// Check for JSON mode
|
|
205
|
+
if (jsonMode && shouldOutputJson(jsonMode.flags)) {
|
|
206
|
+
outputPromptAsJson({
|
|
207
|
+
type: 'list',
|
|
208
|
+
name: 'selection',
|
|
209
|
+
message,
|
|
210
|
+
choices,
|
|
211
|
+
}, createMetadata(jsonMode.commandName, jsonMode.flags));
|
|
212
|
+
// outputPromptAsJson exits, so this is unreachable
|
|
213
|
+
return null;
|
|
214
|
+
}
|
|
215
|
+
// Interactive mode
|
|
216
|
+
const interactiveChoices = choices.map(c => ({
|
|
217
|
+
name: c.name,
|
|
218
|
+
value: c.value,
|
|
219
|
+
}));
|
|
220
|
+
if (allowCancel) {
|
|
221
|
+
interactiveChoices.push({ name: '─'.repeat(20), value: '__separator__' }, { name: 'Cancel', value: cancelValue ?? '__cancel__' });
|
|
222
|
+
}
|
|
223
|
+
const { selection } = await inquirer.prompt([{
|
|
224
|
+
type: 'list',
|
|
225
|
+
name: 'selection',
|
|
226
|
+
message,
|
|
227
|
+
choices: interactiveChoices,
|
|
228
|
+
}]);
|
|
229
|
+
if (selection === '__cancel__' || selection === '__separator__') {
|
|
230
|
+
return null;
|
|
231
|
+
}
|
|
232
|
+
return selection;
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Prompt for input with JSON mode support for AI agents.
|
|
236
|
+
*
|
|
237
|
+
* In JSON mode: outputs field info as JSON and exits
|
|
238
|
+
* In interactive mode: shows prompt and returns input value
|
|
239
|
+
*
|
|
240
|
+
* @param options Configuration for the input
|
|
241
|
+
* @returns The input value (only in interactive mode)
|
|
242
|
+
*/
|
|
243
|
+
async promptForInput(options) {
|
|
244
|
+
const { message, fieldName, defaultValue, validate, jsonMode } = options;
|
|
245
|
+
// Check for JSON mode
|
|
246
|
+
if (jsonMode && shouldOutputJson(jsonMode.flags)) {
|
|
247
|
+
outputPromptAsJson({
|
|
248
|
+
type: 'input',
|
|
249
|
+
name: fieldName,
|
|
250
|
+
message,
|
|
251
|
+
default: defaultValue,
|
|
252
|
+
context: {
|
|
253
|
+
hint: jsonMode.commandHint,
|
|
254
|
+
example: jsonMode.example,
|
|
255
|
+
},
|
|
256
|
+
}, createMetadata(jsonMode.commandName, jsonMode.flags));
|
|
257
|
+
// outputPromptAsJson exits, so this is unreachable
|
|
258
|
+
return '';
|
|
259
|
+
}
|
|
260
|
+
// Interactive mode
|
|
261
|
+
const { value } = await inquirer.prompt([{
|
|
262
|
+
type: 'input',
|
|
263
|
+
name: 'value',
|
|
264
|
+
message,
|
|
265
|
+
default: defaultValue,
|
|
266
|
+
validate,
|
|
267
|
+
}]);
|
|
268
|
+
return value;
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Override run() to delegate to execute() and ensure cleanup
|
|
272
|
+
* Subclasses should implement execute() instead of run()
|
|
273
|
+
*/
|
|
274
|
+
async run() {
|
|
275
|
+
try {
|
|
276
|
+
await this.execute();
|
|
277
|
+
}
|
|
278
|
+
finally {
|
|
279
|
+
await this.cleanup();
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Cleanup handler - ensures storage is closed
|
|
284
|
+
* Called automatically after execute() completes or throws
|
|
285
|
+
*/
|
|
286
|
+
async cleanup() {
|
|
287
|
+
if (this.contextInitialized && this.pmoContext?.storage) {
|
|
288
|
+
try {
|
|
289
|
+
await this.pmoContext.storage.close();
|
|
290
|
+
}
|
|
291
|
+
catch {
|
|
292
|
+
// Ignore close errors - storage might already be closed
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* oclif catch hook - called when an error occurs
|
|
298
|
+
* Ensures cleanup even on errors
|
|
299
|
+
*/
|
|
300
|
+
async catch(error) {
|
|
301
|
+
await this.cleanup();
|
|
302
|
+
throw error;
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* oclif finally hook - called after run() completes
|
|
306
|
+
*/
|
|
307
|
+
async finally(_) {
|
|
308
|
+
await this.cleanup();
|
|
309
|
+
}
|
|
310
|
+
// Convenience getters for common context properties
|
|
311
|
+
/** Storage instance */
|
|
312
|
+
get storage() {
|
|
313
|
+
return this.pmoContext.storage;
|
|
314
|
+
}
|
|
315
|
+
/** PMO directory path */
|
|
316
|
+
get pmoPath() {
|
|
317
|
+
return this.pmoContext.pmoPath;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Create PMO folder structure
|
|
3
|
+
*
|
|
4
|
+
* Two distinct areas:
|
|
5
|
+
* 1. product/ - Living product definitions (specs, requirements, architecture)
|
|
6
|
+
* These don't move - they get updated in place as the product evolves.
|
|
7
|
+
*
|
|
8
|
+
* 2. projects/{id}/ - Implementation work that flows through lifecycle
|
|
9
|
+
* - epics/ with draft/active/complete stages
|
|
10
|
+
* - board.md for tracking tickets
|
|
11
|
+
*
|
|
12
|
+
* @param pmoPath - Path to PMO directory
|
|
13
|
+
* @param projectId - Project ID
|
|
14
|
+
* @returns Path to created project directory
|
|
15
|
+
*/
|
|
16
|
+
export declare function createSpecFolders(pmoPath: string, projectId: string): string;
|
|
17
|
+
/**
|
|
18
|
+
* Get product folder path (for specs/requirements - PMO-wide)
|
|
19
|
+
*
|
|
20
|
+
* @param pmoPath - Path to PMO directory
|
|
21
|
+
* @returns Path to product directory
|
|
22
|
+
*/
|
|
23
|
+
export declare function getProductPath(pmoPath: string): string;
|
|
24
|
+
/**
|
|
25
|
+
* Get epics folder path for a project
|
|
26
|
+
*
|
|
27
|
+
* @param pmoPath - Path to PMO directory
|
|
28
|
+
* @param projectId - Project ID
|
|
29
|
+
* @returns Path to epics directory
|
|
30
|
+
*/
|
|
31
|
+
export declare function getEpicsPath(pmoPath: string, projectId: string): string;
|
|
32
|
+
/**
|
|
33
|
+
* @deprecated Use getProductPath() for specs, getEpicsPath() for implementation work
|
|
34
|
+
*/
|
|
35
|
+
export declare function getSpecFolderPath(pmoPath: string, projectId: string): string;
|
|
36
|
+
/**
|
|
37
|
+
* Get project folder path
|
|
38
|
+
*
|
|
39
|
+
* @param pmoPath - Path to PMO directory
|
|
40
|
+
* @param projectId - Project ID
|
|
41
|
+
* @returns Path to project directory
|
|
42
|
+
*/
|
|
43
|
+
export declare function getProjectPath(pmoPath: string, projectId: string): string;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import * as fs from 'node:fs';
|
|
2
|
+
import * as path from 'node:path';
|
|
3
|
+
/**
|
|
4
|
+
* Create PMO folder structure
|
|
5
|
+
*
|
|
6
|
+
* Two distinct areas:
|
|
7
|
+
* 1. product/ - Living product definitions (specs, requirements, architecture)
|
|
8
|
+
* These don't move - they get updated in place as the product evolves.
|
|
9
|
+
*
|
|
10
|
+
* 2. projects/{id}/ - Implementation work that flows through lifecycle
|
|
11
|
+
* - epics/ with draft/active/complete stages
|
|
12
|
+
* - board.md for tracking tickets
|
|
13
|
+
*
|
|
14
|
+
* @param pmoPath - Path to PMO directory
|
|
15
|
+
* @param projectId - Project ID
|
|
16
|
+
* @returns Path to created project directory
|
|
17
|
+
*/
|
|
18
|
+
export function createSpecFolders(pmoPath, projectId) {
|
|
19
|
+
// Create product folder for specs/requirements (PMO-wide, not per-project)
|
|
20
|
+
const productPath = path.join(pmoPath, 'product');
|
|
21
|
+
fs.mkdirSync(productPath, { recursive: true });
|
|
22
|
+
// Create project folder with epics lifecycle
|
|
23
|
+
const projectPath = path.join(pmoPath, 'projects', projectId);
|
|
24
|
+
const epicsPath = path.join(projectPath, 'epics');
|
|
25
|
+
fs.mkdirSync(path.join(epicsPath, 'draft'), { recursive: true });
|
|
26
|
+
fs.mkdirSync(path.join(epicsPath, 'active'), { recursive: true });
|
|
27
|
+
fs.mkdirSync(path.join(epicsPath, 'complete'), { recursive: true });
|
|
28
|
+
return projectPath;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Get product folder path (for specs/requirements - PMO-wide)
|
|
32
|
+
*
|
|
33
|
+
* @param pmoPath - Path to PMO directory
|
|
34
|
+
* @returns Path to product directory
|
|
35
|
+
*/
|
|
36
|
+
export function getProductPath(pmoPath) {
|
|
37
|
+
return path.join(pmoPath, 'product');
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Get epics folder path for a project
|
|
41
|
+
*
|
|
42
|
+
* @param pmoPath - Path to PMO directory
|
|
43
|
+
* @param projectId - Project ID
|
|
44
|
+
* @returns Path to epics directory
|
|
45
|
+
*/
|
|
46
|
+
export function getEpicsPath(pmoPath, projectId) {
|
|
47
|
+
return path.join(pmoPath, 'projects', projectId, 'epics');
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* @deprecated Use getProductPath() for specs, getEpicsPath() for implementation work
|
|
51
|
+
*/
|
|
52
|
+
export function getSpecFolderPath(pmoPath, projectId) {
|
|
53
|
+
return path.join(pmoPath, 'projects', projectId, 'epics');
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Get project folder path
|
|
57
|
+
*
|
|
58
|
+
* @param pmoPath - Path to PMO directory
|
|
59
|
+
* @param projectId - Project ID
|
|
60
|
+
* @returns Path to project directory
|
|
61
|
+
*/
|
|
62
|
+
export function getProjectPath(pmoPath, projectId) {
|
|
63
|
+
return path.join(pmoPath, 'projects', projectId);
|
|
64
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Epic File Operations
|
|
3
|
+
*
|
|
4
|
+
* Handles creating, moving, and managing epic markdown files
|
|
5
|
+
* in the PMO folder structure.
|
|
6
|
+
*/
|
|
7
|
+
import { Epic, EpicStatus } from './types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Get the epics directory for a project
|
|
10
|
+
*/
|
|
11
|
+
export declare function getEpicsDir(pmoPath: string, projectId?: string): string;
|
|
12
|
+
/**
|
|
13
|
+
* Get the path to an epic's markdown file
|
|
14
|
+
*/
|
|
15
|
+
export declare function getEpicFilePath(pmoPath: string, epicId: string, status: EpicStatus, projectId?: string): string;
|
|
16
|
+
/**
|
|
17
|
+
* Ensure epic status directories exist
|
|
18
|
+
*/
|
|
19
|
+
export declare function ensureEpicDirs(pmoPath: string, projectId?: string): void;
|
|
20
|
+
/**
|
|
21
|
+
* Ticket info for markdown generation
|
|
22
|
+
*/
|
|
23
|
+
export interface TicketInfo {
|
|
24
|
+
id: string;
|
|
25
|
+
title: string;
|
|
26
|
+
status?: string;
|
|
27
|
+
priority?: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Generate markdown content for an epic
|
|
31
|
+
*/
|
|
32
|
+
export declare function generateEpicMarkdown(epic: Epic, tickets?: TicketInfo[]): string;
|
|
33
|
+
/**
|
|
34
|
+
* Update the Tickets section of an existing epic markdown file
|
|
35
|
+
* This is a one-way sync: database → markdown
|
|
36
|
+
*/
|
|
37
|
+
export declare function updateEpicTicketsSection(pmoPath: string, epicId: string, status: EpicStatus, tickets: TicketInfo[], projectId?: string): boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Create an epic markdown file
|
|
40
|
+
*/
|
|
41
|
+
export declare function createEpicFile(pmoPath: string, epic: Epic, projectId?: string): string;
|
|
42
|
+
/**
|
|
43
|
+
* Move an epic file to a new status directory
|
|
44
|
+
*/
|
|
45
|
+
export declare function moveEpicFile(pmoPath: string, epicId: string, fromStatus: EpicStatus, toStatus: EpicStatus, projectId?: string): {
|
|
46
|
+
oldPath: string;
|
|
47
|
+
newPath: string;
|
|
48
|
+
} | null;
|
|
49
|
+
/**
|
|
50
|
+
* Delete an epic file
|
|
51
|
+
*/
|
|
52
|
+
export declare function deleteEpicFile(pmoPath: string, epicId: string, status: EpicStatus, projectId?: string): boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Get relative path from PMO root for display
|
|
55
|
+
*/
|
|
56
|
+
export declare function getRelativeEpicPath(pmoPath: string, epicId: string, status: EpicStatus, projectId?: string): string;
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Epic File Operations
|
|
3
|
+
*
|
|
4
|
+
* Handles creating, moving, and managing epic markdown files
|
|
5
|
+
* in the PMO folder structure.
|
|
6
|
+
*/
|
|
7
|
+
import * as fs from 'node:fs';
|
|
8
|
+
import * as path from 'node:path';
|
|
9
|
+
/**
|
|
10
|
+
* Get the epics directory for a project
|
|
11
|
+
*/
|
|
12
|
+
export function getEpicsDir(pmoPath, projectId = 'default') {
|
|
13
|
+
// For default project, use pmo/epics directly
|
|
14
|
+
// For named projects, use pmo/projects/{projectId}/epics
|
|
15
|
+
if (projectId === 'default') {
|
|
16
|
+
return path.join(pmoPath, 'epics');
|
|
17
|
+
}
|
|
18
|
+
return path.join(pmoPath, 'projects', projectId, 'epics');
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Get the path to an epic's markdown file
|
|
22
|
+
*/
|
|
23
|
+
export function getEpicFilePath(pmoPath, epicId, status, projectId = 'default') {
|
|
24
|
+
const epicsDir = getEpicsDir(pmoPath, projectId);
|
|
25
|
+
return path.join(epicsDir, status, `${epicId}.md`);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Ensure epic status directories exist
|
|
29
|
+
*/
|
|
30
|
+
export function ensureEpicDirs(pmoPath, projectId = 'default') {
|
|
31
|
+
const epicsDir = getEpicsDir(pmoPath, projectId);
|
|
32
|
+
const statuses = ['active', 'draft', 'complete', 'dropped', 'future'];
|
|
33
|
+
for (const status of statuses) {
|
|
34
|
+
const statusDir = path.join(epicsDir, status);
|
|
35
|
+
if (!fs.existsSync(statusDir)) {
|
|
36
|
+
fs.mkdirSync(statusDir, { recursive: true });
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Generate markdown content for an epic
|
|
42
|
+
*/
|
|
43
|
+
export function generateEpicMarkdown(epic, tickets = []) {
|
|
44
|
+
const lines = [];
|
|
45
|
+
// YAML frontmatter
|
|
46
|
+
lines.push('---');
|
|
47
|
+
lines.push(`id: ${epic.id}`);
|
|
48
|
+
lines.push(`title: ${epic.title}`);
|
|
49
|
+
lines.push(`status: ${epic.status}`);
|
|
50
|
+
lines.push(`created: ${epic.createdAt.toISOString()}`);
|
|
51
|
+
if (epic.description) {
|
|
52
|
+
lines.push(`description: ${epic.description}`);
|
|
53
|
+
}
|
|
54
|
+
lines.push('---');
|
|
55
|
+
lines.push('');
|
|
56
|
+
// Title
|
|
57
|
+
lines.push(`# ${epic.title}`);
|
|
58
|
+
lines.push('');
|
|
59
|
+
// Overview section
|
|
60
|
+
lines.push('## Overview');
|
|
61
|
+
if (epic.description) {
|
|
62
|
+
lines.push(epic.description);
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
lines.push('[Describe what this epic covers]');
|
|
66
|
+
}
|
|
67
|
+
lines.push('');
|
|
68
|
+
// Motivation section
|
|
69
|
+
lines.push('## Motivation');
|
|
70
|
+
lines.push('[Why this work matters - the problem being solved or opportunity being captured]');
|
|
71
|
+
lines.push('');
|
|
72
|
+
// Goals section
|
|
73
|
+
lines.push('## Goals');
|
|
74
|
+
lines.push('- [ ] Goal 1');
|
|
75
|
+
lines.push('- [ ] Goal 2');
|
|
76
|
+
lines.push('');
|
|
77
|
+
// Success Criteria section
|
|
78
|
+
lines.push('## Success Criteria');
|
|
79
|
+
lines.push('- [ ] Criterion 1');
|
|
80
|
+
lines.push('');
|
|
81
|
+
// Tickets section
|
|
82
|
+
lines.push('## Tickets');
|
|
83
|
+
lines.push('');
|
|
84
|
+
if (tickets.length === 0) {
|
|
85
|
+
lines.push('_No tickets linked yet. Create tickets with:_');
|
|
86
|
+
lines.push('```bash');
|
|
87
|
+
lines.push(`prlt ticket create --epic ${epic.id} "Task title"`);
|
|
88
|
+
lines.push('```');
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
const doneCount = tickets.filter(t => t.status === 'done').length;
|
|
92
|
+
lines.push(`Progress: ${doneCount}/${tickets.length} complete`);
|
|
93
|
+
lines.push('');
|
|
94
|
+
for (const ticket of tickets) {
|
|
95
|
+
const emoji = ticket.status === 'done' ? '✅' : ticket.status === 'in_progress' ? '🚧' : '📋';
|
|
96
|
+
const priority = ticket.priority ? ` [${ticket.priority}]` : '';
|
|
97
|
+
lines.push(`- ${emoji} ${ticket.id}: ${ticket.title}${priority}`);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
lines.push('');
|
|
101
|
+
return lines.join('\n');
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Update the Tickets section of an existing epic markdown file
|
|
105
|
+
* This is a one-way sync: database → markdown
|
|
106
|
+
*/
|
|
107
|
+
export function updateEpicTicketsSection(pmoPath, epicId, status, tickets, projectId = 'default') {
|
|
108
|
+
const filePath = getEpicFilePath(pmoPath, epicId, status, projectId);
|
|
109
|
+
if (!fs.existsSync(filePath)) {
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
let content = fs.readFileSync(filePath, 'utf-8');
|
|
113
|
+
// Find and replace the Tickets section
|
|
114
|
+
const ticketsSectionRegex = /## Tickets\n[\s\S]*?(?=\n## |\n---|\z|$)/;
|
|
115
|
+
// Generate new tickets section
|
|
116
|
+
const ticketsLines = ['## Tickets', ''];
|
|
117
|
+
if (tickets.length === 0) {
|
|
118
|
+
ticketsLines.push('_No tickets linked yet. Create tickets with:_');
|
|
119
|
+
ticketsLines.push('```bash');
|
|
120
|
+
ticketsLines.push(`prlt ticket create --epic ${epicId} "Task title"`);
|
|
121
|
+
ticketsLines.push('```');
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
const doneCount = tickets.filter(t => t.status === 'done').length;
|
|
125
|
+
ticketsLines.push(`Progress: ${doneCount}/${tickets.length} complete`);
|
|
126
|
+
ticketsLines.push('');
|
|
127
|
+
for (const ticket of tickets) {
|
|
128
|
+
const emoji = ticket.status === 'done' ? '✅' : ticket.status === 'in_progress' ? '🚧' : '📋';
|
|
129
|
+
const priority = ticket.priority ? ` [${ticket.priority}]` : '';
|
|
130
|
+
ticketsLines.push(`- ${emoji} ${ticket.id}: ${ticket.title}${priority}`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
ticketsLines.push('');
|
|
134
|
+
const newTicketsSection = ticketsLines.join('\n');
|
|
135
|
+
if (ticketsSectionRegex.test(content)) {
|
|
136
|
+
// Replace existing section
|
|
137
|
+
content = content.replace(ticketsSectionRegex, newTicketsSection);
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
// Append section at end
|
|
141
|
+
content = content.trimEnd() + '\n\n' + newTicketsSection;
|
|
142
|
+
}
|
|
143
|
+
fs.writeFileSync(filePath, content, 'utf-8');
|
|
144
|
+
return true;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Create an epic markdown file
|
|
148
|
+
*/
|
|
149
|
+
export function createEpicFile(pmoPath, epic, projectId = 'default') {
|
|
150
|
+
ensureEpicDirs(pmoPath, projectId);
|
|
151
|
+
const filePath = getEpicFilePath(pmoPath, epic.id, epic.status, projectId);
|
|
152
|
+
const content = generateEpicMarkdown(epic);
|
|
153
|
+
fs.writeFileSync(filePath, content, 'utf-8');
|
|
154
|
+
return filePath;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Move an epic file to a new status directory
|
|
158
|
+
*/
|
|
159
|
+
export function moveEpicFile(pmoPath, epicId, fromStatus, toStatus, projectId = 'default') {
|
|
160
|
+
ensureEpicDirs(pmoPath, projectId);
|
|
161
|
+
const oldPath = getEpicFilePath(pmoPath, epicId, fromStatus, projectId);
|
|
162
|
+
const newPath = getEpicFilePath(pmoPath, epicId, toStatus, projectId);
|
|
163
|
+
if (!fs.existsSync(oldPath)) {
|
|
164
|
+
return null;
|
|
165
|
+
}
|
|
166
|
+
// Read the file content
|
|
167
|
+
let content = fs.readFileSync(oldPath, 'utf-8');
|
|
168
|
+
// Update the status in frontmatter
|
|
169
|
+
content = content.replace(/^status: .+$/m, `status: ${toStatus}`);
|
|
170
|
+
// Write to new location
|
|
171
|
+
fs.writeFileSync(newPath, content, 'utf-8');
|
|
172
|
+
// Delete old file
|
|
173
|
+
fs.unlinkSync(oldPath);
|
|
174
|
+
return { oldPath, newPath };
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Delete an epic file
|
|
178
|
+
*/
|
|
179
|
+
export function deleteEpicFile(pmoPath, epicId, status, projectId = 'default') {
|
|
180
|
+
const filePath = getEpicFilePath(pmoPath, epicId, status, projectId);
|
|
181
|
+
if (fs.existsSync(filePath)) {
|
|
182
|
+
fs.unlinkSync(filePath);
|
|
183
|
+
return true;
|
|
184
|
+
}
|
|
185
|
+
return false;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Get relative path from PMO root for display
|
|
189
|
+
*/
|
|
190
|
+
export function getRelativeEpicPath(pmoPath, epicId, status, projectId = 'default') {
|
|
191
|
+
const fullPath = getEpicFilePath(pmoPath, epicId, status, projectId);
|
|
192
|
+
// Get path relative to pmo directory's parent (the HQ root)
|
|
193
|
+
const hqRoot = path.dirname(pmoPath);
|
|
194
|
+
return path.relative(hqRoot, fullPath);
|
|
195
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Find PMO directory by checking workspace.db for pmo_projects table
|
|
3
|
+
*
|
|
4
|
+
* Search priority:
|
|
5
|
+
* 1. PRLT_HQ_PATH env var (ONLY when DEVCONTAINER=true - for devcontainer mounts)
|
|
6
|
+
* 2. Current directory tree for HQ with PMO
|
|
7
|
+
* 3. Current directory tree for standalone PMO (.pmo/)
|
|
8
|
+
* 4. ~/.proletariat/config.json activeWorkspace (fallback when NOT in any workspace)
|
|
9
|
+
* 5. Global config for default PMO
|
|
10
|
+
*
|
|
11
|
+
* NOTE: PRLT_HQ_PATH is ignored on host machines to support multiple agents
|
|
12
|
+
* working in different workspaces simultaneously.
|
|
13
|
+
*/
|
|
14
|
+
export declare function findPMO(): string | null;
|