@yemi33/minions 0.1.82 → 0.1.84

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,15 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.84 (2026-03-31)
4
+
5
+ ### Dashboard
6
+ - dashboard/js/render-kb.js
7
+
8
+ ## 0.1.83 (2026-03-31)
9
+
10
+ ### Engine
11
+ - engine/lifecycle.js
12
+
3
13
  ## 0.1.82 (2026-03-31)
4
14
 
5
15
  ### Engine
@@ -1,5 +1,17 @@
1
1
  // render-kb.js — Knowledge base rendering functions extracted from dashboard.html
2
2
 
3
+ const KB_CAT_LABELS = {
4
+ architecture: 'Architecture', conventions: 'Conventions',
5
+ 'project-notes': 'Project Notes', 'build-reports': 'Build Reports',
6
+ reviews: 'Reviews', learnings: 'Learnings', decisions: 'Decisions',
7
+ incidents: 'Incidents', 'api-notes': 'API Notes',
8
+ };
9
+ const KB_CAT_ICONS = {
10
+ architecture: '\u{1F3D7}', conventions: '\u{1F4CF}',
11
+ 'project-notes': '\u{1F4DD}', 'build-reports': '\u{1F6E0}',
12
+ reviews: '\u{1F50D}', learnings: '\u{1F4A1}', decisions: '\u{2696}',
13
+ incidents: '\u{1F6A8}', 'api-notes': '\u{1F517}',
14
+ };
3
15
  let _kbActiveTab = 'all';
4
16
 
5
17
  async function refreshKnowledgeBase() {
@@ -545,11 +545,10 @@ function syncPrsFromOutput(output, agentId, meta, config) {
545
545
 
546
546
  const projects = shared.getProjects(config);
547
547
  const defaultProject = (meta?.project?.name && projects.find(p => p.name === meta.project.name)) || projects[0];
548
- if (!defaultProject) return 0;
548
+ const useCentral = !defaultProject;
549
549
 
550
550
  // Match each PR to its correct project by finding which repo URL appears near the PR number in output
551
551
  function resolveProjectForPr(prId) {
552
- // Look for the PR URL in output to determine which ADO project it belongs to
553
552
  for (const p of projects) {
554
553
  if (!p.prUrlBase) continue;
555
554
  const urlFragment = p.prUrlBase.replace(/pullrequest\/$/, '');
@@ -561,21 +560,32 @@ function syncPrsFromOutput(output, agentId, meta, config) {
561
560
  return defaultProject;
562
561
  }
563
562
 
563
+ // Extract PR URL directly from agent output — no manual construction
564
+ function extractPrUrl(prId) {
565
+ const ghMatch = output.match(new RegExp(`https?://github\\.com/[^\\s"'\\)\\]]*?/pull/${prId}(?:[^\\s"'\\)\\]]*)`, 'i'));
566
+ if (ghMatch) return ghMatch[0].replace(/[.,;:]+$/, '');
567
+ const adoMatch = output.match(new RegExp(`https?://(?:dev\\.azure\\.com|[^/]+\\.visualstudio\\.com)[^\\s"'\\)\\]]*?pullrequest/${prId}(?:[^\\s"'\\)\\]]*)`, 'i'));
568
+ if (adoMatch) return adoMatch[0].replace(/[.,;:]+$/, '');
569
+ return '';
570
+ }
571
+
564
572
  const agentName = config.agents?.[agentId]?.name || agentId;
565
573
  let added = 0;
566
- // Track which project PR files need writing
567
- const dirtyProjects = new Map(); // projectName -> { project, prs, prPath }
574
+ const centralPrPath = path.join(MINIONS_DIR, 'pull-requests.json');
575
+ // Track which PR files need writing keyed by target name
576
+ const dirtyTargets = new Map(); // name -> { prs, prPath }
568
577
 
569
578
  for (const prId of prMatches) {
570
579
  const fullId = `PR-${prId}`;
571
- const targetProject = resolveProjectForPr(prId);
572
- const prPath = shared.projectPrPath(targetProject);
580
+ const targetProject = useCentral ? null : resolveProjectForPr(prId);
581
+ const targetName = targetProject ? targetProject.name : '_central';
582
+ const prPath = targetProject ? shared.projectPrPath(targetProject) : centralPrPath;
573
583
 
574
- // Load PRs for this project (cache per project)
575
- if (!dirtyProjects.has(targetProject.name)) {
576
- dirtyProjects.set(targetProject.name, { project: targetProject, prs: safeJson(prPath) || [], prPath });
584
+ // Load PRs for this target (cache per target)
585
+ if (!dirtyTargets.has(targetName)) {
586
+ dirtyTargets.set(targetName, { prs: safeJson(prPath) || [], prPath });
577
587
  }
578
- const entry = dirtyProjects.get(targetProject.name);
588
+ const entry = dirtyTargets.get(targetName);
579
589
  if (entry.prs.some(p => p.id === fullId || String(p.id).includes(prId))) continue;
580
590
 
581
591
  let title = meta?.item?.title || '';
@@ -592,7 +602,7 @@ function syncPrsFromOutput(output, agentId, meta, config) {
592
602
  reviewStatus: 'pending',
593
603
  status: 'active',
594
604
  created: e.dateStamp(),
595
- url: targetProject.prUrlBase ? targetProject.prUrlBase + prId : '',
605
+ url: extractPrUrl(prId),
596
606
  prdItems: meta?.item?.id ? [meta.item.id] : [],
597
607
  sourcePlan: meta?.item?.sourcePlan || '',
598
608
  itemType: meta?.item?.itemType || ''
@@ -601,9 +611,9 @@ function syncPrsFromOutput(output, agentId, meta, config) {
601
611
  added++;
602
612
  }
603
613
 
604
- for (const [name, entry] of dirtyProjects) {
614
+ for (const [name, entry] of dirtyTargets) {
605
615
  shared.safeWrite(entry.prPath, entry.prs);
606
- e.log('info', `Synced PR(s) from ${agentName}'s output to ${name}/pull-requests.json`);
616
+ e.log('info', `Synced PR(s) from ${agentName}'s output to ${name === '_central' ? 'central' : name}/pull-requests.json`);
607
617
  }
608
618
  return added;
609
619
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yemi33/minions",
3
- "version": "0.1.82",
3
+ "version": "0.1.84",
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"