@yemi33/minions 0.1.320 → 0.1.321

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,10 +1,13 @@
1
1
  # Changelog
2
2
 
3
- ## 0.1.320 (2026-04-03)
3
+ ## 0.1.321 (2026-04-03)
4
4
 
5
5
  ### Fixes
6
6
  - project scan finds git repos — .git was in skipDirs
7
7
 
8
+ ### Other
9
+ - refactor: replace magic strings in remaining engine files with constants
10
+
8
11
  ## 0.1.319 (2026-04-03)
9
12
 
10
13
  ### Other
package/engine/ado.js CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  const path = require('path');
7
7
  const shared = require('./shared');
8
- const { exec, getAdoOrgBase, addPrLink, log, dateStamp } = shared;
8
+ const { exec, getAdoOrgBase, addPrLink, log, dateStamp, PR_STATUS } = shared;
9
9
  const { getPrs } = require('./queries');
10
10
 
11
11
  // Lazy require to avoid circular dependency — only needed for engine().handlePostMerge
@@ -80,7 +80,7 @@ async function forEachActivePr(config, token, callback) {
80
80
  if (!project.adoOrg || !project.adoProject || !project.repositoryId) continue;
81
81
 
82
82
  const prs = getPrs(project);
83
- const activePrs = prs.filter(pr => pr.status === 'active');
83
+ const activePrs = prs.filter(pr => pr.status === PR_STATUS.ACTIVE);
84
84
  if (activePrs.length === 0) continue;
85
85
 
86
86
  let projectUpdated = 0;
@@ -123,18 +123,18 @@ async function pollPrStatus(config) {
123
123
  const prData = await adoFetch(`${repoBase}?api-version=7.1`, token);
124
124
 
125
125
  let newStatus = pr.status;
126
- if (prData.status === 'completed') newStatus = 'merged';
127
- else if (prData.status === 'abandoned') newStatus = 'abandoned';
128
- else if (prData.status === 'active') newStatus = 'active';
126
+ if (prData.status === 'completed') newStatus = PR_STATUS.MERGED;
127
+ else if (prData.status === 'abandoned') newStatus = PR_STATUS.ABANDONED;
128
+ else if (prData.status === 'active') newStatus = PR_STATUS.ACTIVE;
129
129
 
130
130
  if (pr.status !== newStatus) {
131
131
  log('info', `PR ${pr.id} status: ${pr.status} → ${newStatus}`);
132
132
  pr.status = newStatus;
133
133
  updated = true;
134
134
 
135
- if (newStatus === 'merged' || newStatus === 'abandoned') {
135
+ if (newStatus === PR_STATUS.MERGED || newStatus === PR_STATUS.ABANDONED) {
136
136
  if (pr.reviewStatus === 'waiting') {
137
- pr.reviewStatus = newStatus === 'merged' ? 'approved' : 'pending';
137
+ pr.reviewStatus = newStatus === PR_STATUS.MERGED ? 'approved' : 'pending';
138
138
  log('info', `PR ${pr.id} reviewStatus: waiting → ${pr.reviewStatus} (${newStatus})`);
139
139
  }
140
140
  await engine().handlePostMerge(pr, project, config, newStatus);
@@ -157,7 +157,7 @@ async function pollPrStatus(config) {
157
157
  .map(r => r.displayName)
158
158
  .filter(Boolean);
159
159
  // Fallback: if PR was merged and no decisive votes, use completedBy
160
- if (!reviewedBy.length && newStatus === 'merged' && prData.closedBy?.displayName) {
160
+ if (!reviewedBy.length && newStatus === PR_STATUS.MERGED && prData.closedBy?.displayName) {
161
161
  reviewedBy.push(prData.closedBy.displayName);
162
162
  }
163
163
  if (JSON.stringify(pr.reviewedBy || []) !== JSON.stringify(reviewedBy)) {
@@ -184,7 +184,7 @@ async function pollPrStatus(config) {
184
184
  }
185
185
  }
186
186
 
187
- if (newStatus !== 'active') return updated;
187
+ if (newStatus !== PR_STATUS.ACTIVE) return updated;
188
188
 
189
189
  const statusData = await adoFetch(`${repoBase}/statuses?api-version=7.1`, token);
190
190
 
package/engine/cli.js CHANGED
@@ -6,7 +6,7 @@
6
6
  const fs = require('fs');
7
7
  const path = require('path');
8
8
  const shared = require('./shared');
9
- const { safeRead, safeJson, safeWrite } = shared;
9
+ const { safeRead, safeJson, safeWrite, WI_STATUS, WORK_TYPE, PLAN_STATUS, PR_STATUS, DISPATCH_RESULT } = shared;
10
10
  const queries = require('./queries');
11
11
  const { getConfig, getControl, getDispatch, getAgentStatus,
12
12
  MINIONS_DIR, ENGINE_DIR, AGENTS_DIR, PLANS_DIR, PRD_DIR, CONTROL_PATH, DISPATCH_PATH } = queries;
@@ -159,8 +159,8 @@ const commands = {
159
159
  const wiPath = path.join(MINIONS_DIR, "projects", item.meta.project.name, "work-items.json");
160
160
  const wiItems = safeJson(wiPath) || [];
161
161
  const wi = wiItems.find(w => w.id === item.meta.item.id);
162
- if (wi && wi.status !== 'dispatched') {
163
- wi.status = 'dispatched';
162
+ if (wi && wi.status !== WI_STATUS.DISPATCHED) {
163
+ wi.status = WI_STATUS.DISPATCHED;
164
164
  wi.dispatched_to = wi.dispatched_to || agentId;
165
165
  wi.dispatched_at = wi.dispatched_at || new Date().toISOString();
166
166
  safeWrite(wiPath, wiItems);
@@ -210,7 +210,7 @@ const commands = {
210
210
  if (!hasResult && !hasError) continue;
211
211
 
212
212
  const isSuccess = hasResult && !hasError;
213
- const result = isSuccess ? 'success' : 'error';
213
+ const result = isSuccess ? DISPATCH_RESULT.SUCCESS : DISPATCH_RESULT.ERROR;
214
214
 
215
215
  e.log('info', `Orphan recovery: ${agentId} (${item.id}) completed while engine was down — result: ${result}`);
216
216
 
@@ -222,7 +222,7 @@ const commands = {
222
222
 
223
223
  // Update work item status
224
224
  if (item.meta?.item?.id) {
225
- const status = isSuccess ? 'done' : 'failed';
225
+ const status = isSuccess ? WI_STATUS.DONE : WI_STATUS.FAILED;
226
226
  try {
227
227
  lifecycle.updateWorkItemStatus(item.meta, status, isSuccess ? '' : 'Completed while engine was down');
228
228
  } catch {
@@ -286,8 +286,8 @@ const commands = {
286
286
  const items = safeJson(wiPath) || [];
287
287
  let changed = false;
288
288
  for (const item of items) {
289
- if (item.status === 'dispatched' && !activeIds.has(item.id)) {
290
- item.status = 'pending';
289
+ if (item.status === WI_STATUS.DISPATCHED && !activeIds.has(item.id)) {
290
+ item.status = WI_STATUS.PENDING;
291
291
  delete item.dispatched_at;
292
292
  delete item.dispatched_to;
293
293
  changed = true;
@@ -656,7 +656,7 @@ const commands = {
656
656
  id: `W${String(items.length + 1).padStart(3, '0')}`,
657
657
  title: title,
658
658
  type: opts.type || 'implement',
659
- status: 'queued',
659
+ status: WI_STATUS.QUEUED,
660
660
  priority: opts.priority || 'medium',
661
661
  complexity: opts.complexity || 'medium',
662
662
  description: opts.description || title,
@@ -750,7 +750,7 @@ const commands = {
750
750
  }
751
751
 
752
752
  const id = e.addToDispatch({
753
- type: 'plan-to-prd',
753
+ type: WORK_TYPE.PLAN_TO_PRD,
754
754
  agent: agentId,
755
755
  agentName: config.agents[agentId]?.name,
756
756
  agentRole: config.agents[agentId]?.role,
@@ -815,13 +815,13 @@ const commands = {
815
815
  }
816
816
  if (exists && name === 'pullRequests') {
817
817
  const prs = safeJson(filePath) || [];
818
- const pending = prs.filter(p => p.status === 'active' && (p.reviewStatus === 'pending' || p.reviewStatus === 'waiting'));
819
- const needsFix = prs.filter(p => p.status === 'active' && p.reviewStatus === 'changes-requested');
818
+ const pending = prs.filter(p => p.status === PR_STATUS.ACTIVE && (p.reviewStatus === 'pending' || p.reviewStatus === 'waiting'));
819
+ const needsFix = prs.filter(p => p.status === PR_STATUS.ACTIVE && p.reviewStatus === 'changes-requested');
820
820
  console.log(` PRs: ${pending.length} pending review, ${needsFix.length} need fixes`);
821
821
  }
822
822
  if (exists && name === 'workItems') {
823
823
  const items = safeJson(filePath) || [];
824
- const queued = items.filter(i => i.status === 'queued');
824
+ const queued = items.filter(i => i.status === WI_STATUS.QUEUED);
825
825
  console.log(` Items: ${queued.length} queued`);
826
826
  }
827
827
  if (name === 'specs' || name === 'mergedDesignDocs') {
@@ -853,7 +853,7 @@ const commands = {
853
853
  const killed = dispatch.active || [];
854
854
  for (const item of killed) {
855
855
  if (item.meta) {
856
- e.updateWorkItemStatus(item.meta, 'pending', '');
856
+ e.updateWorkItemStatus(item.meta, WI_STATUS.PENDING, '');
857
857
  const itemId = item.meta.item?.id;
858
858
  if (itemId) {
859
859
  const wiPath = (item.meta.source === 'central-work-item' || item.meta.source === 'central-work-item-fanout')
@@ -865,7 +865,7 @@ const commands = {
865
865
  const items = safeJson(wiPath) || [];
866
866
  const target = items.find(i => i.id === itemId);
867
867
  if (target) {
868
- target.status = 'pending';
868
+ target.status = WI_STATUS.PENDING;
869
869
  delete target.dispatched_at;
870
870
  delete target.dispatched_to;
871
871
  delete target.failReason;
package/engine/github.js CHANGED
@@ -5,7 +5,7 @@
5
5
  */
6
6
 
7
7
  const shared = require('./shared');
8
- const { exec, getProjects, projectPrPath, projectWorkItemsPath, safeJson, safeWrite, MINIONS_DIR, addPrLink, getPrLinks, log, dateStamp } = shared;
8
+ const { exec, getProjects, projectPrPath, projectWorkItemsPath, safeJson, safeWrite, MINIONS_DIR, addPrLink, getPrLinks, log, dateStamp, PR_STATUS } = shared;
9
9
  const { getPrs } = require('./queries');
10
10
  const path = require('path');
11
11
 
@@ -53,7 +53,7 @@ async function forEachActiveGhPr(config, callback) {
53
53
  if (!slug) continue;
54
54
 
55
55
  const prs = getPrs(project);
56
- const activePrs = prs.filter(pr => pr.status === 'active');
56
+ const activePrs = prs.filter(pr => pr.status === PR_STATUS.ACTIVE);
57
57
  if (activePrs.length === 0) continue;
58
58
 
59
59
  let projectUpdated = 0;
@@ -79,7 +79,7 @@ async function forEachActiveGhPr(config, callback) {
79
79
  // Also poll manually-linked PRs from central pull-requests.json (extract slug from URL)
80
80
  const centralPath = path.join(MINIONS_DIR, 'pull-requests.json');
81
81
  const centralPrs = safeJson(centralPath) || [];
82
- const activeCentral = centralPrs.filter(pr => pr.status === 'active' && pr.url);
82
+ const activeCentral = centralPrs.filter(pr => pr.status === PR_STATUS.ACTIVE && pr.url);
83
83
  let centralUpdated = 0;
84
84
  for (const pr of activeCentral) {
85
85
  const ghMatch = pr.url.match(/github\.com\/([^/]+\/[^/]+)\/pull\/(\d+)/);
@@ -123,19 +123,19 @@ async function pollPrStatus(config) {
123
123
 
124
124
  // Map GitHub PR state to minions status
125
125
  let newStatus = pr.status;
126
- if (prData.merged) newStatus = 'merged';
127
- else if (prData.state === 'closed') newStatus = 'abandoned';
128
- else if (prData.state === 'open') newStatus = 'active';
126
+ if (prData.merged) newStatus = PR_STATUS.MERGED;
127
+ else if (prData.state === 'closed') newStatus = PR_STATUS.ABANDONED;
128
+ else if (prData.state === 'open') newStatus = PR_STATUS.ACTIVE;
129
129
 
130
130
  if (pr.status !== newStatus) {
131
131
  log('info', `PR ${pr.id} status: ${pr.status} → ${newStatus}`);
132
132
  pr.status = newStatus;
133
133
  updated = true;
134
134
 
135
- if (newStatus === 'merged' || newStatus === 'abandoned') {
135
+ if (newStatus === PR_STATUS.MERGED || newStatus === PR_STATUS.ABANDONED) {
136
136
  // Resolve stale 'waiting' review status — won't be polled again after this
137
137
  if (pr.reviewStatus === 'waiting') {
138
- pr.reviewStatus = newStatus === 'merged' ? 'approved' : 'pending';
138
+ pr.reviewStatus = newStatus === PR_STATUS.MERGED ? 'approved' : 'pending';
139
139
  log('info', `PR ${pr.id} reviewStatus: waiting → ${pr.reviewStatus} (${newStatus})`);
140
140
  }
141
141
  await engine().handlePostMerge(pr, project, config, newStatus);
package/engine/meeting.js CHANGED
@@ -6,7 +6,7 @@
6
6
  const fs = require('fs');
7
7
  const path = require('path');
8
8
  const shared = require('./shared');
9
- const { safeJson, safeWrite, safeRead, uid, log, ENGINE_DEFAULTS } = shared;
9
+ const { safeJson, safeWrite, safeRead, uid, log, ENGINE_DEFAULTS, WORK_TYPE, DISPATCH_RESULT } = shared;
10
10
  const queries = require('./queries');
11
11
  const { getDispatch, getConfig } = queries;
12
12
  const { renderPlaybook } = require('./playbook');
@@ -118,7 +118,7 @@ function discoverMeetingWork(config) {
118
118
  if (!prompt) continue;
119
119
 
120
120
  work.push({
121
- type: 'meeting',
121
+ type: WORK_TYPE.MEETING,
122
122
  agent: concluder,
123
123
  agentName: agents[concluder]?.name || concluder,
124
124
  agentRole: agents[concluder]?.role || 'Agent',
@@ -165,7 +165,7 @@ function discoverMeetingWork(config) {
165
165
  if (!prompt) continue;
166
166
 
167
167
  work.push({
168
- type: 'meeting',
168
+ type: WORK_TYPE.MEETING,
169
169
  agent: agentId,
170
170
  agentName: agents[agentId]?.name || agentId,
171
171
  agentRole: agents[agentId]?.role || 'Agent',
@@ -278,7 +278,7 @@ function _killMeetingDispatches(meetingId) {
278
278
  dp.active = (dp.active || []).filter(d => d.meta?.meetingId !== meetingId);
279
279
  dp.completed = dp.completed || [];
280
280
  for (const d of toKill) {
281
- dp.completed.push({ ...d, result: 'error', reason: 'Meeting ended/advanced by human', completed_at: new Date().toISOString() });
281
+ dp.completed.push({ ...d, result: DISPATCH_RESULT.ERROR, reason: 'Meeting ended/advanced by human', completed_at: new Date().toISOString() });
282
282
  }
283
283
  if (dp.completed.length > 100) dp.completed = dp.completed.slice(-100);
284
284
  return dp;
@@ -7,7 +7,7 @@
7
7
  const fs = require('fs');
8
8
  const path = require('path');
9
9
  const shared = require('./shared');
10
- const { safeJson, safeWrite, safeRead, safeReadDir, uid, log, ts, dateStamp, mutateJsonFileLocked } = shared;
10
+ const { safeJson, safeWrite, safeRead, safeReadDir, uid, log, ts, dateStamp, mutateJsonFileLocked, WI_STATUS, WORK_TYPE, PLAN_STATUS, PR_STATUS } = shared;
11
11
  const { parseCronExpr, shouldRunNow } = require('./scheduler');
12
12
 
13
13
  const PIPELINES_DIR = path.join(__dirname, '..', 'pipelines');
@@ -172,7 +172,7 @@ function executeTaskStage(stage, stageState, run, config) {
172
172
  type: item.type || stage.taskType || 'explore',
173
173
  priority: item.priority || stage.priority || 'medium',
174
174
  agent: item.agent || stage.agent || '',
175
- status: 'pending',
175
+ status: WI_STATUS.PENDING,
176
176
  created: ts(),
177
177
  createdBy: 'pipeline:' + run.pipelineId,
178
178
  branch: `pipeline/${run.pipelineId}/${stage.id}`,
@@ -243,9 +243,9 @@ function executePlanStage(stage, stageState, run, config) {
243
243
  workItems.push({
244
244
  id: wiId,
245
245
  title: `Convert plan to PRD: ${path.basename(filePath)}`,
246
- type: 'plan-to-prd',
246
+ type: WORK_TYPE.PLAN_TO_PRD,
247
247
  priority: 'high',
248
- status: 'pending',
248
+ status: WI_STATUS.PENDING,
249
249
  planFile: path.basename(filePath),
250
250
  created: ts(),
251
251
  createdBy: 'pipeline:' + run.pipelineId,
@@ -347,7 +347,7 @@ function isStageComplete(stage, stageState, run, config) {
347
347
  if (ids.length === 0) return false;
348
348
  return ids.every(id => {
349
349
  const wi = workItems.find(w => w.id === id);
350
- return !wi || wi.status === 'done' || wi.status === 'failed'; // missing = treat as done
350
+ return !wi || wi.status === WI_STATUS.DONE || wi.status === WI_STATUS.FAILED; // missing = treat as done
351
351
  });
352
352
  }
353
353
  case 'meeting': {
@@ -372,7 +372,7 @@ function isStageComplete(stage, stageState, run, config) {
372
372
  const prdWiIds = artifacts.workItems || [];
373
373
  const prdDone = prdWiIds.every(id => {
374
374
  const wi = all.find(w => w.id === id);
375
- return !wi || wi.status === 'done' || wi.status === 'failed'; // missing = treat as done
375
+ return !wi || wi.status === WI_STATUS.DONE || wi.status === WI_STATUS.FAILED; // missing = treat as done
376
376
  });
377
377
  if (!prdDone) return false;
378
378
 
@@ -390,7 +390,7 @@ function isStageComplete(stage, stageState, run, config) {
390
390
  }
391
391
  // Find materialized work items for discovered PRDs
392
392
  for (const prdFile of (artifacts.prds || [])) {
393
- const prdItems = all.filter(w => w.sourcePlan === prdFile && w.type !== 'plan-to-prd');
393
+ const prdItems = all.filter(w => w.sourcePlan === prdFile && w.type !== WORK_TYPE.PLAN_TO_PRD);
394
394
  for (const wi of prdItems) {
395
395
  if (!(artifacts.workItems || []).includes(wi.id)) {
396
396
  artifacts.workItems = artifacts.workItems || [];
@@ -405,8 +405,8 @@ function isStageComplete(stage, stageState, run, config) {
405
405
  for (const prdFile of artifacts.prds) {
406
406
  const prdPath = path.join(prdDir, prdFile);
407
407
  const prd = safeJson(prdPath);
408
- if (prd && prd.status === 'awaiting-approval') {
409
- prd.status = 'approved';
408
+ if (prd && prd.status === PLAN_STATUS.AWAITING_APPROVAL) {
409
+ prd.status = PLAN_STATUS.APPROVED;
410
410
  prd.approvedAt = ts();
411
411
  prd.approvedBy = 'pipeline:' + run.pipelineId;
412
412
  safeWrite(prdPath, prd);
@@ -420,7 +420,7 @@ function isStageComplete(stage, stageState, run, config) {
420
420
  if (implementIds.length === 0 && artifacts.prds?.length > 0) return false; // items not materialized yet
421
421
  return implementIds.every(id => {
422
422
  const wi = all.find(w => w.id === id);
423
- return !wi || wi.status === 'done' || wi.status === 'failed'; // missing = treat as done
423
+ return !wi || wi.status === WI_STATUS.DONE || wi.status === WI_STATUS.FAILED; // missing = treat as done
424
424
  });
425
425
  }
426
426
  case 'merge-prs': {
@@ -431,7 +431,7 @@ function isStageComplete(stage, stageState, run, config) {
431
431
  const prs = safeJson(shared.projectPrPath(project)) || [];
432
432
  for (const prId of prIds) {
433
433
  const pr = prs.find(p => p.id === prId);
434
- if (pr && pr.status !== 'merged' && pr.status !== 'abandoned') return false;
434
+ if (pr && pr.status !== PR_STATUS.MERGED && pr.status !== PR_STATUS.ABANDONED) return false;
435
435
  }
436
436
  }
437
437
  return true;
@@ -9,7 +9,7 @@ const path = require('path');
9
9
  const shared = require('./shared');
10
10
  const queries = require('./queries');
11
11
 
12
- const { safeJson, safeRead, getProjects, log, dateStamp } = shared;
12
+ const { safeJson, safeRead, getProjects, log, dateStamp, WI_STATUS, WORK_TYPE, PR_STATUS, DISPATCH_RESULT } = shared;
13
13
  const { getConfig, getDispatch, getNotes, getAgentCharter, getPrs, AGENTS_DIR } = queries;
14
14
 
15
15
  const MINIONS_DIR = path.resolve(__dirname, '..');
@@ -135,7 +135,7 @@ function resolveTaskContext(item, config) {
135
135
  // Check work-items to find which plan file this agent created
136
136
  const workItems = safeJson(path.join(MINIONS_DIR, 'work-items.json')) || [];
137
137
  const agentPlanItems = workItems.filter(w =>
138
- w.type === 'plan' && w.dispatched_to === agent.id && w.status === 'done' && w._planFileName
138
+ w.type === WORK_TYPE.PLAN && w.dispatched_to === agent.id && w.status === WI_STATUS.DONE && w._planFileName
139
139
  ).sort((a, b) => (b.completedAt || '').localeCompare(a.completedAt || ''));
140
140
 
141
141
  if (agentPlanItems.length > 0) {
@@ -390,7 +390,7 @@ function buildAgentContext(agentId, config, project) {
390
390
 
391
391
  // Recent completions (last 5, not 10)
392
392
  const recentCompleted = (dispatch.completed || []).slice(-5).reverse().map(d =>
393
- `- **${d.agent}** ${d.result === 'success' ? 'completed' : 'failed'}: ${(d.task || '').slice(0, 80)}${d.resultSummary ? ' — ' + d.resultSummary.slice(0, 100) : ''}`
393
+ `- **${d.agent}** ${d.result === DISPATCH_RESULT.SUCCESS ? 'completed' : 'failed'}: ${(d.task || '').slice(0, 80)}${d.resultSummary ? ' — ' + d.resultSummary.slice(0, 100) : ''}`
394
394
  );
395
395
  if (recentCompleted.length > 0) {
396
396
  context += `## Recently Completed\n\n${recentCompleted.join('\n')}\n\n`;
@@ -400,13 +400,13 @@ function buildAgentContext(agentId, config, project) {
400
400
  const projects = getProjects(config);
401
401
  const allPrs = [];
402
402
  for (const p of projects) {
403
- const prs = getPrs(p).filter(pr => pr.status === 'active' || pr.status === 'linked');
403
+ const prs = getPrs(p).filter(pr => pr.status === PR_STATUS.ACTIVE || pr.status === 'linked');
404
404
  for (const pr of prs) allPrs.push({ ...pr, _project: p.name });
405
405
  }
406
406
  // Also check central pull-requests.json
407
407
  try {
408
408
  const centralPrs = safeJson(path.join(MINIONS_DIR, 'pull-requests.json')) || [];
409
- for (const pr of centralPrs.filter(pr => pr.status === 'active' || pr.status === 'linked')) {
409
+ for (const pr of centralPrs.filter(pr => pr.status === PR_STATUS.ACTIVE || pr.status === 'linked')) {
410
410
  if (!allPrs.some(p => p.id === pr.id)) allPrs.push({ ...pr, _project: 'central' });
411
411
  }
412
412
  } catch (e) { log('warn', 'read central pull-requests: ' + e.message); }
@@ -450,10 +450,10 @@ function buildBaseVars(agentId, config, project) {
450
450
  }
451
451
 
452
452
  function selectPlaybook(workType, item) {
453
- if (item?.branchStrategy === 'shared-branch' && (workType === 'implement' || workType === 'implement:large')) {
453
+ if (item?.branchStrategy === 'shared-branch' && (workType === WORK_TYPE.IMPLEMENT || workType === WORK_TYPE.IMPLEMENT_LARGE)) {
454
454
  return 'implement-shared';
455
455
  }
456
- if (workType === 'review' && !item?._pr && !item?.pr_id) {
456
+ if (workType === WORK_TYPE.REVIEW && !item?._pr && !item?.pr_id) {
457
457
  return 'work-item';
458
458
  }
459
459
  const typeSpecificPlaybooks = ['explore', 'review', 'test', 'plan-to-prd', 'plan', 'ask', 'verify', 'decompose', 'meeting-investigate', 'meeting-debate', 'meeting-conclude'];
@@ -24,7 +24,7 @@
24
24
  const fs = require('fs');
25
25
  const path = require('path');
26
26
  const shared = require('./shared');
27
- const { safeJson, safeWrite, mutateJsonFileLocked } = shared;
27
+ const { safeJson, safeWrite, mutateJsonFileLocked, WI_STATUS } = shared;
28
28
 
29
29
  const SCHEDULE_RUNS_PATH = path.join(__dirname, 'schedule-runs.json');
30
30
 
@@ -125,7 +125,7 @@ function discoverScheduledWork(config) {
125
125
  type: sched.type || 'implement',
126
126
  priority: sched.priority || 'medium',
127
127
  description: sched.description || sched.title,
128
- status: 'pending',
128
+ status: WI_STATUS.PENDING,
129
129
  created: new Date().toISOString(),
130
130
  createdBy: 'scheduler',
131
131
  agent: sched.agent || null,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yemi33/minions",
3
- "version": "0.1.320",
3
+ "version": "0.1.321",
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"