@yemi33/minions 0.1.1708 → 0.1.1709

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,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.1709 (2026-05-04)
4
+
5
+ ### Fixes
6
+ - auto-heal projects with missing workSources at engine boot
7
+
3
8
  ## 0.1.1708 (2026-05-04)
4
9
 
5
10
  ### Fixes
package/engine/cli.js CHANGED
@@ -379,6 +379,28 @@ const commands = {
379
379
  // refactor. No disk write — the on-disk config still carries `ccModel`.
380
380
  try { shared.applyLegacyCcModelMigration(config, { logger: e.log }); }
381
381
  catch (err) { e.log('warn', `legacy ccModel migration failed: ${err.message}`); }
382
+
383
+ // Auto-heal projects missing workSources (cloned-repo / hand-rolled-config
384
+ // footgun): without this block, discoverFromWorkItems / discoverFromPrs
385
+ // bail silently and the engine looks healthy but never dispatches. The
386
+ // disk-side mutation re-derives heal state from the on-disk copy so we
387
+ // don't clobber a concurrent dashboard write between the in-memory check
388
+ // and the lock acquire. skipWriteIfUnchanged makes the write a no-op when
389
+ // nothing needed healing (e.g. dashboard already fixed it).
390
+ try {
391
+ const heal = shared.backfillProjectWorkSourceDefaults(config);
392
+ if (heal.changed) {
393
+ const configPath = path.join(shared.MINIONS_DIR, 'config.json');
394
+ shared.mutateJsonFileLocked(configPath, (onDisk) => {
395
+ shared.backfillProjectWorkSourceDefaults(onDisk);
396
+ return onDisk;
397
+ }, { defaultValue: {}, skipWriteIfUnchanged: true });
398
+ for (const h of heal.healed) {
399
+ e.log('info', `Auto-healed project "${h.project}" — backfilled missing workSources: ${h.sources.join(', ')}`);
400
+ }
401
+ console.log(` Auto-healed ${heal.healed.length} project(s) with missing workSources defaults — engine will now dispatch their work.`);
402
+ }
403
+ } catch (err) { e.log('warn', `workSources auto-heal failed: ${err.message}`); }
382
404
  const interval = config.engine?.tickInterval || shared.ENGINE_DEFAULTS.tickInterval;
383
405
 
384
406
  const { getProjects } = require('./shared');
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "runtime": "copilot",
3
3
  "models": null,
4
- "cachedAt": "2026-05-04T16:42:47.140Z"
4
+ "cachedAt": "2026-05-04T16:53:06.222Z"
5
5
  }
package/engine/shared.js CHANGED
@@ -1185,6 +1185,44 @@ function projectWorkSourceWarnings(config, getDataCounts) {
1185
1185
  return warnings;
1186
1186
  }
1187
1187
 
1188
+ /**
1189
+ * Boot-time auto-heal for the cloned-repo / hand-rolled-config footgun: any
1190
+ * project missing a `workSources.workItems` or `workSources.pullRequests`
1191
+ * sub-block gets the dashboard's default backfilled. We only touch *missing*
1192
+ * sub-blocks — an explicit `enabled: false` is treated as user intent and
1193
+ * left alone.
1194
+ *
1195
+ * Pure helper — mutates `config` in place and returns
1196
+ * `{ changed: boolean, healed: Array<{ project, sources }> }` so the caller
1197
+ * can decide whether to persist + log. Returns `{ changed: false, healed: [] }`
1198
+ * for null/empty/malformed input.
1199
+ */
1200
+ function backfillProjectWorkSourceDefaults(config) {
1201
+ const result = { changed: false, healed: [] };
1202
+ if (!config || typeof config !== 'object') return result;
1203
+ const projects = Array.isArray(config.projects) ? config.projects : [];
1204
+ for (const project of projects) {
1205
+ if (!project || typeof project !== 'object') continue;
1206
+ const filled = [];
1207
+ if (!project.workSources || typeof project.workSources !== 'object') {
1208
+ project.workSources = {};
1209
+ }
1210
+ if (!project.workSources.pullRequests) {
1211
+ project.workSources.pullRequests = { enabled: true, cooldownMinutes: 30 };
1212
+ filled.push('pullRequests');
1213
+ }
1214
+ if (!project.workSources.workItems) {
1215
+ project.workSources.workItems = { enabled: true, cooldownMinutes: 0 };
1216
+ filled.push('workItems');
1217
+ }
1218
+ if (filled.length > 0) {
1219
+ result.changed = true;
1220
+ result.healed.push({ project: project.name, sources: filled });
1221
+ }
1222
+ }
1223
+ return result;
1224
+ }
1225
+
1188
1226
  // ─── Status & Type Constants ─────────────────────────────────────────────────
1189
1227
 
1190
1228
  const WI_STATUS = {
@@ -2581,6 +2619,7 @@ module.exports = {
2581
2619
  applyLegacyCcModelMigration, _resetLegacyCcModelMigrationFlag,
2582
2620
  runtimeConfigWarnings,
2583
2621
  projectWorkSourceWarnings,
2622
+ backfillProjectWorkSourceDefaults,
2584
2623
  WI_STATUS, DONE_STATUSES, PLAN_TERMINAL_STATUSES, WORK_TYPE, PLAN_STATUS, PRD_ITEM_STATUS, PRD_MATERIALIZABLE, PR_STATUS, PR_POLLABLE_STATUSES, PR_PENDING_REASON, DISPATCH_RESULT, trackReviewMetric, queuePlanToPrd,
2585
2624
  WATCH_STATUS, WATCH_TARGET_TYPE, WATCH_CONDITION, WATCH_ABSOLUTE_CONDITIONS,
2586
2625
  PIPELINE_STATUS, STAGE_TYPE, MEETING_STATUS, AGENT_STATUS,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yemi33/minions",
3
- "version": "0.1.1708",
3
+ "version": "0.1.1709",
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"