@yemi33/minions 0.1.81 → 0.1.82

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,17 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.82 (2026-03-31)
4
+
5
+ ### Engine
6
+ - engine/lifecycle.js
7
+
8
+ ### Dashboard
9
+ - dashboard.js
10
+ - dashboard/js/command-center.js
11
+
12
+ ### Playbooks
13
+ - implement.md
14
+
3
15
  ## 0.1.81 (2026-03-31)
4
16
 
5
17
  ### Dashboard
@@ -384,6 +384,45 @@ async function ccExecuteAction(action) {
384
384
  }
385
385
  break;
386
386
  }
387
+ case 'schedule': {
388
+ const url = action._update ? '/api/schedules/update' : '/api/schedules';
389
+ const res = await fetch(url, {
390
+ method: 'POST', headers: { 'Content-Type': 'application/json' },
391
+ body: JSON.stringify({
392
+ id: action.id, title: action.title, cron: action.cron,
393
+ type: action.workType || 'implement',
394
+ project: action.project, agent: action.agent,
395
+ description: action.description, priority: action.priority,
396
+ enabled: action.enabled !== false,
397
+ })
398
+ });
399
+ if (!res.ok) { const d = await res.json().catch(() => ({})); throw new Error(d.error || 'Schedule create failed'); }
400
+ status.innerHTML = '&#10003; Schedule ' + (action._update ? 'updated' : 'created') + ': <strong>' + escHtml(action.id) + '</strong>';
401
+ status.style.color = 'var(--green)';
402
+ break;
403
+ }
404
+ case 'delete-schedule': {
405
+ const res = await fetch('/api/schedules/delete', {
406
+ method: 'POST', headers: { 'Content-Type': 'application/json' },
407
+ body: JSON.stringify({ id: action.id })
408
+ });
409
+ if (!res.ok) { const d = await res.json().catch(() => ({})); throw new Error(d.error || 'Schedule delete failed'); }
410
+ status.innerHTML = '&#10003; Deleted schedule: <strong>' + escHtml(action.id) + '</strong>';
411
+ status.style.color = 'var(--orange)';
412
+ break;
413
+ }
414
+ case 'create-meeting': {
415
+ const res = await fetch('/api/meetings', {
416
+ method: 'POST', headers: { 'Content-Type': 'application/json' },
417
+ body: JSON.stringify({ topic: action.topic, agents: action.agents, rounds: action.rounds, project: action.project })
418
+ });
419
+ if (!res.ok) { const d = await res.json().catch(() => ({})); throw new Error(d.error || 'Meeting create failed'); }
420
+ const d = await res.json();
421
+ status.innerHTML = '&#10003; Meeting started: <strong>' + escHtml(action.topic) + '</strong>' + (d.id ? ' (' + escHtml(d.id) + ')' : '');
422
+ status.style.color = 'var(--green)';
423
+ wakeEngine();
424
+ break;
425
+ }
387
426
  default:
388
427
  status.innerHTML = '? Unknown action: ' + escHtml(action.type);
389
428
  status.style.color = 'var(--muted)';
package/dashboard.js CHANGED
@@ -371,6 +371,9 @@ Available action types:
371
371
  - **plan-edit**: Revise/edit a plan .md file. Fields: file (plan .md filename from plans/), instruction (what to change).
372
372
  - **execute-plan**: Execute an existing plan .md file. Fields: file (plan .md filename), project (optional)
373
373
  - **file-edit**: Edit any minions file via LLM. Fields: file (path relative to minions dir), instruction (what to change).
374
+ - **schedule**: Create or update a scheduled task. Fields: id (unique slug), title, cron (3-field: minute hour dayOfWeek), workType (implement/test/explore/ask/review/fix), project (optional), agent (optional), description (optional), priority (optional), enabled (default true). Example cron: "0 9 2" = every Tuesday at 9am.
375
+ - **delete-schedule**: Delete a scheduled task. Fields: id.
376
+ - **create-meeting**: Start a team meeting. Fields: topic, agents (array of agent IDs), rounds (optional, default 3), project (optional).
374
377
 
375
378
  ## Rules
376
379
 
@@ -419,7 +422,8 @@ ${projects}
419
422
  ### Scheduled Tasks
420
423
  ${schedSummary}
421
424
 
422
- To discover all available dashboard APIs, fetch GET http://localhost:7331/api/routes — it returns every endpoint with method, path, description, and accepted parameters.
425
+ ### Dashboard API (all endpoints)
426
+ ${_getApiRoutesSummary()}
423
427
 
