bosun 0.36.8 → 0.37.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.
Files changed (58) hide show
  1. package/.env.example +2 -32
  2. package/README.md +19 -3
  3. package/agent-prompts.mjs +0 -91
  4. package/bosun.config.example.json +3 -0
  5. package/bosun.schema.json +10 -0
  6. package/config.mjs +6 -75
  7. package/copilot-shell.mjs +18 -1
  8. package/desktop/desktop-shortcuts.mjs +200 -27
  9. package/desktop/main.mjs +734 -113
  10. package/desktop/package.json +1 -2
  11. package/desktop/preload.mjs +39 -0
  12. package/desktop-shortcut.mjs +106 -13
  13. package/fleet-coordinator.mjs +4 -16
  14. package/maintenance.mjs +1 -2
  15. package/monitor.mjs +234 -3261
  16. package/package.json +8 -5
  17. package/primary-agent.mjs +47 -8
  18. package/session-tracker.mjs +30 -1
  19. package/setup-web-server.mjs +208 -0
  20. package/task-cli.mjs +4 -38
  21. package/task-executor.mjs +153 -2838
  22. package/telegram-bot.mjs +55 -140
  23. package/ui/app.js +237 -29
  24. package/ui/components/agent-selector.js +26 -4
  25. package/ui/components/workspace-switcher.js +18 -6
  26. package/ui/demo.html +115 -0
  27. package/ui/index.html +17 -3
  28. package/ui/modules/icon-utils.js +57 -0
  29. package/ui/modules/settings-schema.js +4 -4
  30. package/ui/modules/streaming.js +15 -0
  31. package/ui/modules/vision-stream.js +196 -22
  32. package/ui/modules/voice-client-sdk.js +567 -60
  33. package/ui/modules/voice-client.js +740 -15
  34. package/ui/modules/voice-fallback.js +28 -6
  35. package/ui/modules/voice-overlay.js +1505 -494
  36. package/ui/setup.html +618 -106
  37. package/ui/styles/components.css +65 -0
  38. package/ui/styles/layout.css +4 -0
  39. package/ui/styles/sessions.css +24 -0
  40. package/ui/tabs/agents.js +125 -28
  41. package/ui/tabs/chat.js +233 -21
  42. package/ui/tabs/settings.js +318 -109
  43. package/ui/tabs/tasks.js +5 -11
  44. package/ui-server.mjs +458 -123
  45. package/vision-session-state.mjs +35 -0
  46. package/voice-action-dispatcher.mjs +163 -20
  47. package/voice-agents-sdk.mjs +32 -10
  48. package/voice-auth-manager.mjs +95 -28
  49. package/voice-relay.mjs +555 -81
  50. package/voice-tools.mjs +1565 -92
  51. package/workflow-engine.mjs +38 -0
  52. package/workflow-migration.mjs +2 -0
  53. package/workflow-nodes.mjs +1101 -0
  54. package/workflow-templates/agents.mjs +1 -0
  55. package/workflow-templates/github.mjs +2 -1
  56. package/workflow-templates/reliability.mjs +2 -0
  57. package/workflow-templates/task-lifecycle.mjs +595 -0
  58. package/workflow-templates.mjs +144 -3
package/.env.example CHANGED
@@ -4,8 +4,8 @@
4
4
  # All variables are optional unless marked [REQUIRED].
5
5
  # Boolean flags use true/false (preferred). Legacy 1/0 is still accepted.
6
6
  # Profile guidance:
7
- # - Local development: DEVMODE=true, DEVMODE_MONITOR_MONITOR_ENABLED=true, *_TRANSPORT=sdk
8
- # - End-user stable: DEVMODE=false, DEVMODE_MONITOR_MONITOR_ENABLED=false, *_TRANSPORT=sdk
7
+ # - Local development: DEVMODE=true, *_TRANSPORT=sdk
8
+ # - End-user stable: DEVMODE=false, *_TRANSPORT=sdk
9
9
 
10
10
  # ─── Task Claims and Coordination ─────────────────────────────────────────────
11
11
  # Shared state manager enables distributed task coordination across multiple
@@ -222,10 +222,6 @@ VOICE_DELEGATE_EXECUTOR=codex-sdk
222
222
  # SENTINEL_RESTART_BACKOFF_SEC=5
