@yemi33/minions 0.1.466 → 0.1.467

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.467 (2026-04-07)
4
+
5
+ ### Fixes
6
+ - plan execute uses mutateJsonFileLocked for atomic check-and-insert
7
+
3
8
  ## 0.1.466 (2026-04-07)
4
9
 
5
10
  ### Fixes
package/dashboard.js CHANGED
@@ -2160,22 +2160,25 @@ If nothing to do: { "duplicates": [], "reclassify": [], "remove": [] }`;
2160
2160
  const planPath = path.join(MINIONS_DIR, 'plans', body.file);
2161
2161
  if (!fs.existsSync(planPath)) return jsonReply(res, 404, { error: 'plan file not found' });
2162
2162
 
2163
- // Check if already queued
2163
+ // Atomic check-and-insert to prevent duplicates and races with engine
2164
2164
  const centralPath = path.join(MINIONS_DIR, 'work-items.json');
2165
- const items = JSON.parse(safeRead(centralPath) || '[]');
2166
- const existing = items.find(w => w.type === 'plan-to-prd' && w.planFile === body.file && w.status !== 'failed' && w.status !== 'cancelled');
2167
- if (existing) return jsonReply(res, 200, { ok: true, id: existing.id, alreadyQueued: true });
2168
-
2165
+ let existingId = null;
2169
2166
  const id = 'W-' + shared.uid();
2170
- items.push({
2171
- id, title: 'Convert plan to PRD: ' + body.file.replace('.md', ''),
2172
- type: 'plan-to-prd', priority: 'high',
2173
- description: 'Plan file: plans/' + body.file,
2174
- status: 'pending', created: new Date().toISOString(),
2175
- createdBy: 'dashboard:execute', project: body.project || '',
2176
- planFile: body.file,
2177
- });
2178
- safeWrite(centralPath, items);
2167
+ mutateJsonFileLocked(centralPath, (items) => {
2168
+ if (!Array.isArray(items)) items = [];
2169
+ const existing = items.find(w => w.type === 'plan-to-prd' && w.planFile === body.file && w.status !== 'failed' && w.status !== 'cancelled');
2170
+ if (existing) { existingId = existing.id; return items; }
2171
+ items.push({
2172
+ id, title: 'Convert plan to PRD: ' + body.file.replace('.md', ''),
2173
+ type: 'plan-to-prd', priority: 'high',
2174
+ description: 'Plan file: plans/' + body.file,
2175
+ status: 'pending', created: new Date().toISOString(),
2176
+ createdBy: 'dashboard:execute', project: body.project || '',
2177
+ planFile: body.file,
2178
+ });
2179
+ return items;
2180
+ }, { defaultValue: [] });
2181
+ if (existingId) return jsonReply(res, 200, { ok: true, id: existingId, alreadyQueued: true });
2179
2182
  invalidateStatusCache();
2180
2183
  return jsonReply(res, 200, { ok: true, id });
2181
2184
  } catch (e) { return jsonReply(res, 400, { error: e.message }); }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yemi33/minions",
3
- "version": "0.1.466",
3
+ "version": "0.1.467",
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"