424
428
  For details on any of the above, use your tools to read files under \`${MINIONS_DIR}\`.`;
425
429
  }
@@ -446,6 +450,16 @@ function parseCCActions(text) {
446
450
  return { text: displayText, actions };
447
451
  }
448
452
 
453
+ // ── API routes reference for CC — populated by server setup ──────────────────
454
+ let _apiRoutesRef = null; // set to ROUTES array once server initializes
455
+ function _getApiRoutesSummary() {
456
+ if (!_apiRoutesRef) return '(API routes not yet loaded — fetch GET /api/routes to discover endpoints)';
457
+ return _apiRoutesRef
458
+ .filter(r => r.path !== '/api/routes' && typeof r.path === 'string')
459
+ .map(r => `- \`${r.method} ${r.path}\` — ${r.desc}${r.params ? ' | Params: ' + r.params : ''}`)
460
+ .join('\n');
461
+ }
462
+
449
463
  // ── Shared LLM call core — used by CC panel and doc modals ──────────────────
450
464
 
451
465
  // Session store for doc modals — keyed by filePath or title, persisted to disk
@@ -3310,6 +3324,9 @@ What would you like to discuss or change? When you're happy, say "approve" and I
3310
3324
  { method: 'POST', path: '/api/settings/routing', desc: 'Update routing.md', params: 'content', handler: handleSettingsRouting },
3311
3325
  ];
3312
3326
 
3327
+ // Expose routes to CC preamble builder (once, on first request)
3328
+ if (!_apiRoutesRef) _apiRoutesRef = ROUTES;
3329
+
3313
3330
  // ── Route Dispatcher ────────────────────────────────────────────────────────
3314
3331
 
3315
3332
  const pathname = req.url.split('?')[0];
@@ -1136,8 +1136,8 @@ function runPostCompletionHooks(dispatchItem, agentId, code, stdout, config) {
1136
1136
  const projects = shared.getProjects(config);
1137
1137
  const existingPrFound = Object.values(getPrLinks()).includes(meta.item.id);
1138
1138
  if (!existingPrFound) {
1139
- e.log('warn', `Agent completed implement task ${meta.item.id} but no PR was created`);
1140
- // Set noPr flag on the work item so the dashboard can surface this
1139
+ e.log('warn', `Agent completed implement task ${meta.item.id} but no PR was created — reverting to failed for retry`);
1140
+ // Revert to failed so auto-retry can re-attempt with PR creation
1141
1141
  let wiPath;
1142
1142
  if (meta.source === 'central-work-item' || meta.source === 'central-work-item-fanout') {
1143
1143
  wiPath = path.join(MINIONS_DIR, 'work-items.json');
@@ -1149,6 +1149,18 @@ function runPostCompletionHooks(dispatchItem, agentId, code, stdout, config) {
1149
1149
  const wi = items.find(i => i.id === meta.item.id);
1150
1150
  if (wi) {
1151
1151
  wi.noPr = true;
1152
+ wi.failReason = 'Completed without creating a pull request';
1153
+ const retries = wi._retryCount || 0;
1154
+ if (retries < 3) {
1155
+ wi.status = 'pending';
1156
+ wi._retryCount = retries + 1;
1157
+ delete wi.dispatched_at;
1158
+ delete wi.dispatched_to;
1159
+ e.log('info', `Auto-retry ${retries + 1}/3 for ${meta.item.id} (no PR created)`);
1160
+ } else {
1161
+ wi.status = 'failed';
1162
+ e.log('warn', `${meta.item.id} failed after 3 retries — no PR created`);
1163
+ }
1152
1164
  shared.safeWrite(wiPath, items);
1153
1165
  }
1154
1166
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yemi33/minions",
3
- "version": "0.1.81",
3
+ "version": "0.1.82",
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"
@@ -56,7 +56,9 @@ cd {{team_root}}
56
56
  git worktree remove ../worktrees/{{branch_name}} --force
57
57
  ```
58
58
 
59
- ## Create PR
59
+ ## Create PR (MANDATORY)
60
+
61
+ **Your task is NOT complete until a pull request exists.** If PR creation fails, retry up to 3 times before reporting the error.
60
62
 
61
63
  {{pr_create_instructions}}
62
64
  - sourceRefName: `refs/heads/{{branch_name}}`