223
223
  # After manual /stop, suppress auto-restart for this many minutes (default: 10)
224
224
  # SENTINEL_MANUAL_STOP_HOLD_MIN=10
225
- # In devmode, validate monitor-monitor freshness before restart decisions (default: 1)
226
- # SENTINEL_MONITOR_MONITOR_CHECK_ENABLED=true
227
- # Max acceptable monitor-monitor age in minutes (default: 20)
228
- # SENTINEL_MONITOR_MONITOR_MAX_AGE_MIN=20
229
225
 
230
226
  # ─── Notification Batching (RECOMMENDED) ─────────────────────────────────────
231
227
  # Batch notifications into periodic summaries instead of spamming individual messages
@@ -776,31 +772,6 @@ VK_RECOVERY_PORT=54089
776
772
  # scripts check for this and exit silently if not present, preventing
777
773
  # hooks from firing in standalone Copilot/Codex/Claude sessions.
778
774
 
779
- # ─── Devmode Monitor-Monitor (24/7 reliability guardian) ───────────────────
780
- # Prompt is injected directly from bosun source (no .github/agents file required).
781
- # Enabled by default in devmode source checkouts. Set to false to disable.
782
- # DEVMODE_MONITOR_MONITOR_ENABLED=true
783
- # Poll interval for monitor-monitor runs (milliseconds). Default: 300000 (5 min)
784
- # DEVMODE_MONITOR_MONITOR_INTERVAL_MS=300000
785
- # Status stream update interval (milliseconds). Default: 1800000 (30 min)
786
- # DEVMODE_MONITOR_MONITOR_STATUS_INTERVAL_MS=1800000
787
- # Per-run timeout before watchdog abort/failover (milliseconds).
788
- # Default is 21600000 (6h) for long-running reliability analysis sessions.
789
- # 30 minutes (1800000) is safe if you prefer faster failover on stuck runs.
790
- # Watchdog abort triggers at timeout+60s, then accelerated force-reset at +120s.
791
- # Set this explicitly to avoid inherited shell
792
- # defaults (for example DEVMODE_AUTO_CODE_FIX_TIMEOUT_MS=300000).
793
- # DEVMODE_MONITOR_MONITOR_TIMEOUT_MS=1800000
794
- # Optional timeout bounds (applied only when set):
795
- # DEVMODE_MONITOR_MONITOR_TIMEOUT_MIN_MS=600000
796
- # DEVMODE_MONITOR_MONITOR_TIMEOUT_MAX_MS=7200000
797
- # Optional override for Claude tool access (comma-separated)
798
- # DEVMODE_MONITOR_MONITOR_CLAUDE_ALLOWED_TOOLS=Read,Write,Edit,Grep,Glob,Bash,WebSearch,Task,Skill
799
- # Legacy alias: DEVMODE_AUTO_CODE_FIX=true also enables this subsystem.
800
- # Legacy timeout fallback: if DEVMODE_MONITOR_MONITOR_TIMEOUT_MS is unset and
801
- # DEVMODE_AUTO_CODE_FIX_TIMEOUT_MS is set, monitor-monitor will use it (and
802
- # still apply DEVMODE_MONITOR_MONITOR_TIMEOUT_MIN_MS/MAX_MS bounds if provided).
803
-
804
775
  # ─── Copilot SDK (Primary Agent) ─────────────────────────────────────────────
805
776
  # Requires GitHub Copilot CLI installed and authenticated.
806
777
  # Set to true to disable Copilot SDK (primary agent) usage.
@@ -1046,7 +1017,6 @@ COPILOT_CLOUD_DISABLED=true
1046
1017
  # Files in that folder are loaded automatically and are intended for per-project customization.
1047
1018
  # You can also override any prompt path explicitly with env vars:
1048
1019
  # BOSUN_PROMPT_PLANNER=.bosun/agents/task-planner.md
1049
- # BOSUN_PROMPT_MONITOR_MONITOR=.bosun/agents/monitor-monitor.md
1050
1020
  # BOSUN_PROMPT_TASK_EXECUTOR=.bosun/agents/task-executor.md
1051
1021
  # BOSUN_PROMPT_REVIEWER=.bosun/agents/reviewer.md
