mio-agent-runtime 0.5.14 → 0.5.16

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.
@@ -5,7 +5,10 @@ const fs = require('fs')
5
5
  const path = require('path')
6
6
  const crypto = require('crypto')
7
7
  const readline = require('readline')
8
- const { execFileSync } = require('child_process')
8
+ const { execFileSync } = require('child_process')
9
+ const { getEvolutionStatus } = require('../runtime-modules.js')
10
+ const { listHostCapabilities } = require('../host-capabilities.js')
11
+ const { createEvolutionCutoverTools } = require('../evolution-cutover.js')
9
12
 
10
13
  const SERVER_INFO = { name: 'mio-intelligence-mcp', version: '0.1.0' }
11
14
  const PROTOCOL_VERSION = '2024-11-05'
@@ -20,11 +23,10 @@ const queryPath = path.join(dataDir, 'queries.jsonl')
20
23
  const agentsPath = path.join(dataDir, 'agents.jsonl')
21
24
  const subscriptionPath = path.join(dataDir, 'subscriptions.jsonl')
22
25
  const digestStatePath = path.join(dataDir, 'digest_state.json')
23
- const ideasPath = path.join(dataDir, 'ideas.jsonl')
24
- const suggestionsPath = path.join(dataDir, 'suggestions.jsonl')
25
- fs.mkdirSync(dataDir, { recursive: true })
26
-
27
- const { loadPhase0, summarizePhase0, renderPhase0Markdown } = require('./phase0')
26
+ fs.mkdirSync(dataDir, { recursive: true })
27
+
28
+ const { loadPhase0, summarizePhase0, renderPhase0Markdown } = require('./phase0')
29
+ const evolutionCutover = createEvolutionCutoverTools({ dataDir, appendJsonl, readJsonl, projectName })
28
30
 
29
31
  let runtimeContext = {}
30
32
  try {
@@ -1594,188 +1596,132 @@ const TOOLS = [
1594
1596
  },
1595
1597
  },
1596
1598
  },
1597
- {
1598
- name: 'mio.evolution.report',
1599
- description: 'Generate cross-agent evolution report: ecosystem summary, agent performance comparison, cross-agent patterns, memory health, and optimization suggestions (ADR-017 Evolution plane).',
1599
+ {
1600
+ name: 'mio.evolution.report',
1601
+ description: 'Generate cross-agent evolution report: ecosystem summary, agent performance comparison, cross-agent patterns, memory health, and optimization suggestions (ADR-017 Evolution plane).',
1600
1602
  inputSchema: {
1601
1603
  type: 'object',
1602
1604
  properties: {
1603
1605
  project: { type: 'string', description: 'Project name filter. Defaults to current repository.' },
1604
1606
  period: { type: 'string', description: 'Time window: 24h, 7d, 30d, or all (default).' },
1605
1607
  },
1606
- },
1607
- },
1608
- {
1609
- name: 'mio.task.record_outcome',
1610
- description: 'Record task outcome with agent registry update and auto-claim experience reuse in one atomic call. Combines observer.ingest + agent stats + auto-claim for a complete task lifecycle closure.',
1611
- inputSchema: {
1612
- type: 'object',
1613
- properties: {
1614
- outcome: { type: 'string', description: 'Task outcome: success, failure, or aborted.' },
1615
- task: { type: 'string', description: 'Brief task description.' },
1616
- summary: { type: 'string', description: 'Optional task summary.' },
1617
- verification: { type: 'string', description: 'Optional verification details.' },
1618
- agentId: { type: 'string', description: 'Agent identifier. Defaults to MIO_CONTEXT agentId.' },
1619
- project: { type: 'string', description: 'Project name. Defaults to current repository.' },
1620
- traceId: { type: 'string', description: 'Optional custom trace ID. Auto-generated if omitted.' },
1621
- },
1622
- required: ['outcome'],
1623
- },
1608
+ },
1624
1609
  },
