bosun 0.40.21 → 0.41.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +8 -0
- package/README.md +20 -0
- package/agent/agent-custom-tools.mjs +23 -5
- package/agent/agent-event-bus.mjs +248 -6
- package/agent/agent-pool.mjs +131 -30
- package/agent/agent-work-analyzer.mjs +8 -16
- package/agent/primary-agent.mjs +81 -7
- package/agent/retry-queue.mjs +164 -0
- package/bench/swebench/bosun-swebench.mjs +5 -0
- package/bosun.config.example.json +25 -0
- package/bosun.schema.json +825 -183
- package/cli.mjs +267 -8
- package/config/config-doctor.mjs +51 -2
- package/config/config.mjs +232 -5
- package/github/github-auth-manager.mjs +70 -19
- package/infra/library-manager.mjs +894 -60
- package/infra/monitor.mjs +701 -69
- package/infra/runtime-accumulator.mjs +376 -84
- package/infra/session-tracker.mjs +95 -28
- package/infra/test-runtime.mjs +267 -0
- package/lib/codebase-audit.mjs +133 -18
- package/package.json +30 -8
- package/server/setup-web-server.mjs +29 -1
- package/server/ui-server.mjs +1571 -49
- package/setup.mjs +27 -24
- package/shell/codex-shell.mjs +34 -3
- package/shell/copilot-shell.mjs +50 -8
- package/task/msg-hub.mjs +193 -0
- package/task/pipeline.mjs +544 -0
- package/task/task-claims.mjs +6 -10
- package/task/task-cli.mjs +38 -2
- package/task/task-executor-pipeline.mjs +143 -0
- package/task/task-executor.mjs +36 -27
- package/telegram/get-telegram-chat-id.mjs +57 -47
- package/ui/components/chat-view.js +18 -1
- package/ui/components/workspace-switcher.js +321 -9
- package/ui/demo-defaults.js +17830 -10433
- package/ui/demo.html +9 -1
- package/ui/modules/router.js +1 -1
- package/ui/modules/settings-schema.js +2 -0
- package/ui/modules/state.js +54 -57
- package/ui/modules/voice-client-sdk.js +376 -37
- package/ui/modules/voice-client.js +173 -33
- package/ui/setup.html +68 -2
- package/ui/styles/components.css +571 -1
- package/ui/styles.css +201 -1
- package/ui/tabs/dashboard.js +74 -0
- package/ui/tabs/library.js +410 -55
- package/ui/tabs/logs.js +10 -0
- package/ui/tabs/settings.js +178 -99
- package/ui/tabs/tasks.js +1083 -507
- package/ui/tabs/telemetry.js +34 -0
- package/ui/tabs/workflow-canvas-utils.mjs +38 -1
- package/ui/tabs/workflows.js +1275 -402
- package/voice/voice-agents-sdk.mjs +2 -2
- package/voice/voice-relay.mjs +28 -20
- package/workflow/declarative-workflows.mjs +145 -0
- package/workflow/msg-hub.mjs +237 -0
- package/workflow/pipeline-workflows.mjs +287 -0
- package/workflow/pipeline.mjs +828 -315
- package/workflow/project-detection.mjs +559 -0
- package/workflow/workflow-cli.mjs +128 -0
- package/workflow/workflow-contract.mjs +433 -232
- package/workflow/workflow-engine.mjs +510 -47
- package/workflow/workflow-nodes/custom-loader.mjs +251 -0
- package/workflow/workflow-nodes.mjs +2024 -184
- package/workflow/workflow-templates.mjs +118 -24
- package/workflow-templates/agents.mjs +20 -20
- package/workflow-templates/bosun-native.mjs +212 -2
- package/workflow-templates/code-quality.mjs +20 -14
- package/workflow-templates/continuation-loop.mjs +339 -0
- package/workflow-templates/github.mjs +516 -40
- package/workflow-templates/planning.mjs +446 -17
- package/workflow-templates/reliability.mjs +65 -12
- package/workflow-templates/task-batch.mjs +27 -10
- package/workflow-templates/task-execution.mjs +752 -0
- package/workflow-templates/task-lifecycle.mjs +117 -14
- package/workspace/context-cache.mjs +66 -18
- package/workspace/workspace-manager.mjs +153 -1
- package/workflow-templates/issue-continuation.mjs +0 -243
|
@@ -46,12 +46,30 @@ export const ERROR_RECOVERY_TEMPLATE = {
|
|
|
46
46
|
}, { x: 400, y: 180 }),
|
|
47
47
|
|
|
48
48
|
node("analyze-error", "action.run_agent", "Analyze Failure", {
|
|
49
|
-
prompt:
|
|
49
|
+
prompt:
|
|
50
|
+
"Analyze the following task failure and suggest the most likely minimal fix.\n\n" +
|
|
51
|
+
"Task: {{taskTitle}} ({{taskId}})\n" +
|
|
52
|
+
"Retry attempt: {{$data?.retryCount || 0}}/{{$data?.maxRetries || 3}}\n" +
|
|
53
|
+
"Branch: {{branch}}\n" +
|
|
54
|
+
"Base branch: {{baseBranch}}\n" +
|
|
55
|
+
"Worktree: {{worktreePath}}\n\n" +
|
|
56
|
+
"Last error:\n{{lastError}}",
|
|
50
57
|
timeoutMs: 300000,
|
|
51
58
|
}, { x: 200, y: 330 }),
|
|
52
59
|
|
|
53
60
|
node("retry-task", "action.run_agent", "Retry Task", {
|
|
54
|
-
prompt:
|
|
61
|
+
prompt:
|
|
62
|
+
"{{taskExecutorRetryPrompt}}\n\n" +
|
|
63
|
+
"Failure context:\n" +
|
|
64
|
+
"- taskId: {{taskId}}\n" +
|
|
65
|
+
"- taskTitle: {{taskTitle}}\n" +
|
|
66
|
+
"- branch: {{branch}}\n" +
|
|
67
|
+
"- baseBranch: {{baseBranch}}\n" +
|
|
68
|
+
"- worktreePath: {{worktreePath}}\n" +
|
|
69
|
+
"- retryCount: {{$data?.retryCount || 0}}/{{$data?.maxRetries || 3}}\n" +
|
|
70
|
+
"- lastError: {{lastError}}\n" +
|
|
71
|
+
"- recoveryAnalysis: {{$ctx.getNodeOutput('analyze-error')?.output || ''}}\n\n" +
|
|
72
|
+
"Use the analysis to choose a different approach if the previous attempt failed.",
|
|
55
73
|
timeoutMs: 3600000,
|
|
56
74
|
failOnError: true,
|
|
57
75
|
maxRetries: "{{maxRetries}}",
|
|
@@ -69,13 +87,17 @@ export const ERROR_RECOVERY_TEMPLATE = {
|
|
|
69
87
|
}, { x: 90, y: 760 }),
|
|
70
88
|
|
|
71
89
|
node("escalate", "notify.telegram", "Escalate to Human", {
|
|
72
|
-
message:
|
|
90
|
+
message:
|
|
91
|
+
":alert: Task **{{taskTitle}}** failed after {{maxRetries}} attempts. Manual intervention needed.\n\n" +
|
|
92
|
+
"Last error: {{lastError}}\n\n" +
|
|
93
|
+
"Recovery analysis: {{$ctx.getNodeOutput('analyze-error')?.output || ''}}",
|
|
73
94
|
}, { x: 600, y: 620 }),
|
|
74
95
|
|
|
75
96
|
node("chain-repair", "action.execute_workflow", "Trigger Repair Workflow", {
|
|
76
97
|
workflowId: "template-task-repair-worktree",
|
|
77
98
|
mode: "dispatch",
|
|
78
|
-
input:
|
|
99
|
+
input:
|
|
100
|
+
"(() => { const analysisRaw = String($ctx.getNodeOutput('analyze-error')?.output || '').trim(); const retryOutputRaw = String($ctx.getNodeOutput('retry-task')?.output || '').trim(); const retryErrorRaw = String($ctx.getNodeOutput('retry-task')?.error || '').trim(); const truncate = (value, limit = 2000) => value.length > limit ? `${value.slice(0, limit)}...` : value; const diagnostics = [String($data?.lastError || '').trim(), analysisRaw ? `Recovery analysis:\n${truncate(analysisRaw)}` : '', retryOutputRaw ? `Retry output:\n${truncate(retryOutputRaw)}` : '', retryErrorRaw ? `Retry error:\n${truncate(retryErrorRaw)}` : ''].filter(Boolean).join('\n\n'); return { taskId: $data?.taskId, taskTitle: $data?.taskTitle, worktreePath: $data?.worktreePath, branch: $data?.branch, baseBranch: $data?.baseBranch, error: diagnostics || String($data?.lastError || ''), recoveryAnalysis: truncate(analysisRaw), retryResult: { success: $ctx.getNodeOutput('retry-task')?.success === true, output: truncate(retryOutputRaw), error: truncate(retryErrorRaw) } }; })()",
|
|
79
101
|
}, { x: 400, y: 760 }),
|
|
80
102
|
],
|
|
81
103
|
edges: [
|
|
@@ -92,7 +114,7 @@ export const ERROR_RECOVERY_TEMPLATE = {
|
|
|
92
114
|
author: "bosun",
|
|
93
115
|
version: 1,
|
|
94
116
|
createdAt: "2025-02-24T00:00:00Z",
|
|
95
|
-
templateVersion: "1.0
|
|
117
|
+
templateVersion: "1.1.0",
|
|
96
118
|
tags: ["error", "recovery", "autofix"],
|
|
97
119
|
requiredTemplates: ["template-task-repair-worktree"],
|
|
98
120
|
replaces: {
|
|
@@ -458,6 +480,20 @@ export const TASK_FINALIZATION_GUARD_TEMPLATE = {
|
|
|
458
480
|
},
|
|
459
481
|
}, { x: 240, y: 900 }),
|
|
460
482
|
|
|
483
|
+
node("handoff-pr-progressor", "action.execute_workflow", "Dispatch PR Progressor", {
|
|
484
|
+
workflowId: "template-bosun-pr-progressor",
|
|
485
|
+
mode: "dispatch",
|
|
486
|
+
input: {
|
|
487
|
+
taskId: "{{taskId}}",
|
|
488
|
+
taskTitle: "{{taskTitle}}",
|
|
489
|
+
branch: "{{branch}}",
|
|
490
|
+
baseBranch: "{{baseBranch}}",
|
|
491
|
+
prNumber: "{{$data?.prNumber ?? $ctx.getNodeOutput('create-pr')?.prNumber ?? null}}",
|
|
492
|
+
prUrl: "{{$data?.prUrl || $ctx.getNodeOutput('create-pr')?.prUrl || ''}}",
|
|
493
|
+
repo: "{{$data?.repo || $data?.repoSlug || $data?.repository || $ctx.getNodeOutput('create-pr')?.repoSlug || ''}}",
|
|
494
|
+
},
|
|
495
|
+
}, { x: 240, y: 1040 }),
|
|
496
|
+
|
|
461
497
|
node("mark-todo-failed", "action.update_task_status", "Mark Todo (Checks Failed)", {
|
|
462
498
|
taskId: "{{taskId}}",
|
|
463
499
|
status: "todo",
|
|
@@ -497,13 +533,13 @@ export const TASK_FINALIZATION_GUARD_TEMPLATE = {
|
|
|
497
533
|
node("notify-pass", "notify.log", "Log Finalization Success", {
|
|
498
534
|
message: "Task {{taskId}} finalization passed — moved to inreview",
|
|
499
535
|
level: "info",
|
|
500
|
-
}, { x: 240, y:
|
|
536
|
+
}, { x: 240, y: 1180 }),
|
|
501
537
|
|
|
502
538
|
node("chain-archiver", "flow.universal", "Queue Archival", {
|
|
503
539
|
workflowId: "template-task-archiver",
|
|
504
540
|
mode: "dispatch",
|
|
505
541
|
input: "({taskId: $data?.taskId, taskTitle: $data?.taskTitle, completedAt: new Date().toISOString(), taskJson: JSON.stringify($data?.task || {id: $data?.taskId, title: $data?.taskTitle})})",
|
|
506
|
-
}, { x: 240, y:
|
|
542
|
+
}, { x: 240, y: 1320 }),
|
|
507
543
|
|
|
508
544
|
node("end-success", "flow.end", "End Success", {
|
|
509
545
|
status: "completed",
|
|
@@ -513,7 +549,7 @@ export const TASK_FINALIZATION_GUARD_TEMPLATE = {
|
|
|
513
549
|
taskId: "{{taskId}}",
|
|
514
550
|
taskTitle: "{{taskTitle}}",
|
|
515
551
|
},
|
|
516
|
-
}, { x: 240, y:
|
|
552
|
+
}, { x: 240, y: 1450 }),
|
|
517
553
|
|
|
518
554
|
node("notify-fail", "notify.telegram", "Notify Finalization Failure", {
|
|
519
555
|
message: ":alert: Task finalization failed for **{{taskTitle}}** ({{taskId}}). Repair workflow handoff triggered.",
|
|
@@ -543,7 +579,8 @@ export const TASK_FINALIZATION_GUARD_TEMPLATE = {
|
|
|
543
579
|
edge("create-pr", "create-pr-success"),
|
|
544
580
|
edge("create-pr-success", "mark-inreview", { condition: "$output?.result === true", port: "yes" }),
|
|
545
581
|
edge("create-pr-success", "mark-todo-failed", { condition: "$output?.result !== true", port: "no" }),
|
|
546
|
-
edge("mark-inreview", "
|
|
582
|
+
edge("mark-inreview", "handoff-pr-progressor"),
|
|
583
|
+
edge("handoff-pr-progressor", "notify-pass"),
|
|
547
584
|
edge("notify-skip-missing-context", "end-success"),
|
|
548
585
|
edge("notify-pass", "chain-archiver"),
|
|
549
586
|
edge("chain-archiver", "end-success"),
|
|
@@ -557,7 +594,7 @@ export const TASK_FINALIZATION_GUARD_TEMPLATE = {
|
|
|
557
594
|
createdAt: "2026-02-26T00:00:00Z",
|
|
558
595
|
templateVersion: "1.0.1",
|
|
559
596
|
tags: ["finalization", "quality-gate", "prepush", "handoff", "reliability"],
|
|
560
|
-
requiredTemplates: ["template-task-archiver"],
|
|
597
|
+
requiredTemplates: ["template-task-archiver", "template-bosun-pr-progressor"],
|
|
561
598
|
replaces: {
|
|
562
599
|
module: "task-executor.mjs",
|
|
563
600
|
functions: ["_handleTaskResult finalization gate"],
|
|
@@ -659,6 +696,20 @@ export const TASK_REPAIR_WORKTREE_TEMPLATE = {
|
|
|
659
696
|
},
|
|
660
697
|
}, { x: 250, y: 1020 }),
|
|
661
698
|
|
|
699
|
+
node("handoff-pr-progressor", "action.execute_workflow", "Dispatch PR Progressor", {
|
|
700
|
+
workflowId: "template-bosun-pr-progressor",
|
|
701
|
+
mode: "dispatch",
|
|
702
|
+
input: {
|
|
703
|
+
taskId: "{{taskId}}",
|
|
704
|
+
taskTitle: "{{taskTitle}}",
|
|
705
|
+
branch: "{{branch}}",
|
|
706
|
+
baseBranch: "{{baseBranch}}",
|
|
707
|
+
prNumber: "{{$data?.prNumber ?? $ctx.getNodeOutput('create-pr')?.prNumber ?? null}}",
|
|
708
|
+
prUrl: "{{$data?.prUrl || $ctx.getNodeOutput('create-pr')?.prUrl || ''}}",
|
|
709
|
+
repo: "{{$data?.repo || $data?.repoSlug || $data?.repository || $ctx.getNodeOutput('create-pr')?.repoSlug || ''}}",
|
|
710
|
+
},
|
|
711
|
+
}, { x: 250, y: 1160 }),
|
|
712
|
+
|
|
662
713
|
node("mark-todo", "action.update_task_status", "Mark Todo (Repair Failed)", {
|
|
663
714
|
taskId: "{{taskId}}",
|
|
664
715
|
status: "todo",
|
|
@@ -676,7 +727,7 @@ export const TASK_REPAIR_WORKTREE_TEMPLATE = {
|
|
|
676
727
|
node("notify-success", "notify.telegram", "Notify Repair Success", {
|
|
677
728
|
message: ":check: Repair workflow recovered **{{taskTitle}}** ({{taskId}}) and moved it to inreview.",
|
|
678
729
|
silent: true,
|
|
679
|
-
}, { x: 250, y:
|
|
730
|
+
}, { x: 250, y: 1300 }),
|
|
680
731
|
|
|
681
732
|
node("notify-escalate", "notify.telegram", "Escalate Repair Failure", {
|
|
682
733
|
message: ":alert: Repair workflow could not recover **{{taskTitle}}** ({{taskId}}). Manual intervention required.",
|
|
@@ -700,7 +751,8 @@ export const TASK_REPAIR_WORKTREE_TEMPLATE = {
|
|
|
700
751
|
edge("create-pr", "create-pr-success"),
|
|
701
752
|
edge("create-pr-success", "mark-inreview", { condition: "$output?.result === true", port: "yes" }),
|
|
702
753
|
edge("create-pr-success", "mark-todo", { condition: "$output?.result !== true", port: "no" }),
|
|
703
|
-
edge("mark-inreview", "
|
|
754
|
+
edge("mark-inreview", "handoff-pr-progressor"),
|
|
755
|
+
edge("handoff-pr-progressor", "notify-success"),
|
|
704
756
|
edge("mark-todo", "notify-escalate"),
|
|
705
757
|
edge("no-worktree", "notify-escalate"),
|
|
706
758
|
],
|
|
@@ -710,6 +762,7 @@ export const TASK_REPAIR_WORKTREE_TEMPLATE = {
|
|
|
710
762
|
createdAt: "2026-02-26T00:00:00Z",
|
|
711
763
|
templateVersion: "1.0.1",
|
|
712
764
|
tags: ["repair", "recovery", "worktree", "resilience", "automation"],
|
|
765
|
+
requiredTemplates: ["template-bosun-pr-progressor"],
|
|
713
766
|
replaces: {
|
|
714
767
|
module: "task-executor.mjs",
|
|
715
768
|
functions: ["retry/escalation recovery path"],
|
|
@@ -35,8 +35,9 @@ export const TASK_BATCH_PROCESSOR_TEMPLATE = {
|
|
|
35
35
|
"using the Task Lifecycle sub-workflow. Automatically picks up tasks " +
|
|
36
36
|
"when backlog drops below threshold, fans out execution across " +
|
|
37
37
|
"available slots, and reports batch results.",
|
|
38
|
-
category: "
|
|
38
|
+
category: "task-execution",
|
|
39
39
|
enabled: true,
|
|
40
|
+
core: true,
|
|
40
41
|
recommended: true,
|
|
41
42
|
trigger: "trigger.task_available",
|
|
42
43
|
variables: {
|
|
@@ -50,7 +51,7 @@ export const TASK_BATCH_PROCESSOR_TEMPLATE = {
|
|
|
50
51
|
// ── Trigger: Tasks available for processing ──────────────────────────
|
|
51
52
|
node("trigger", "trigger.task_available", "Tasks Available?", {
|
|
52
53
|
maxParallel: "{{maxConcurrent}}",
|
|
53
|
-
pollIntervalMs:
|
|
54
|
+
pollIntervalMs: 15000,
|
|
54
55
|
status: "{{pollStatus}}",
|
|
55
56
|
}, { x: 400, y: 50 }),
|
|
56
57
|
|
|
@@ -90,7 +91,7 @@ export const TASK_BATCH_PROCESSOR_TEMPLATE = {
|
|
|
90
91
|
|
|
91
92
|
// ── Fan-out: dispatch each task to the lifecycle workflow ─────────────
|
|
92
93
|
node("dispatch-tasks", "loop.for_each", "Dispatch Tasks", {
|
|
93
|
-
items: "{{
|
|
94
|
+
items: "{{query-tasks.output}}",
|
|
94
95
|
itemVariable: "currentTask",
|
|
95
96
|
indexVariable: "taskIndex",
|
|
96
97
|
maxConcurrent: "{{maxConcurrent}}",
|
|
@@ -112,7 +113,7 @@ export const TASK_BATCH_PROCESSOR_TEMPLATE = {
|
|
|
112
113
|
// ── Notify on completion ─────────────────────────────────────────────
|
|
113
114
|
node("notify-complete", "notify.telegram", "Batch Summary", {
|
|
114
115
|
channel: "{{notifyChannel}}",
|
|
115
|
-
message: "Task batch completed: {{
|
|
116
|
+
message: "Task batch completed: {{dispatch-tasks.successCount}}/{{dispatch-tasks.totalItems}} succeeded ({{dispatch-tasks.failCount}} failed)",
|
|
116
117
|
}, { x: 400, y: 700 }),
|
|
117
118
|
],
|
|
118
119
|
edges: [
|
|
@@ -145,7 +146,7 @@ export const TASK_BATCH_PR_TEMPLATE = {
|
|
|
145
146
|
"Simplified batch processor that picks todo tasks, runs the agent on " +
|
|
146
147
|
"each, and creates pull requests for any that produce commits. Ideal " +
|
|
147
148
|
"for autonomous mode where tasks should flow straight to PRs.",
|
|
148
|
-
category: "
|
|
149
|
+
category: "task-execution",
|
|
149
150
|
enabled: true,
|
|
150
151
|
recommended: false,
|
|
151
152
|
trigger: "trigger.task_available",
|
|
@@ -161,7 +162,7 @@ export const TASK_BATCH_PR_TEMPLATE = {
|
|
|
161
162
|
// ── Trigger ──────────────────────────────────────────────────────────
|
|
162
163
|
node("trigger", "trigger.task_available", "Tasks Available?", {
|
|
163
164
|
maxParallel: "{{maxConcurrent}}",
|
|
164
|
-
pollIntervalMs:
|
|
165
|
+
pollIntervalMs: 15000,
|
|
165
166
|
status: "{{pollStatus}}",
|
|
166
167
|
}, { x: 400, y: 50 }),
|
|
167
168
|
|
|
@@ -194,7 +195,7 @@ export const TASK_BATCH_PR_TEMPLATE = {
|
|
|
194
195
|
|
|
195
196
|
// ── Fan-out: per-task agent + PR ─────────────────────────────────────
|
|
196
197
|
node("for-each-task", "loop.for_each", "Process Each Task", {
|
|
197
|
-
items: "{{
|
|
198
|
+
items: "{{query-tasks.output}}",
|
|
198
199
|
itemVariable: "task",
|
|
199
200
|
indexVariable: "idx",
|
|
200
201
|
maxConcurrent: "{{maxConcurrent}}",
|
|
@@ -240,11 +241,25 @@ export const TASK_BATCH_PR_TEMPLATE = {
|
|
|
240
241
|
status: "inreview",
|
|
241
242
|
}, { x: 400, y: 1090 }),
|
|
242
243
|
|
|
244
|
+
node("handoff-pr-progressor", "action.execute_workflow", "Dispatch PR Progressor", {
|
|
245
|
+
workflowId: "template-bosun-pr-progressor",
|
|
246
|
+
mode: "dispatch",
|
|
247
|
+
input: {
|
|
248
|
+
taskId: "{{task.taskId}}",
|
|
249
|
+
taskTitle: "{{task.taskTitle}}",
|
|
250
|
+
branch: "{{task.branch}}",
|
|
251
|
+
baseBranch: "{{defaultBaseBranch}}",
|
|
252
|
+
prNumber: "{{$ctx.getNodeOutput('create-pr')?.prNumber ?? null}}",
|
|
253
|
+
prUrl: "{{$ctx.getNodeOutput('create-pr')?.prUrl || ''}}",
|
|
254
|
+
repo: "{{$ctx.getNodeOutput('create-pr')?.repoSlug || $data?.repo || $data?.repoSlug || $data?.repository || ''}}",
|
|
255
|
+
},
|
|
256
|
+
}, { x: 400, y: 1160 }),
|
|
257
|
+
|
|
243
258
|
node("join-batch-outcomes", "flow.join", "Join Batch Outcomes", {
|
|
244
259
|
mode: "all",
|
|
245
|
-
sourceNodeIds: ["detect-commits", "
|
|
260
|
+
sourceNodeIds: ["detect-commits", "handoff-pr-progressor"],
|
|
246
261
|
includeSkipped: true,
|
|
247
|
-
}, { x: 400, y:
|
|
262
|
+
}, { x: 400, y: 1230 }),
|
|
248
263
|
|
|
249
264
|
// ── Batch complete notification ──────────────────────────────────────
|
|
250
265
|
node("notify", "notify.telegram", "Batch Complete", {
|
|
@@ -262,7 +277,8 @@ export const TASK_BATCH_PR_TEMPLATE = {
|
|
|
262
277
|
edge("push-branch", "create-pr"),
|
|
263
278
|
edge("create-pr", "set-inreview"),
|
|
264
279
|
edge("detect-commits", "join-batch-outcomes", { condition: "result.hasNewCommits !== true" }),
|
|
265
|
-
edge("set-inreview", "
|
|
280
|
+
edge("set-inreview", "handoff-pr-progressor"),
|
|
281
|
+
edge("handoff-pr-progressor", "join-batch-outcomes"),
|
|
266
282
|
edge("join-batch-outcomes", "notify"),
|
|
267
283
|
],
|
|
268
284
|
metadata: {
|
|
@@ -271,5 +287,6 @@ export const TASK_BATCH_PR_TEMPLATE = {
|
|
|
271
287
|
createdAt: "2026-03-15T00:00:00Z",
|
|
272
288
|
templateVersion: "1.0.0",
|
|
273
289
|
tags: ["task", "batch", "pr", "agent", "autonomous"],
|
|
290
|
+
requiredTemplates: ["template-bosun-pr-progressor"],
|
|
274
291
|
},
|
|
275
292
|
};
|