@yemi33/minions 0.1.935 → 0.1.937

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/CHANGELOG.md CHANGED
@@ -1,8 +1,9 @@
1
1
  # Changelog
2
2
 
3
- ## 0.1.935 (2026-04-14)
3
+ ## 0.1.937 (2026-04-14)
4
4
 
5
5
  ### Features
6
+ - make ADO poll frequency configurable and ungate reconcilePrs
6
7
  - certificate-based auth for Teams integration (#1027)
7
8
  - add adoPollEnabled/ghPollEnabled engine settings
8
9
  - doc-chat abort kills LLM process + queued messages auto-process
@@ -22,6 +23,7 @@
22
23
  - add red dot notification on CC tab when response completes (#934) (#946)
23
24
 
24
25
  ### Fixes
26
+ - deduplicate work item creation by title
25
27
  - persist adoPollEnabled/ghPollEnabled in settings save
26
28
  - prevent _consolidationInFlight race from stale force-reset timeout (#1023)
27
29
  - stop perpetual ADO poll retry when token unavailable (#1021)
@@ -41,7 +43,6 @@
41
43
  - pipeline artifact links use pushModalBack instead of setTimeout race (#993)
42
44
  - close unclosed code fences and lone backticks in renderMd (#991)
43
45
  - PRD item status stuck at dispatched when fix completes (#989)
44
- - dep merge ancestor pruning + pre-flight simulation (#958) (#979)
45
46
 
46
47
  ### Other
47
48
  - test(preflight): add unit tests for findClaudeBinary, runPreflight, printPreflight, checkOrExit (#953)
@@ -49,8 +49,12 @@ async function openSettings() {
49
49
  settingsToggle('Auto-decompose', 'set-autoDecompose', e.autoDecompose !== false, 'Large implement items are auto-split into sub-tasks') +
50
50
  settingsToggle('Allow Temp Agents', 'set-allowTempAgents', !!e.allowTempAgents, 'Spawn ephemeral agents when all permanent agents are busy') +
51
51
  settingsToggle('Auto-archive Plans', 'set-autoArchive', !!e.autoArchive, 'Automatically archive plans after verify completes (off = manual archive via dashboard)') +
52
- settingsToggle('ADO Polling', 'set-adoPollEnabled', e.adoPollEnabled !== false, 'Poll ADO PR status, comments, and reconciliation on each tick cycle') +
53
- settingsToggle('GitHub Polling', 'set-ghPollEnabled', e.ghPollEnabled !== false, 'Poll GitHub PR status, comments, and reconciliation on each tick cycle') +
52
+ settingsToggle('ADO Polling', 'set-adoPollEnabled', e.adoPollEnabled !== false, 'Poll ADO PR status and comments each tick (reconciliation always runs)') +
53
+ settingsToggle('GitHub Polling', 'set-ghPollEnabled', e.ghPollEnabled !== false, 'Poll GitHub PR status and comments each tick (reconciliation always runs)') +
54
+ '</div>' +
55
+ '<div style="display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-bottom:16px">' +
56
+ settingsField('ADO Status Poll Frequency', 'set-adoPollStatusEvery', e.adoPollStatusEvery || 6, 'ticks', 'Poll ADO PR build/review/merge status every N ticks (~6 min at default tick rate)') +
57
+ settingsField('ADO Comments Poll Frequency', 'set-adoPollCommentsEvery', e.adoPollCommentsEvery || 12, 'ticks', 'Poll ADO PR human comments every N ticks (~12 min at default tick rate)') +
54
58
  '</div>' +
55
59
  '<div style="display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-bottom:16px">' +
56
60
  settingsField('Eval Max Iterations', 'set-evalMaxIterations', e.evalMaxIterations || 3, '', 'Max review→fix cycles before escalating (1-10)') +
@@ -235,6 +239,8 @@ async function saveSettings() {
235
239
  autoArchive: document.getElementById('set-autoArchive').checked,
236
240
  adoPollEnabled: document.getElementById('set-adoPollEnabled').checked,
237
241
  ghPollEnabled: document.getElementById('set-ghPollEnabled').checked,
242
+ adoPollStatusEvery: document.getElementById('set-adoPollStatusEvery').value,
243
+ adoPollCommentsEvery: document.getElementById('set-adoPollCommentsEvery').value,
238
244
  evalMaxIterations: document.getElementById('set-evalMaxIterations').value,
239
245
  evalMaxCost: document.getElementById('set-evalMaxCost').value || null,
240
246
  maxBuildFixAttempts: document.getElementById('set-maxBuildFixAttempts').value,
package/dashboard.js CHANGED
@@ -1486,11 +1486,18 @@ const server = http.createServer(async (req, res) => {
1486
1486
  if (body.references) item.references = body.references;
1487
1487
  if (body.acceptanceCriteria) item.acceptanceCriteria = body.acceptanceCriteria;
1488
1488
  if (body.skipPr) item.skipPr = true;
1489
+ let dupId = null;
1489
1490
  mutateJsonFileLocked(wiPath, (items) => {
1490
1491
  if (!Array.isArray(items)) items = [];
1492
+ const existing = items.find(i =>
1493
+ i.title === item.title &&
1494
+ (i.status === WI_STATUS.PENDING || i.status === WI_STATUS.DISPATCHED)
1495
+ );
1496
+ if (existing) { dupId = existing.id; return items; }
1491
1497
  items.push(item);
1492
1498
  return items;
1493
1499
  });
1500
+ if (dupId) return jsonReply(res, 409, { ok: true, id: dupId, duplicate: true });
1494
1501
  return jsonReply(res, 200, { ok: true, id });
1495
1502
  } catch (e) { return jsonReply(res, 400, { error: e.message }); }
1496
1503
  }
@@ -3730,6 +3737,7 @@ What would you like to discuss or change? When you're happy, say "approve" and I
3730
3737
  meetingRoundTimeout: [60000],
3731
3738
  versionCheckInterval: [60000],
3732
3739
  maxBuildFixAttempts: [1, 10],
3740
+ adoPollStatusEvery: [1], adoPollCommentsEvery: [1],
3733
3741
  };
3734
3742
  for (const [key, [min, max]] of Object.entries(numericFields)) {
3735
3743
  if (e[key] !== undefined) {
package/engine/shared.js CHANGED
@@ -549,6 +549,8 @@ const ENGINE_DEFAULTS = {
549
549
  buildFixGracePeriod: 600000, // 10min — wait for CI to run after build fix before re-dispatching
550
550
  adoPollEnabled: true, // poll ADO PR status, comments, and reconciliation on each tick cycle
551
551
  ghPollEnabled: true, // poll GitHub PR status, comments, and reconciliation on each tick cycle
552
+ adoPollStatusEvery: 6, // poll ADO PR build/review/merge status every N ticks (~6 min at default interval)
553
+ adoPollCommentsEvery: 12, // poll ADO PR human comments every N ticks (~12 min at default interval)
552
554
  autoCompletePrs: false, // auto-merge PRs when builds green + review approved (opt-in)
553
555
  prMergeMethod: 'squash', // merge method: squash, merge, rebase
554
556
  ignoredCommentAuthors: [], // comments from these authors are auto-closed and never trigger fixes
package/engine.js CHANGED
@@ -3122,11 +3122,13 @@ async function tickInner() {
3122
3122
 
3123
3123
  const adoPollEnabled = config.engine?.adoPollEnabled ?? DEFAULTS.adoPollEnabled;
3124
3124
  const ghPollEnabled = config.engine?.ghPollEnabled ?? DEFAULTS.ghPollEnabled;
3125
+ const adoPollStatusEvery = Math.max(1, Number(config.engine?.adoPollStatusEvery) || DEFAULTS.adoPollStatusEvery);
3126
+ const adoPollCommentsEvery = Math.max(1, Number(config.engine?.adoPollCommentsEvery) || DEFAULTS.adoPollCommentsEvery);
3125
3127
 
3126
- // 2.6. Poll PR status: build, review, merge (every 6 ticks = ~3 minutes)
3128
+ // 2.6. Poll PR status: build, review, merge (every adoPollStatusEvery ticks, default ~6 minutes)
3127
3129
  // Awaited so PR state is consistent before discoverWork reads it
3128
3130
  // Also re-polls early if previous tick had ADO auth failures (stale build status recovery)
3129
- if (tickCount % 6 === 0 || needsAdoPollRetry()) {
3131
+ if (tickCount % adoPollStatusEvery === 0 || needsAdoPollRetry()) {
3130
3132
  if (adoPollEnabled) {
3131
3133
  try { await pollPrStatus(config); } catch (err) { log('warn', `ADO PR status poll error: ${err?.message || err}${err?.stack ? ' | ' + err.stack.split('\n')[1]?.trim() : ''}`); }
3132
3134
  }
@@ -3152,16 +3154,17 @@ async function tickInner() {
3152
3154
  } catch (err) { log('warn', `Plan completion check error: ${err?.message || err}`); }
3153
3155
  }
3154
3156
 
3155
- // 2.7. Poll PR threads for human comments (every 12 ticks = ~6 minutes)
3156
- if (tickCount % 12 === 0) {
3157
+ // 2.7. Poll PR threads for human comments (every adoPollCommentsEvery ticks, default ~12 minutes)
3158
+ if (tickCount % adoPollCommentsEvery === 0) {
3157
3159
  if (adoPollEnabled) {
3158
3160
  try { await pollPrHumanComments(config); } catch (err) { log('warn', `ADO PR comment poll error: ${err?.message || err}${err?.stack ? ' | ' + err.stack.split('\n')[1]?.trim() : ''}`); }
3159
- try { await reconcilePrs(config); } catch (err) { log('warn', `ADO PR reconciliation error: ${err?.message || err}${err?.stack ? ' | ' + err.stack.split('\n')[1]?.trim() : ''}`); }
3160
3161
  }
3161
3162
  if (ghPollEnabled) {
3162
3163
  try { await ghPollPrHumanComments(config); } catch (err) { log('warn', `GitHub PR comment poll error: ${err?.message || err}${err?.stack ? ' | ' + err.stack.split('\n')[1]?.trim() : ''}`); }
3163
- try { await ghReconcilePrs(config); } catch (err) { log('warn', `GitHub PR reconciliation error: ${err?.message || err}${err?.stack ? ' | ' + err.stack.split('\n')[1]?.trim() : ''}`); }
3164
3164
  }
3165
+ // Reconciliation runs regardless of poll flags — it's a recovery sweep, not a convenience poll
3166
+ try { await reconcilePrs(config); } catch (err) { log('warn', `ADO PR reconciliation error: ${err?.message || err}${err?.stack ? ' | ' + err.stack.split('\n')[1]?.trim() : ''}`); }
3167
+ try { await ghReconcilePrs(config); } catch (err) { log('warn', `GitHub PR reconciliation error: ${err?.message || err}${err?.stack ? ' | ' + err.stack.split('\n')[1]?.trim() : ''}`); }
3165
3168
  }
3166
3169
 
3167
3170
  // 2.9. Stalled dispatch detection — auto-retry failed items blocking the graph (every 20 ticks = ~10 min)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yemi33/minions",
3
- "version": "0.1.935",
3
+ "version": "0.1.937",
4
4
  "description": "Multi-agent AI dev team that runs from ~/.minions/ — five autonomous agents share a single engine, dashboard, and knowledge base",
5
5
  "bin": {
6
6
  "minions": "bin/minions.js"