1625
1610
  {
1626
- name: 'mio.idea.generate',
1627
- description: 'Generate creative ideas or multiple candidate solutions based on a given goal, context, and constraints.',
1611
+ name: 'mio.evolution.status',
1612
+ description: 'Report composed mio-agent-runtime module health from the canonical runtime module registry.',
1613
+ inputSchema: {
1614
+ type: 'object',
1615
+ properties: {},
1616
+ },
1617
+ },
1618
+ {
1619
+ name: 'mio.host.capabilities',
1620
+ description: 'List installed desktop host adapters and the safe capability surface they expose to runtime modules.',
1621
+ inputSchema: {
1622
+ type: 'object',
1623
+ properties: {},
1624
+ },
1625
+ },
1626
+ {
1627
+ name: 'mio.evolution.shadow.record',
1628
+ description: 'Record a shadow comparison between legacy and modular runtime outputs without changing authority.',
1628
1629
  inputSchema: {
1629
1630
  type: 'object',
1630
- required: ['goal'],
1631
1631
  properties: {
1632
- goal: { type: 'string', description: 'The goal or problem description for which to generate ideas.' },
1633
- context: { type: 'string', description: '(Optional) Additional background information, such as prior decisions or known problems.' },
1634
- constraints: { type: 'array', items: { type: 'string' }, description: '(Optional) List of constraints, e.g. "no new dependencies", "must be implementable as a plugin".' },
1635
- numIdeas: { type: 'integer', description: '(Optional) Number of ideas to return, default 3.', default: 3, minimum: 1 }
1632
+ label: { type: 'string', description: 'Human-readable comparison label.' },
1633
+ project: { type: 'string', description: 'Project name. Defaults to current repository.' },
1634
+ legacy: { type: 'object', description: 'Legacy path output snapshot.' },
1635
+ modular: { type: 'object', description: 'Modular path output snapshot.' },
1636
+ input: { type: 'object', description: 'Optional sanitized input snapshot.' },
1636
1637
  },
1637
- additionalProperties: false
1638
+ required: ['legacy', 'modular'],
1638
1639
  },
1639
1640
  },
1640
1641
  {
1641
- name: 'mio.idea.list',
1642
- description: 'List previously generated ideas, optionally filtered by keyword, strategy, or time window.',
1642
+ name: 'mio.evolution.dual_write.record',
1643
+ description: 'Record a dual-write sample result for legacy and modular state paths without switching authority.',
1643
1644
  inputSchema: {
1644
1645
  type: 'object',
1645
1646
  properties: {
1646
- goal: { type: 'string', description: '(Optional) Filter ideas whose goal contains this keyword.' },
1647
- strategy: { type: 'string', description: '(Optional) Filter by generation strategy (e.g. SCAMPER, Analogy).' },
1648
- limit: { type: 'integer', description: '(Optional) Max results, default 10.', default: 10, minimum: 1 },
1649
- period: { type: 'string', description: '(Optional) Time window: 24h, 7d, 30d, or all (default).' }
1650
- }
1647
+ label: { type: 'string', description: 'Human-readable dual-write label.' },
1648
+ project: { type: 'string', description: 'Project name. Defaults to current repository.' },
1649
+ authoritative: { type: 'string', description: 'Authoritative path: legacy or modular. Defaults to legacy.' },
1650
+ legacyResult: { type: 'object', description: 'Legacy write result snapshot.' },
1651
+ modularResult: { type: 'object', description: 'Modular write result snapshot.' },
1652
+ record: { type: 'object', description: 'Optional sanitized record metadata.' },
1653
+ },
1654
+ required: ['legacyResult', 'modularResult'],
1651
1655
  },
1652
1656
  },
1653
1657
  {
1654
- name: 'mio.evolution.suggest',
1655
- description: 'Analyze ecosystem data and produce prioritized improvement suggestions with next actions and expected impact.',
1658
+ name: 'mio.evolution.cutover.readiness',
1659
+ description: 'Assess whether shadow and dual-write samples are sufficient to consider modular runtime cutover.',
1656
1660
  inputSchema: {
1657
1661
  type: 'object',
1658
1662
  properties: {
1659
- project: { type: 'string', description: 'Project name filter. Defaults to current repository.' }
1660
- }
1663
+ project: { type: 'string', description: 'Project name. Defaults to current repository.' },
1664
+ minShadowRuns: { type: 'number', description: 'Minimum shadow comparison samples required. Defaults to 5.' },
1665
+ maxMismatchRate: { type: 'number', description: 'Allowed shadow mismatch rate. Defaults to 0.' },
1666
+ },
1661
1667
  },
1662
1668
  },
