@yemi33/minions 0.1.1008 → 0.1.1010

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.1010 (2026-04-16)
4
+
5
+ ### Other
6
+ - chore: test publish workflow fix
7
+
3
8
  ## 0.1.1008 (2026-04-16)
4
9
 
5
10
  ### Features
@@ -27,6 +27,19 @@ async function refreshKnowledgeBase() {
27
27
  } catch (e) { console.error('kb refresh:', e.message); }
28
28
  }
29
29
 
30
+ function kbNewestFirst(a, b) {
31
+ return (b.sortTs || 0) - (a.sortTs || 0) ||
32
+ (b.date || '').localeCompare(a.date || '') ||
33
+ (a.title || '').localeCompare(b.title || '');
34
+ }
35
+
36
+ function kbPinnedNewestFirst(a, b) {
37
+ const aPinned = isPinned(kbPinKey(a.category, a.file));
38
+ const bPinned = isPinned(kbPinKey(b.category, b.file));
39
+ if (aPinned !== bPinned) return aPinned ? -1 : 1;
40
+ return kbNewestFirst(a, b);
41
+ }
42
+
30
43
  function renderKnowledgeBase() {
31
44
  _syncPinsFromServer();
32
45
  const tabsEl = document.getElementById('kb-tabs');
@@ -74,18 +87,13 @@ function renderKnowledgeBase() {
74
87
  let items;
75
88
  if (_kbActiveTab === 'pinned') {
76
89
  items = allItems.filter(i => isPinned(kbPinKey(i.category, i.file)));
90
+ items.sort(kbNewestFirst);
77
91
  } else if (_kbActiveTab === 'all') {
78
92
  items = allItems.slice();
79
- items.sort((a, b) => (b.date || '').localeCompare(a.date || ''));
93
+ items.sort(kbPinnedNewestFirst);
80
94
  } else {
81
95
  items = allItems.filter(i => i.category === _kbActiveTab);
82
- }
83
-
84
- // Stable sort — pinned items float to top (skip on pinned tab where all are pinned)
85
- if (_kbActiveTab !== 'pinned') {
86
- items.sort(function(a, b) {
87
- return (isPinned(kbPinKey(a.category, a.file)) ? 0 : 1) - (isPinned(kbPinKey(b.category, b.file)) ? 0 : 1);
88
- });
96
+ items.sort(kbPinnedNewestFirst);
89
97
  }
90
98
 
91
99
  if (items.length === 0) {
package/dashboard.js CHANGED
@@ -2415,9 +2415,12 @@ If nothing to do: { "duplicates": [], "reclassify": [], "remove": [] }`;
2415
2415
  if (!fs.existsSync(srcPath)) continue;
2416
2416
  if (!fs.existsSync(destDir)) fs.mkdirSync(destDir, { recursive: true });
2417
2417
  try {
2418
+ const srcStats = fs.statSync(srcPath);
2418
2419
  const content = safeRead(srcPath);
2419
2420
  const updated = content.replace(/^(category:\s*).+$/m, `$1${r.to}`);
2420
- safeWrite(path.join(destDir, entry.file), updated);
2421
+ const destPath = path.join(destDir, entry.file);
2422
+ safeWrite(destPath, updated);
2423
+ fs.utimesSync(destPath, srcStats.atime, srcStats.mtime);
2421
2424
  safeUnlink(srcPath);
2422
2425
  reclassified++;
2423
2426
  } catch (e) { console.error('kb reclassify:', e.message); }
package/engine/queries.js CHANGED
@@ -630,6 +630,11 @@ let _kbCache = null;
630
630
  let _kbCacheTs = 0;
631
631
  const KB_CACHE_TTL = 30000; // 30s — KB changes infrequently
632
632
 
633
+ function invalidateKnowledgeBaseCache() {
634
+ _kbCache = null;
635
+ _kbCacheTs = 0;
636
+ }
637
+
633
638
  function getKnowledgeBaseEntries() {
634
639
  const now = Date.now();
635
640
  if (_kbCache && (now - _kbCacheTs) < KB_CACHE_TTL) return _kbCache;
@@ -639,23 +644,32 @@ function getKnowledgeBaseEntries() {
639
644
  const catDir = path.join(KNOWLEDGE_DIR, cat);
640
645
  const files = safeReadDir(catDir).filter(f => f.endsWith('.md'));
641
646
  for (const f of files) {
642
- const content = safeRead(path.join(catDir, f)) || '';
647
+ const filePath = path.join(catDir, f);
648
+ const content = safeRead(filePath) || '';
643
649
  const titleMatch = content.match(/^#\s+(.+)/m);
644
650
  const title = titleMatch ? titleMatch[1].trim() : f.replace(/\.md$/, '');
645
651
  const agentMatch = f.match(/^\d{4}-\d{2}-\d{2}-(\w+)-/);
646
- const dateMatch = f.match(/^(\d{4}-\d{2}-\d{2})/);
652
+ const dateMatch = f.match(/^(\d{4}-\d{2}-\d{2})/) || content.match(/^date:\s*(\d{4}-\d{2}-\d{2})$/m);
647
653
  const sourceMatch = content.match(/^source:\s*(.+)/m);
654
+ let sortTs = 0;
655
+ try { sortTs = fs.statSync(filePath).mtimeMs || 0; } catch {}
656
+ const displayDate = dateMatch ? dateMatch[1] : (sortTs ? new Date(sortTs).toISOString().slice(0, 10) : '');
648
657
  entries.push({
649
658
  cat, file: f, title,
650
659
  agent: agentMatch ? agentMatch[1] : '',
651
- date: dateMatch ? dateMatch[1] : '',
660
+ date: displayDate,
661
+ sortTs,
652
662
  source: sourceMatch ? sourceMatch[1].trim() : '',
653
663
  preview: content.slice(0, 200),
654
664
  size: content.length,
655
665
  });
656
666
  }
657
667
  }
658
- entries.sort((a, b) => (b.date || '').localeCompare(a.date || ''));
668
+ entries.sort((a, b) =>
669
+ (b.sortTs || 0) - (a.sortTs || 0) ||
670
+ (b.date || '').localeCompare(a.date || '') ||
671
+ a.title.localeCompare(b.title)
672
+ );
659
673
  _kbCache = entries;
660
674
  _kbCacheTs = now;
661
675
  return entries;
@@ -1092,6 +1106,7 @@ module.exports = {
1092
1106
  readHeadTail, // exported for testing
1093
1107
  detectInFlightTool, // exported for testing
1094
1108
  resetPrdInfoCache,
1109
+ invalidateKnowledgeBaseCache,
1095
1110
 
1096
1111
  // Core state
1097
1112
  getConfig, getControl, getDispatch, getDispatchQueue, invalidateDispatchCache,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yemi33/minions",
3
- "version": "0.1.1008",
3
+ "version": "0.1.1010",
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"