@proletariat/cli 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +512 -253
- package/bin/dev.cmd +3 -0
- package/bin/dev.js +5 -0
- package/bin/run.cmd +3 -0
- package/bin/run.js +23 -0
- package/dist/commands/action/create.d.ts +21 -0
- package/dist/commands/action/create.js +126 -0
- package/dist/commands/action/delete.d.ts +17 -0
- package/dist/commands/action/delete.js +78 -0
- package/dist/commands/action/index.d.ts +15 -0
- package/dist/commands/action/index.js +107 -0
- package/dist/commands/action/list.d.ts +14 -0
- package/dist/commands/action/list.js +89 -0
- package/dist/commands/action/run.d.ts +19 -0
- package/dist/commands/action/run.js +179 -0
- package/dist/commands/action/show.d.ts +15 -0
- package/dist/commands/action/show.js +47 -0
- package/dist/commands/action/update.d.ts +22 -0
- package/dist/commands/action/update.js +168 -0
- package/dist/commands/agent/index.d.ts +13 -0
- package/dist/commands/agent/index.js +131 -0
- package/dist/commands/agent/list.d.ts +7 -0
- package/dist/commands/agent/list.js +126 -0
- package/dist/commands/agent/login.d.ts +16 -0
- package/dist/commands/agent/login.js +146 -0
- package/dist/commands/agent/rebuild.d.ts +18 -0
- package/dist/commands/agent/rebuild.js +133 -0
- package/dist/commands/agent/restart.d.ts +17 -0
- package/dist/commands/agent/restart.js +116 -0
- package/dist/commands/agent/shell.d.ts +23 -0
- package/dist/commands/agent/shell.js +378 -0
- package/dist/commands/agent/staff/add.d.ts +15 -0
- package/dist/commands/agent/staff/add.js +281 -0
- package/dist/commands/agent/staff/index.d.ts +14 -0
- package/dist/commands/agent/staff/index.js +90 -0
- package/dist/commands/agent/staff/list.d.ts +7 -0
- package/dist/commands/agent/staff/list.js +90 -0
- package/dist/commands/agent/staff/remove.d.ts +16 -0
- package/dist/commands/agent/staff/remove.js +137 -0
- package/dist/commands/agent/status.d.ts +17 -0
- package/dist/commands/agent/status.js +139 -0
- package/dist/commands/agent/temp/cleanup.d.ts +23 -0
- package/dist/commands/agent/temp/cleanup.js +388 -0
- package/dist/commands/agent/temp/index.d.ts +14 -0
- package/dist/commands/agent/temp/index.js +82 -0
- package/dist/commands/agent/temp/list.d.ts +7 -0
- package/dist/commands/agent/temp/list.js +108 -0
- package/dist/commands/agent/themes/add-names.d.ts +10 -0
- package/dist/commands/agent/themes/add-names.js +67 -0
- package/dist/commands/agent/themes/create.d.ts +13 -0
- package/dist/commands/agent/themes/create.js +66 -0
- package/dist/commands/agent/themes/index.d.ts +9 -0
- package/dist/commands/agent/themes/index.js +194 -0
- package/dist/commands/agent/themes/list.d.ts +6 -0
- package/dist/commands/agent/themes/list.js +41 -0
- package/dist/commands/agent/themes/set.d.ts +12 -0
- package/dist/commands/agent/themes/set.js +77 -0
- package/dist/commands/agent/visit.d.ts +16 -0
- package/dist/commands/agent/visit.js +88 -0
- package/dist/commands/autocomplete/setup.d.ts +14 -0
- package/dist/commands/autocomplete/setup.js +154 -0
- package/dist/commands/board/index.d.ts +17 -0
- package/dist/commands/board/index.js +255 -0
- package/dist/commands/board/watch.d.ts +13 -0
- package/dist/commands/board/watch.js +52 -0
- package/dist/commands/branch/create.d.ts +50 -0
- package/dist/commands/branch/create.js +624 -0
- package/dist/commands/branch/index.d.ts +13 -0
- package/dist/commands/branch/index.js +50 -0
- package/dist/commands/branch/list.d.ts +17 -0
- package/dist/commands/branch/list.js +120 -0
- package/dist/commands/branch/validate.d.ts +15 -0
- package/dist/commands/branch/validate.js +73 -0
- package/dist/commands/commit.d.ts +71 -0
- package/dist/commands/commit.js +499 -0
- package/dist/commands/docker/clean.d.ts +13 -0
- package/dist/commands/docker/clean.js +224 -0
- package/dist/commands/docker/index.d.ts +19 -0
- package/dist/commands/docker/index.js +274 -0
- package/dist/commands/docker/list.d.ts +16 -0
- package/dist/commands/docker/list.js +200 -0
- package/dist/commands/docker/logs.d.ts +14 -0
- package/dist/commands/docker/logs.js +118 -0
- package/dist/commands/docker/prune.d.ts +14 -0
- package/dist/commands/docker/prune.js +211 -0
- package/dist/commands/docker/restart.d.ts +14 -0
- package/dist/commands/docker/restart.js +129 -0
- package/dist/commands/docker/shell.d.ts +14 -0
- package/dist/commands/docker/shell.js +103 -0
- package/dist/commands/docker/start.d.ts +12 -0
- package/dist/commands/docker/start.js +92 -0
- package/dist/commands/docker/status.d.ts +7 -0
- package/dist/commands/docker/status.js +40 -0
- package/dist/commands/docker/stop.d.ts +14 -0
- package/dist/commands/docker/stop.js +134 -0
- package/dist/commands/docker/sync.d.ts +15 -0
- package/dist/commands/docker/sync.js +112 -0
- package/dist/commands/epic/activate.d.ts +13 -0
- package/dist/commands/epic/activate.js +118 -0
- package/dist/commands/epic/archive.d.ts +14 -0
- package/dist/commands/epic/archive.js +132 -0
- package/dist/commands/epic/create.d.ts +15 -0
- package/dist/commands/epic/create.js +137 -0
- package/dist/commands/epic/index.d.ts +13 -0
- package/dist/commands/epic/index.js +88 -0
- package/dist/commands/epic/link/block.d.ts +14 -0
- package/dist/commands/epic/link/block.js +79 -0
- package/dist/commands/epic/link/duplicates.d.ts +14 -0
- package/dist/commands/epic/link/duplicates.js +66 -0
- package/dist/commands/epic/link/index.d.ts +19 -0
- package/dist/commands/epic/link/index.js +242 -0
- package/dist/commands/epic/link/relates.d.ts +14 -0
- package/dist/commands/epic/link/relates.js +66 -0
- package/dist/commands/epic/link/remove.d.ts +16 -0
- package/dist/commands/epic/link/remove.js +89 -0
- package/dist/commands/epic/list.d.ts +11 -0
- package/dist/commands/epic/list.js +87 -0
- package/dist/commands/epic/move.d.ts +15 -0
- package/dist/commands/epic/move.js +184 -0
- package/dist/commands/epic/progress.d.ts +16 -0
- package/dist/commands/epic/progress.js +166 -0
- package/dist/commands/epic/project.d.ts +15 -0
- package/dist/commands/epic/project.js +219 -0
- package/dist/commands/epic/reorder.d.ts +21 -0
- package/dist/commands/epic/reorder.js +160 -0
- package/dist/commands/epic/spec.d.ts +15 -0
- package/dist/commands/epic/spec.js +191 -0
- package/dist/commands/epic/ticket.d.ts +18 -0
- package/dist/commands/epic/ticket.js +291 -0
- package/dist/commands/epic/view.d.ts +13 -0
- package/dist/commands/epic/view.js +117 -0
- package/dist/commands/execution/index.d.ts +13 -0
- package/dist/commands/execution/index.js +70 -0
- package/dist/commands/execution/list.d.ts +15 -0
- package/dist/commands/execution/list.js +144 -0
- package/dist/commands/execution/logs.d.ts +18 -0
- package/dist/commands/execution/logs.js +161 -0
- package/dist/commands/execution/stop.d.ts +22 -0
- package/dist/commands/execution/stop.js +248 -0
- package/dist/commands/gh/index.d.ts +9 -0
- package/dist/commands/gh/index.js +53 -0
- package/dist/commands/gh/login.d.ts +6 -0
- package/dist/commands/gh/login.js +57 -0
- package/dist/commands/gh/status.d.ts +6 -0
- package/dist/commands/gh/status.js +48 -0
- package/dist/commands/gh/token.d.ts +6 -0
- package/dist/commands/gh/token.js +59 -0
- package/dist/commands/init.d.ts +26 -0
- package/dist/commands/init.js +200 -0
- package/dist/commands/phase/create.d.ts +22 -0
- package/dist/commands/phase/create.js +123 -0
- package/dist/commands/phase/delete.d.ts +17 -0
- package/dist/commands/phase/delete.js +73 -0
- package/dist/commands/phase/list.d.ts +12 -0
- package/dist/commands/phase/list.js +76 -0
- package/dist/commands/phase/move.d.ts +17 -0
- package/dist/commands/phase/move.js +115 -0
- package/dist/commands/phase/template/apply.d.ts +17 -0
- package/dist/commands/phase/template/apply.js +106 -0
- package/dist/commands/phase/template/create.d.ts +16 -0
- package/dist/commands/phase/template/create.js +58 -0
- package/dist/commands/phase/template/delete.d.ts +17 -0
- package/dist/commands/phase/template/delete.js +98 -0
- package/dist/commands/phase/template/index.d.ts +15 -0
- package/dist/commands/phase/template/index.js +128 -0
- package/dist/commands/phase/template/list.d.ts +16 -0
- package/dist/commands/phase/template/list.js +95 -0
- package/dist/commands/phase/template/update.d.ts +17 -0
- package/dist/commands/phase/template/update.js +89 -0
- package/dist/commands/phase/update.d.ts +23 -0
- package/dist/commands/phase/update.js +174 -0
- package/dist/commands/pmo/init.d.ts +25 -0
- package/dist/commands/pmo/init.js +341 -0
- package/dist/commands/pr/create.d.ts +17 -0
- package/dist/commands/pr/create.js +242 -0
- package/dist/commands/pr/index.d.ts +9 -0
- package/dist/commands/pr/index.js +68 -0
- package/dist/commands/pr/link.d.ts +14 -0
- package/dist/commands/pr/link.js +212 -0
- package/dist/commands/pr/status.d.ts +12 -0
- package/dist/commands/pr/status.js +161 -0
- package/dist/commands/project/archive.d.ts +17 -0
- package/dist/commands/project/archive.js +83 -0
- package/dist/commands/project/create.d.ts +22 -0
- package/dist/commands/project/create.js +143 -0
- package/dist/commands/project/delete.d.ts +17 -0
- package/dist/commands/project/delete.js +128 -0
- package/dist/commands/project/index.d.ts +13 -0
- package/dist/commands/project/index.js +64 -0
- package/dist/commands/project/list.d.ts +14 -0
- package/dist/commands/project/list.js +96 -0
- package/dist/commands/project/spec.d.ts +18 -0
- package/dist/commands/project/spec.js +216 -0
- package/dist/commands/project/unarchive.d.ts +15 -0
- package/dist/commands/project/unarchive.js +35 -0
- package/dist/commands/project/view.d.ts +16 -0
- package/dist/commands/project/view.js +94 -0
- package/dist/commands/repo/add.d.ts +21 -0
- package/dist/commands/repo/add.js +118 -0
- package/dist/commands/repo/index.d.ts +13 -0
- package/dist/commands/repo/index.js +114 -0
- package/dist/commands/repo/list.d.ts +13 -0
- package/dist/commands/repo/list.js +96 -0
- package/dist/commands/repo/remove.d.ts +23 -0
- package/dist/commands/repo/remove.js +217 -0
- package/dist/commands/repo/view.d.ts +15 -0
- package/dist/commands/repo/view.js +99 -0
- package/dist/commands/session/attach.d.ts +40 -0
- package/dist/commands/session/attach.js +307 -0
- package/dist/commands/session/index.d.ts +13 -0
- package/dist/commands/session/index.js +64 -0
- package/dist/commands/session/list.d.ts +21 -0
- package/dist/commands/session/list.js +181 -0
- package/dist/commands/spec/create.d.ts +19 -0
- package/dist/commands/spec/create.js +130 -0
- package/dist/commands/spec/index.d.ts +13 -0
- package/dist/commands/spec/index.js +68 -0
- package/dist/commands/spec/link/depends.d.ts +14 -0
- package/dist/commands/spec/link/depends.js +64 -0
- package/dist/commands/spec/link/duplicates.d.ts +14 -0
- package/dist/commands/spec/link/duplicates.js +63 -0
- package/dist/commands/spec/link/index.d.ts +19 -0
- package/dist/commands/spec/link/index.js +200 -0
- package/dist/commands/spec/link/relates.d.ts +14 -0
- package/dist/commands/spec/link/relates.js +63 -0
- package/dist/commands/spec/link/remove.d.ts +16 -0
- package/dist/commands/spec/link/remove.js +94 -0
- package/dist/commands/spec/list.d.ts +12 -0
- package/dist/commands/spec/list.js +75 -0
- package/dist/commands/spec/plan.d.ts +15 -0
- package/dist/commands/spec/plan.js +108 -0
- package/dist/commands/spec/ticket.d.ts +18 -0
- package/dist/commands/spec/ticket.js +160 -0
- package/dist/commands/spec/view.d.ts +15 -0
- package/dist/commands/spec/view.js +163 -0
- package/dist/commands/status/create.d.ts +21 -0
- package/dist/commands/status/create.js +140 -0
- package/dist/commands/status/delete.d.ts +13 -0
- package/dist/commands/status/delete.js +77 -0
- package/dist/commands/status/index.d.ts +14 -0
- package/dist/commands/status/index.js +91 -0
- package/dist/commands/status/list.d.ts +12 -0
- package/dist/commands/status/list.js +93 -0
- package/dist/commands/status/move.d.ts +14 -0
- package/dist/commands/status/move.js +120 -0
- package/dist/commands/status/update.d.ts +20 -0
- package/dist/commands/status/update.js +180 -0
- package/dist/commands/template/delete.d.ts +15 -0
- package/dist/commands/template/delete.js +142 -0
- package/dist/commands/template/index.d.ts +10 -0
- package/dist/commands/template/index.js +64 -0
- package/dist/commands/template/list.d.ts +18 -0
- package/dist/commands/template/list.js +157 -0
- package/dist/commands/template/phase/apply.d.ts +14 -0
- package/dist/commands/template/phase/apply.js +41 -0
- package/dist/commands/template/phase/create.d.ts +12 -0
- package/dist/commands/template/phase/create.js +29 -0
- package/dist/commands/template/phase/delete.d.ts +13 -0
- package/dist/commands/template/phase/delete.js +34 -0
- package/dist/commands/template/phase/index.d.ts +10 -0
- package/dist/commands/template/phase/index.js +62 -0
- package/dist/commands/template/phase/list.d.ts +11 -0
- package/dist/commands/template/phase/list.js +34 -0
- package/dist/commands/template/phase/update.d.ts +13 -0
- package/dist/commands/template/phase/update.js +35 -0
- package/dist/commands/template/ticket/apply.d.ts +17 -0
- package/dist/commands/template/ticket/apply.js +58 -0
- package/dist/commands/template/ticket/delete.d.ts +13 -0
- package/dist/commands/template/ticket/delete.js +34 -0
- package/dist/commands/template/ticket/index.d.ts +10 -0
- package/dist/commands/template/ticket/index.js +62 -0
- package/dist/commands/template/ticket/list.d.ts +11 -0
- package/dist/commands/template/ticket/list.js +34 -0
- package/dist/commands/template/ticket/save.d.ts +13 -0
- package/dist/commands/template/ticket/save.js +35 -0
- package/dist/commands/ticket/bulk.d.ts +13 -0
- package/dist/commands/ticket/bulk.js +145 -0
- package/dist/commands/ticket/complete.d.ts +16 -0
- package/dist/commands/ticket/complete.js +170 -0
- package/dist/commands/ticket/create.d.ts +22 -0
- package/dist/commands/ticket/create.js +390 -0
- package/dist/commands/ticket/delete.d.ts +16 -0
- package/dist/commands/ticket/delete.js +178 -0
- package/dist/commands/ticket/edit.d.ts +27 -0
- package/dist/commands/ticket/edit.js +322 -0
- package/dist/commands/ticket/epic.d.ts +20 -0
- package/dist/commands/ticket/epic.js +333 -0
- package/dist/commands/ticket/index.d.ts +13 -0
- package/dist/commands/ticket/index.js +103 -0
- package/dist/commands/ticket/link/block.d.ts +14 -0
- package/dist/commands/ticket/link/block.js +94 -0
- package/dist/commands/ticket/link/duplicates.d.ts +14 -0
- package/dist/commands/ticket/link/duplicates.js +93 -0
- package/dist/commands/ticket/link/index.d.ts +19 -0
- package/dist/commands/ticket/link/index.js +239 -0
- package/dist/commands/ticket/link/relates.d.ts +14 -0
- package/dist/commands/ticket/link/relates.js +93 -0
- package/dist/commands/ticket/link/remove.d.ts +16 -0
- package/dist/commands/ticket/link/remove.js +128 -0
- package/dist/commands/ticket/list.d.ts +24 -0
- package/dist/commands/ticket/list.js +431 -0
- package/dist/commands/ticket/move.d.ts +18 -0
- package/dist/commands/ticket/move.js +212 -0
- package/dist/commands/ticket/project.d.ts +18 -0
- package/dist/commands/ticket/project.js +254 -0
- package/dist/commands/ticket/reassign.d.ts +19 -0
- package/dist/commands/ticket/reassign.js +279 -0
- package/dist/commands/ticket/spec.d.ts +18 -0
- package/dist/commands/ticket/spec.js +259 -0
- package/dist/commands/ticket/status.d.ts +13 -0
- package/dist/commands/ticket/status.js +87 -0
- package/dist/commands/ticket/template/apply.d.ts +25 -0
- package/dist/commands/ticket/template/apply.js +249 -0
- package/dist/commands/ticket/template/create.d.ts +19 -0
- package/dist/commands/ticket/template/create.js +210 -0
- package/dist/commands/ticket/template/delete.d.ts +17 -0
- package/dist/commands/ticket/template/delete.js +92 -0
- package/dist/commands/ticket/template/index.d.ts +15 -0
- package/dist/commands/ticket/template/index.js +118 -0
- package/dist/commands/ticket/template/list.d.ts +16 -0
- package/dist/commands/ticket/template/list.js +110 -0
- package/dist/commands/ticket/template/save.d.ts +14 -0
- package/dist/commands/ticket/template/save.js +110 -0
- package/dist/commands/ticket/update.d.ts +18 -0
- package/dist/commands/ticket/update.js +325 -0
- package/dist/commands/ticket/view.d.ts +13 -0
- package/dist/commands/ticket/view.js +80 -0
- package/dist/commands/whoami.d.ts +9 -0
- package/dist/commands/whoami.js +103 -0
- package/dist/commands/work/complete.d.ts +13 -0
- package/dist/commands/work/complete.js +121 -0
- package/dist/commands/work/index.d.ts +13 -0
- package/dist/commands/work/index.js +70 -0
- package/dist/commands/work/ready.d.ts +24 -0
- package/dist/commands/work/ready.js +290 -0
- package/dist/commands/work/revise.d.ts +19 -0
- package/dist/commands/work/revise.js +377 -0
- package/dist/commands/work/spawn-all.d.ts +17 -0
- package/dist/commands/work/spawn-all.js +58 -0
- package/dist/commands/work/spawn.d.ts +29 -0
- package/dist/commands/work/spawn.js +728 -0
- package/dist/commands/work/start.d.ts +39 -0
- package/dist/commands/work/start.js +1393 -0
- package/dist/commands/work/watch.d.ts +31 -0
- package/dist/commands/work/watch.js +359 -0
- package/dist/commands/workflow/create.d.ts +18 -0
- package/dist/commands/workflow/create.js +119 -0
- package/dist/commands/workflow/delete.d.ts +17 -0
- package/dist/commands/workflow/delete.js +119 -0
- package/dist/commands/workflow/index.d.ts +15 -0
- package/dist/commands/workflow/index.js +75 -0
- package/dist/commands/workflow/list.d.ts +15 -0
- package/dist/commands/workflow/list.js +75 -0
- package/dist/commands/workflow/switch.d.ts +13 -0
- package/dist/commands/workflow/switch.js +117 -0
- package/dist/commands/workflow/view.d.ts +16 -0
- package/dist/commands/workflow/view.js +114 -0
- package/dist/commands/workspace/add.d.ts +12 -0
- package/dist/commands/workspace/add.js +74 -0
- package/dist/commands/workspace/list.d.ts +9 -0
- package/dist/commands/workspace/list.js +153 -0
- package/dist/commands/workspace/remove.d.ts +13 -0
- package/dist/commands/workspace/remove.js +98 -0
- package/dist/commands/workspace/use.d.ts +12 -0
- package/dist/commands/workspace/use.js +111 -0
- package/dist/hooks/init.d.ts +11 -0
- package/dist/hooks/init.js +57 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/lib/agents/commands.d.ts +189 -0
- package/dist/lib/agents/commands.js +893 -0
- package/dist/lib/agents/index.d.ts +54 -0
- package/dist/lib/agents/index.js +382 -0
- package/dist/lib/branch/index.d.ts +120 -0
- package/dist/lib/branch/index.js +334 -0
- package/dist/lib/colors.d.ts +94 -0
- package/dist/lib/colors.js +68 -0
- package/dist/lib/commands/docker-command.d.ts +21 -0
- package/dist/lib/commands/docker-command.js +27 -0
- package/dist/lib/database/index.d.ts +176 -0
- package/dist/lib/database/index.js +581 -0
- package/dist/lib/docker/resolve.d.ts +38 -0
- package/dist/lib/docker/resolve.js +175 -0
- package/dist/lib/execution/config.d.ts +150 -0
- package/dist/lib/execution/config.js +541 -0
- package/dist/lib/execution/devcontainer.d.ts +85 -0
- package/dist/lib/execution/devcontainer.js +594 -0
- package/dist/lib/execution/index.d.ts +10 -0
- package/dist/lib/execution/index.js +10 -0
- package/dist/lib/execution/runners.d.ts +53 -0
- package/dist/lib/execution/runners.js +1182 -0
- package/dist/lib/execution/spawner.d.ts +85 -0
- package/dist/lib/execution/spawner.js +548 -0
- package/dist/lib/execution/storage.d.ts +159 -0
- package/dist/lib/execution/storage.js +425 -0
- package/dist/lib/execution/types.d.ts +145 -0
- package/dist/lib/execution/types.js +157 -0
- package/dist/lib/init/index.d.ts +75 -0
- package/dist/lib/init/index.js +355 -0
- package/dist/lib/machine-config.d.ts +170 -0
- package/dist/lib/machine-config.js +386 -0
- package/dist/lib/pmo/base-command.d.ts +195 -0
- package/dist/lib/pmo/base-command.js +319 -0
- package/dist/lib/pmo/create-spec-folders.d.ts +43 -0
- package/dist/lib/pmo/create-spec-folders.js +64 -0
- package/dist/lib/pmo/epic-files.d.ts +56 -0
- package/dist/lib/pmo/epic-files.js +195 -0
- package/dist/lib/pmo/find-pmo.d.ts +14 -0
- package/dist/lib/pmo/find-pmo.js +172 -0
- package/dist/lib/pmo/index.d.ts +109 -0
- package/dist/lib/pmo/index.js +501 -0
- package/dist/lib/pmo/markdown.d.ts +31 -0
- package/dist/lib/pmo/markdown.js +245 -0
- package/dist/lib/pmo/pmo-context.d.ts +27 -0
- package/dist/lib/pmo/pmo-context.js +44 -0
- package/dist/lib/pmo/schema.d.ts +82 -0
- package/dist/lib/pmo/schema.js +531 -0
- package/dist/lib/pmo/spec-parser.d.ts +25 -0
- package/dist/lib/pmo/spec-parser.js +205 -0
- package/dist/lib/pmo/spec-types.d.ts +43 -0
- package/dist/lib/pmo/spec-types.js +7 -0
- package/dist/lib/pmo/storage/actions.d.ts +34 -0
- package/dist/lib/pmo/storage/actions.js +177 -0
- package/dist/lib/pmo/storage/base.d.ts +47 -0
- package/dist/lib/pmo/storage/base.js +858 -0
- package/dist/lib/pmo/storage/dependencies.d.ts +61 -0
- package/dist/lib/pmo/storage/dependencies.js +267 -0
- package/dist/lib/pmo/storage/epics.d.ts +46 -0
- package/dist/lib/pmo/storage/epics.js +243 -0
- package/dist/lib/pmo/storage/helpers.d.ts +33 -0
- package/dist/lib/pmo/storage/helpers.js +148 -0
- package/dist/lib/pmo/storage/index.d.ts +186 -0
- package/dist/lib/pmo/storage/index.js +689 -0
- package/dist/lib/pmo/storage/phases.d.ts +65 -0
- package/dist/lib/pmo/storage/phases.js +392 -0
- package/dist/lib/pmo/storage/projects.d.ts +79 -0
- package/dist/lib/pmo/storage/projects.js +303 -0
- package/dist/lib/pmo/storage/specs.d.ts +77 -0
- package/dist/lib/pmo/storage/specs.js +389 -0
- package/dist/lib/pmo/storage/statuses.d.ts +63 -0
- package/dist/lib/pmo/storage/statuses.js +404 -0
- package/dist/lib/pmo/storage/subtasks.d.ts +37 -0
- package/dist/lib/pmo/storage/subtasks.js +184 -0
- package/dist/lib/pmo/storage/templates.d.ts +40 -0
- package/dist/lib/pmo/storage/templates.js +210 -0
- package/dist/lib/pmo/storage/tickets.d.ts +57 -0
- package/dist/lib/pmo/storage/tickets.js +453 -0
- package/dist/lib/pmo/storage/types.d.ts +200 -0
- package/dist/lib/pmo/storage/types.js +5 -0
- package/dist/lib/pmo/storage/views.d.ts +44 -0
- package/dist/lib/pmo/storage/views.js +355 -0
- package/dist/lib/pmo/storage-sqlite.d.ts +7 -0
- package/dist/lib/pmo/storage-sqlite.js +7 -0
- package/dist/lib/pmo/sync-manager.d.ts +92 -0
- package/dist/lib/pmo/sync-manager.js +229 -0
- package/dist/lib/pmo/types.d.ts +710 -0
- package/dist/lib/pmo/types.js +108 -0
- package/dist/lib/pmo/utils.d.ts +122 -0
- package/dist/lib/pmo/utils.js +174 -0
- package/dist/lib/pmo/watcher.d.ts +43 -0
- package/dist/lib/pmo/watcher.js +208 -0
- package/dist/lib/pr/index.d.ts +150 -0
- package/dist/lib/pr/index.js +483 -0
- package/dist/lib/prompt-json.d.ts +231 -0
- package/dist/lib/prompt-json.js +213 -0
- package/dist/lib/repos/index.d.ts +81 -0
- package/dist/lib/repos/index.js +679 -0
- package/dist/lib/styles.d.ts +98 -0
- package/dist/lib/styles.js +195 -0
- package/dist/lib/themes.d.ts +128 -0
- package/dist/lib/themes.js +301 -0
- package/dist/lib/ui/BoardUI.d.ts +21 -0
- package/dist/lib/ui/BoardUI.js +85 -0
- package/dist/lib/ui/ClaimTicketUI.d.ts +17 -0
- package/dist/lib/ui/ClaimTicketUI.js +64 -0
- package/dist/lib/ui/CreateTicketUI.d.ts +13 -0
- package/dist/lib/ui/CreateTicketUI.js +101 -0
- package/dist/lib/workspace.d.ts +66 -0
- package/dist/lib/workspace.js +204 -0
- package/oclif.manifest.json +10593 -0
- package/package.json +103 -56
- package/LICENSE +0 -21
- package/dist/bin/prlt.d.ts +0 -11
- package/dist/bin/prlt.d.ts.map +0 -1
- package/dist/bin/prlt.js +0 -144
- package/dist/bin/prlt.js.map +0 -1
- package/dist/lib/config/index.d.ts +0 -14
- package/dist/lib/config/index.d.ts.map +0 -1
- package/dist/lib/config/index.js +0 -142
- package/dist/lib/config/index.js.map +0 -1
- package/dist/lib/config/upgrade.d.ts +0 -2
- package/dist/lib/config/upgrade.d.ts.map +0 -1
- package/dist/lib/config/upgrade.js +0 -248
- package/dist/lib/config/upgrade.js.map +0 -1
- package/dist/lib/themes/index.d.ts +0 -8
- package/dist/lib/themes/index.d.ts.map +0 -1
- package/dist/lib/themes/index.js +0 -80
- package/dist/lib/themes/index.js.map +0 -1
- package/dist/lib/utils/helpers.d.ts +0 -4
- package/dist/lib/utils/helpers.d.ts.map +0 -1
- package/dist/lib/utils/helpers.js +0 -39
- package/dist/lib/utils/helpers.js.map +0 -1
- package/dist/lib/utils/logger.d.ts +0 -4
- package/dist/lib/utils/logger.d.ts.map +0 -1
- package/dist/lib/utils/logger.js +0 -28
- package/dist/lib/utils/logger.js.map +0 -1
- package/dist/lib/workspace/index.d.ts +0 -13
- package/dist/lib/workspace/index.d.ts.map +0 -1
- package/dist/lib/workspace/index.js +0 -116
- package/dist/lib/workspace/index.js.map +0 -1
- package/dist/lib/worktree/index.d.ts +0 -7
- package/dist/lib/worktree/index.d.ts.map +0 -1
- package/dist/lib/worktree/index.js +0 -362
- package/dist/lib/worktree/index.js.map +0 -1
- package/dist/lib/worktree/migrate.d.ts +0 -2
- package/dist/lib/worktree/migrate.d.ts.map +0 -1
- package/dist/lib/worktree/migrate.js +0 -214
- package/dist/lib/worktree/migrate.js.map +0 -1
- package/dist/lib/worktree/repair.d.ts +0 -3
- package/dist/lib/worktree/repair.d.ts.map +0 -1
- package/dist/lib/worktree/repair.js +0 -320
- package/dist/lib/worktree/repair.js.map +0 -1
- package/dist/types/index.d.ts +0 -57
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/index.js +0 -3
- package/dist/types/index.js.map +0 -1
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Board view operations.
|
|
3
|
+
*/
|
|
4
|
+
import { PMO_TABLES } from '../schema.js';
|
|
5
|
+
import { PMOError, } from '../types.js';
|
|
6
|
+
import { slugify } from '../utils.js';
|
|
7
|
+
import { getAcceptanceCriteriaSync } from './helpers.js';
|
|
8
|
+
const T = PMO_TABLES;
|
|
9
|
+
export class ViewStorage {
|
|
10
|
+
ctx;
|
|
11
|
+
constructor(ctx) {
|
|
12
|
+
this.ctx = ctx;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* List board views.
|
|
16
|
+
*/
|
|
17
|
+
async listBoardViews(filter) {
|
|
18
|
+
let sql = `SELECT * FROM ${T.board_views}`;
|
|
19
|
+
const conditions = [];
|
|
20
|
+
const params = [];
|
|
21
|
+
if (filter?.projectId) {
|
|
22
|
+
conditions.push('project_id = ?');
|
|
23
|
+
params.push(filter.projectId);
|
|
24
|
+
}
|
|
25
|
+
if (filter?.isDefault !== undefined) {
|
|
26
|
+
conditions.push('is_default = ?');
|
|
27
|
+
params.push(filter.isDefault ? 1 : 0);
|
|
28
|
+
}
|
|
29
|
+
if (filter?.search) {
|
|
30
|
+
conditions.push('(name LIKE ? OR description LIKE ?)');
|
|
31
|
+
const searchTerm = `%${filter.search}%`;
|
|
32
|
+
params.push(searchTerm, searchTerm);
|
|
33
|
+
}
|
|
34
|
+
if (conditions.length > 0) {
|
|
35
|
+
sql += ' WHERE ' + conditions.join(' AND ');
|
|
36
|
+
}
|
|
37
|
+
sql += ' ORDER BY is_default DESC, name ASC';
|
|
38
|
+
const rows = this.ctx.db.prepare(sql).all(...params);
|
|
39
|
+
return rows.map((row) => this.rowToBoardView(row));
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Get a board view by ID.
|
|
43
|
+
*/
|
|
44
|
+
async getBoardView(id) {
|
|
45
|
+
const row = this.ctx.db.prepare(`SELECT * FROM ${T.board_views} WHERE id = ?`).get(id);
|
|
46
|
+
if (!row)
|
|
47
|
+
return null;
|
|
48
|
+
return this.rowToBoardView(row);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Create a new board view.
|
|
52
|
+
*/
|
|
53
|
+
async createBoardView(view) {
|
|
54
|
+
if (!view.projectId) {
|
|
55
|
+
throw new PMOError('INVALID', 'Project ID is required');
|
|
56
|
+
}
|
|
57
|
+
if (!view.name) {
|
|
58
|
+
throw new PMOError('INVALID', 'View name is required');
|
|
59
|
+
}
|
|
60
|
+
const id = view.id || slugify(view.name) + '-' + Date.now().toString(36);
|
|
61
|
+
const now = Date.now();
|
|
62
|
+
const filters = JSON.stringify(view.filters || {});
|
|
63
|
+
// If this is set as default, unset other defaults for this project
|
|
64
|
+
if (view.isDefault) {
|
|
65
|
+
this.ctx.db.prepare(`
|
|
66
|
+
UPDATE ${T.board_views} SET is_default = 0 WHERE project_id = ?
|
|
67
|
+
`).run(view.projectId);
|
|
68
|
+
}
|
|
69
|
+
this.ctx.db.prepare(`
|
|
70
|
+
INSERT INTO ${T.board_views} (id, project_id, name, description, is_default, filters, group_by, sort_by, created_at, updated_at)
|
|
71
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
72
|
+
`).run(id, view.projectId, view.name, view.description || null, view.isDefault ? 1 : 0, filters, view.groupBy || null, view.sortBy || null, now, now);
|
|
73
|
+
return (await this.getBoardView(id));
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Update a board view.
|
|
77
|
+
*/
|
|
78
|
+
async updateBoardView(id, changes) {
|
|
79
|
+
const existing = await this.getBoardView(id);
|
|
80
|
+
if (!existing) {
|
|
81
|
+
throw new PMOError('NOT_FOUND', `Board view not found: ${id}`);
|
|
82
|
+
}
|
|
83
|
+
const updates = ['updated_at = ?'];
|
|
84
|
+
const params = [Date.now()];
|
|
85
|
+
if (changes.name !== undefined) {
|
|
86
|
+
updates.push('name = ?');
|
|
87
|
+
params.push(changes.name);
|
|
88
|
+
}
|
|
89
|
+
if (changes.description !== undefined) {
|
|
90
|
+
updates.push('description = ?');
|
|
91
|
+
params.push(changes.description || null);
|
|
92
|
+
}
|
|
93
|
+
if (changes.isDefault !== undefined) {
|
|
94
|
+
// If setting as default, unset other defaults for this project
|
|
95
|
+
if (changes.isDefault) {
|
|
96
|
+
this.ctx.db.prepare(`
|
|
97
|
+
UPDATE ${T.board_views} SET is_default = 0 WHERE project_id = ?
|
|
98
|
+
`).run(existing.projectId);
|
|
99
|
+
}
|
|
100
|
+
updates.push('is_default = ?');
|
|
101
|
+
params.push(changes.isDefault ? 1 : 0);
|
|
102
|
+
}
|
|
103
|
+
if (changes.filters !== undefined) {
|
|
104
|
+
updates.push('filters = ?');
|
|
105
|
+
params.push(JSON.stringify(changes.filters));
|
|
106
|
+
}
|
|
107
|
+
if (changes.groupBy !== undefined) {
|
|
108
|
+
updates.push('group_by = ?');
|
|
109
|
+
params.push(changes.groupBy || null);
|
|
110
|
+
}
|
|
111
|
+
if (changes.sortBy !== undefined) {
|
|
112
|
+
updates.push('sort_by = ?');
|
|
113
|
+
params.push(changes.sortBy || null);
|
|
114
|
+
}
|
|
115
|
+
params.push(id);
|
|
116
|
+
this.ctx.db.prepare(`UPDATE ${T.board_views} SET ${updates.join(', ')} WHERE id = ?`).run(...params);
|
|
117
|
+
return (await this.getBoardView(id));
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Delete a board view.
|
|
121
|
+
*/
|
|
122
|
+
async deleteBoardView(id) {
|
|
123
|
+
const result = this.ctx.db.prepare(`DELETE FROM ${T.board_views} WHERE id = ?`).run(id);
|
|
124
|
+
if (result.changes === 0) {
|
|
125
|
+
throw new PMOError('NOT_FOUND', `Board view not found: ${id}`);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Get the default board view for a project.
|
|
130
|
+
*/
|
|
131
|
+
async getDefaultBoardView(projectId) {
|
|
132
|
+
const row = this.ctx.db.prepare(`
|
|
133
|
+
SELECT * FROM ${T.board_views} WHERE project_id = ? AND is_default = 1
|
|
134
|
+
`).get(projectId);
|
|
135
|
+
if (!row)
|
|
136
|
+
return null;
|
|
137
|
+
return this.rowToBoardView(row);
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Get board with optional filters applied.
|
|
141
|
+
*/
|
|
142
|
+
async getBoardWithView(projectId, viewId, filters) {
|
|
143
|
+
let viewFilters = {};
|
|
144
|
+
let viewSortBy;
|
|
145
|
+
// Load view if specified
|
|
146
|
+
if (viewId) {
|
|
147
|
+
const view = await this.getBoardView(viewId);
|
|
148
|
+
if (view) {
|
|
149
|
+
viewFilters = view.filters;
|
|
150
|
+
viewSortBy = view.sortBy;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
// Override with explicit filters if provided
|
|
154
|
+
const effectiveFilters = { ...viewFilters, ...filters };
|
|
155
|
+
// Get project metadata
|
|
156
|
+
const projectRow = this.ctx.db.prepare(`SELECT * FROM ${T.projects} WHERE id = ?`).get(projectId);
|
|
157
|
+
if (!projectRow) {
|
|
158
|
+
throw new PMOError('NOT_FOUND', `Project not found: ${projectId}. Run init() first.`);
|
|
159
|
+
}
|
|
160
|
+
// Get the project's workflow
|
|
161
|
+
const projectMeta = this.ctx.db.prepare(`
|
|
162
|
+
SELECT workflow_id FROM ${T.projects} WHERE id = ?
|
|
163
|
+
`).get(projectId);
|
|
164
|
+
const workflowId = projectMeta?.workflow_id || 'default';
|
|
165
|
+
// Get workflow statuses as columns
|
|
166
|
+
const columnRows = this.ctx.db.prepare(`
|
|
167
|
+
SELECT id, workflow_id, name, position
|
|
168
|
+
FROM ${T.workflow_statuses}
|
|
169
|
+
WHERE workflow_id = ?
|
|
170
|
+
ORDER BY position
|
|
171
|
+
`).all(workflowId);
|
|
172
|
+
// Filter columns if columnIds filter is set
|
|
173
|
+
const filteredColumnRows = effectiveFilters.columnIds?.length
|
|
174
|
+
? columnRows.filter((col) => effectiveFilters.columnIds.includes(col.id))
|
|
175
|
+
: columnRows;
|
|
176
|
+
// Get tickets with filters applied
|
|
177
|
+
const columns = await Promise.all(filteredColumnRows.map(async (col) => {
|
|
178
|
+
const tickets = await this.getTicketsForColumnWithFilters(col.id, projectId, effectiveFilters);
|
|
179
|
+
// Apply sorting if specified
|
|
180
|
+
const sortedTickets = viewSortBy ? this.sortTickets(tickets, viewSortBy) : tickets;
|
|
181
|
+
return {
|
|
182
|
+
id: col.id,
|
|
183
|
+
name: col.name,
|
|
184
|
+
position: col.position,
|
|
185
|
+
tickets: sortedTickets,
|
|
186
|
+
};
|
|
187
|
+
}));
|
|
188
|
+
return {
|
|
189
|
+
id: projectRow.id,
|
|
190
|
+
name: projectRow.name,
|
|
191
|
+
columns,
|
|
192
|
+
updatedAt: new Date(projectRow.updated_at),
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Get tickets for a column (workflow status) with filters applied.
|
|
197
|
+
*/
|
|
198
|
+
async getTicketsForColumnWithFilters(columnId, projectId, filters) {
|
|
199
|
+
// columnId is now a workflow_status id
|
|
200
|
+
let sql = `
|
|
201
|
+
SELECT t.*,
|
|
202
|
+
ws.position as board_position,
|
|
203
|
+
ws.name as column_name,
|
|
204
|
+
ws.name as status_name,
|
|
205
|
+
ws.category as status_category
|
|
206
|
+
FROM ${T.tickets} t
|
|
207
|
+
LEFT JOIN ${T.workflow_statuses} ws ON t.status_id = ws.id
|
|
208
|
+
WHERE t.status_id = ? AND t.project_id = ?
|
|
209
|
+
`;
|
|
210
|
+
const params = [columnId, projectId];
|
|
211
|
+
// Apply filters
|
|
212
|
+
if (filters.assignee !== undefined) {
|
|
213
|
+
if (filters.assignee === 'unassigned') {
|
|
214
|
+
sql += ' AND (t.assignee IS NULL OR t.assignee = "")';
|
|
215
|
+
}
|
|
216
|
+
else {
|
|
217
|
+
sql += ' AND t.assignee = ?';
|
|
218
|
+
params.push(filters.assignee);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
if (filters.owner !== undefined) {
|
|
222
|
+
sql += ' AND t.owner = ?';
|
|
223
|
+
params.push(filters.owner);
|
|
224
|
+
}
|
|
225
|
+
if (filters.priority !== undefined) {
|
|
226
|
+
sql += ' AND UPPER(t.priority) = UPPER(?)';
|
|
227
|
+
params.push(filters.priority);
|
|
228
|
+
}
|
|
229
|
+
if (filters.statusCategory !== undefined) {
|
|
230
|
+
sql += ' AND ws.category = ?';
|
|
231
|
+
params.push(filters.statusCategory);
|
|
232
|
+
}
|
|
233
|
+
if (filters.statusId !== undefined) {
|
|
234
|
+
sql += ' AND t.status_id = ?';
|
|
235
|
+
params.push(filters.statusId);
|
|
236
|
+
}
|
|
237
|
+
if (filters.epicId !== undefined) {
|
|
238
|
+
sql += ' AND t.epic_id = ?';
|
|
239
|
+
params.push(filters.epicId);
|
|
240
|
+
}
|
|
241
|
+
if (filters.search !== undefined) {
|
|
242
|
+
sql += ' AND (t.title LIKE ? OR t.description LIKE ?)';
|
|
243
|
+
const searchTerm = `%${filters.search}%`;
|
|
244
|
+
params.push(searchTerm, searchTerm);
|
|
245
|
+
}
|
|
246
|
+
// Order by priority then created_at
|
|
247
|
+
sql += ` ORDER BY
|
|
248
|
+
CASE t.priority
|
|
249
|
+
WHEN 'P0' THEN 0
|
|
250
|
+
WHEN 'P1' THEN 1
|
|
251
|
+
WHEN 'P2' THEN 2
|
|
252
|
+
WHEN 'P3' THEN 3
|
|
253
|
+
ELSE 4
|
|
254
|
+
END,
|
|
255
|
+
t.created_at ASC`;
|
|
256
|
+
const rows = this.ctx.db.prepare(sql).all(...params);
|
|
257
|
+
return Promise.all(rows.map((row) => this.rowToTicketWithColumn(row)));
|
|
258
|
+
}
|
|
259
|
+
async rowToTicketWithColumn(row) {
|
|
260
|
+
// Get subtasks
|
|
261
|
+
const subtaskRows = this.ctx.db.prepare(`
|
|
262
|
+
SELECT * FROM ${T.subtasks} WHERE ticket_id = ? ORDER BY position
|
|
263
|
+
`).all(row.id);
|
|
264
|
+
const subtasks = subtaskRows.map((s) => ({
|
|
265
|
+
id: s.id,
|
|
266
|
+
title: s.title,
|
|
267
|
+
done: s.done === 1,
|
|
268
|
+
}));
|
|
269
|
+
// Get metadata
|
|
270
|
+
const metadataRows = this.ctx.db.prepare(`
|
|
271
|
+
SELECT key, value FROM ${T.ticket_metadata} WHERE ticket_id = ?
|
|
272
|
+
`).all(row.id);
|
|
273
|
+
const metadata = {};
|
|
274
|
+
for (const m of metadataRows) {
|
|
275
|
+
metadata[m.key] = m.value;
|
|
276
|
+
}
|
|
277
|
+
// Parse labels from JSON
|
|
278
|
+
let labels = [];
|
|
279
|
+
try {
|
|
280
|
+
labels = row.labels ? JSON.parse(row.labels) : [];
|
|
281
|
+
}
|
|
282
|
+
catch {
|
|
283
|
+
labels = [];
|
|
284
|
+
}
|
|
285
|
+
return {
|
|
286
|
+
id: row.id,
|
|
287
|
+
title: row.title,
|
|
288
|
+
description: row.description || undefined,
|
|
289
|
+
priority: row.priority || undefined,
|
|
290
|
+
category: row.category || undefined,
|
|
291
|
+
statusId: row.status_id || '',
|
|
292
|
+
statusName: row.status_name || undefined,
|
|
293
|
+
statusCategory: row.status_category,
|
|
294
|
+
status: row.status,
|
|
295
|
+
owner: row.owner || undefined,
|
|
296
|
+
assignee: row.assignee || undefined,
|
|
297
|
+
branch: row.branch || undefined,
|
|
298
|
+
specId: row.spec_id || undefined,
|
|
299
|
+
epicId: row.epic_id || undefined,
|
|
300
|
+
subtasks,
|
|
301
|
+
labels,
|
|
302
|
+
metadata,
|
|
303
|
+
acceptanceCriteria: getAcceptanceCriteriaSync(this.ctx.db, row.id),
|
|
304
|
+
createdAt: new Date(row.created_at),
|
|
305
|
+
updatedAt: new Date(row.updated_at),
|
|
306
|
+
lastSyncedFromSpec: row.last_synced_from_spec
|
|
307
|
+
? new Date(row.last_synced_from_spec)
|
|
308
|
+
: undefined,
|
|
309
|
+
lastSyncedFromBoard: row.last_synced_from_board
|
|
310
|
+
? new Date(row.last_synced_from_board)
|
|
311
|
+
: undefined,
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
sortTickets(tickets, sortBy) {
|
|
315
|
+
const sorted = [...tickets];
|
|
316
|
+
switch (sortBy) {
|
|
317
|
+
case 'priority': {
|
|
318
|
+
const priorityOrder = { HIGH: 0, MEDIUM: 1, LOW: 2 };
|
|
319
|
+
sorted.sort((a, b) => {
|
|
320
|
+
const aOrder = priorityOrder[(a.priority || 'MEDIUM').toUpperCase()] ?? 3;
|
|
321
|
+
const bOrder = priorityOrder[(b.priority || 'MEDIUM').toUpperCase()] ?? 3;
|
|
322
|
+
return aOrder - bOrder;
|
|
323
|
+
});
|
|
324
|
+
break;
|
|
325
|
+
}
|
|
326
|
+
case 'created':
|
|
327
|
+
sorted.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
|
|
328
|
+
break;
|
|
329
|
+
case 'updated':
|
|
330
|
+
sorted.sort((a, b) => b.updatedAt.getTime() - a.updatedAt.getTime());
|
|
331
|
+
break;
|
|
332
|
+
case 'title':
|
|
333
|
+
sorted.sort((a, b) => a.title.localeCompare(b.title));
|
|
334
|
+
break;
|
|
335
|
+
case 'assignee':
|
|
336
|
+
sorted.sort((a, b) => (a.assignee || '').localeCompare(b.assignee || ''));
|
|
337
|
+
break;
|
|
338
|
+
}
|
|
339
|
+
return sorted;
|
|
340
|
+
}
|
|
341
|
+
rowToBoardView(row) {
|
|
342
|
+
return {
|
|
343
|
+
id: row.id,
|
|
344
|
+
projectId: row.project_id,
|
|
345
|
+
name: row.name,
|
|
346
|
+
description: row.description || undefined,
|
|
347
|
+
isDefault: row.is_default === 1,
|
|
348
|
+
filters: row.filters ? JSON.parse(row.filters) : {},
|
|
349
|
+
groupBy: row.group_by,
|
|
350
|
+
sortBy: row.sort_by,
|
|
351
|
+
createdAt: new Date(row.created_at),
|
|
352
|
+
updatedAt: new Date(row.updated_at),
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PMO Sync Manager
|
|
3
|
+
*
|
|
4
|
+
* Handles automatic bi-directional sync between SQLite database and board.md:
|
|
5
|
+
* - Auto-sync from board.md before read operations (if file is newer)
|
|
6
|
+
* - Auto-export to board.md after write operations
|
|
7
|
+
*
|
|
8
|
+
* Uses hybrid mtime + content-based sync detection:
|
|
9
|
+
* 1. Check mtime first (fast) - if unchanged, skip
|
|
10
|
+
* 2. If mtime changed, compare content - if same, just update stored mtime
|
|
11
|
+
* 3. If content differs, perform full sync
|
|
12
|
+
*
|
|
13
|
+
* Multi-project support:
|
|
14
|
+
* - Default project: pmo/board.md
|
|
15
|
+
* - Other projects: pmo/board-{projectId}.md
|
|
16
|
+
*
|
|
17
|
+
* Clock source: Uses filesystem mtime which comes from the OS system clock
|
|
18
|
+
* (computer/VM clock depending on where the filesystem resides)
|
|
19
|
+
*/
|
|
20
|
+
import { SQLiteStorage } from './storage-sqlite.js';
|
|
21
|
+
/**
|
|
22
|
+
* Get the board path for a project
|
|
23
|
+
* Standard: pmo/projects/{projectId}/kanban.md
|
|
24
|
+
* Falls back to legacy paths for backwards compatibility
|
|
25
|
+
*/
|
|
26
|
+
export declare function getBoardPath(pmoPath: string, projectId: string): string;
|
|
27
|
+
export interface SyncMetadata {
|
|
28
|
+
lastSyncAt: number;
|
|
29
|
+
lastBoardMtime: number;
|
|
30
|
+
lastDbWriteAt: number;
|
|
31
|
+
contentHash?: string;
|
|
32
|
+
}
|
|
33
|
+
export interface PMOContext {
|
|
34
|
+
pmoPath: string;
|
|
35
|
+
storage: SQLiteStorage;
|
|
36
|
+
storageType: 'sqlite' | 'git';
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Get sync metadata from database
|
|
40
|
+
*/
|
|
41
|
+
export declare function getSyncMetadata(storage: SQLiteStorage): SyncMetadata | null;
|
|
42
|
+
/**
|
|
43
|
+
* Update sync metadata after a sync operation
|
|
44
|
+
*/
|
|
45
|
+
export declare function updateSyncMetadata(storage: SQLiteStorage, boardMtime: number, contentHash?: string): void;
|
|
46
|
+
/**
|
|
47
|
+
* Check if board.md mtime has changed (fast check)
|
|
48
|
+
*/
|
|
49
|
+
export declare function boardMtimeChanged(pmoPath: string, storage: SQLiteStorage, projectId?: string): boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Check if board.md content has actually changed (slower, content-based check)
|
|
52
|
+
* Only called when mtime indicates a potential change
|
|
53
|
+
*/
|
|
54
|
+
export declare function boardContentChanged(pmoPath: string, storage: SQLiteStorage, content: string): boolean;
|
|
55
|
+
/**
|
|
56
|
+
* Auto-sync from board.md if it has changes
|
|
57
|
+
* Uses hybrid mtime + content approach:
|
|
58
|
+
* 1. If mtime unchanged -> skip (fast path)
|
|
59
|
+
* 2. If mtime changed -> check content hash
|
|
60
|
+
* 3. If content same -> just update mtime, skip sync
|
|
61
|
+
* 4. If content different -> perform sync
|
|
62
|
+
*
|
|
63
|
+
* Returns: true if sync performed, false otherwise
|
|
64
|
+
*/
|
|
65
|
+
export declare function autoSyncFromBoard(pmoPath: string, storage: SQLiteStorage, logger?: (msg: string) => void, projectId?: string): boolean;
|
|
66
|
+
/**
|
|
67
|
+
* Auto-export database to board.md after write operations
|
|
68
|
+
*
|
|
69
|
+
* DISABLED: Markdown sync is disabled. DB is the sole source of truth.
|
|
70
|
+
* To re-enable, uncomment the function body below.
|
|
71
|
+
*/
|
|
72
|
+
export declare function autoExportToBoard(_pmoPath: string, _storage: SQLiteStorage, _logger?: (msg: string) => void, _projectId?: string): Promise<void>;
|
|
73
|
+
/**
|
|
74
|
+
* Get the workspace.db path from a PMO path
|
|
75
|
+
* PMO can be at <workspace>/pmo or <workspace>/repos/<repo>/pmo
|
|
76
|
+
* workspace.db is always at <workspace>/.proletariat/workspace.db
|
|
77
|
+
*/
|
|
78
|
+
export declare function getWorkspaceDbPath(pmoPath: string): string;
|
|
79
|
+
/**
|
|
80
|
+
* Get storage with auto-sync from board.md (for read operations)
|
|
81
|
+
* Use this when you need to READ from the database
|
|
82
|
+
*
|
|
83
|
+
* Note: storageType parameter controls sync strategy, not storage engine.
|
|
84
|
+
* - All modes use SQLite (workspace.db) for storage
|
|
85
|
+
* - 'git' mode enables multi-machine sync via git push/pull
|
|
86
|
+
* - 'sqlite' mode is local-only (no multi-machine sync)
|
|
87
|
+
*/
|
|
88
|
+
export declare function getStorageWithAutoSync(pmoPath: string, storageType: 'sqlite' | 'git', logger?: (msg: string) => void): SQLiteStorage;
|
|
89
|
+
/**
|
|
90
|
+
* Wrapper for write operations that auto-exports to board.md after
|
|
91
|
+
*/
|
|
92
|
+
export declare function withAutoExport<T>(pmoPath: string, storage: SQLiteStorage, operation: () => Promise<T>, logger?: (msg: string) => void): Promise<T>;
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PMO Sync Manager
|
|
3
|
+
*
|
|
4
|
+
* Handles automatic bi-directional sync between SQLite database and board.md:
|
|
5
|
+
* - Auto-sync from board.md before read operations (if file is newer)
|
|
6
|
+
* - Auto-export to board.md after write operations
|
|
7
|
+
*
|
|
8
|
+
* Uses hybrid mtime + content-based sync detection:
|
|
9
|
+
* 1. Check mtime first (fast) - if unchanged, skip
|
|
10
|
+
* 2. If mtime changed, compare content - if same, just update stored mtime
|
|
11
|
+
* 3. If content differs, perform full sync
|
|
12
|
+
*
|
|
13
|
+
* Multi-project support:
|
|
14
|
+
* - Default project: pmo/board.md
|
|
15
|
+
* - Other projects: pmo/board-{projectId}.md
|
|
16
|
+
*
|
|
17
|
+
* Clock source: Uses filesystem mtime which comes from the OS system clock
|
|
18
|
+
* (computer/VM clock depending on where the filesystem resides)
|
|
19
|
+
*/
|
|
20
|
+
import * as fs from 'node:fs';
|
|
21
|
+
import * as path from 'node:path';
|
|
22
|
+
import * as crypto from 'node:crypto';
|
|
23
|
+
import { SQLiteStorage } from './storage-sqlite.js';
|
|
24
|
+
import { parseBoard } from './markdown.js';
|
|
25
|
+
/**
|
|
26
|
+
* Get the board path for a project
|
|
27
|
+
* Standard: pmo/projects/{projectId}/kanban.md
|
|
28
|
+
* Falls back to legacy paths for backwards compatibility
|
|
29
|
+
*/
|
|
30
|
+
export function getBoardPath(pmoPath, projectId) {
|
|
31
|
+
const kanbanPath = path.join(pmoPath, 'projects', projectId, 'kanban.md');
|
|
32
|
+
const legacyBoardPath = path.join(pmoPath, 'projects', projectId, 'board.md');
|
|
33
|
+
const legacyProjectKanbanPath = path.join(pmoPath, 'projects', projectId, `${projectId}-kanban.md`);
|
|
34
|
+
const legacyProjectPath = path.join(pmoPath, 'projects', projectId, `${projectId}.md`);
|
|
35
|
+
// Check paths in order of preference
|
|
36
|
+
if (fs.existsSync(kanbanPath)) {
|
|
37
|
+
return kanbanPath;
|
|
38
|
+
}
|
|
39
|
+
if (fs.existsSync(legacyBoardPath)) {
|
|
40
|
+
return legacyBoardPath;
|
|
41
|
+
}
|
|
42
|
+
if (fs.existsSync(legacyProjectKanbanPath)) {
|
|
43
|
+
return legacyProjectKanbanPath;
|
|
44
|
+
}
|
|
45
|
+
if (fs.existsSync(legacyProjectPath)) {
|
|
46
|
+
return legacyProjectPath;
|
|
47
|
+
}
|
|
48
|
+
// Default to standard kanban.md for new projects
|
|
49
|
+
return kanbanPath;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Compute SHA-256 hash of content
|
|
53
|
+
*/
|
|
54
|
+
function computeHash(content) {
|
|
55
|
+
return crypto.createHash('sha256').update(content).digest('hex');
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Get sync metadata from database
|
|
59
|
+
*/
|
|
60
|
+
export function getSyncMetadata(storage) {
|
|
61
|
+
const meta = storage.getCacheMetadata();
|
|
62
|
+
if (!meta)
|
|
63
|
+
return null;
|
|
64
|
+
return {
|
|
65
|
+
lastSyncAt: meta.cacheBuiltAt,
|
|
66
|
+
lastBoardMtime: meta.boardMtime,
|
|
67
|
+
lastDbWriteAt: meta.cacheBuiltAt,
|
|
68
|
+
contentHash: meta.contentHash,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Update sync metadata after a sync operation
|
|
73
|
+
*/
|
|
74
|
+
export function updateSyncMetadata(storage, boardMtime, contentHash) {
|
|
75
|
+
storage.setCacheMetadata({
|
|
76
|
+
boardMtime,
|
|
77
|
+
cacheBuiltAt: Date.now(),
|
|
78
|
+
contentHash,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Check if board.md mtime has changed (fast check)
|
|
83
|
+
*/
|
|
84
|
+
export function boardMtimeChanged(pmoPath, storage, projectId = 'default') {
|
|
85
|
+
const boardPath = getBoardPath(pmoPath, projectId);
|
|
86
|
+
if (!fs.existsSync(boardPath)) {
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
const stats = fs.statSync(boardPath);
|
|
90
|
+
const meta = getSyncMetadata(storage);
|
|
91
|
+
if (!meta) {
|
|
92
|
+
// No sync metadata - board.md exists but never synced
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
// board.md mtime differs from last sync
|
|
96
|
+
return stats.mtimeMs !== meta.lastBoardMtime;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Check if board.md content has actually changed (slower, content-based check)
|
|
100
|
+
* Only called when mtime indicates a potential change
|
|
101
|
+
*/
|
|
102
|
+
export function boardContentChanged(pmoPath, storage, content) {
|
|
103
|
+
const meta = getSyncMetadata(storage);
|
|
104
|
+
if (!meta || !meta.contentHash) {
|
|
105
|
+
// No content hash stored - assume changed
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
const currentHash = computeHash(content);
|
|
109
|
+
return currentHash !== meta.contentHash;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Auto-sync from board.md if it has changes
|
|
113
|
+
* Uses hybrid mtime + content approach:
|
|
114
|
+
* 1. If mtime unchanged -> skip (fast path)
|
|
115
|
+
* 2. If mtime changed -> check content hash
|
|
116
|
+
* 3. If content same -> just update mtime, skip sync
|
|
117
|
+
* 4. If content different -> perform sync
|
|
118
|
+
*
|
|
119
|
+
* Returns: true if sync performed, false otherwise
|
|
120
|
+
*/
|
|
121
|
+
export function autoSyncFromBoard(pmoPath, storage, logger, projectId = 'default') {
|
|
122
|
+
const boardPath = getBoardPath(pmoPath, projectId);
|
|
123
|
+
if (!fs.existsSync(boardPath)) {
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
// Fast path: mtime unchanged
|
|
127
|
+
if (!boardMtimeChanged(pmoPath, storage, projectId)) {
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
// Mtime changed - read content and check hash
|
|
131
|
+
const markdown = fs.readFileSync(boardPath, 'utf-8');
|
|
132
|
+
const stats = fs.statSync(boardPath);
|
|
133
|
+
const contentHash = computeHash(markdown);
|
|
134
|
+
// Check if content actually changed
|
|
135
|
+
if (!boardContentChanged(pmoPath, storage, markdown)) {
|
|
136
|
+
// Content same, just update mtime (file was touched but not modified)
|
|
137
|
+
updateSyncMetadata(storage, stats.mtimeMs, contentHash);
|
|
138
|
+
if (logger) {
|
|
139
|
+
logger(`📋 ${path.basename(boardPath)} touched but unchanged, updated mtime`);
|
|
140
|
+
}
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
// Content changed - perform full sync
|
|
144
|
+
const board = parseBoard(markdown, projectId);
|
|
145
|
+
storage.rebuildFromBoard(board);
|
|
146
|
+
// Update sync metadata with new mtime and hash
|
|
147
|
+
updateSyncMetadata(storage, stats.mtimeMs, contentHash);
|
|
148
|
+
if (logger) {
|
|
149
|
+
logger(`📥 Auto-synced from ${path.basename(boardPath)}`);
|
|
150
|
+
}
|
|
151
|
+
return true;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Auto-export database to board.md after write operations
|
|
155
|
+
*
|
|
156
|
+
* DISABLED: Markdown sync is disabled. DB is the sole source of truth.
|
|
157
|
+
* To re-enable, uncomment the function body below.
|
|
158
|
+
*/
|
|
159
|
+
export async function autoExportToBoard(_pmoPath, _storage, _logger, _projectId) {
|
|
160
|
+
// DISABLED: Markdown export disabled - DB is source of truth
|
|
161
|
+
// Uncomment below to re-enable:
|
|
162
|
+
/*
|
|
163
|
+
const pid = _projectId ?? _storage.getCurrentProjectId();
|
|
164
|
+
const boardPath = getBoardPath(_pmoPath, pid);
|
|
165
|
+
|
|
166
|
+
// Generate markdown from current database state
|
|
167
|
+
const markdown = await _storage.getBoardMarkdown();
|
|
168
|
+
|
|
169
|
+
// Write to board.md
|
|
170
|
+
fs.writeFileSync(boardPath, markdown);
|
|
171
|
+
|
|
172
|
+
// Update sync metadata with new mtime and content hash
|
|
173
|
+
const stats = fs.statSync(boardPath);
|
|
174
|
+
const contentHash = computeHash(markdown);
|
|
175
|
+
updateSyncMetadata(_storage, stats.mtimeMs, contentHash);
|
|
176
|
+
|
|
177
|
+
if (_logger) {
|
|
178
|
+
_logger(`📤 Auto-exported to ${path.basename(boardPath)}`);
|
|
179
|
+
}
|
|
180
|
+
*/
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Get the workspace.db path from a PMO path
|
|
184
|
+
* PMO can be at <workspace>/pmo or <workspace>/repos/<repo>/pmo
|
|
185
|
+
* workspace.db is always at <workspace>/.proletariat/workspace.db
|
|
186
|
+
*/
|
|
187
|
+
export function getWorkspaceDbPath(pmoPath) {
|
|
188
|
+
// Search upward from PMO path to find .proletariat/workspace.db
|
|
189
|
+
let currentDir = path.dirname(pmoPath); // Start from parent of pmo/
|
|
190
|
+
while (currentDir !== '/') {
|
|
191
|
+
const dbPath = path.join(currentDir, '.proletariat', 'workspace.db');
|
|
192
|
+
if (fs.existsSync(dbPath)) {
|
|
193
|
+
return dbPath;
|
|
194
|
+
}
|
|
195
|
+
currentDir = path.dirname(currentDir);
|
|
196
|
+
}
|
|
197
|
+
// Fallback to old behavior if not found
|
|
198
|
+
const workspacePath = path.dirname(pmoPath);
|
|
199
|
+
return path.join(workspacePath, '.proletariat', 'workspace.db');
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Get storage with auto-sync from board.md (for read operations)
|
|
203
|
+
* Use this when you need to READ from the database
|
|
204
|
+
*
|
|
205
|
+
* Note: storageType parameter controls sync strategy, not storage engine.
|
|
206
|
+
* - All modes use SQLite (workspace.db) for storage
|
|
207
|
+
* - 'git' mode enables multi-machine sync via git push/pull
|
|
208
|
+
* - 'sqlite' mode is local-only (no multi-machine sync)
|
|
209
|
+
*/
|
|
210
|
+
export function getStorageWithAutoSync(pmoPath, storageType, logger) {
|
|
211
|
+
// Storage is always workspace.db (unified PMO tables with foreign keys to agents)
|
|
212
|
+
const dbPath = getWorkspaceDbPath(pmoPath);
|
|
213
|
+
if (!fs.existsSync(dbPath)) {
|
|
214
|
+
throw new Error(`Database not found at ${dbPath}. Run 'prlt init' first.`);
|
|
215
|
+
}
|
|
216
|
+
// Note: Storage no longer holds project context - projectId is passed explicitly to operations
|
|
217
|
+
const storage = new SQLiteStorage(dbPath);
|
|
218
|
+
return storage;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Wrapper for write operations that auto-exports to board.md after
|
|
222
|
+
*/
|
|
223
|
+
export async function withAutoExport(pmoPath, storage, operation, logger) {
|
|
224
|
+
// Run the operation
|
|
225
|
+
const result = await operation();
|
|
226
|
+
// Auto-export to board.md
|
|
227
|
+
await autoExportToBoard(pmoPath, storage, logger);
|
|
228
|
+
return result;
|
|
229
|
+
}
|