1663
- ]
1664
-
1665
- function handleIdeaGenerate(args = {}) {
1666
- const goal = String(args.goal || '').trim()
1667
- if (!goal) throw new Error('idea.generate requires a goal')
1668
- const numIdeas = Math.min(Math.max(Number(args.numIdeas) || 3, 1), 10)
1669
- const context = args.context ? String(args.context).trim() : ''
1670
- const constraints = Array.isArray(args.constraints) ? args.constraints.map(String) : []
1671
-
1672
- // Query Mio memory for related context
1673
- const relatedRecords = readJsonl(memoryPath)
1674
- .filter(r => r.archived !== true)
1675
- .filter(r => {
1676
- const text = (r.content || '').toLowerCase()
1677
- const goalLower = goal.toLowerCase()
1678
- // Support both space-separated (English) and continuous (Chinese) matching
1679
- const goalWords = goalLower.split(/\s+/).filter(w => w.length > 2)
1680
- // For Chinese: extract 2-char n-grams as search tokens
1681
- const ngrams = []
1682
- for (let i = 0; i < goalLower.length - 1; i++) {
1683
- const ng = goalLower.slice(i, i + 2)
1684
- if (ng.trim().length === 2) ngrams.push(ng)
1685
- }
1686
- const allTokens = [...new Set([...goalWords, ...ngrams])]
1687
- return allTokens.some(t => text.includes(t))
1688
- })
1689
- .slice(0, 8)
1690
-
1691
- const relatedMemoryText = relatedRecords.length > 0
1692
- ? relatedRecords.map(r => '- [' + r.kind + '] ' + (r.content || '').slice(0, 200)).join('\n')
1693
- : '(no related memories found)'
1694
-
1695
- const strategies = [
1696
- {
1697
- name: 'SCAMPER',
1698
- prompt: 'Apply SCAMPER: Substitute, Combine, Adapt, Modify, Put to another use, Eliminate, Reverse. ' +
1699
- 'For goal: ' + goal + '. What novel combination or modification of existing elements could work?'
1700
- },
1701
- {
1702
- name: 'Analogy',
1703
- prompt: 'By analogy: What similar problem has been solved in a completely different domain? ' +
1704
- 'For goal: ' + goal + '. What approach from another field (biology, economics, gaming, logistics) transfers here?'
1705
- },
1706
- {
1707
- name: 'First-Principles',
1708
- prompt: 'First principles: Strip away all assumptions. What are the absolute basics of ' + goal + '? ' +
1709
- 'What would you build if you had no prior art, no constraints, no legacy?'
1669
+ {
1670
+ name: 'mio.evolution.migration.plan',
1671
+ description: 'Preview a state migration plan between legacy and modular records without writing state.',
1672
+ inputSchema: {
1673
+ type: 'object',
1674
+ properties: {
1675
+ legacyRecords: { type: 'array', items: { type: 'object' }, description: 'Legacy state records.' },
1676
+ modularRecords: { type: 'array', items: { type: 'object' }, description: 'Existing modular state records.' },
1677
+ },
1710
1678
  },
1711
- {
1712
- name: 'Random-Stimulus',
1713
- prompt: 'Random stimulus: Pick an unrelated concept (a relay race, a restaurant menu, a river delta, a beehive). ' +
1714
- 'How does it relate to ' + goal + '? What structural or procedural parallel exists?'
1679
+ },
1680
+ {
1681
+ name: 'mio.evolution.authority.plan',
1682
+ description: 'Create a gated authority switch plan from legacy to modular runtime without applying it.',
1683
+ inputSchema: {
1684
+ type: 'object',
1685
+ properties: {
1686
+ readiness: { type: 'object', description: 'Result from mio.evolution.cutover.readiness.' },
1687
+ from: { type: 'string', description: 'Current authoritative path. Defaults to legacy.' },
1688
+ to: { type: 'string', description: 'Target authoritative path. Defaults to modular.' },
1689
+ },
1690
+ required: ['readiness'],
1715
1691
  },
1716
- {
1717
- name: 'Constraint-Inversion',
1718
- prompt: 'Constraint inversion: Instead of ' + goal + ', what is the OPPOSITE goal? ' +
1719
- 'How would you deliberately make things worse? Now invert the inversion — what does that reveal about the real solution?'
1720
- }
1721
- ]
1722
-
1723
- const selectedStrategies = strategies.slice(0, numIdeas)
1724
- const ideas = []
1725
-
1726
- for (let i = 0; i < selectedStrategies.length; i++) {
1727
- const s = selectedStrategies[i]
1728
- const idea = {
1729
- id: createId('idea'),
1730
- title: 'Idea #' + (i + 1) + ' (' + s.name + '): ' + goal,
1731
- description: 'Goal: ' + goal + '\n\n' +
1732
- 'Strategy: ' + s.name + '\n\n' +
1733
- 'Related Mio memory:\n' + relatedMemoryText + '\n\n' +
1734
- (context ? 'Context: ' + context + '\n\n' : '') +
1735
- (constraints.length > 0 ? 'Constraints:\n' + constraints.map(c => '- ' + c).join('\n') + '\n\n' : '') +
1736
- 'Strategy prompt: ' + s.prompt + '\n\n' +
1737
- 'Suggestion: Consider prototyping the idea and measuring its impact against prior decisions.',
1738
- provenance: {
1739
- strategy: s.name,
1740
- relatedMemoryIds: relatedRecords.map(r => r.id).slice(0, 5),
1692
+ },
1693
+ {
1694
+ name: 'mio.evolution.cutover.apply',
1695
+ description: 'Dry-run an authority switch plan. This stage refuses real cutover and never mutates authority state.',
1696
+ inputSchema: {
1697
+ type: 'object',
1698
+ properties: {
1699
+ dryRun: { type: 'boolean', description: 'Must be true. Real cutover is intentionally gated.' },
1700
+ project: { type: 'string', description: 'Project name. Defaults to current repository.' },
1701
+ plan: { type: 'object', description: 'Authority switch plan from mio.evolution.authority.plan.' },
1741
1702
  },
1742
- generatedAt: new Date().toISOString(),
1743
- goal,
1744
- context: context || null,
1745
- constraints,
1746
- }
1747
- ideas.push(idea)
1748
- }
1749
-
1750
- // Persist to ideas.jsonl
1751
- for (const idea of ideas) {
1752
- appendJsonl(ideasPath, idea)
1753
- }
1754
-
1755
- return { ideas, count: ideas.length, goal, strategies: ideas.map(i => i.provenance.strategy) }
1756
- }
1757
-
1758
- function listIdeas(args = {}) {
1759
- if (!fs.existsSync(ideasPath)) return { ideas: [], count: 0, total: 0 }
1760
- const now = Date.now()
1761
- const period = String(args.period || 'all').trim()
1762
- const periodMs = period === '24h' ? 86400000 : period === '7d' ? 604800000 : period === '30d' ? 2592000000 : Infinity
1763
- const cutoff = periodMs === Infinity ? 0 : now - periodMs
1764
- const goalFilter = args.goal ? String(args.goal).toLowerCase() : null
1765
- const strategyFilter = args.strategy ? String(args.strategy).trim().toLowerCase() : null
1766
- const limit = Math.min(Math.max(Number(args.limit) || 10, 1), 50)
1767
- const all = fs.readFileSync(ideasPath, 'utf8').split('\n').filter(Boolean).map(line => {
1768
- try { return JSON.parse(line) } catch (_) { return null }
1769
- }).filter(Boolean)
1770
- const filtered = all.filter(idea => {
1771
- if (cutoff && new Date(idea.generatedAt).getTime() < cutoff) return false
1772
- if (goalFilter && !String(idea.goal || '').toLowerCase().includes(goalFilter)) return false
1773
- if (strategyFilter && String(idea.provenance?.strategy || '').toLowerCase() !== strategyFilter) return false
1774
- return true
1775
- })
1776
- return { ideas: filtered.slice(-limit), count: filtered.length, total: all.length }
1777
- }
1778
-
1703
+ required: ['dryRun', 'plan'],
1704
+ },
1705
+ },
1706
+ {
1707
+ name: 'mio.task.record_outcome',
1708
+ description: 'Record task outcome with agent registry update and auto-claim experience reuse in one atomic call. Combines observer.ingest + agent stats + auto-claim for a complete task lifecycle closure.',
1709
+ inputSchema: {
1710
+ type: 'object',
1711
+ properties: {
1712
+ outcome: { type: 'string', description: 'Task outcome: success, failure, or aborted.' },
1713
+ task: { type: 'string', description: 'Brief task description.' },
1714
+ summary: { type: 'string', description: 'Optional task summary.' },
1715
+ verification: { type: 'string', description: 'Optional verification details.' },
1716
+ agentId: { type: 'string', description: 'Agent identifier. Defaults to MIO_CONTEXT agentId.' },
1717
+ project: { type: 'string', description: 'Project name. Defaults to current repository.' },
1718
+ traceId: { type: 'string', description: 'Optional custom trace ID. Auto-generated if omitted.' },
1719
+ },
1720
+ required: ['outcome'],
1721
+ },
1722
+ },
1723
+ ]
1724
+
1779
1725
  async function callTool(name, args = {}) {
1780
1726
  switch (name) {
1781
1727
  case 'mio.memory.query':
@@ -1812,77 +1758,31 @@ async function callTool(name, args = {}) {
1812
1758
  return listAgents(args)
1813
1759
  case 'mio.agent.report':
1814
1760
  return reportAgent(args)
1815
- case 'mio.evolution.report':
1816
- return evolutionReport(args)
1761
+ case 'mio.evolution.report':
1762
+ return evolutionReport(args)
1763
+ case 'mio.evolution.status':
1764
+ return getEvolutionStatus()
1765
+ case 'mio.host.capabilities':
1766
+ return listHostCapabilities()
1767
+ case 'mio.evolution.shadow.record':
1768
+ return evolutionCutover.recordShadowComparison(args)
1769
+ case 'mio.evolution.dual_write.record':
1770
+ return evolutionCutover.recordDualWrite(args)
1771
+ case 'mio.evolution.cutover.readiness':
1772
+ return evolutionCutover.cutoverReadiness(args)
1773
+ case 'mio.evolution.migration.plan':
1774
+ return evolutionCutover.migrationPlan(args)
1775
+ case 'mio.evolution.authority.plan':
1776
+ return evolutionCutover.authorityPlan(args)
1777
+ case 'mio.evolution.cutover.apply':
1778
+ return evolutionCutover.applyCutover(args)
1817
1779
  case 'mio.task.record_outcome':
1818
1780
  return recordTaskOutcome(args)
1819
- case 'mio.idea.generate':
1820
- return handleIdeaGenerate(args)
1821
- case 'mio.idea.list':
1822
- return listIdeas(args)
1823
- case 'mio.evolution.suggest':
1824
- return evolutionSuggest(args)
1825
- case 'mio.dashboard.start':
1826
- return handleDashboardStart(args)
1827
- case 'mio.dashboard.stop':
1828
- return handleDashboardStop()
1829
- case 'mio.dashboard.status':
1830
- return handleDashboardStatus()
1831
1781
  default:
1832
1782
  throw new Error(`Unknown tool: ${name}`)
1833
1783
  }
1834
1784
  }
1835
1785
 
1836
- const DASHBOARD_PORT = 8787
1837
- const dashboardPidPath = () => path.join(dataDir, 'dashboard.pid')
1838
-
1839
- function isDashboardRunning() {
1840
- const pidFile = dashboardPidPath()
1841
- if (!fs.existsSync(pidFile)) return false
1842
- try {
1843
- const pid = parseInt(fs.readFileSync(pidFile, 'utf8').trim(), 10)
1844
- process.kill(pid, 0)
1845
- return true
1846
- } catch (_) {
1847
- return false
1848
- }
1849
- }
1850
-
1851
- function handleDashboardStart(args = {}) {
1852
- const port = parseInt(args.port || process.env.MIO_DASHBOARD_PORT || DASHBOARD_PORT, 10)
1853
- const url = 'http://localhost:' + port
1854
- if (isDashboardRunning()) {
1855
- if (args.open) { try { require('child_process').exec('start ' + url) } catch (_) {} }
1856
- return { url: url, running: true, message: 'Dashboard already running at ' + url }
1857
- }
1858
- const serverScript = path.join(__dirname, 'dashboard-server.js')
1859
- const child = require('child_process').spawn(process.execPath, [serverScript, String(port)], {
1860
- env: Object.assign({}, process.env, { MIO_DATA_DIR: dataDir }),
1861
- detached: true,
1862
- stdio: 'ignore',
1863
- })
1864
- child.unref()
1865
- fs.writeFileSync(dashboardPidPath(), String(child.pid))
1866
- if (args.open) { try { require('child_process').exec('start ' + url) } catch (_) {} }
1867
- return { url: url, running: true, pid: child.pid, message: 'Dashboard started at ' + url }
1868
- }
1869
-
1870
- function handleDashboardStop() {
1871
- const pidFile = dashboardPidPath()
1872
- if (!fs.existsSync(pidFile)) return { running: false, message: 'Dashboard not running.' }
1873
- try {
1874
- const pid = parseInt(fs.readFileSync(pidFile, 'utf8').trim(), 10)
1875
- process.kill(pid, 'SIGTERM')
1876
- } catch (_) {}
1877
- try { fs.unlinkSync(pidFile) } catch (_) {}
1878
- return { running: false, message: 'Dashboard stopped.' }
1879
- }
1880
-
1881
- function handleDashboardStatus() {
1882
- const running = isDashboardRunning()
1883
- return { running: running, url: running ? 'http://localhost:' + DASHBOARD_PORT : null }
1884
- }
1885
-
1886
1786
  function jsonRpcResult(id, result) {
1887
1787
  return { jsonrpc: '2.0', id, result }
1888
1788
  }
@@ -2197,65 +2097,4 @@ function recordTaskOutcome(args = {}) {
2197
2097
  }
2198
2098
  }
2199
2099
 
2200
-
2201
- function evolutionSuggest(args = {}) {
2202
- const project = args.project || projectName()
2203
- const now = Date.now()
2204
- const memories = readJsonl(memoryPath)
2205
- const traces = readJsonl(tracePath)
2206
- const reuses = readJsonl(experienceReusePath)
2207
- const ideas = fs.existsSync(ideasPath)
2208
- ? fs.readFileSync(ideasPath, 'utf8').split('\n').filter(Boolean).map(l => { try { return JSON.parse(l) } catch (_) { return null } }).filter(Boolean)
2209
- : []
2210
- const agentIds = new Set()
2211
- traces.forEach((t) => { if (t.agent) agentIds.add(t.agent) })
2212
- const outcomes = traces.filter((t) => t.event_type === 'task_outcome')
2213
- const successes = outcomes.filter((t) => t.outcome === 'success').length
2214
- const successRate = outcomes.length > 0 ? Math.round((successes / outcomes.length) * 100) : 0
2215
- const verifiedReuses = reuses.filter((r) => r.confirmed && r.reuse && r.behaviorChanged && r.outcomeImproved)
2216
- const pendingReuses = reuses.filter((r) => r.source === 'auto_claim' && !r.confirmed)
2217
- const decisions = memories.filter((m) => m.kind === 'decision')
2218
- const problems = memories.filter((m) => m.kind === 'problem')
2219
- const shortMemories = memories.filter((m) => String(m.content || '').trim().length < 20)
2220
- const ideasWithoutMemory = ideas.filter((i) => !i.provenance?.relatedMemoryIds?.length)
2221
- const suggestions = []
2222
-
2223
- if (agentIds.size >= 2) {
2224
- const agentStats = []
2225
- for (const id of agentIds) {
2226
- const ao = outcomes.filter((t) => t.agent === id)
2227
- const as = ao.filter((t) => t.outcome === 'success').length
2228
- agentStats.push({ id, total: ao.length, success: as, rate: ao.length > 0 ? Math.round(as / ao.length * 100) : 0 })
2229
- }
2230
- agentStats.sort((a, b) => b.rate - a.rate)
2231
- const best = agentStats[0], worst = agentStats[agentStats.length - 1]
2232
- if (best.total >= 5 && worst.total >= 5 && best.rate - worst.rate >= 15) {
2233
- suggestions.push({ category: 'routing', priority: 'high', title: 'Route tasks to ' + best.id, description: best.id + ' has ' + best.rate + '% success rate vs ' + worst.id + ' at ' + worst.rate + '%.', nextAction: 'Update task routing rules to prefer ' + best.id, impact: 'Could improve overall success rate by ~' + Math.round((best.rate - worst.rate) * 0.3) + '%', basedOn: 'task_outcome comparison' })
2234
- }
2235
- }
2236
- if (shortMemories.length > 5 && memories.length > 10) {
2237
- suggestions.push({ category: 'memory', priority: 'medium', title: 'Enrich ' + shortMemories.length + ' short memory records', description: Math.round(shortMemories.length / memories.length * 100) + '% of memories have content < 20 chars.', nextAction: 'Review and expand short memory records, or archive irrelevant ones.', impact: 'Improves memory.query recall precision', basedOn: 'memory.jsonl analysis' })
2238
- }
2239
- if (pendingReuses.length >= 5) {
2240
- suggestions.push({ category: 'evidence', priority: 'medium', title: 'Confirm ' + pendingReuses.length + ' pending auto-claims', description: pendingReuses.length + ' auto-claimed reuses await confirmation.', nextAction: 'Call mio.experience.confirm on each auto_claim id.', impact: 'Increases verified reuse count toward Phase 0 threshold', basedOn: 'experience_reuse.jsonl' })
2241
- }
2242
- const crossAgent = verifiedReuses.filter((r) => r.sourceAgent !== r.targetAgent)
2243
- if (agentIds.size >= 2 && crossAgent.length === 0) {
2244
- suggestions.push({ category: 'interop', priority: 'high', title: 'Enable cross-agent experience sharing', description: 'Multiple agents exist but no cross-agent reuse detected.', nextAction: 'Ensure all agents query shared memory before designing solutions.', impact: 'Unlocks core Agent Control Plane value', basedOn: 'experience_reuse.jsonl' })
2245
- }
2246
- if (ideas.length > 0 && ideasWithoutMemory.length > ideas.length * 0.5) {
2247
- suggestions.push({ category: 'creativity', priority: 'low', title: 'Improve idea grounding (' + ideasWithoutMemory.length + ' ungrounded)', description: Math.round(ideasWithoutMemory.length / ideas.length * 100) + '% of ideas lack related memory context.', nextAction: 'Record more decision/problem memories to enrich the idea pipeline.', impact: 'Higher-quality, more context-aware ideas', basedOn: 'ideas.jsonl provenance' })
2248
- }
2249
- if (problems.length >= 3) {
2250
- const recent = problems.filter((p) => (now - new Date(p.timestamp).getTime()) < 7 * 86400000)
2251
- if (recent.length >= 2) {
2252
- suggestions.push({ category: 'health', priority: 'high', title: recent.length + ' problems in last 7 days', description: 'Recurring problems may indicate systemic issues.', nextAction: 'Review recent problems, identify root causes, create decision records.', impact: 'Prevents problem accumulation', basedOn: 'memory.jsonl recent problems' })
2253
- }
2254
- }
2255
- suggestions.sort((a, b) => ({ high: 0, medium: 1, low: 2 }[a.priority] || 2) - ({ high: 0, medium: 1, low: 2 }[b.priority] || 2))
2256
- const record = { id: 'evo_' + Date.now(), timestamp: new Date().toISOString(), project, metrics: { agents: agentIds.size, tasks: outcomes.length, successRate, memories: memories.length, decisions: decisions.length, problems: problems.length, verifiedReuses: verifiedReuses.length, pendingReuses: pendingReuses.length, ideas: ideas.length }, suggestions }
2257
- try { fs.appendFileSync(suggestionsPath, JSON.stringify(record) + '\n') } catch (_) {}
2258
- return record
2259
- }
2260
-
2261
2100
  module.exports = { TOOLS, callTool, handleMessage, readJsonl, appendJsonl, rl }
@@ -1,18 +1,18 @@
1
- {
2
- "name": "@mio/mio-intelligence-mcp",
3
- "version": "0.1.0",
4
- "private": true,
5
- "description": "Mio Agent Enhancement Layer - MCP-first intelligence core",
6
- "type": "commonjs",
7
- "main": "index.js",
8
- "bin": {
9
- "mio-intelligence-mcp": "index.js"
10
- },
11
- "scripts": {
12
- "start": "node index.js",
13
- "check": "node --check index.js"
14
- },
15
- "engines": {
16
- "node": ">=18"
17
- }
1
+ {
2
+ "name": "@akemi-mio/mio-intelligence-mcp",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "description": "Mio Agent Enhancement Layer - MCP-first intelligence core",
6
+ "type": "commonjs",
7
+ "main": "index.js",
8
+ "bin": {
9
+ "mio-intelligence-mcp": "index.js"
10
+ },
11
+ "scripts": {
12
+ "start": "node index.js",
13
+ "check": "node --check index.js"
14
+ },
15
+ "engines": {
16
+ "node": ">=18"
17
+ }
18
18
  }