bosun 0.40.2 → 0.40.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -0
- package/cli.mjs +127 -69
- package/config/config.mjs +35 -15
- package/desktop/package.json +2 -2
- package/infra/monitor.mjs +52 -16
- package/infra/session-tracker.mjs +1 -0
- package/infra/sync-engine.mjs +6 -1
- package/infra/update-check.mjs +16 -10
- package/kanban/kanban-adapter.mjs +19 -4
- package/kanban/ve-orchestrator.ps1 +25 -0
- package/package.json +1 -1
- package/server/ui-server.mjs +502 -39
- package/task/task-executor.mjs +690 -6
- package/task/task-store.mjs +116 -1
- package/ui/components/kanban-board.js +137 -9
- package/ui/components/shared.js +107 -45
- package/ui/demo-defaults.js +20 -20
- package/ui/demo.html +26 -1
- package/ui/modules/mui.js +600 -397
- package/ui/styles/components.css +43 -3
- package/ui/styles/kanban.css +66 -11
- package/ui/styles.monolith.css +89 -0
- package/ui/tabs/agents.js +194 -20
- package/ui/tabs/tasks.js +673 -162
- package/workflow/workflow-engine.mjs +30 -29
- package/workflow/workflow-nodes.mjs +321 -22
- package/workflow/workflow-templates.mjs +1 -1
- package/workflow-templates/task-batch.mjs +10 -10
- package/workspace/workspace-manager.mjs +25 -0
- package/workspace/worktree-manager.mjs +8 -2
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* - TASK_BATCH_PR_TEMPLATE (batch → agent → PR shortcut)
|
|
11
11
|
*
|
|
12
12
|
* DAG overview:
|
|
13
|
-
* trigger.
|
|
13
|
+
* trigger.task_available
|
|
14
14
|
* → condition.expression (is coordinator or solo?)
|
|
15
15
|
* → action.run_command (list todo tasks)
|
|
16
16
|
* → loop.for_each (fan-out, maxConcurrent tasks at a time)
|
|
@@ -38,9 +38,8 @@ export const TASK_BATCH_PROCESSOR_TEMPLATE = {
|
|
|
38
38
|
category: "lifecycle",
|
|
39
39
|
enabled: true,
|
|
40
40
|
recommended: true,
|
|
41
|
-
trigger: "trigger.
|
|
41
|
+
trigger: "trigger.task_available",
|
|
42
42
|
variables: {
|
|
43
|
-
backlogThreshold: 3,
|
|
44
43
|
maxConcurrent: 3,
|
|
45
44
|
pollStatus: "todo",
|
|
46
45
|
maxBatchSize: 10,
|
|
@@ -48,9 +47,10 @@ export const TASK_BATCH_PROCESSOR_TEMPLATE = {
|
|
|
48
47
|
notifyChannel: "telegram",
|
|
49
48
|
},
|
|
50
49
|
nodes: [
|
|
51
|
-
// ── Trigger:
|
|
52
|
-
node("trigger", "trigger.
|
|
53
|
-
|
|
50
|
+
// ── Trigger: Tasks available for processing ──────────────────────────
|
|
51
|
+
node("trigger", "trigger.task_available", "Tasks Available?", {
|
|
52
|
+
maxParallel: "{{maxConcurrent}}",
|
|
53
|
+
pollIntervalMs: 60000,
|
|
54
54
|
status: "{{pollStatus}}",
|
|
55
55
|
}, { x: 400, y: 50 }),
|
|
56
56
|
|
|
@@ -141,9 +141,8 @@ export const TASK_BATCH_PR_TEMPLATE = {
|
|
|
141
141
|
category: "lifecycle",
|
|
142
142
|
enabled: true,
|
|
143
143
|
recommended: false,
|
|
144
|
-
trigger: "trigger.
|
|
144
|
+
trigger: "trigger.task_available",
|
|
145
145
|
variables: {
|
|
146
|
-
backlogThreshold: 3,
|
|
147
146
|
maxConcurrent: 2,
|
|
148
147
|
pollStatus: "todo",
|
|
149
148
|
maxBatchSize: 5,
|
|
@@ -153,8 +152,9 @@ export const TASK_BATCH_PR_TEMPLATE = {
|
|
|
153
152
|
},
|
|
154
153
|
nodes: [
|
|
155
154
|
// ── Trigger ──────────────────────────────────────────────────────────
|
|
156
|
-
node("trigger", "trigger.
|
|
157
|
-
|
|
155
|
+
node("trigger", "trigger.task_available", "Tasks Available?", {
|
|
156
|
+
maxParallel: "{{maxConcurrent}}",
|
|
157
|
+
pollIntervalMs: 60000,
|
|
158
158
|
status: "{{pollStatus}}",
|
|
159
159
|
}, { x: 400, y: 50 }),
|
|
160
160
|
|
|
@@ -44,6 +44,14 @@ function getChildProcess() {
|
|
|
44
44
|
return _childProcessModule;
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
+
function sanitizeGitProcessEnv(baseEnv = process.env) {
|
|
48
|
+
const env = { ...baseEnv };
|
|
49
|
+
delete env.GIT_DIR;
|
|
50
|
+
delete env.GIT_WORK_TREE;
|
|
51
|
+
delete env.GIT_INDEX_FILE;
|
|
52
|
+
return env;
|
|
53
|
+
}
|
|
54
|
+
|
|
47
55
|
// Lazy-loaded reference to repo-config.mjs (resolved on first use)
|
|
48
56
|
let _repoConfigModule = null;
|
|
49
57
|
|
|
@@ -247,6 +255,7 @@ function cloneIntoExistingRepoPath(childProcess, repoUrl, repoPath) {
|
|
|
247
255
|
timeout: 300000,
|
|
248
256
|
stdio: ["pipe", "pipe", "pipe"],
|
|
249
257
|
cwd: repoPath,
|
|
258
|
+
env: sanitizeGitProcessEnv(),
|
|
250
259
|
});
|
|
251
260
|
}
|
|
252
261
|
|
|
@@ -321,6 +330,7 @@ function buildGitPullFailureDetails(err, repoPath, childProcess) {
|
|
|
321
330
|
encoding: "utf8",
|
|
322
331
|
timeout: 10_000,
|
|
323
332
|
stdio: ["pipe", "pipe", "pipe"],
|
|
333
|
+
env: sanitizeGitProcessEnv(),
|
|
324
334
|
}),
|
|
325
335
|
);
|
|
326
336
|
if (statusOut) {
|
|
@@ -393,6 +403,16 @@ export function listWorkspaces(configDir, opts = {}) {
|
|
|
393
403
|
const standardExists = existsSync(standardPath);
|
|
394
404
|
let effectivePath = standardPath;
|
|
395
405
|
let exists = standardExists;
|
|
406
|
+
const repoUrlRaw = String(repo.url || "").trim();
|
|
407
|
+
const looksLikeRemoteUrl =
|
|
408
|
+
/^https?:\/\//i.test(repoUrlRaw) ||
|
|
409
|
+
/^git@[^:]+:/i.test(repoUrlRaw) ||
|
|
410
|
+
/^ssh:\/\//i.test(repoUrlRaw);
|
|
411
|
+
const repoUrlPath = repoUrlRaw && !looksLikeRemoteUrl ? resolve(repoUrlRaw) : null;
|
|
412
|
+
if (!standardExists && repoUrlPath && existsSync(repoUrlPath)) {
|
|
413
|
+
effectivePath = repoUrlPath;
|
|
414
|
+
exists = true;
|
|
415
|
+
}
|
|
396
416
|
if (!standardExists && repoRootOverride) {
|
|
397
417
|
const altPath = resolve(repoRootOverride, repo.name);
|
|
398
418
|
if (existsSync(altPath)) {
|
|
@@ -571,6 +591,7 @@ export function addRepoToWorkspace(configDir, workspaceId, { url, name, branch,
|
|
|
571
591
|
encoding: "utf8",
|
|
572
592
|
timeout: 300000, // 5 minutes
|
|
573
593
|
stdio: ["pipe", "pipe", "pipe"],
|
|
594
|
+
env: sanitizeGitProcessEnv(),
|
|
574
595
|
});
|
|
575
596
|
|
|
576
597
|
if (result.status !== 0) {
|
|
@@ -698,6 +719,7 @@ export function pullWorkspaceRepos(configDir, workspaceId) {
|
|
|
698
719
|
encoding: "utf8",
|
|
699
720
|
timeout: 300000,
|
|
700
721
|
stdio: ["pipe", "pipe", "pipe"],
|
|
722
|
+
env: sanitizeGitProcessEnv(),
|
|
701
723
|
});
|
|
702
724
|
if (clone.status !== 0) {
|
|
703
725
|
const stderr = String(clone.stderr || clone.stdout || "");
|
|
@@ -787,6 +809,7 @@ export function pullWorkspaceRepos(configDir, workspaceId) {
|
|
|
787
809
|
encoding: "utf8",
|
|
788
810
|
timeout: 120000,
|
|
789
811
|
stdio: ["pipe", "pipe", "pipe"],
|
|
812
|
+
env: sanitizeGitProcessEnv(),
|
|
790
813
|
});
|
|
791
814
|
results.push({ name: repo.name, success: true });
|
|
792
815
|
} catch (err) {
|
|
@@ -939,6 +962,7 @@ export function detectWorkspaces(configDir) {
|
|
|
939
962
|
encoding: "utf8",
|
|
940
963
|
timeout: 3000,
|
|
941
964
|
stdio: ["pipe", "pipe", "ignore"],
|
|
965
|
+
env: sanitizeGitProcessEnv(),
|
|
942
966
|
}).trim();
|
|
943
967
|
slug = extractSlug(remote);
|
|
944
968
|
} catch { /* no remote */ }
|
|
@@ -986,3 +1010,4 @@ export function initializeWorkspaces(configDir, opts = {}) {
|
|
|
986
1010
|
|
|
987
1011
|
return { workspaces: [], isNew: true };
|
|
988
1012
|
}
|
|
1013
|
+
|
|
@@ -65,7 +65,7 @@ const GIT_ENV = {
|
|
|
65
65
|
*/
|
|
66
66
|
function fixGitConfigCorruption(repoRoot) {
|
|
67
67
|
try {
|
|
68
|
-
const bareResult = spawnSync("git", ["config", "--
|
|
68
|
+
const bareResult = spawnSync("git", ["config", "--bool", "--get", "core.bare"], {
|
|
69
69
|
cwd: repoRoot,
|
|
70
70
|
encoding: "utf8",
|
|
71
71
|
timeout: 5000,
|
|
@@ -75,7 +75,13 @@ function fixGitConfigCorruption(repoRoot) {
|
|
|
75
75
|
console.warn(
|
|
76
76
|
`${TAG} :alert: Detected core.bare=true on main repo — fixing git config corruption`,
|
|
77
77
|
);
|
|
78
|
-
spawnSync("git", ["config", "--
|
|
78
|
+
spawnSync("git", ["config", "--local", "core.bare", "false"], {
|
|
79
|
+
cwd: repoRoot,
|
|
80
|
+
encoding: "utf8",
|
|
81
|
+
timeout: 5000,
|
|
82
|
+
env: { ...process.env, ...GIT_ENV },
|
|
83
|
+
});
|
|
84
|
+
spawnSync("git", ["config", "--local", "--unset-all", "core.worktree"], {
|
|
79
85
|
cwd: repoRoot,
|
|
80
86
|
encoding: "utf8",
|
|
81
87
|
timeout: 5000,
|