@proletariat/cli 0.3.71 → 0.3.73
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/dist/commands/action/create.d.ts +6 -2
- package/dist/commands/action/create.js +108 -40
- package/dist/commands/action/create.js.map +1 -1
- package/dist/commands/action/delete.js +1 -1
- package/dist/commands/action/delete.js.map +1 -1
- package/dist/commands/action/list.d.ts +1 -1
- package/dist/commands/action/list.js +12 -10
- package/dist/commands/action/list.js.map +1 -1
- package/dist/commands/action/run.js +3 -3
- package/dist/commands/action/run.js.map +1 -1
- package/dist/commands/action/show.js +25 -4
- package/dist/commands/action/show.js.map +1 -1
- package/dist/commands/action/update.d.ts +6 -2
- package/dist/commands/action/update.js +131 -53
- package/dist/commands/action/update.js.map +1 -1
- package/dist/commands/agent/auth.js +4 -0
- package/dist/commands/agent/auth.js.map +1 -1
- package/dist/commands/agent/cleanup.js +1 -1
- package/dist/commands/agent/cleanup.js.map +1 -1
- package/dist/commands/agent/discover.js +1 -0
- package/dist/commands/agent/discover.js.map +1 -1
- package/dist/commands/agent/index.js +2 -0
- package/dist/commands/agent/index.js.map +1 -1
- package/dist/commands/agent/rebuild.js +1 -1
- package/dist/commands/agent/rebuild.js.map +1 -1
- package/dist/commands/agent/remove.js +1 -1
- package/dist/commands/agent/remove.js.map +1 -1
- package/dist/commands/agent/restart.js +1 -1
- package/dist/commands/agent/restart.js.map +1 -1
- package/dist/commands/agent/visit.js +1 -1
- package/dist/commands/agent/visit.js.map +1 -1
- package/dist/commands/asana/connect.js +6 -5
- package/dist/commands/asana/connect.js.map +1 -1
- package/dist/commands/asana/import.js +4 -4
- package/dist/commands/asana/import.js.map +1 -1
- package/dist/commands/asana/sync.js +3 -3
- package/dist/commands/asana/sync.js.map +1 -1
- package/dist/commands/autocomplete/setup.js +2 -1
- package/dist/commands/autocomplete/setup.js.map +1 -1
- package/dist/commands/board/index.js +1 -0
- package/dist/commands/board/index.js.map +1 -1
- package/dist/commands/board/view.js +1 -1
- package/dist/commands/board/view.js.map +1 -1
- package/dist/commands/branch/create.js +1 -1
- package/dist/commands/branch/create.js.map +1 -1
- package/dist/commands/branch/validate.js +2 -0
- package/dist/commands/branch/validate.js.map +1 -1
- package/dist/commands/branch/where.js +1 -0
- package/dist/commands/branch/where.js.map +1 -1
- package/dist/commands/category/create.js +3 -0
- package/dist/commands/category/create.js.map +1 -1
- package/dist/commands/category/delete.js +3 -0
- package/dist/commands/category/delete.js.map +1 -1
- package/dist/commands/category/rename.js +6 -0
- package/dist/commands/category/rename.js.map +1 -1
- package/dist/commands/claude/index.js +5 -5
- package/dist/commands/claude/index.js.map +1 -1
- package/dist/commands/claude/open.js +5 -0
- package/dist/commands/claude/open.js.map +1 -1
- package/dist/commands/commit.js +1 -1
- package/dist/commands/commit.js.map +1 -1
- package/dist/commands/config/index.js +6 -1
- package/dist/commands/config/index.js.map +1 -1
- package/dist/commands/dashboard.js +1 -0
- package/dist/commands/dashboard.js.map +1 -1
- package/dist/commands/diet.js +1 -0
- package/dist/commands/diet.js.map +1 -1
- package/dist/commands/docker/clean.js +2 -0
- package/dist/commands/docker/clean.js.map +1 -1
- package/dist/commands/docker/index.js +1 -0
- package/dist/commands/docker/index.js.map +1 -1
- package/dist/commands/docker/logs.js +6 -0
- package/dist/commands/docker/logs.js.map +1 -1
- package/dist/commands/docker/prune.js +1 -0
- package/dist/commands/docker/prune.js.map +1 -1
- package/dist/commands/docker/restart.js +5 -0
- package/dist/commands/docker/restart.js.map +1 -1
- package/dist/commands/docker/start.js +4 -0
- package/dist/commands/docker/start.js.map +1 -1
- package/dist/commands/docker/stop.js +4 -0
- package/dist/commands/docker/stop.js.map +1 -1
- package/dist/commands/epic/activate.js +1 -1
- package/dist/commands/epic/activate.js.map +1 -1
- package/dist/commands/epic/archive.js +1 -1
- package/dist/commands/epic/archive.js.map +1 -1
- package/dist/commands/epic/create.js +4 -0
- package/dist/commands/epic/create.js.map +1 -1
- package/dist/commands/epic/delete.js +1 -1
- package/dist/commands/epic/delete.js.map +1 -1
- package/dist/commands/epic/move.js +1 -1
- package/dist/commands/epic/move.js.map +1 -1
- package/dist/commands/epic/progress.js +1 -0
- package/dist/commands/epic/progress.js.map +1 -1
- package/dist/commands/epic/project.js +1 -1
- package/dist/commands/epic/project.js.map +1 -1
- package/dist/commands/epic/reorder.js +1 -1
- package/dist/commands/epic/reorder.js.map +1 -1
- package/dist/commands/epic/spec.js +1 -1
- package/dist/commands/epic/spec.js.map +1 -1
- package/dist/commands/epic/ticket.js +1 -1
- package/dist/commands/epic/ticket.js.map +1 -1
- package/dist/commands/epic/view.js +1 -1
- package/dist/commands/epic/view.js.map +1 -1
- package/dist/commands/execution/config.js +7 -1
- package/dist/commands/execution/config.js.map +1 -1
- package/dist/commands/execution/list.js +1 -0
- package/dist/commands/execution/list.js.map +1 -1
- package/dist/commands/execution/logs.js +1 -0
- package/dist/commands/execution/logs.js.map +1 -1
- package/dist/commands/execution/stop.js +2 -0
- package/dist/commands/execution/stop.js.map +1 -1
- package/dist/commands/execution/view.js +3 -1
- package/dist/commands/execution/view.js.map +1 -1
- package/dist/commands/feedback/list.js +2 -0
- package/dist/commands/feedback/list.js.map +1 -1
- package/dist/commands/feedback/submit.js +2 -0
- package/dist/commands/feedback/submit.js.map +1 -1
- package/dist/commands/feedback/view.js +2 -0
- package/dist/commands/feedback/view.js.map +1 -1
- package/dist/commands/gh/login.js +1 -1
- package/dist/commands/gh/login.js.map +1 -1
- package/dist/commands/gh/token.js +1 -1
- package/dist/commands/gh/token.js.map +1 -1
- package/dist/commands/linear/auth.js +4 -4
- package/dist/commands/linear/auth.js.map +1 -1
- package/dist/commands/linear/connect.js +10 -5
- package/dist/commands/linear/connect.js.map +1 -1
- package/dist/commands/linear/import.js +4 -3
- package/dist/commands/linear/import.js.map +1 -1
- package/dist/commands/linear/sync.js +3 -3
- package/dist/commands/linear/sync.js.map +1 -1
- package/dist/commands/link/create.js +1 -1
- package/dist/commands/link/create.js.map +1 -1
- package/dist/commands/link/list.js +1 -1
- package/dist/commands/link/list.js.map +1 -1
- package/dist/commands/link/remove.js +1 -1
- package/dist/commands/link/remove.js.map +1 -1
- package/dist/commands/media/add.js +2 -1
- package/dist/commands/media/add.js.map +1 -1
- package/dist/commands/media/index.js +2 -0
- package/dist/commands/media/index.js.map +1 -1
- package/dist/commands/media/list.js +1 -0
- package/dist/commands/media/list.js.map +1 -1
- package/dist/commands/media/preprocess.js +1 -1
- package/dist/commands/media/preprocess.js.map +1 -1
- package/dist/commands/media/remove.js +2 -1
- package/dist/commands/media/remove.js.map +1 -1
- package/dist/commands/media/show.js +1 -1
- package/dist/commands/media/show.js.map +1 -1
- package/dist/commands/monday/connect.js +4 -4
- package/dist/commands/monday/connect.js.map +1 -1
- package/dist/commands/monday/sync.js +4 -4
- package/dist/commands/monday/sync.js.map +1 -1
- package/dist/commands/new.js +1 -0
- package/dist/commands/new.js.map +1 -1
- package/dist/commands/orchestrator/start.js +2 -0
- package/dist/commands/orchestrator/start.js.map +1 -1
- package/dist/commands/phase/delete.js +1 -1
- package/dist/commands/phase/delete.js.map +1 -1
- package/dist/commands/phase/move.js +1 -1
- package/dist/commands/phase/move.js.map +1 -1
- package/dist/commands/phase/template/delete.js +1 -0
- package/dist/commands/phase/template/delete.js.map +1 -1
- package/dist/commands/phase/update.js +1 -1
- package/dist/commands/phase/update.js.map +1 -1
- package/dist/commands/pmo/init.js +2 -2
- package/dist/commands/pmo/init.js.map +1 -1
- package/dist/commands/pr/checks.js +1 -1
- package/dist/commands/pr/checks.js.map +1 -1
- package/dist/commands/pr/create.js +1 -1
- package/dist/commands/pr/create.js.map +1 -1
- package/dist/commands/pr/index.js +1 -1
- package/dist/commands/pr/index.js.map +1 -1
- package/dist/commands/pr/link.js +3 -3
- package/dist/commands/pr/link.js.map +1 -1
- package/dist/commands/pr/list.js +1 -1
- package/dist/commands/pr/list.js.map +1 -1
- package/dist/commands/pr/merge.js +1 -1
- package/dist/commands/pr/merge.js.map +1 -1
- package/dist/commands/pr/status.js +1 -1
- package/dist/commands/pr/status.js.map +1 -1
- package/dist/commands/priority/add.js +2 -2
- package/dist/commands/priority/add.js.map +1 -1
- package/dist/commands/priority/remove.js +2 -2
- package/dist/commands/priority/remove.js.map +1 -1
- package/dist/commands/priority/set.js +2 -2
- package/dist/commands/priority/set.js.map +1 -1
- package/dist/commands/project/archive.js +1 -1
- package/dist/commands/project/archive.js.map +1 -1
- package/dist/commands/project/create.js +4 -0
- package/dist/commands/project/create.js.map +1 -1
- package/dist/commands/project/delete.js +1 -1
- package/dist/commands/project/delete.js.map +1 -1
- package/dist/commands/project/spec.js +1 -1
- package/dist/commands/project/spec.js.map +1 -1
- package/dist/commands/project/unarchive.js +1 -1
- package/dist/commands/project/unarchive.js.map +1 -1
- package/dist/commands/project/update.js +1 -1
- package/dist/commands/project/update.js.map +1 -1
- package/dist/commands/project/view.js +1 -1
- package/dist/commands/project/view.js.map +1 -1
- package/dist/commands/pull.js +3 -0
- package/dist/commands/pull.js.map +1 -1
- package/dist/commands/qa/index.js +4 -4
- package/dist/commands/qa/index.js.map +1 -1
- package/dist/commands/repo/add.js +1 -1
- package/dist/commands/repo/add.js.map +1 -1
- package/dist/commands/repo/create.js +1 -1
- package/dist/commands/repo/create.js.map +1 -1
- package/dist/commands/repo/remove.js +2 -2
- package/dist/commands/repo/remove.js.map +1 -1
- package/dist/commands/repo/view.js +1 -1
- package/dist/commands/repo/view.js.map +1 -1
- package/dist/commands/roadmap/create.js +1 -0
- package/dist/commands/roadmap/create.js.map +1 -1
- package/dist/commands/session/create.js +4 -0
- package/dist/commands/session/create.js.map +1 -1
- package/dist/commands/session/exec.js +4 -0
- package/dist/commands/session/exec.js.map +1 -1
- package/dist/commands/session/health.js +2 -0
- package/dist/commands/session/health.js.map +1 -1
- package/dist/commands/session/inspect.js +3 -0
- package/dist/commands/session/inspect.js.map +1 -1
- package/dist/commands/session/peek.js +1 -0
- package/dist/commands/session/peek.js.map +1 -1
- package/dist/commands/session/restart.js +4 -0
- package/dist/commands/session/restart.js.map +1 -1
- package/dist/commands/shortcut/connect.js +4 -4
- package/dist/commands/shortcut/connect.js.map +1 -1
- package/dist/commands/staff/remove.js +1 -1
- package/dist/commands/staff/remove.js.map +1 -1
- package/dist/commands/status/delete.js +2 -1
- package/dist/commands/status/delete.js.map +1 -1
- package/dist/commands/status/list.js +1 -0
- package/dist/commands/status/list.js.map +1 -1
- package/dist/commands/status/move.js +2 -1
- package/dist/commands/status/move.js.map +1 -1
- package/dist/commands/status/update.js +1 -1
- package/dist/commands/status/update.js.map +1 -1
- package/dist/commands/telemetry/disable.js +1 -0
- package/dist/commands/telemetry/disable.js.map +1 -1
- package/dist/commands/telemetry/enable.js +1 -0
- package/dist/commands/telemetry/enable.js.map +1 -1
- package/dist/commands/telemetry/index.js +1 -0
- package/dist/commands/telemetry/index.js.map +1 -1
- package/dist/commands/template/apply.js +2 -2
- package/dist/commands/template/apply.js.map +1 -1
- package/dist/commands/template/delete.js +1 -0
- package/dist/commands/template/delete.js.map +1 -1
- package/dist/commands/template/save.js +1 -0
- package/dist/commands/template/save.js.map +1 -1
- package/dist/commands/template/update.js +1 -0
- package/dist/commands/template/update.js.map +1 -1
- package/dist/commands/ticket/complete.js +1 -1
- package/dist/commands/ticket/complete.js.map +1 -1
- package/dist/commands/ticket/create.js +14 -4
- package/dist/commands/ticket/create.js.map +1 -1
- package/dist/commands/ticket/delete.js +23 -8
- package/dist/commands/ticket/delete.js.map +1 -1
- package/dist/commands/ticket/edit.js +2 -2
- package/dist/commands/ticket/edit.js.map +1 -1
- package/dist/commands/ticket/link/block.js +1 -1
- package/dist/commands/ticket/link/block.js.map +1 -1
- package/dist/commands/ticket/link/duplicates.js +1 -1
- package/dist/commands/ticket/link/duplicates.js.map +1 -1
- package/dist/commands/ticket/link/relates.js +1 -1
- package/dist/commands/ticket/link/relates.js.map +1 -1
- package/dist/commands/ticket/list.d.ts +0 -8
- package/dist/commands/ticket/list.js +15 -121
- package/dist/commands/ticket/list.js.map +1 -1
- package/dist/commands/ticket/move.js +34 -7
- package/dist/commands/ticket/move.js.map +1 -1
- package/dist/commands/ticket/resolve.js +2 -2
- package/dist/commands/ticket/resolve.js.map +1 -1
- package/dist/commands/ticket/status.js +1 -1
- package/dist/commands/ticket/status.js.map +1 -1
- package/dist/commands/ticket/template/delete.js +1 -0
- package/dist/commands/ticket/template/delete.js.map +1 -1
- package/dist/commands/ticket/template/save.js +1 -0
- package/dist/commands/ticket/template/save.js.map +1 -1
- package/dist/commands/ticket/update.js +1 -0
- package/dist/commands/ticket/update.js.map +1 -1
- package/dist/commands/ticket/view.js +1 -1
- package/dist/commands/ticket/view.js.map +1 -1
- package/dist/commands/tools/add.js +6 -0
- package/dist/commands/tools/add.js.map +1 -1
- package/dist/commands/tools/remove.js +3 -0
- package/dist/commands/tools/remove.js.map +1 -1
- package/dist/commands/trello/configure.js +5 -5
- package/dist/commands/trello/configure.js.map +1 -1
- package/dist/commands/trello/import.js +4 -4
- package/dist/commands/trello/import.js.map +1 -1
- package/dist/commands/trello/sync.js +3 -3
- package/dist/commands/trello/sync.js.map +1 -1
- package/dist/commands/version/bump.js +3 -0
- package/dist/commands/version/bump.js.map +1 -1
- package/dist/commands/work/complete.js +34 -1
- package/dist/commands/work/complete.js.map +1 -1
- package/dist/commands/work/hooks/add.js +7 -0
- package/dist/commands/work/hooks/add.js.map +1 -1
- package/dist/commands/work/hooks/list.js +2 -0
- package/dist/commands/work/hooks/list.js.map +1 -1
- package/dist/commands/work/hooks/remove.js +4 -0
- package/dist/commands/work/hooks/remove.js.map +1 -1
- package/dist/commands/work/hooks/toggle.js +4 -0
- package/dist/commands/work/hooks/toggle.js.map +1 -1
- package/dist/commands/work/ready.js +48 -7
- package/dist/commands/work/ready.js.map +1 -1
- package/dist/commands/work/resolve.js +1 -1
- package/dist/commands/work/resolve.js.map +1 -1
- package/dist/commands/work/review.js +3 -1
- package/dist/commands/work/review.js.map +1 -1
- package/dist/commands/work/revise.js +1 -1
- package/dist/commands/work/revise.js.map +1 -1
- package/dist/commands/work/source/set.js +3 -0
- package/dist/commands/work/source/set.js.map +1 -1
- package/dist/commands/work/source.js +1 -0
- package/dist/commands/work/source.js.map +1 -1
- package/dist/commands/work/spawn.js +4 -3
- package/dist/commands/work/spawn.js.map +1 -1
- package/dist/commands/work/start.js +121 -24
- package/dist/commands/work/start.js.map +1 -1
- package/dist/commands/work/watch.js +1 -1
- package/dist/commands/work/watch.js.map +1 -1
- package/dist/commands/workflow/delete.js +1 -1
- package/dist/commands/workflow/delete.js.map +1 -1
- package/dist/commands/workflow/setup.d.ts +24 -0
- package/dist/commands/workflow/setup.js +351 -0
- package/dist/commands/workflow/setup.js.map +1 -0
- package/dist/commands/workflow/switch.js +1 -1
- package/dist/commands/workflow/switch.js.map +1 -1
- package/dist/commands/workflow/view.js +1 -1
- package/dist/commands/workflow/view.js.map +1 -1
- package/dist/commands/workflow-rule/create.d.ts +19 -0
- package/dist/commands/workflow-rule/create.js +141 -0
- package/dist/commands/workflow-rule/create.js.map +1 -0
- package/dist/commands/workflow-rule/delete.d.ts +18 -0
- package/dist/commands/workflow-rule/delete.js +72 -0
- package/dist/commands/workflow-rule/delete.js.map +1 -0
- package/dist/commands/workflow-rule/index.d.ts +16 -0
- package/dist/commands/workflow-rule/index.js +83 -0
- package/dist/commands/workflow-rule/index.js.map +1 -0
- package/dist/commands/workflow-rule/list.d.ts +17 -0
- package/dist/commands/workflow-rule/list.js +72 -0
- package/dist/commands/workflow-rule/list.js.map +1 -0
- package/dist/commands/workflow-rule/update.d.ts +22 -0
- package/dist/commands/workflow-rule/update.js +84 -0
- package/dist/commands/workflow-rule/update.js.map +1 -0
- package/dist/commands/workspace/add.js +5 -0
- package/dist/commands/workspace/add.js.map +1 -1
- package/dist/commands/workspace/remove.js +1 -1
- package/dist/commands/workspace/remove.js.map +1 -1
- package/dist/hooks/init.js +37 -11
- package/dist/hooks/init.js.map +1 -1
- package/dist/hooks/postrun.d.ts +6 -4
- package/dist/hooks/postrun.js +25 -18
- package/dist/hooks/postrun.js.map +1 -1
- package/dist/lib/database/drizzle-schema.d.ts +269 -4
- package/dist/lib/database/drizzle-schema.js +22 -2
- package/dist/lib/database/drizzle-schema.js.map +1 -1
- package/dist/lib/database/migrations/0003_actions_redesign.d.ts +15 -0
- package/dist/lib/database/migrations/0003_actions_redesign.js +105 -0
- package/dist/lib/database/migrations/0003_actions_redesign.js.map +1 -0
- package/dist/lib/database/migrations/0004_workflow_rules.d.ts +2 -0
- package/dist/lib/database/migrations/0004_workflow_rules.js +25 -0
- package/dist/lib/database/migrations/0004_workflow_rules.js.map +1 -0
- package/dist/lib/database/migrations/index.js +4 -0
- package/dist/lib/database/migrations/index.js.map +1 -1
- package/dist/lib/events/events.d.ts +13 -1
- package/dist/lib/execution/commit-validation.d.ts +58 -0
- package/dist/lib/execution/commit-validation.js +252 -0
- package/dist/lib/execution/commit-validation.js.map +1 -0
- package/dist/lib/execution/config.js +3 -0
- package/dist/lib/execution/config.js.map +1 -1
- package/dist/lib/execution/storage.d.ts +24 -1
- package/dist/lib/execution/storage.js +35 -6
- package/dist/lib/execution/storage.js.map +1 -1
- package/dist/lib/flags/resolver.js +3 -6
- package/dist/lib/flags/resolver.js.map +1 -1
- package/dist/lib/linear/client.d.ts +4 -0
- package/dist/lib/linear/client.js +12 -0
- package/dist/lib/linear/client.js.map +1 -1
- package/dist/lib/onboarding/wizard.js +3 -3
- package/dist/lib/onboarding/wizard.js.map +1 -1
- package/dist/lib/pmo/base-command.d.ts +21 -1
- package/dist/lib/pmo/base-command.js +28 -4
- package/dist/lib/pmo/base-command.js.map +1 -1
- package/dist/lib/pmo/schema.d.ts +3 -1
- package/dist/lib/pmo/schema.js +25 -3
- package/dist/lib/pmo/schema.js.map +1 -1
- package/dist/lib/pmo/storage/actions.d.ts +5 -3
- package/dist/lib/pmo/storage/actions.js +89 -23
- package/dist/lib/pmo/storage/actions.js.map +1 -1
- package/dist/lib/pmo/storage/base.d.ts +5 -0
- package/dist/lib/pmo/storage/base.js +203 -20
- package/dist/lib/pmo/storage/base.js.map +1 -1
- package/dist/lib/pmo/storage/index.d.ts +9 -2
- package/dist/lib/pmo/storage/index.js +28 -3
- package/dist/lib/pmo/storage/index.js.map +1 -1
- package/dist/lib/pmo/storage/types.d.ts +19 -2
- package/dist/lib/pmo/storage/workflow-rules.d.ts +35 -0
- package/dist/lib/pmo/storage/workflow-rules.js +183 -0
- package/dist/lib/pmo/storage/workflow-rules.js.map +1 -0
- package/dist/lib/pmo/sync-manager.js +6 -0
- package/dist/lib/pmo/sync-manager.js.map +1 -1
- package/dist/lib/pmo/types.d.ts +59 -4
- package/dist/lib/pmo/types.js.map +1 -1
- package/dist/lib/prompt-command.js +1 -1
- package/dist/lib/prompt-command.js.map +1 -1
- package/dist/lib/prompt-json.d.ts +19 -11
- package/dist/lib/prompt-json.js +32 -17
- package/dist/lib/prompt-json.js.map +1 -1
- package/dist/lib/providers/index.d.ts +11 -0
- package/dist/lib/providers/index.js +11 -0
- package/dist/lib/providers/index.js.map +1 -0
- package/dist/lib/providers/linear-provider.d.ts +26 -0
- package/dist/lib/providers/linear-provider.js +339 -0
- package/dist/lib/providers/linear-provider.js.map +1 -0
- package/dist/lib/providers/pmo-provider.d.ts +20 -0
- package/dist/lib/providers/pmo-provider.js +83 -0
- package/dist/lib/providers/pmo-provider.js.map +1 -0
- package/dist/lib/providers/resolver.d.ts +44 -0
- package/dist/lib/providers/resolver.js +82 -0
- package/dist/lib/providers/resolver.js.map +1 -0
- package/dist/lib/providers/types.d.ts +136 -0
- package/dist/lib/providers/types.js +12 -0
- package/dist/lib/providers/types.js.map +1 -0
- package/dist/lib/telemetry/analytics.d.ts +25 -7
- package/dist/lib/telemetry/analytics.js +123 -58
- package/dist/lib/telemetry/analytics.js.map +1 -1
- package/dist/lib/update-prompt.d.ts +3 -3
- package/dist/lib/update-prompt.js +15 -10
- package/dist/lib/update-prompt.js.map +1 -1
- package/dist/lib/work-lifecycle/action-chaining.d.ts +61 -0
- package/dist/lib/work-lifecycle/action-chaining.js +211 -0
- package/dist/lib/work-lifecycle/action-chaining.js.map +1 -0
- package/dist/lib/work-lifecycle/index.d.ts +4 -0
- package/dist/lib/work-lifecycle/index.js +4 -0
- package/dist/lib/work-lifecycle/index.js.map +1 -1
- package/dist/lib/work-lifecycle/post-execution.d.ts +85 -0
- package/dist/lib/work-lifecycle/post-execution.js +120 -0
- package/dist/lib/work-lifecycle/post-execution.js.map +1 -0
- package/dist/lib/work-lifecycle/rule-evaluator.d.ts +38 -0
- package/dist/lib/work-lifecycle/rule-evaluator.js +102 -0
- package/dist/lib/work-lifecycle/rule-evaluator.js.map +1 -0
- package/oclif.manifest.json +4248 -3757
- package/package.json +1 -1
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Action Chaining Handler
|
|
3
|
+
*
|
|
4
|
+
* Listens for workflow_rule:matched events on the EventBus and automatically
|
|
5
|
+
* spawns the next agent action when an on_enter rule fires.
|
|
6
|
+
*
|
|
7
|
+
* Example chain:
|
|
8
|
+
* implement completes → lifecycle hook moves to Review →
|
|
9
|
+
* on_enter rule fires merge → ticket moves to Done
|
|
10
|
+
*
|
|
11
|
+
* Safety guards:
|
|
12
|
+
* - Max chain depth of 5 per ticket to prevent infinite loops
|
|
13
|
+
* - Skips if an agent is already running for the ticket
|
|
14
|
+
* - Only fires on_enter rules (manual rules are user-initiated)
|
|
15
|
+
* - Respects the enabled flag on rules
|
|
16
|
+
*/
|
|
17
|
+
import type Database from 'better-sqlite3';
|
|
18
|
+
import type { SQLiteStorage } from '../pmo/storage-sqlite.js';
|
|
19
|
+
export declare class ActionChainingHandler {
|
|
20
|
+
private unsubscribers;
|
|
21
|
+
private chainDepths;
|
|
22
|
+
private db;
|
|
23
|
+
private storage;
|
|
24
|
+
private pmoPath;
|
|
25
|
+
private log;
|
|
26
|
+
constructor(db: Database.Database, storage: SQLiteStorage, pmoPath: string, log?: (msg: string) => void);
|
|
27
|
+
/**
|
|
28
|
+
* Start listening for workflow rule matches.
|
|
29
|
+
*/
|
|
30
|
+
start(): void;
|
|
31
|
+
/**
|
|
32
|
+
* Stop listening for events and clean up.
|
|
33
|
+
*/
|
|
34
|
+
stop(): void;
|
|
35
|
+
/**
|
|
36
|
+
* Handle a workflow rule match by spawning the next action in the chain.
|
|
37
|
+
*/
|
|
38
|
+
private handleRuleMatched;
|
|
39
|
+
/**
|
|
40
|
+
* Spawn an agent to execute the chained action.
|
|
41
|
+
* Lazily resolves workspace info and agent selection.
|
|
42
|
+
*/
|
|
43
|
+
private spawnChainedAction;
|
|
44
|
+
/**
|
|
45
|
+
* Get the current chain depth for a ticket (for testing/debugging).
|
|
46
|
+
*/
|
|
47
|
+
getChainDepth(ticketId: string): number;
|
|
48
|
+
/**
|
|
49
|
+
* Reset chain depth for a ticket (e.g., when a ticket is manually moved).
|
|
50
|
+
*/
|
|
51
|
+
resetChainDepth(ticketId: string): void;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Initialize and start the action chaining handler.
|
|
55
|
+
* Safe to call multiple times — subsequent calls are no-ops.
|
|
56
|
+
*/
|
|
57
|
+
export declare function initActionChaining(db: Database.Database, storage: SQLiteStorage, pmoPath: string, log?: (msg: string) => void): ActionChainingHandler;
|
|
58
|
+
/**
|
|
59
|
+
* Stop the action chaining handler (primarily for testing).
|
|
60
|
+
*/
|
|
61
|
+
export declare function stopActionChaining(): void;
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Action Chaining Handler
|
|
3
|
+
*
|
|
4
|
+
* Listens for workflow_rule:matched events on the EventBus and automatically
|
|
5
|
+
* spawns the next agent action when an on_enter rule fires.
|
|
6
|
+
*
|
|
7
|
+
* Example chain:
|
|
8
|
+
* implement completes → lifecycle hook moves to Review →
|
|
9
|
+
* on_enter rule fires merge → ticket moves to Done
|
|
10
|
+
*
|
|
11
|
+
* Safety guards:
|
|
12
|
+
* - Max chain depth of 5 per ticket to prevent infinite loops
|
|
13
|
+
* - Skips if an agent is already running for the ticket
|
|
14
|
+
* - Only fires on_enter rules (manual rules are user-initiated)
|
|
15
|
+
* - Respects the enabled flag on rules
|
|
16
|
+
*/
|
|
17
|
+
import { getEventBus } from '../events/event-bus.js';
|
|
18
|
+
import { PMO_TABLES } from '../pmo/schema.js';
|
|
19
|
+
import { ExecutionStorage } from '../execution/storage.js';
|
|
20
|
+
import { trackEvent } from '../telemetry/analytics.js';
|
|
21
|
+
// =============================================================================
|
|
22
|
+
// Constants
|
|
23
|
+
// =============================================================================
|
|
24
|
+
/** Maximum chain depth per ticket to prevent infinite loops. */
|
|
25
|
+
const MAX_CHAIN_DEPTH = 5;
|
|
26
|
+
// =============================================================================
|
|
27
|
+
// Handler
|
|
28
|
+
// =============================================================================
|
|
29
|
+
export class ActionChainingHandler {
|
|
30
|
+
unsubscribers = [];
|
|
31
|
+
chainDepths = new Map();
|
|
32
|
+
db;
|
|
33
|
+
storage;
|
|
34
|
+
pmoPath;
|
|
35
|
+
log;
|
|
36
|
+
constructor(db, storage, pmoPath, log) {
|
|
37
|
+
this.db = db;
|
|
38
|
+
this.storage = storage;
|
|
39
|
+
this.pmoPath = pmoPath;
|
|
40
|
+
this.log = log ?? (() => { });
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Start listening for workflow rule matches.
|
|
44
|
+
*/
|
|
45
|
+
start() {
|
|
46
|
+
const bus = getEventBus();
|
|
47
|
+
this.unsubscribers.push(bus.on('workflow_rule:matched', (event) => {
|
|
48
|
+
void this.handleRuleMatched(event);
|
|
49
|
+
}));
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Stop listening for events and clean up.
|
|
53
|
+
*/
|
|
54
|
+
stop() {
|
|
55
|
+
for (const unsub of this.unsubscribers) {
|
|
56
|
+
unsub();
|
|
57
|
+
}
|
|
58
|
+
this.unsubscribers = [];
|
|
59
|
+
this.chainDepths.clear();
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Handle a workflow rule match by spawning the next action in the chain.
|
|
63
|
+
*/
|
|
64
|
+
async handleRuleMatched(event) {
|
|
65
|
+
const { ticketId, actionId, ruleId, trigger, toState } = event;
|
|
66
|
+
// Only fire on_enter rules — manual rules are user-initiated
|
|
67
|
+
if (trigger !== 'on_enter')
|
|
68
|
+
return;
|
|
69
|
+
// Check chain depth to prevent infinite loops
|
|
70
|
+
const depth = this.chainDepths.get(ticketId) ?? 0;
|
|
71
|
+
if (depth >= MAX_CHAIN_DEPTH) {
|
|
72
|
+
this.log(`[action-chain] Depth limit reached for ${ticketId} (depth=${depth}, max=${MAX_CHAIN_DEPTH}). Stopping chain.`);
|
|
73
|
+
trackEvent('action_chain_blocked', null, {
|
|
74
|
+
ticket_id: ticketId,
|
|
75
|
+
action_id: actionId,
|
|
76
|
+
rule_id: ruleId,
|
|
77
|
+
reason: 'max_depth',
|
|
78
|
+
depth: String(depth),
|
|
79
|
+
});
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
// Check if an agent is already running for this ticket
|
|
83
|
+
const executionStorage = new ExecutionStorage(this.db);
|
|
84
|
+
const runningExec = executionStorage.getRunningExecution(ticketId);
|
|
85
|
+
if (runningExec) {
|
|
86
|
+
this.log(`[action-chain] Agent already running for ${ticketId} (execution=${runningExec.id}). Skipping chain.`);
|
|
87
|
+
trackEvent('action_chain_blocked', null, {
|
|
88
|
+
ticket_id: ticketId,
|
|
89
|
+
action_id: actionId,
|
|
90
|
+
rule_id: ruleId,
|
|
91
|
+
reason: 'agent_running',
|
|
92
|
+
});
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
// Look up the action
|
|
96
|
+
const action = this.db
|
|
97
|
+
.prepare(`SELECT * FROM ${PMO_TABLES.actions} WHERE id = ?`)
|
|
98
|
+
.get(actionId);
|
|
99
|
+
if (!action) {
|
|
100
|
+
this.log(`[action-chain] Action ${actionId} not found. Skipping chain for ${ticketId}.`);
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
// Increment chain depth before spawning
|
|
104
|
+
this.chainDepths.set(ticketId, depth + 1);
|
|
105
|
+
this.log(`[action-chain] Firing action "${action.name}" for ${ticketId} (rule=${ruleId}, state=${toState}, depth=${depth + 1})`);
|
|
106
|
+
// Spawn the agent
|
|
107
|
+
try {
|
|
108
|
+
await this.spawnChainedAction(ticketId, event.projectId, action);
|
|
109
|
+
trackEvent('action_chain_fired', null, {
|
|
110
|
+
ticket_id: ticketId,
|
|
111
|
+
action_id: actionId,
|
|
112
|
+
action_name: action.name,
|
|
113
|
+
rule_id: ruleId,
|
|
114
|
+
to_state: toState,
|
|
115
|
+
chain_depth: String(depth + 1),
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
catch (error) {
|
|
119
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
120
|
+
this.log(`[action-chain] Failed to spawn action "${action.name}" for ${ticketId}: ${errorMsg}`);
|
|
121
|
+
trackEvent('action_chain_error', null, {
|
|
122
|
+
ticket_id: ticketId,
|
|
123
|
+
action_id: actionId,
|
|
124
|
+
rule_id: ruleId,
|
|
125
|
+
error: errorMsg,
|
|
126
|
+
});
|
|
127
|
+
// Roll back chain depth on failure so it can be retried
|
|
128
|
+
this.chainDepths.set(ticketId, depth);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Spawn an agent to execute the chained action.
|
|
133
|
+
* Lazily resolves workspace info and agent selection.
|
|
134
|
+
*/
|
|
135
|
+
async spawnChainedAction(ticketId, projectId, action) {
|
|
136
|
+
// Lazy imports to avoid circular dependencies and reduce startup cost
|
|
137
|
+
const { getWorkspaceInfo } = await import('../agents/commands.js');
|
|
138
|
+
const { spawnAgentForTicket, getAvailableAgents } = await import('../execution/spawner.js');
|
|
139
|
+
// Get workspace info (may throw if not in a workspace)
|
|
140
|
+
const workspaceInfo = getWorkspaceInfo();
|
|
141
|
+
// Get execution storage for agent availability check
|
|
142
|
+
const executionStorage = new ExecutionStorage(this.db);
|
|
143
|
+
// Get available agents
|
|
144
|
+
const availableAgents = getAvailableAgents(workspaceInfo, executionStorage);
|
|
145
|
+
if (availableAgents.length === 0) {
|
|
146
|
+
this.log(`[action-chain] No agents available for ${ticketId}. Chain paused.`);
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
// Select the first available agent
|
|
150
|
+
const agentName = availableAgents[0];
|
|
151
|
+
// Get the ticket
|
|
152
|
+
const ticket = await this.storage.getTicket(ticketId);
|
|
153
|
+
if (!ticket) {
|
|
154
|
+
this.log(`[action-chain] Ticket ${ticketId} not found. Skipping.`);
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
// Ensure projectId is set on ticket
|
|
158
|
+
if (!ticket.projectId) {
|
|
159
|
+
ticket.projectId = projectId;
|
|
160
|
+
}
|
|
161
|
+
// Spawn the agent with the action's configuration
|
|
162
|
+
// Note: chained actions always run in background mode
|
|
163
|
+
const result = await spawnAgentForTicket(ticket, agentName, this.storage, executionStorage, workspaceInfo, this.db, this.pmoPath, {
|
|
164
|
+
displayMode: 'background',
|
|
165
|
+
log: (msg) => this.log(`[action-chain] ${msg}`),
|
|
166
|
+
});
|
|
167
|
+
if (result.success) {
|
|
168
|
+
this.log(`[action-chain] Spawned ${agentName} for ${ticketId} → action "${action.name}" (execution=${result.executionId})`);
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
throw new Error(result.error || 'Unknown spawn error');
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Get the current chain depth for a ticket (for testing/debugging).
|
|
176
|
+
*/
|
|
177
|
+
getChainDepth(ticketId) {
|
|
178
|
+
return this.chainDepths.get(ticketId) ?? 0;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Reset chain depth for a ticket (e.g., when a ticket is manually moved).
|
|
182
|
+
*/
|
|
183
|
+
resetChainDepth(ticketId) {
|
|
184
|
+
this.chainDepths.delete(ticketId);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
// =============================================================================
|
|
188
|
+
// Singleton
|
|
189
|
+
// =============================================================================
|
|
190
|
+
let _handler;
|
|
191
|
+
/**
|
|
192
|
+
* Initialize and start the action chaining handler.
|
|
193
|
+
* Safe to call multiple times — subsequent calls are no-ops.
|
|
194
|
+
*/
|
|
195
|
+
export function initActionChaining(db, storage, pmoPath, log) {
|
|
196
|
+
if (!_handler) {
|
|
197
|
+
_handler = new ActionChainingHandler(db, storage, pmoPath, log);
|
|
198
|
+
_handler.start();
|
|
199
|
+
}
|
|
200
|
+
return _handler;
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Stop the action chaining handler (primarily for testing).
|
|
204
|
+
*/
|
|
205
|
+
export function stopActionChaining() {
|
|
206
|
+
if (_handler) {
|
|
207
|
+
_handler.stop();
|
|
208
|
+
_handler = undefined;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
//# sourceMappingURL=action-chaining.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"action-chaining.js","sourceRoot":"","sources":["../../../src/lib/work-lifecycle/action-chaining.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,3 +8,7 @@
|
|
|
8
8
|
export type { WorkEventSource, WorkStartedEvent, WorkStatusChangedEvent, WorkPRCreatedEvent, WorkCompletedEvent, } from './events.js';
|
|
9
9
|
export { WorkLifecycleAdapter, initWorkLifecycleAdapter, stopWorkLifecycleAdapter, } from './adapter.js';
|
|
10
10
|
export { initHookManager, stopHookManager, } from './hooks/index.js';
|
|
11
|
+
export { handlePostExecutionTransition, type PostExecutionContext, type PostExecutionResult, } from './post-execution.js';
|
|
12
|
+
export { validateCommits, tryValidateCommits, type CommitValidationResult, } from '../execution/commit-validation.js';
|
|
13
|
+
export { WorkflowRuleEvaluator, initWorkflowRuleEvaluator, stopWorkflowRuleEvaluator, } from './rule-evaluator.js';
|
|
14
|
+
export { ActionChainingHandler, initActionChaining, stopActionChaining, } from './action-chaining.js';
|
|
@@ -7,4 +7,8 @@
|
|
|
7
7
|
*/
|
|
8
8
|
export { WorkLifecycleAdapter, initWorkLifecycleAdapter, stopWorkLifecycleAdapter, } from './adapter.js';
|
|
9
9
|
export { initHookManager, stopHookManager, } from './hooks/index.js';
|
|
10
|
+
export { handlePostExecutionTransition, } from './post-execution.js';
|
|
11
|
+
export { validateCommits, tryValidateCommits, } from '../execution/commit-validation.js';
|
|
12
|
+
export { WorkflowRuleEvaluator, initWorkflowRuleEvaluator, stopWorkflowRuleEvaluator, } from './rule-evaluator.js';
|
|
13
|
+
export { ActionChainingHandler, initActionChaining, stopActionChaining, } from './action-chaining.js';
|
|
10
14
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/work-lifecycle/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAUH,OAAO,EACL,oBAAoB,EACpB,wBAAwB,EACxB,wBAAwB,GACzB,MAAM,cAAc,CAAA;AAErB,OAAO,EACL,eAAe,EACf,eAAe,GAChB,MAAM,kBAAkB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/work-lifecycle/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAUH,OAAO,EACL,oBAAoB,EACpB,wBAAwB,EACxB,wBAAwB,GACzB,MAAM,cAAc,CAAA;AAErB,OAAO,EACL,eAAe,EACf,eAAe,GAChB,MAAM,kBAAkB,CAAA;AAEzB,OAAO,EACL,6BAA6B,GAG9B,MAAM,qBAAqB,CAAA;AAE5B,OAAO,EACL,eAAe,EACf,kBAAkB,GAEnB,MAAM,mCAAmC,CAAA;AAE1C,OAAO,EACL,qBAAqB,EACrB,yBAAyB,EACzB,yBAAyB,GAC1B,MAAM,qBAAqB,CAAA;AAE5B,OAAO,EACL,qBAAqB,EACrB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,sBAAsB,CAAA"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Post-Execution Transition Hook
|
|
3
|
+
*
|
|
4
|
+
* Handles automatic ticket state transitions after an action execution completes.
|
|
5
|
+
* Primary use case: when the implement action completes and a PR was created,
|
|
6
|
+
* automatically move the ticket from In Progress to Review.
|
|
7
|
+
*
|
|
8
|
+
* Includes commit validation (PRLT-984): before auto-transitioning, checks that
|
|
9
|
+
* meaningful code was committed on the branch. Prevents agents that only wrote
|
|
10
|
+
* boilerplate (README) from being marked as ready for review.
|
|
11
|
+
*
|
|
12
|
+
* Uses the provider abstraction to write directly to the configured provider
|
|
13
|
+
* (Linear, Jira, etc.) — not through the local PMO as a cache layer.
|
|
14
|
+
* The local PMO is just the default provider for users without integrations.
|
|
15
|
+
*/
|
|
16
|
+
import Database from 'better-sqlite3';
|
|
17
|
+
import type { StateCategory } from '../pmo/types.js';
|
|
18
|
+
import type { ProviderStorage } from '../providers/types.js';
|
|
19
|
+
import { type CommitValidationResult } from '../execution/commit-validation.js';
|
|
20
|
+
export interface PostExecutionContext {
|
|
21
|
+
ticketId: string;
|
|
22
|
+
actionId?: string;
|
|
23
|
+
/** Agent name — used to resolve the agent's repository for commit validation */
|
|
24
|
+
agentName?: string;
|
|
25
|
+
/** Branch name — used for commit validation */
|
|
26
|
+
branch?: string;
|
|
27
|
+
/** Agent directory path — used to find the git repository */
|
|
28
|
+
agentDir?: string;
|
|
29
|
+
/** Repo worktree names within agentDir */
|
|
30
|
+
repoWorktrees?: string[];
|
|
31
|
+
}
|
|
32
|
+
export interface PostExecutionResult {
|
|
33
|
+
transitioned: boolean;
|
|
34
|
+
fromState?: string;
|
|
35
|
+
toState?: string;
|
|
36
|
+
/** Which provider handled the transition */
|
|
37
|
+
provider?: string;
|
|
38
|
+
/** Error from the provider (transition may have partially succeeded) */
|
|
39
|
+
providerError?: string;
|
|
40
|
+
/** Commit validation result (PRLT-984) — present when validation was attempted */
|
|
41
|
+
validation?: CommitValidationResult;
|
|
42
|
+
/** True if the transition was blocked by commit validation */
|
|
43
|
+
blockedByValidation?: boolean;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Minimal storage interface for post-execution transitions.
|
|
47
|
+
* @deprecated Use ProviderStorage from providers/types.ts instead.
|
|
48
|
+
*/
|
|
49
|
+
export interface PostExecutionStorage {
|
|
50
|
+
getTicket: (id: string) => Promise<{
|
|
51
|
+
id: string;
|
|
52
|
+
projectId?: string;
|
|
53
|
+
statusName?: string;
|
|
54
|
+
statusCategory?: StateCategory | null;
|
|
55
|
+
metadata?: Record<string, string> | null;
|
|
56
|
+
} | null>;
|
|
57
|
+
getProjectBoard: (projectId: string) => Promise<{
|
|
58
|
+
columns: Array<{
|
|
59
|
+
name: string;
|
|
60
|
+
}>;
|
|
61
|
+
} | null>;
|
|
62
|
+
moveTicket: (projectId: string, ticketId: string, columnName: string) => Promise<unknown>;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Check if a completed execution should trigger an automatic state transition.
|
|
66
|
+
*
|
|
67
|
+
* When an execution completes and the ticket:
|
|
68
|
+
* 1. Is in a "started" category (e.g., In Progress)
|
|
69
|
+
* 2. Has a PR URL in its metadata
|
|
70
|
+
* 3. Has meaningful code committed (not just boilerplate) — PRLT-984
|
|
71
|
+
*
|
|
72
|
+
* Then automatically move the ticket to the Review column via the appropriate
|
|
73
|
+
* provider (Linear, Jira, or local PMO).
|
|
74
|
+
*
|
|
75
|
+
* Provider resolution:
|
|
76
|
+
* - If the ticket has an external_source (e.g., 'linear') and that provider
|
|
77
|
+
* is configured, write directly to that provider's API.
|
|
78
|
+
* - Otherwise, write to the local PMO (default for users without integrations).
|
|
79
|
+
*
|
|
80
|
+
* @param context - Execution context with ticket and optional action/agent info
|
|
81
|
+
* @param storage - PMO storage instance for ticket operations
|
|
82
|
+
* @param db - Database for work column settings and provider config
|
|
83
|
+
* @returns Result indicating whether a transition occurred
|
|
84
|
+
*/
|
|
85
|
+
export declare function handlePostExecutionTransition(context: PostExecutionContext, storage: PostExecutionStorage | ProviderStorage, db: Database.Database): Promise<PostExecutionResult>;
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Post-Execution Transition Hook
|
|
3
|
+
*
|
|
4
|
+
* Handles automatic ticket state transitions after an action execution completes.
|
|
5
|
+
* Primary use case: when the implement action completes and a PR was created,
|
|
6
|
+
* automatically move the ticket from In Progress to Review.
|
|
7
|
+
*
|
|
8
|
+
* Includes commit validation (PRLT-984): before auto-transitioning, checks that
|
|
9
|
+
* meaningful code was committed on the branch. Prevents agents that only wrote
|
|
10
|
+
* boilerplate (README) from being marked as ready for review.
|
|
11
|
+
*
|
|
12
|
+
* Uses the provider abstraction to write directly to the configured provider
|
|
13
|
+
* (Linear, Jira, etc.) — not through the local PMO as a cache layer.
|
|
14
|
+
* The local PMO is just the default provider for users without integrations.
|
|
15
|
+
*/
|
|
16
|
+
import { getWorkColumnSetting, findColumnByName } from '../pmo/utils.js';
|
|
17
|
+
import { resolveTicketProvider } from '../providers/resolver.js';
|
|
18
|
+
import { tryValidateCommits } from '../execution/commit-validation.js';
|
|
19
|
+
/**
|
|
20
|
+
* Check if a completed execution should trigger an automatic state transition.
|
|
21
|
+
*
|
|
22
|
+
* When an execution completes and the ticket:
|
|
23
|
+
* 1. Is in a "started" category (e.g., In Progress)
|
|
24
|
+
* 2. Has a PR URL in its metadata
|
|
25
|
+
* 3. Has meaningful code committed (not just boilerplate) — PRLT-984
|
|
26
|
+
*
|
|
27
|
+
* Then automatically move the ticket to the Review column via the appropriate
|
|
28
|
+
* provider (Linear, Jira, or local PMO).
|
|
29
|
+
*
|
|
30
|
+
* Provider resolution:
|
|
31
|
+
* - If the ticket has an external_source (e.g., 'linear') and that provider
|
|
32
|
+
* is configured, write directly to that provider's API.
|
|
33
|
+
* - Otherwise, write to the local PMO (default for users without integrations).
|
|
34
|
+
*
|
|
35
|
+
* @param context - Execution context with ticket and optional action/agent info
|
|
36
|
+
* @param storage - PMO storage instance for ticket operations
|
|
37
|
+
* @param db - Database for work column settings and provider config
|
|
38
|
+
* @returns Result indicating whether a transition occurred
|
|
39
|
+
*/
|
|
40
|
+
export async function handlePostExecutionTransition(context, storage, db) {
|
|
41
|
+
// Get the ticket to check current state and PR status
|
|
42
|
+
const ticket = await storage.getTicket(context.ticketId);
|
|
43
|
+
if (!ticket || !ticket.projectId) {
|
|
44
|
+
return { transitioned: false };
|
|
45
|
+
}
|
|
46
|
+
// Only auto-transition tickets that are in the "started" category (In Progress)
|
|
47
|
+
if (ticket.statusCategory !== 'started') {
|
|
48
|
+
return { transitioned: false };
|
|
49
|
+
}
|
|
50
|
+
// Check if a PR was created (PR URL exists in ticket metadata)
|
|
51
|
+
const prUrl = ticket.metadata?.pr_url;
|
|
52
|
+
if (!prUrl) {
|
|
53
|
+
return { transitioned: false };
|
|
54
|
+
}
|
|
55
|
+
// PRLT-984: Validate that meaningful code was committed before transitioning.
|
|
56
|
+
// If agent info is available (branch + agentDir), run commit validation.
|
|
57
|
+
// If validation fails, block the auto-transition.
|
|
58
|
+
let validation;
|
|
59
|
+
if (context.branch && context.agentDir) {
|
|
60
|
+
try {
|
|
61
|
+
const result = tryValidateCommits(context.agentDir, context.branch, context.repoWorktrees);
|
|
62
|
+
if (result) {
|
|
63
|
+
validation = result;
|
|
64
|
+
if (!result.passed) {
|
|
65
|
+
return {
|
|
66
|
+
transitioned: false,
|
|
67
|
+
fromState: ticket.statusName,
|
|
68
|
+
validation,
|
|
69
|
+
blockedByValidation: true,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
// Non-fatal: validation failure shouldn't block everything.
|
|
76
|
+
// If we can't validate, allow the transition to proceed.
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
// Get the Review column name
|
|
80
|
+
const targetColumnName = getWorkColumnSetting(db, 'review');
|
|
81
|
+
// Get board columns to find the review column
|
|
82
|
+
const board = await storage.getProjectBoard(ticket.projectId);
|
|
83
|
+
if (!board) {
|
|
84
|
+
return { transitioned: false };
|
|
85
|
+
}
|
|
86
|
+
const columnNames = board.columns.map(col => col.name);
|
|
87
|
+
const reviewColumn = findColumnByName(columnNames, targetColumnName);
|
|
88
|
+
if (!reviewColumn) {
|
|
89
|
+
return { transitioned: false };
|
|
90
|
+
}
|
|
91
|
+
// Already in Review — skip
|
|
92
|
+
if (ticket.statusName === reviewColumn) {
|
|
93
|
+
return { transitioned: false };
|
|
94
|
+
}
|
|
95
|
+
// Resolve the appropriate provider for this ticket
|
|
96
|
+
// Cast to ProviderStorage — at runtime the actual object is SQLiteStorage
|
|
97
|
+
// which implements the full interface. For post-execution, only moveTicket is used.
|
|
98
|
+
const provider = resolveTicketProvider(context.ticketId, ticket.projectId, db, storage, ticket.metadata);
|
|
99
|
+
// Move ticket via the provider
|
|
100
|
+
const previousState = ticket.statusName;
|
|
101
|
+
const moveResult = await provider.moveTicket(context.ticketId, reviewColumn);
|
|
102
|
+
if (!moveResult.success) {
|
|
103
|
+
return {
|
|
104
|
+
transitioned: false,
|
|
105
|
+
fromState: previousState,
|
|
106
|
+
toState: reviewColumn,
|
|
107
|
+
provider: moveResult.provider,
|
|
108
|
+
providerError: moveResult.error,
|
|
109
|
+
validation,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
return {
|
|
113
|
+
transitioned: true,
|
|
114
|
+
fromState: previousState,
|
|
115
|
+
toState: reviewColumn,
|
|
116
|
+
provider: moveResult.provider,
|
|
117
|
+
validation,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=post-execution.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"post-execution.js","sourceRoot":"","sources":["../../../src/lib/work-lifecycle/post-execution.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workflow Rule Evaluator
|
|
3
|
+
*
|
|
4
|
+
* Subscribes to ticket:status_changed events on the global EventBus and
|
|
5
|
+
* evaluates workflow rules when a ticket enters a new state.
|
|
6
|
+
*
|
|
7
|
+
* For on_enter rules, emits a work:rule_matched event so that
|
|
8
|
+
* downstream systems (orchestrators, hooks) can fire the associated action.
|
|
9
|
+
* For manual rules, the match is logged but no action is auto-fired.
|
|
10
|
+
*/
|
|
11
|
+
import type Database from 'better-sqlite3';
|
|
12
|
+
export declare class WorkflowRuleEvaluator {
|
|
13
|
+
private unsubscribers;
|
|
14
|
+
private db;
|
|
15
|
+
constructor(db: Database.Database);
|
|
16
|
+
/**
|
|
17
|
+
* Start listening for ticket state changes.
|
|
18
|
+
*/
|
|
19
|
+
start(): void;
|
|
20
|
+
/**
|
|
21
|
+
* Stop listening for events.
|
|
22
|
+
*/
|
|
23
|
+
stop(): void;
|
|
24
|
+
/**
|
|
25
|
+
* Evaluate workflow rules for a status change event.
|
|
26
|
+
* Finds all enabled rules matching the new state and emits events for on_enter rules.
|
|
27
|
+
*/
|
|
28
|
+
private evaluate;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Initialize and start the workflow rule evaluator.
|
|
32
|
+
* Safe to call multiple times — subsequent calls are no-ops.
|
|
33
|
+
*/
|
|
34
|
+
export declare function initWorkflowRuleEvaluator(db: Database.Database): WorkflowRuleEvaluator;
|
|
35
|
+
/**
|
|
36
|
+
* Stop the workflow rule evaluator (primarily for testing).
|
|
37
|
+
*/
|
|
38
|
+
export declare function stopWorkflowRuleEvaluator(): void;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workflow Rule Evaluator
|
|
3
|
+
*
|
|
4
|
+
* Subscribes to ticket:status_changed events on the global EventBus and
|
|
5
|
+
* evaluates workflow rules when a ticket enters a new state.
|
|
6
|
+
*
|
|
7
|
+
* For on_enter rules, emits a work:rule_matched event so that
|
|
8
|
+
* downstream systems (orchestrators, hooks) can fire the associated action.
|
|
9
|
+
* For manual rules, the match is logged but no action is auto-fired.
|
|
10
|
+
*/
|
|
11
|
+
import { getEventBus } from '../events/event-bus.js';
|
|
12
|
+
import { PMO_TABLES } from '../pmo/schema.js';
|
|
13
|
+
export class WorkflowRuleEvaluator {
|
|
14
|
+
unsubscribers = [];
|
|
15
|
+
db;
|
|
16
|
+
constructor(db) {
|
|
17
|
+
this.db = db;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Start listening for ticket state changes.
|
|
21
|
+
*/
|
|
22
|
+
start() {
|
|
23
|
+
const bus = getEventBus();
|
|
24
|
+
this.unsubscribers.push(bus.on('ticket:status_changed', (event) => {
|
|
25
|
+
this.evaluate(event);
|
|
26
|
+
}));
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Stop listening for events.
|
|
30
|
+
*/
|
|
31
|
+
stop() {
|
|
32
|
+
for (const unsub of this.unsubscribers) {
|
|
33
|
+
unsub();
|
|
34
|
+
}
|
|
35
|
+
this.unsubscribers = [];
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Evaluate workflow rules for a status change event.
|
|
39
|
+
* Finds all enabled rules matching the new state and emits events for on_enter rules.
|
|
40
|
+
*/
|
|
41
|
+
evaluate(event) {
|
|
42
|
+
if (!event.newStatusName)
|
|
43
|
+
return;
|
|
44
|
+
try {
|
|
45
|
+
// Find all enabled rules where to_state matches the new status
|
|
46
|
+
const rows = this.db.prepare(`
|
|
47
|
+
SELECT * FROM ${PMO_TABLES.workflow_rules}
|
|
48
|
+
WHERE to_state = ? AND enabled = 1
|
|
49
|
+
`).all(event.newStatusName);
|
|
50
|
+
if (rows.length === 0)
|
|
51
|
+
return;
|
|
52
|
+
const bus = getEventBus();
|
|
53
|
+
for (const row of rows) {
|
|
54
|
+
// If from_state is set, it must match the previous status
|
|
55
|
+
if (row.from_state && row.from_state !== event.previousStatusName) {
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
// Emit rule_matched event for on_enter triggers
|
|
59
|
+
if (row.trigger === 'on_enter') {
|
|
60
|
+
bus.emit('workflow_rule:matched', {
|
|
61
|
+
ruleId: row.id,
|
|
62
|
+
ticketId: event.ticketId,
|
|
63
|
+
projectId: event.projectId,
|
|
64
|
+
actionId: row.action_id,
|
|
65
|
+
trigger: row.trigger,
|
|
66
|
+
fromState: row.from_state,
|
|
67
|
+
toState: row.to_state,
|
|
68
|
+
timestamp: new Date(),
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
// Rule evaluation errors are non-fatal
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
// =============================================================================
|
|
79
|
+
// Singleton
|
|
80
|
+
// =============================================================================
|
|
81
|
+
let _evaluator;
|
|
82
|
+
/**
|
|
83
|
+
* Initialize and start the workflow rule evaluator.
|
|
84
|
+
* Safe to call multiple times — subsequent calls are no-ops.
|
|
85
|
+
*/
|
|
86
|
+
export function initWorkflowRuleEvaluator(db) {
|
|
87
|
+
if (!_evaluator) {
|
|
88
|
+
_evaluator = new WorkflowRuleEvaluator(db);
|
|
89
|
+
_evaluator.start();
|
|
90
|
+
}
|
|
91
|
+
return _evaluator;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Stop the workflow rule evaluator (primarily for testing).
|
|
95
|
+
*/
|
|
96
|
+
export function stopWorkflowRuleEvaluator() {
|
|
97
|
+
if (_evaluator) {
|
|
98
|
+
_evaluator.stop();
|
|
99
|
+
_evaluator = undefined;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=rule-evaluator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rule-evaluator.js","sourceRoot":"","sources":["../../../src/lib/work-lifecycle/rule-evaluator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAA;AAEpD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAY7C,MAAM,OAAO,qBAAqB;IACxB,aAAa,GAAsB,EAAE,CAAA;IACrC,EAAE,CAAmB;IAE7B,YAAY,EAAqB;QAC/B,IAAI,CAAC,EAAE,GAAG,EAAE,CAAA;IACd,CAAC;IAED;;OAEG;IACH,KAAK;QACH,MAAM,GAAG,GAAG,WAAW,EAAE,CAAA;QAEzB,IAAI,CAAC,aAAa,CAAC,IAAI,CACrB,GAAG,CAAC,EAAE,CAAC,uBAAuB,EAAE,CAAC,KAA+B,EAAE,EAAE;YAClE,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;QACtB,CAAC,CAAC,CACH,CAAA;IACH,CAAC;IAED;;OAEG;IACH,IAAI;QACF,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACvC,KAAK,EAAE,CAAA;QACT,CAAC;QACD,IAAI,CAAC,aAAa,GAAG,EAAE,CAAA;IACzB,CAAC;IAED;;;OAGG;IACK,QAAQ,CAAC,KAA+B;QAC9C,IAAI,CAAC,KAAK,CAAC,aAAa;YAAE,OAAM;QAEhC,IAAI,CAAC;YACH,+DAA+D;YAC/D,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC;wBACX,UAAU,CAAC,cAAc;;OAE1C,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,aAAa,CAAsB,CAAA;YAEhD,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAM;YAE7B,MAAM,GAAG,GAAG,WAAW,EAAE,CAAA;YAEzB,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;gBACvB,0DAA0D;gBAC1D,IAAI,GAAG,CAAC,UAAU,IAAI,GAAG,CAAC,UAAU,KAAK,KAAK,CAAC,kBAAkB,EAAE,CAAC;oBAClE,SAAQ;gBACV,CAAC;gBAED,gDAAgD;gBAChD,IAAI,GAAG,CAAC,OAAO,KAAK,UAAU,EAAE,CAAC;oBAC/B,GAAG,CAAC,IAAI,CAAC,uBAAuB,EAAE;wBAChC,MAAM,EAAE,GAAG,CAAC,EAAE;wBACd,QAAQ,EAAE,KAAK,CAAC,QAAQ;wBACxB,SAAS,EAAE,KAAK,CAAC,SAAS;wBAC1B,QAAQ,EAAE,GAAG,CAAC,SAAS;wBACvB,OAAO,EAAE,GAAG,CAAC,OAA8B;wBAC3C,SAAS,EAAE,GAAG,CAAC,UAAU;wBACzB,OAAO,EAAE,GAAG,CAAC,QAAQ;wBACrB,SAAS,EAAE,IAAI,IAAI,EAAE;qBACtB,CAAC,CAAA;gBACJ,CAAC;YACH,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,uCAAuC;QACzC,CAAC;IACH,CAAC;CACF;AAED,gFAAgF;AAChF,YAAY;AACZ,gFAAgF;AAEhF,IAAI,UAA6C,CAAA;AAEjD;;;GAGG;AACH,MAAM,UAAU,yBAAyB,CAAC,EAAqB;IAC7D,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,UAAU,GAAG,IAAI,qBAAqB,CAAC,EAAE,CAAC,CAAA;QAC1C,UAAU,CAAC,KAAK,EAAE,CAAA;IACpB,CAAC;IACD,OAAO,UAAU,CAAA;AACnB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,yBAAyB;IACvC,IAAI,UAAU,EAAE,CAAC;QACf,UAAU,CAAC,IAAI,EAAE,CAAA;QACjB,UAAU,GAAG,SAAS,CAAA;IACxB,CAAC;AACH,CAAC"}
|