1052
1022
  # BOSUN_PROMPT_SDK_CONFLICT_RESOLVER=.bosun/agents/sdk-conflict-resolver.md
package/README.md CHANGED
@@ -3,10 +3,10 @@
3
3
  </p>
4
4
  <h1 align="center">bosun</h1>
5
5
 
6
- Bosun is a production-grade supervisor for AI coding agents. It routes tasks across executors, automates PR lifecycles, and keeps operators in control through Telegram, the Mini App dashboard, and optional WhatsApp notifications.
6
+ Bosun is a production-grade control plane for an autonomous software engineer. It plans and routes work across executors, automates PR lifecycles, and keeps operators in control through Telegram, the Mini App dashboard, and optional WhatsApp notifications.
7
7
 
8
8
  <p align="center">
9
- <a href="https://bosun.virtengine.com">Website</a> · <a href="https://bosun.virtengine.com/docs/">Docs</a> · <a href="https://github.com/virtengine/bosun?tab=readme-ov-file#bosun">GitHub</a> · <a href="https://www.npmjs.com/package/bosun">npm</a> · <a href="https://github.com/virtengine/bosun/issues">Issues</a>
9
+ <a href="https://bosun.engineer">Website</a> · <a href="https://bosun.engineer/docs/">Docs</a> · <a href="https://github.com/virtengine/bosun?tab=readme-ov-file#bosun">GitHub</a> · <a href="https://www.npmjs.com/package/bosun">npm</a> · <a href="https://github.com/virtengine/bosun/issues">Issues</a>
10
10
  </p>
11
11
 
12
12
  <p align="center">
@@ -82,6 +82,22 @@ Fallback admin auth (secondary path) is available and stores only Argon2id hash
82
82
  - Provides Telegram control and a Mini App dashboard
83
83
  - Integrates with GitHub, Jira, and Vibe-Kanban boards
84
84
 
85
+ ## Autonomous Engineer Workflow Capabilities
86
+
87
+ Bosun workflows provide a professional, end-to-end execution loop for autonomous delivery:
88
+
89
+ - Trigger intake: consume issues, comments, schedules, and webhook events
90
+ - Planning and decomposition: convert goals into scoped tasks with execution context
91
+ - Routed execution: dispatch tasks to the best executor profile with retries and failover
92
+ - Quality gates: enforce test/build/review checks before merge decisions
93
+ - Recovery and escalation: auto-heal stalled runs, then escalate with clear operator signals
94
+
95
+ Setup profiles for default workflow behavior:
96
+
97
+ - Manual Dispatch: human-directed flow with guardrails and review automations
98
+ - Balanced (Recommended): daily default with PR quality gates and targeted self-healing
99
+ - Autonomous: expanded end-to-end automation for planning, recovery, and maintenance
100
+
85
101
  ### Executor quick-start
86
102
 
87
103
  | Executor | `primaryAgent` value | Key env vars |
@@ -103,7 +119,7 @@ Set `primaryAgent` in `.bosun/bosun.config.json` or choose an executor preset du
103
119
 
104
120
  ## Documentation
105
121
 
106
- **Published docs (website):** https://bosun.virtengine.com/docs/
122
+ **Published docs (website):** https://bosun.engineer/docs/
107
123
 
108
124
  **Source docs (markdown):** `_docs/` is the source of truth for long-form documentation. The website should be generated from the same markdown content so docs stay in sync.
109
125
 
package/agent-prompts.mjs CHANGED
@@ -17,16 +17,6 @@ const PROMPT_DEFS = [
17
17
  filename: "orchestrator.md",
18
18
  description: "Primary task execution prompt for autonomous task agents.",
19
19
  },
