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.
@@ -10,7 +10,7 @@
10
10
  * - TASK_BATCH_PR_TEMPLATE (batch → agent → PR shortcut)
11
11
  *
12
12
  * DAG overview:
13
- * trigger.task_low
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.task_low",
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: Backlog drops below threshold ───────────────────────────
52
- node("trigger", "trigger.task_low", "Backlog Low?", {
53
- threshold: "{{backlogThreshold}}",
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.task_low",
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.task_low", "Backlog Low?", {
157
- threshold: "{{backlogThreshold}}",
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", "--local", "core.bare"], {
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", "--unset", "core.bare"], {
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,