@yemi33/minions 0.1.1663 → 0.1.1664

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,9 +1,13 @@
1
1
  # Changelog
2
2
 
3
- ## 0.1.1663 (2026-05-01)
3
+ ## 0.1.1664 (2026-05-01)
4
+
5
+ ### Features
6
+ - prevent duplicate PR fix dispatch (#1953)
7
+
8
+ ## 0.1.1662 (2026-05-01)
4
9
 
5
10
  ### Other
6
- - test(shared): add unit tests for PR URL parsing & scope helpers (#1949)
7
11
  - test(scheduler): add unit tests for cron parsing edge cases & discovery flow (#1948)
8
12
 
9
13
  ## 0.1.1661 (2026-05-01)
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "runtime": "copilot",
3
3
  "models": null,
4
- "cachedAt": "2026-05-01T15:03:53.784Z"
4
+ "cachedAt": "2026-05-01T19:29:49.074Z"
5
5
  }
@@ -59,16 +59,52 @@ function mutateDispatch(mutator) {
59
59
 
60
60
  // ─── Add to Dispatch ─────────────────────────────────────────────────────────
61
61
 
62
- function getPrDispatchDedupeKey(entry) {
63
- if (!entry?.meta?.pr || !entry?.meta?.project || !entry?.type) return null;
64
- const type = entry.type === WORK_TYPE.FIX ? WORK_TYPE.FIX : entry.type;
62
+ function getDispatchProjectKey(project) {
63
+ if (!project) return '';
64
+ return project.name || (project.localPath ? path.resolve(project.localPath).toLowerCase() : '');
65
+ }
66
+
67
+ function getPrDispatchTargetKey(entry) {
68
+ if (!entry?.meta?.pr || !entry?.meta?.project) return null;
65
69
  const project = entry.meta.project;
66
- const projectKey = project.name
67
- || (project.localPath ? path.resolve(project.localPath).toLowerCase() : '');
70
+ const projectKey = getDispatchProjectKey(project);
68
71
  if (!projectKey) return null;
69
72
  const prKey = shared.getCanonicalPrId(project, entry.meta.pr, entry.meta.pr?.url || '');
70
73
  if (!prKey) return null;
71
- return `${projectKey}:${type}:${prKey}`;
74
+ return `${projectKey}:${prKey}`;
75
+ }
76
+
77
+ function getPrDispatchDedupeKey(entry) {
78
+ if (!entry?.type) return null;
79
+ const targetKey = getPrDispatchTargetKey(entry);
80
+ if (!targetKey) return null;
81
+ const type = entry.type === WORK_TYPE.FIX ? WORK_TYPE.FIX : entry.type;
82
+ return `${targetKey}:${type}`;
83
+ }
84
+
85
+ function getBranchDispatchLockKey(entry) {
86
+ const branch = entry?.meta?.branch || entry?.meta?.pr?.branch || '';
87
+ if (!branch) return null;
88
+ const normalizedBranch = shared.sanitizeBranch(branch);
89
+ if (!normalizedBranch) return null;
90
+ const projectKey = getDispatchProjectKey(entry?.meta?.project) || 'default';
91
+ return `${projectKey}:${normalizedBranch}`;
92
+ }
93
+
94
+ function findActivePrOrBranchLock(dispatch, item) {
95
+ if (item?.type !== WORK_TYPE.FIX) return null;
96
+ const active = dispatch.active || [];
97
+ const prTargetKey = getPrDispatchTargetKey(item);
98
+ if (prTargetKey) {
99
+ const existing = active.find(d => getPrDispatchTargetKey(d) === prTargetKey);
100
+ if (existing) return { existing, reason: `active PR dispatch ${prTargetKey}` };
101
+ }
102
+
103
+ const branchLockKey = getBranchDispatchLockKey(item);
104
+ if (!branchLockKey) return null;
105
+ const existing = active.find(d => getBranchDispatchLockKey(d) === branchLockKey);
106
+ if (!existing) return null;
107
+ return { existing, reason: `active branch dispatch ${branchLockKey}` };
72
108
  }
73
109
 
74
110
  function addToDispatch(item) {
@@ -106,6 +142,11 @@ function addToDispatch(item) {
106
142
  return dispatch;
107
143
  }
108
144
  }
145
+ const activeLock = findActivePrOrBranchLock(dispatch, item);
146
+ if (activeLock) {
147
+ log('info', `Dedup: skipping ${item.id} — ${activeLock.reason} already in ${activeLock.existing.id}`);
148
+ return dispatch;
149
+ }
109
150
  dispatch.pending.push(item);
110
151
  added = true;
111
152
  return dispatch;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yemi33/minions",
3
- "version": "0.1.1663",
3
+ "version": "0.1.1664",
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"