20
- {
21
- key: "planner",
22
- filename: "task-planner.md",
23
- description: "Backlog planning prompt used by task planner runs.",
24
- },
25
- {
26
- key: "monitorMonitor",
27
- filename: "monitor-monitor.md",
28
- description: "Long-running reliability monitor prompt used in devmode.",
29
- },
30
20
  {
31
21
  key: "taskExecutor",
32
22
  filename: "task-executor.md",
@@ -199,68 +189,6 @@ apply patterns discovered by previous agents:
199
189
  After completing a task, if you discovered a non-obvious pattern, workaround, or
200
190
  domain-specific fact, write or update a skill file at \`.bosun/skills/<module>.md\`
201
191
  so the next agent benefits from your investigation.
202
- `,
203
- planner: `# Codex-Task-Planner Agent
204
-
205
- You generate production-grade backlog tasks for autonomous executors.
206
-
207
- ## Mission
208
-
209
- 1. Analyze current repo and delivery state.
210
- 2. Identify highest-value next work.
211
- 3. Create concrete, execution-ready tasks.
212
-
213
- ## Requirements
214
-
215
- - Avoid vague tasks and duplicate work.
216
- - Balance reliability fixes, feature delivery, and debt reduction.
217
- - Every task includes implementation steps, acceptance criteria, and verification plan.
218
- - Every task title starts with one size label: [xs], [s], [m], [l], [xl], [xxl].
219
- - Prefer task sets that can run in parallel with low file overlap.
220
- - Do not call any kanban API, CLI, or external service to create tasks.
221
- The workflow will automatically materialize your output into kanban tasks.
222
- - Output must be machine-parseable JSON — see Output Contract below.
223
- - Task objects must be valid for Bosun backlog creation with fields:
224
- \'title\', \'description\', \'implementation_steps\', \'acceptance_criteria\',
225
- \'verification\', optional \'base_branch\'.
226
- - Do not emit empty or placeholder tasks. Every task must be actionable and execution-ready.
227
-
228
- ## Output Contract (MANDATORY — STRICT)
229
-
230
- Your ENTIRE response must be a single fenced JSON block. Do NOT include any
231
- text, commentary, explanations, or markdown before or after the JSON block.
232
- The downstream parser extracts JSON from fenced blocks — any deviation causes
233
- task creation to hard-fail.
234
-
235
- Return exactly this shape:
236
-
237
- \`\`\`json
238
- {
239
- "tasks": [
240
- {
241
- "title": "[m] feat(veid): example task title",
242
- "description": "Problem statement and scope",
243
- "implementation_steps": ["step 1", "step 2"],
244
- "acceptance_criteria": ["criterion 1", "criterion 2"],
245
- "verification": ["test/check 1", "test/check 2"],
246
- "base_branch": "origin/veid"
247
- }
248
- ]
249
- }
250
- \`\`\`
251
-
252
- Rules:
253
- - The \`tasks\` array MUST contain at least the requested task count.
254
- - Do NOT output partial JSON, truncated arrays, or commentary mixed with JSON.
255
- - Keep titles unique and specific.
256
- - Keep file overlap low across tasks to maximize parallel execution.
257
- - Descriptions must include concrete implementation details, not generic intent text.
258
- - Include verification commands/checks that a worker can run without additional planning.
259
- - **Module branch routing:** When the task title follows conventional commit format
260
- \`feat(module):\` or \`fix(module):\`, set \`base_branch\` to \`origin/<module>\`.
261
- This routes the task to the module's dedicated branch for parallel, isolated development.
262
- Examples: \`feat(veid):\` → \`"base_branch": "origin/veid"\`, \`fix(market):\` → \`"base_branch": "origin/market"\`.
263
- Omit \`base_branch\` for cross-cutting tasks that span multiple modules.
264
192
  `,
265
193
  taskManager: `# Bosun Task Manager Agent
266
194
 
@@ -305,8 +233,6 @@ bosun task stats --json
305
233
  # Bulk import from JSON file
306
234
  bosun task import ./backlog.json
307
235
 
308
- # Trigger AI task planner
309
- bosun task plan --count 5 --reason "Sprint planning"
310
236
  \`\`\`
311
237
 
312
238
  ### 2. REST API (port 18432 — always available when bosun daemon runs)
@@ -440,23 +366,6 @@ draft → todo → inprogress → inreview → done
440
366
  7. **Module branch routing** — When a task title follows conventional commit format
441
367
  \`feat(module):\` or \`fix(module):\`, set \`baseBranch\` to \`origin/<module>\` to route the task
442
368
  to the module's dedicated branch for parallel, isolated development.
443
- `,
444
- monitorMonitor: `# Bosun-Monitor Agent
445
-
446
- You are the always-on reliability guardian for bosun in devmode.
447
-
448
- ## Core Role
449
-
450
- - Monitor logs, failures, and agent/orchestrator behavior continuously.
451
- - Immediately fix reliability regressions and execution blockers.
452
- - Improve prompt/tool/executor reliability to reduce failure loops.
453
- - Only when runtime is healthy, perform code-analysis improvements.
454
-
455
- ## Constraints
456
-
457
- - Operate only in devmode.
458
- - Do not commit/push/initiate PR lifecycle changes in this context.
459
- - Apply focused fixes, run focused validation, and keep monitoring.
460
369
  `,
461
370
  taskExecutor: `# {{TASK_ID}} — {{TASK_TITLE}}
462
371
 
@@ -2,6 +2,9 @@
2
2
  "$schema": "./bosun.schema.json",
3
3
  "projectName": "my-project",
4
4
  "primaryAgent": "codex-sdk",
5
+
6
+ "_comment_workflowFirst": "Set to true to run everything as workflows (task lifecycle, PR management, etc.)",
7
+ "workflowFirst": false,
5
8
  "kanban": {
6
9
  "backend": "vk"
7
10
  },
package/bosun.schema.json CHANGED
@@ -33,6 +33,16 @@
33
33
  "watchEnabled": { "type": "boolean" },
34
34
  "echoLogs": { "type": "boolean" },
35
35
  "autoFixEnabled": { "type": "boolean" },
36
+ "workflowFirst": {
37
+ "type": "boolean",
38
+ "default": false,
39
+ "description": "When true, all modules start in WORKFLOW mode by default. The task executor lifecycle is fully delegated to workflow templates (workflowOwnsTaskLifecycle). Bosun acts as a thin shell around the workflow engine."
40
+ },
41
+ "workflowOwnsTaskLifecycle": {
42
+ "type": "boolean",
43
+ "default": false,
44
+ "description": "Delegate task finalization and recovery to workflow automation instead of the legacy TaskExecutor. Automatically set to true when workflowFirst is enabled."
45
+ },
36
46
  "interactiveShellEnabled": { "type": "boolean" },
37
47
  "shellEnabled": { "type": "boolean" },
38
48
  "codexEnabled": { "type": "boolean" },
package/config.mjs CHANGED
@@ -506,7 +506,9 @@ function normalizeExecutorModels(executor, models, variant = "DEFAULT") {
506
506
  );
507
507
  return inferred.length > 0 ? inferred : [...known];
508
508
  }
509
- return input.filter((model) => known.has(model));
509
+ // Preserve custom/deployment slugs in addition to known models so user-provided
510
+ // model routing survives normalization (for example Azure deployment names).
511
+ return [...new Set(input.filter(Boolean))];
510
512
  }
511
513
 
512
514
  function normalizeExecutorEntry(entry, index = 0, total = 1) {
@@ -540,49 +542,8 @@ function normalizeExecutorEntry(entry, index = 0, total = 1) {
540
542
  };
541
543
  }
542
544
 
543
- function buildDefaultTriggerTemplates({
544
- plannerMode,
545
- plannerPerCapitaThreshold,
546
- plannerIdleSlotThreshold,
547
- plannerDedupHours,
548
- } = {}) {
545
+ function buildDefaultTriggerTemplates() {
549
546
  return [
550
- {
551
- id: "task-planner",
552
- name: "Task Planner",
553
- description: "Create planning tasks when backlog/slot metrics indicate replenishment.",
554
- enabled: false,
555
- action: "task-planner",
556
- trigger: {
557
- anyOf: [
558
- {
559
- kind: "metric",
560
- metric: "backlogPerCapita",
561
- operator: "lt",
562
- value: plannerPerCapitaThreshold,
563
- },
564
- {
565
- kind: "metric",
566
- metric: "idleSlots",
567
- operator: "gte",
568
- value: plannerIdleSlotThreshold,
569
- },
570
- {
571
- kind: "metric",
572
- metric: "backlogRemaining",
573
- operator: "eq",
574
- value: 0,
575
- },
576
- ],
577
- },
578
- minIntervalMinutes: Math.max(1, Number(plannerDedupHours || 6) * 60),
579
- config: {
580
- plannerMode,
581
- defaultTaskCount: Number(process.env.TASK_PLANNER_DEFAULT_COUNT || "30"),
582
- executor: "auto",
583
- model: "auto",
584
- },
585
- },
586
547
  {
587
548
  id: "daily-review-digest",
588
549
  name: "Daily Review Digest",
@@ -1990,32 +1951,8 @@ export function loadConfig(argv = process.argv, options = {}) {
1990
1951
  "summary"
1991
1952
  ).toLowerCase();
1992
1953
 
1993
- // ── Task Planner ─────────────────────────────────────────
1994
- // Mode: "codex-sdk" (default) runs Codex directly, "kanban" creates a VK
1995
- // task for a real agent to plan, "disabled" turns off the planner entirely.
1996
- const plannerMode = (
1997
- process.env.TASK_PLANNER_MODE ||
1998
- configData.plannerMode ||
1999
- (mode === "generic" ? "disabled" : "codex-sdk")
2000
- ).toLowerCase();
2001
- const plannerPerCapitaThreshold = Number(
2002
- process.env.TASK_PLANNER_PER_CAPITA_THRESHOLD || "1",
2003
- );
2004
- const plannerIdleSlotThreshold = Number(
2005
- process.env.TASK_PLANNER_IDLE_SLOT_THRESHOLD || "1",
2006
- );
2007
- const plannerDedupHours = Number(process.env.TASK_PLANNER_DEDUP_HOURS || "6");
2008
- const plannerDedupMs = Number.isFinite(plannerDedupHours)
2009
- ? plannerDedupHours * 60 * 60 * 1000
2010
- : 24 * 60 * 60 * 1000;
2011
-
2012
1954
  const triggerSystemDefaults = Object.freeze({
2013
- templates: buildDefaultTriggerTemplates({
2014
- plannerMode,
2015
- plannerPerCapitaThreshold,
2016
- plannerIdleSlotThreshold,
2017
- plannerDedupHours,
2018
- }),
1955
+ templates: buildDefaultTriggerTemplates(),
2019
1956
  defaults: Object.freeze({
2020
1957
  executor: "auto",
2021
1958
  model: "auto",
@@ -2290,12 +2227,6 @@ export function loadConfig(argv = process.argv, options = {}) {
2290
2227
  telegramCommandEnabled,
2291
2228
  telegramVerbosity,
2292
2229
 
2293
- // Task Planner
2294
- plannerMode,
2295
- plannerPerCapitaThreshold,
2296
- plannerIdleSlotThreshold,
2297
- plannerDedupHours,
2298
- plannerDedupMs,
2299
2230
  triggerSystem,
2300
2231
 
2301
2232
  // GitHub Reconciler
@@ -2349,7 +2280,7 @@ export function loadConfig(argv = process.argv, options = {}) {
2349
2280
  configData.trustedCreators ||
2350
2281
  process.env.BOSUN_TRUSTED_CREATORS?.split(",") ||
2351
2282
  [],
2352
- // Enforce all new tasks go to backlog unless planner config allows auto-push
2283
+ // Enforce all new tasks go to backlog
2353
2284
  enforceBacklog:
2354
2285
  typeof configData.enforceBacklog === "boolean"
2355
2286
  ? configData.enforceBacklog
package/copilot-shell.mjs CHANGED
@@ -469,9 +469,26 @@ async function ensureClientStarted() {
469
469
  const modeLabel = clientOptions.cliUrl ? "remote" : "local (stdio)";
470
470
  console.log(`[copilot-shell] starting client in ${modeLabel} mode`);
471
471
 
472
+ const START_TIMEOUT_MS =
473
+ Number(process.env.COPILOT_START_TIMEOUT_MS) || 20_000;
474
+
472
475
  await withSanitizedOpenAiEnv(async () => {
473
476
  copilotClient = new Cls(clientOptions);
474
- await copilotClient.start();
477
+ await Promise.race([
478
+ copilotClient.start(),
479
+ new Promise((_, reject) =>
480
+ setTimeout(
481
+ () =>
482
+ reject(
483
+ new Error(
484
+ `Copilot CLI failed to start within ${START_TIMEOUT_MS / 1000}s — ` +
485
+ `verify COPILOT_CLI_PATH or run \`gh auth login\``,
486
+ ),
487
+ ),
488
+ START_TIMEOUT_MS,
489
+ ),
490
+ ),
491
+ ]);
475
492
  });
476
493
  clientStarted = true;
477
494
  console.log("[copilot-shell] client started");