mio-agent-runtime 0.14.1 → 0.16.0
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/README.md +32 -4
- package/bin/mio.js +214 -120
- package/package.json +3 -3
- package/server/creativity-engine.js +153 -3
- package/server/mechanism-registry.js +99 -0
- package/server/memory-store.js +12 -1
- package/server/mio-intelligence-mcp/index.js +314 -193
package/bin/mio.js
CHANGED
|
@@ -23,7 +23,8 @@ const { createEvolutionCutoverTools } = require('../server/evolution-cutover.js'
|
|
|
23
23
|
const { createMemoryStore } = require('../server/memory-store.js')
|
|
24
24
|
const { createExperienceStore } = require('../server/experience-store.js')
|
|
25
25
|
const { createPolicyStore } = require('../server/policy-store.js')
|
|
26
|
-
const { CreativityEngine, sourcesFromInsights } = require('../server/creativity-engine.js')
|
|
26
|
+
const { CreativityEngine, sourcesFromInsights, adoptHypothesis } = require('../server/creativity-engine.js')
|
|
27
|
+
const { mechanismRegistry, mechanismPromote, mechanismRollback } = require('../server/mechanism-registry.js')
|
|
27
28
|
const { buildAutoSources, topUpSources } = require('../server/creativity-sources.js')
|
|
28
29
|
const { runIdeaGenerate, groundingFrom } = require('../server/idea-generate.js')
|
|
29
30
|
const { createAgentStore } = require('../server/agent-store.js')
|
|
@@ -71,15 +72,11 @@ function readJsonl(file) {
|
|
|
71
72
|
|
|
72
73
|
function projectName() {
|
|
73
74
|
try {
|
|
74
|
-
const commonDir = execFileSync(
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
encoding: 'utf8',
|
|
80
|
-
stdio: ['ignore', 'pipe', 'ignore'],
|
|
81
|
-
}
|
|
82
|
-
).trim()
|
|
75
|
+
const commonDir = execFileSync('git', ['rev-parse', '--path-format=absolute', '--git-common-dir'], {
|
|
76
|
+
cwd: process.cwd(),
|
|
77
|
+
encoding: 'utf8',
|
|
78
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
79
|
+
}).trim()
|
|
83
80
|
if (commonDir) return path.basename(path.dirname(commonDir))
|
|
84
81
|
} catch (_) {}
|
|
85
82
|
return path.basename(process.cwd())
|
|
@@ -193,7 +190,7 @@ function printMigrationPlan(plan, useJson) {
|
|
|
193
190
|
if (useJson) return jsonOrText(plan, true)
|
|
194
191
|
console.log(`Migration plan: ${plan.ready ? 'ready' : 'conflicts'}`)
|
|
195
192
|
console.log(
|
|
196
|
-
`legacy=${plan.summary.legacy} modular=${plan.summary.modular} toCreate=${plan.summary.toCreate} conflicts=${plan.summary.conflicts}
|
|
193
|
+
`legacy=${plan.summary.legacy} modular=${plan.summary.modular} toCreate=${plan.summary.toCreate} conflicts=${plan.summary.conflicts}`,
|
|
197
194
|
)
|
|
198
195
|
}
|
|
199
196
|
|
|
@@ -457,7 +454,9 @@ function splitTagsOption(args, name) {
|
|
|
457
454
|
function recallCommand(args, useJson) {
|
|
458
455
|
const query = args[1]
|
|
459
456
|
if (!query) {
|
|
460
|
-
console.error(
|
|
457
|
+
console.error(
|
|
458
|
+
'Usage: mio recall "<query>" [--project name] [--scope project|global|all] [--kind kind] [--tags a,b] [--limit n] [--json]',
|
|
459
|
+
)
|
|
461
460
|
process.exitCode = 1
|
|
462
461
|
return
|
|
463
462
|
}
|
|
@@ -479,9 +478,7 @@ function recallCommand(args, useJson) {
|
|
|
479
478
|
return
|
|
480
479
|
}
|
|
481
480
|
if (useJson) return jsonOrText(result, true)
|
|
482
|
-
console.log(
|
|
483
|
-
`Mio memory: ${result.count} result(s) for "${result.query}" (project=${result.project}, scope=${result.scope})`
|
|
484
|
-
)
|
|
481
|
+
console.log(`Mio memory: ${result.count} result(s) for "${result.query}" (project=${result.project}, scope=${result.scope})`)
|
|
485
482
|
result.results.forEach((record, index) => {
|
|
486
483
|
const date = (record.timestamp || '').slice(0, 10)
|
|
487
484
|
console.log(`${index + 1}. [${record.kind || 'note'}] ${record.content}`)
|
|
@@ -523,9 +520,7 @@ function tracesCommand(args, useJson) {
|
|
|
523
520
|
.filter(([, value]) => value !== null && value !== undefined)
|
|
524
521
|
.map(([key, value]) => `${key}=${value}`)
|
|
525
522
|
.join(', ')
|
|
526
|
-
console.log(
|
|
527
|
-
`Mio traces: ${result.matched} matched / ${result.total} total${filters ? ' (' + filters + ')' : ''}`
|
|
528
|
-
)
|
|
523
|
+
console.log(`Mio traces: ${result.matched} matched / ${result.total} total${filters ? ' (' + filters + ')' : ''}`)
|
|
529
524
|
const summary = Object.entries(result.summary.byOutcome)
|
|
530
525
|
.map(([key, value]) => `${key}=${value}`)
|
|
531
526
|
.join(' ')
|
|
@@ -534,7 +529,7 @@ function tracesCommand(args, useJson) {
|
|
|
534
529
|
const time = (trace.timestamp || '').replace('T', ' ').slice(0, 19)
|
|
535
530
|
const brief = trace.payload && trace.payload.summary ? ' | ' + String(trace.payload.summary).slice(0, 100) : ''
|
|
536
531
|
console.log(
|
|
537
|
-
`${index + 1}. ${time} [${trace.event_type || '?'}${trace.outcome ? '/' + trace.outcome : ''}] ${trace.agent || '?'} @ ${trace.project || '?'}${brief}
|
|
532
|
+
`${index + 1}. ${time} [${trace.event_type || '?'}${trace.outcome ? '/' + trace.outcome : ''}] ${trace.agent || '?'} @ ${trace.project || '?'}${brief}`,
|
|
538
533
|
)
|
|
539
534
|
console.log(` ${trace.id} trace_id=${trace.trace_id || '-'}`)
|
|
540
535
|
})
|
|
@@ -587,15 +582,11 @@ function digestCommand(args, useJson) {
|
|
|
587
582
|
targetCwds = [explicitCwd]
|
|
588
583
|
} else if (explicitProject) {
|
|
589
584
|
const wanted = String(explicitProject).toLowerCase()
|
|
590
|
-
targetCwds = Object.keys(state.contexts).filter(
|
|
591
|
-
(cwd) => path.basename(cwd).toLowerCase() === wanted,
|
|
592
|
-
)
|
|
585
|
+
targetCwds = Object.keys(state.contexts).filter((cwd) => path.basename(cwd).toLowerCase() === wanted)
|
|
593
586
|
} else {
|
|
594
587
|
// No explicit target: only write to workspaces this digest has data for.
|
|
595
588
|
// A workspace with no matching project gets nothing.
|
|
596
|
-
targetCwds = Object.keys(state.contexts).filter((cwd) =>
|
|
597
|
-
projectLine.has(path.basename(cwd).toLowerCase()),
|
|
598
|
-
)
|
|
589
|
+
targetCwds = Object.keys(state.contexts).filter((cwd) => projectLine.has(path.basename(cwd).toLowerCase()))
|
|
599
590
|
}
|
|
600
591
|
|
|
601
592
|
let written = 0
|
|
@@ -633,9 +624,7 @@ function digestCommand(args, useJson) {
|
|
|
633
624
|
console.log(report.markdown)
|
|
634
625
|
console.log(`Report saved: ${reportFile}`)
|
|
635
626
|
if (report.writeBack) {
|
|
636
|
-
console.log(
|
|
637
|
-
`Write-back: ${report.writeBack.workspaces} workspace(s), ${report.writeBack.skipped} skipped (no digest data)`,
|
|
638
|
-
)
|
|
627
|
+
console.log(`Write-back: ${report.writeBack.workspaces} workspace(s), ${report.writeBack.skipped} skipped (no digest data)`)
|
|
639
628
|
if (report.writeBack.failures && report.writeBack.failures.length > 0) {
|
|
640
629
|
console.error(` ${report.writeBack.failures.length} write-back failure(s):`)
|
|
641
630
|
for (const f of report.writeBack.failures) console.error(` - ${f.workspace}: ${f.error}`)
|
|
@@ -665,7 +654,7 @@ function pruneCommand(args, useJson) {
|
|
|
665
654
|
}
|
|
666
655
|
if (useJson) return jsonOrText(result, true)
|
|
667
656
|
console.log(
|
|
668
|
-
`Prune ${dryRun ? 'plan (dry-run)' : 'result'}: cutoff ${result.cutoff}, days=${days}${includeMemory ? ', memory included' : ''}
|
|
657
|
+
`Prune ${dryRun ? 'plan (dry-run)' : 'result'}: cutoff ${result.cutoff}, days=${days}${includeMemory ? ', memory included' : ''}`,
|
|
669
658
|
)
|
|
670
659
|
for (const file of result.files) {
|
|
671
660
|
console.log(`- ${file.file}: ${file.total} total -> keep ${file.kept}, remove ${file.removed}`)
|
|
@@ -678,18 +667,24 @@ function pruneCommand(args, useJson) {
|
|
|
678
667
|
function rememberCommand(args, useJson) {
|
|
679
668
|
const content = args[1]
|
|
680
669
|
if (!content) {
|
|
681
|
-
console.error(
|
|
670
|
+
console.error(
|
|
671
|
+
'Usage: mio remember "<content>" [--kind decision|context|problem|note] [--tags a,b] [--hypothesis-id id] [--scope project|global] [--project name] [--json]',
|
|
672
|
+
)
|
|
682
673
|
process.exitCode = 1
|
|
683
674
|
return
|
|
684
675
|
}
|
|
685
676
|
const flags = args.slice(2)
|
|
686
677
|
const store = cliMemoryStore()
|
|
678
|
+
// optionValue returns the next token even if it is another flag; a bare
|
|
679
|
+
// trailing `--hypothesis-id` must not swallow `--json` as a "uuid".
|
|
680
|
+
const hypothesisId = optionValue(flags, '--hypothesis-id')
|
|
687
681
|
let record
|
|
688
682
|
try {
|
|
689
683
|
record = store.recordMemory({
|
|
690
684
|
content,
|
|
691
685
|
kind: optionValue(flags, '--kind'),
|
|
692
686
|
tags: splitTagsOption(flags, '--tags'),
|
|
687
|
+
hypothesisId: hypothesisId && !hypothesisId.startsWith('--') ? hypothesisId : undefined,
|
|
693
688
|
scope: optionValue(flags, '--scope'),
|
|
694
689
|
project: optionValue(flags, '--project'),
|
|
695
690
|
source: 'cli',
|
|
@@ -706,8 +701,18 @@ function rememberCommand(args, useJson) {
|
|
|
706
701
|
// Every flag that consumes the next token. A positional directly after one of
|
|
707
702
|
// these is that flag's value, not an id.
|
|
708
703
|
const VALUE_FLAGS = new Set([
|
|
709
|
-
'--ids',
|
|
710
|
-
'--
|
|
704
|
+
'--ids',
|
|
705
|
+
'--reason',
|
|
706
|
+
'--project',
|
|
707
|
+
'--limit',
|
|
708
|
+
'--scope',
|
|
709
|
+
'--keep',
|
|
710
|
+
'--by',
|
|
711
|
+
'--notes',
|
|
712
|
+
'--source-agent',
|
|
713
|
+
'--target-agent',
|
|
714
|
+
'--experience-id',
|
|
715
|
+
'--status',
|
|
711
716
|
])
|
|
712
717
|
|
|
713
718
|
// Accept ids both as `--ids a,b,c` and as bare positionals
|
|
@@ -737,9 +742,7 @@ function collectIds(flags) {
|
|
|
737
742
|
|
|
738
743
|
function printMemoryAnalyze(result) {
|
|
739
744
|
const project = result.project || 'all'
|
|
740
|
-
console.log(
|
|
741
|
-
`Memory analyze: ${result.total} active, ${result.archived} archived (project=${project})`,
|
|
742
|
-
)
|
|
745
|
+
console.log(`Memory analyze: ${result.total} active, ${result.archived} archived (project=${project})`)
|
|
743
746
|
console.log(`layers: project=${result.layers.project} global=${result.layers.global}`)
|
|
744
747
|
const kinds = Object.entries(result.byKind)
|
|
745
748
|
if (kinds.length > 0) {
|
|
@@ -809,9 +812,7 @@ function printMemoryMerge(result) {
|
|
|
809
812
|
return
|
|
810
813
|
}
|
|
811
814
|
|
|
812
|
-
console.log(
|
|
813
|
-
`Merged ${result.archivedCount} record(s) into ${result.survivor.id} (project=${result.project || 'current'})`,
|
|
814
|
-
)
|
|
815
|
+
console.log(`Merged ${result.archivedCount} record(s) into ${result.survivor.id} (project=${result.project || 'current'})`)
|
|
815
816
|
console.log(`survivor: ${result.survivor.contentLength} chars, ${result.survivor.timestamp || 'no timestamp'}`)
|
|
816
817
|
if (result.divergentContent) console.log('note: content differed across members; the survivor body was chosen explicitly')
|
|
817
818
|
console.log(`supersedes: ${result.survivor.supersedes.join(', ')}`)
|
|
@@ -917,7 +918,11 @@ function memoryCommand(args, useJson) {
|
|
|
917
918
|
const matched = all.filter((r) => idSet.has(r.id))
|
|
918
919
|
console.log(`Forget preview: ${ids.length} id(s) (project=${previewProject})`)
|
|
919
920
|
for (const record of matched) {
|
|
920
|
-
console.log(
|
|
921
|
+
console.log(
|
|
922
|
+
` ${record.id} ${String(record.content || '')
|
|
923
|
+
.replace(/\s+/g, ' ')
|
|
924
|
+
.slice(0, 80)}`,
|
|
925
|
+
)
|
|
921
926
|
}
|
|
922
927
|
for (const id of ids) {
|
|
923
928
|
if (!matched.some((r) => r.id === id)) console.log(` ${id} (not found)`)
|
|
@@ -1071,9 +1076,7 @@ Options:
|
|
|
1071
1076
|
}
|
|
1072
1077
|
|
|
1073
1078
|
function printExperienceList(result) {
|
|
1074
|
-
console.log(
|
|
1075
|
-
`Experience reuse: ${result.count} shown of ${result.total} (project=${result.project || 'all'}, status=${result.status})`,
|
|
1076
|
-
)
|
|
1079
|
+
console.log(`Experience reuse: ${result.count} shown of ${result.total} (project=${result.project || 'all'}, status=${result.status})`)
|
|
1077
1080
|
if (result.count === 0) {
|
|
1078
1081
|
console.log('No reuse records match.')
|
|
1079
1082
|
return
|
|
@@ -1082,23 +1085,15 @@ function printExperienceList(result) {
|
|
|
1082
1085
|
const state = record.confirmed ? 'confirmed' : 'pending'
|
|
1083
1086
|
const badge = record.reuse && record.behaviorChanged && record.outcomeImproved ? 'verified' : state
|
|
1084
1087
|
const arrow = `${record.sourceAgent || '?'} -> ${record.targetAgent || '?'}`
|
|
1085
|
-
const flags = [
|
|
1086
|
-
record.reuse ? 'reused' : null,
|
|
1087
|
-
record.behaviorChanged ? 'changed' : null,
|
|
1088
|
-
record.outcomeImproved ? 'improved' : null,
|
|
1089
|
-
]
|
|
1088
|
+
const flags = [record.reuse ? 'reused' : null, record.behaviorChanged ? 'changed' : null, record.outcomeImproved ? 'improved' : null]
|
|
1090
1089
|
.filter(Boolean)
|
|
1091
1090
|
.join(',')
|
|
1092
1091
|
console.log(`${index + 1}. [${badge}] ${record.experienceId} ${arrow}`)
|
|
1093
|
-
console.log(
|
|
1094
|
-
` ${flags || 'no effect flags'} | ${(record.timestamp || '').slice(0, 19)} | ${record.id}`,
|
|
1095
|
-
)
|
|
1092
|
+
console.log(` ${flags || 'no effect flags'} | ${(record.timestamp || '').slice(0, 19)} | ${record.id}`)
|
|
1096
1093
|
if (record.notes) console.log(` note: ${record.notes}`)
|
|
1097
1094
|
})
|
|
1098
1095
|
// Only auto_claims are confirmable — experience.confirm rejects anything else.
|
|
1099
|
-
const pending = result.records
|
|
1100
|
-
.filter((record) => record.source === 'auto_claim' && !record.confirmed)
|
|
1101
|
-
.map((record) => record.id)
|
|
1096
|
+
const pending = result.records.filter((record) => record.source === 'auto_claim' && !record.confirmed).map((record) => record.id)
|
|
1102
1097
|
if (pending.length > 0) {
|
|
1103
1098
|
console.log('')
|
|
1104
1099
|
console.log(
|
|
@@ -1154,11 +1149,7 @@ function experienceCommand(args, useJson) {
|
|
|
1154
1149
|
return
|
|
1155
1150
|
}
|
|
1156
1151
|
// Absent = keep whatever the auto-claim recorded; --no-improved rejects it.
|
|
1157
|
-
const improved = flagPresent(flags, '--no-improved')
|
|
1158
|
-
? false
|
|
1159
|
-
: flagPresent(flags, '--outcome-improved')
|
|
1160
|
-
? true
|
|
1161
|
-
: undefined
|
|
1152
|
+
const improved = flagPresent(flags, '--no-improved') ? false : flagPresent(flags, '--outcome-improved') ? true : undefined
|
|
1162
1153
|
result = store.confirmReuse({
|
|
1163
1154
|
ids,
|
|
1164
1155
|
outcomeImproved: improved,
|
|
@@ -1256,9 +1247,7 @@ function printPolicyCheck(result) {
|
|
|
1256
1247
|
console.log('Try a more specific action, e.g. mio policy check "npm publish".')
|
|
1257
1248
|
} else if (diag && diag.lowSample) {
|
|
1258
1249
|
console.log('')
|
|
1259
|
-
console.log(
|
|
1260
|
-
`NOTE: only ${diag.sampleSize} matching trace(s); treat the level above as a weak signal.`,
|
|
1261
|
-
)
|
|
1250
|
+
console.log(`NOTE: only ${diag.sampleSize} matching trace(s); treat the level above as a weak signal.`)
|
|
1262
1251
|
}
|
|
1263
1252
|
|
|
1264
1253
|
console.log(`\n${result.suggestion}`)
|
|
@@ -1496,9 +1485,7 @@ function insightGenerateCommand(args, useJson) {
|
|
|
1496
1485
|
return Promise.resolve(result).then((resolved) => {
|
|
1497
1486
|
if (useJson) return jsonOrText(resolved, true)
|
|
1498
1487
|
if (!resolved || resolved.generated === 0) {
|
|
1499
|
-
console.log(
|
|
1500
|
-
`No insights generated: ${(resolved && resolved.reason) || 'nothing notable in the given context'}`
|
|
1501
|
-
)
|
|
1488
|
+
console.log(`No insights generated: ${(resolved && resolved.reason) || 'nothing notable in the given context'}`)
|
|
1502
1489
|
return
|
|
1503
1490
|
}
|
|
1504
1491
|
console.log(`Generated ${resolved.generated} insight(s)`)
|
|
@@ -1619,7 +1606,10 @@ function printObserverEssays(essays) {
|
|
|
1619
1606
|
}
|
|
1620
1607
|
for (const essay of essays) {
|
|
1621
1608
|
console.log(`- ${essay.file} (${essay.type}, ${String(essay.created).slice(0, 10)})`)
|
|
1622
|
-
const firstLine =
|
|
1609
|
+
const firstLine =
|
|
1610
|
+
String(essay.content || '')
|
|
1611
|
+
.split('\n')
|
|
1612
|
+
.find((l) => l.trim()) || ''
|
|
1623
1613
|
if (firstLine) console.log(` ${firstLine.replace(/\s+/g, ' ').slice(0, 120)}`)
|
|
1624
1614
|
}
|
|
1625
1615
|
console.log(`\n${essays.length} essay(s)`)
|
|
@@ -1956,7 +1946,9 @@ function printObserverServe(result) {
|
|
|
1956
1946
|
}
|
|
1957
1947
|
console.log(`Observer research scheduler running (base-dir=${result.baseDir})`)
|
|
1958
1948
|
console.log(` ${result.schedule ? result.schedule.collectors : 'collectors started'}`)
|
|
1959
|
-
console.log(
|
|
1949
|
+
console.log(
|
|
1950
|
+
` pipeline: first tick ${result.schedule ? result.schedule.pipelineFirstTickMs : 5000}ms, then every ${result.schedule ? result.schedule.pipelineTickMs : 60000}ms`,
|
|
1951
|
+
)
|
|
1960
1952
|
console.log(' Stops with Ctrl+C (or `mio observe --stop` when started that way).')
|
|
1961
1953
|
}
|
|
1962
1954
|
|
|
@@ -2066,11 +2058,12 @@ function observerCommand(args, useJson) {
|
|
|
2066
2058
|
|
|
2067
2059
|
function creativityUsage(write = console.log) {
|
|
2068
2060
|
write(`Usage:
|
|
2069
|
-
mio creativity status Show hypothesis counts
|
|
2061
|
+
mio creativity status Show hypothesis counts, recent top ideas, adoption join
|
|
2070
2062
|
mio creativity list List hypotheses (--status active|validated|rejected|draft, --sort novelty, --limit N)
|
|
2071
2063
|
|
|
2072
2064
|
mio creativity generate Generate hypotheses by combining sources (needs 2+ --source, calls an LLM)
|
|
2073
2065
|
mio creativity ferment Review/refine active hypotheses (calls an LLM)
|
|
2066
|
+
mio creativity adopt Record an adoption event for a stored hypothesis (writes traces only)
|
|
2074
2067
|
|
|
2075
2068
|
Options:
|
|
2076
2069
|
--status name Filter list by status
|
|
@@ -2098,6 +2091,10 @@ function printCreativityStatus(result) {
|
|
|
2098
2091
|
console.log('Creativity engine:')
|
|
2099
2092
|
console.log(` hypotheses: ${result.hypotheses} combos: ${result.combos} experiments: ${result.experiments}`)
|
|
2100
2093
|
console.log(` active: ${result.active} validated: ${result.validated} rejected: ${result.rejected} draft: ${result.draft}`)
|
|
2094
|
+
const adoption = result.adoption || { adopted: 0, claimed: 0, evidenced: 0 }
|
|
2095
|
+
console.log(
|
|
2096
|
+
` adoption: ${adoption.adopted} adopted (events=${adoption.claimed} tags=${adoption.evidenced}) — derived join, not a metric`,
|
|
2097
|
+
)
|
|
2101
2098
|
if (result.recentIdeas.length === 0) {
|
|
2102
2099
|
console.log('No hypotheses yet.')
|
|
2103
2100
|
return
|
|
@@ -2118,7 +2115,9 @@ function printCreativityList(items) {
|
|
|
2118
2115
|
items.forEach((h, index) => {
|
|
2119
2116
|
const when = h.createdAt ? new Date(h.createdAt).toISOString().slice(0, 19).replace('T', ' ') : ''
|
|
2120
2117
|
const labels = Array.isArray(h.sourceLabels) && h.sourceLabels.length > 0 ? h.sourceLabels.join(' + ') : '—'
|
|
2121
|
-
console.log(
|
|
2118
|
+
console.log(
|
|
2119
|
+
`${index + 1}. [${h.status}]${h.adopted ? ' [adopted]' : ''} ${h.title} (N=${h.novelty} F=${h.feasibility} I=${h.impact} score=${h.score}${h.noveltyScore !== undefined ? ` noveltyScore=${h.noveltyScore}` : ''})`,
|
|
2120
|
+
)
|
|
2122
2121
|
console.log(` ${labels} | ${when} | ${h.id}`)
|
|
2123
2122
|
if (h.fermentCount) console.log(` fermented ${h.fermentCount}x`)
|
|
2124
2123
|
})
|
|
@@ -2161,7 +2160,7 @@ function printCreativityErrors(errors, label) {
|
|
|
2161
2160
|
if (!Array.isArray(errors) || errors.length === 0) return
|
|
2162
2161
|
console.log(`\n${errors.length} ${label}(s) failed:`)
|
|
2163
2162
|
for (const err of errors) {
|
|
2164
|
-
const who = err.pair ? err.pair.join(' + ') :
|
|
2163
|
+
const who = err.pair ? err.pair.join(' + ') : err.title || err.id
|
|
2165
2164
|
console.log(`- ${who}: ${err.error}`)
|
|
2166
2165
|
}
|
|
2167
2166
|
}
|
|
@@ -2296,10 +2295,45 @@ function creativityFermentCommand(args, useJson) {
|
|
|
2296
2295
|
})
|
|
2297
2296
|
}
|
|
2298
2297
|
|
|
2298
|
+
// mio.creativity.adopt from the terminal: same shared adoptHypothesis the MCP
|
|
2299
|
+
// server calls, same enforcement (id must exist; --memory-id must already
|
|
2300
|
+
// carry the hypothesis:<id> tag), event written to MIO_HOME/traces.jsonl.
|
|
2301
|
+
function creativityAdoptCommand(args, useJson) {
|
|
2302
|
+
const flags = args.slice(2)
|
|
2303
|
+
const hypothesisId = flags[0] && !flags[0].startsWith('--') ? String(flags[0]).trim() : ''
|
|
2304
|
+
if (!hypothesisId) {
|
|
2305
|
+
console.error('mio creativity adopt requires <hypothesisId>')
|
|
2306
|
+
console.error('Usage: mio creativity adopt <hypothesisId> [--memory-id id] [--task-id id] [--note text] [--json]')
|
|
2307
|
+
process.exitCode = 1
|
|
2308
|
+
return
|
|
2309
|
+
}
|
|
2310
|
+
|
|
2311
|
+
let result
|
|
2312
|
+
try {
|
|
2313
|
+
result = adoptHypothesis(
|
|
2314
|
+
cliCreativityEngine(),
|
|
2315
|
+
{
|
|
2316
|
+
hypothesisId,
|
|
2317
|
+
memoryId: optionValue(flags, '--memory-id'),
|
|
2318
|
+
taskId: optionValue(flags, '--task-id'),
|
|
2319
|
+
note: optionValue(flags, '--note'),
|
|
2320
|
+
},
|
|
2321
|
+
cliTaskStore().ingestObservation,
|
|
2322
|
+
MIO_HOME,
|
|
2323
|
+
)
|
|
2324
|
+
} catch (error) {
|
|
2325
|
+
console.error(error.message || error)
|
|
2326
|
+
process.exitCode = 1
|
|
2327
|
+
return
|
|
2328
|
+
}
|
|
2329
|
+
if (useJson) return jsonOrText(result, true)
|
|
2330
|
+
console.log(`Adopted hypothesis ${result.hypothesisId}`)
|
|
2331
|
+
console.log(` event: ${result.event && result.event.trace_id ? result.event.trace_id : 'creativity.adopt'}`)
|
|
2332
|
+
}
|
|
2333
|
+
|
|
2299
2334
|
function ideaUsage() {
|
|
2300
2335
|
console.error('usage: mio idea generate --goal "one line" [--context "..."] [--constraint "..."] [--num N] [--json]')
|
|
2301
2336
|
}
|
|
2302
|
-
|
|
2303
2337
|
async function ideaGenerateCommand(args, useJson) {
|
|
2304
2338
|
const flags = args.slice(2)
|
|
2305
2339
|
const goal = (optionValue(flags, '--goal') || '').trim()
|
|
@@ -2366,7 +2400,9 @@ async function ideaGenerateCommand(args, useJson) {
|
|
|
2366
2400
|
console.log(`Generated ${result.ideas.length} idea(s) (grounded with ${result.groundedWith} memories)`)
|
|
2367
2401
|
result.ideas.forEach((idea) => {
|
|
2368
2402
|
console.log(`- [${idea.hypothesis.status}] ${idea.title}`)
|
|
2369
|
-
console.log(
|
|
2403
|
+
console.log(
|
|
2404
|
+
` novelty=${idea.hypothesis.novelty} feasibility=${idea.hypothesis.feasibility} impact=${idea.hypothesis.impact} | ${idea.hypothesis.id}`,
|
|
2405
|
+
)
|
|
2370
2406
|
if (idea.provenance && idea.provenance.technique) console.log(` technique=${idea.provenance.technique}`)
|
|
2371
2407
|
if (idea.hypothesis.rejectionReason) console.log(` rejected: ${idea.hypothesis.rejectionReason}`)
|
|
2372
2408
|
})
|
|
@@ -2390,6 +2426,7 @@ function creativityCommand(args, useJson) {
|
|
|
2390
2426
|
}
|
|
2391
2427
|
if (sub === 'generate') return creativityGenerateCommand(args, useJson)
|
|
2392
2428
|
if (sub === 'ferment') return creativityFermentCommand(args, useJson)
|
|
2429
|
+
if (sub === 'adopt') return creativityAdoptCommand(args, useJson)
|
|
2393
2430
|
|
|
2394
2431
|
if (!['status', 'list'].includes(sub)) {
|
|
2395
2432
|
console.error(`Unknown creativity subcommand: ${sub}`)
|
|
@@ -2429,6 +2466,86 @@ function creativityCommand(args, useJson) {
|
|
|
2429
2466
|
else printCreativityList(result)
|
|
2430
2467
|
}
|
|
2431
2468
|
|
|
2469
|
+
function mechanismUsage(write = console.log) {
|
|
2470
|
+
write(`mio mechanism <subcommand> — mechanism registry (promotion/rollback)
|
|
2471
|
+
|
|
2472
|
+
Subcommands:
|
|
2473
|
+
mio mechanism registry List versions and promotion requests (--mechanism-id, --status)
|
|
2474
|
+
mio mechanism promote submit ... Submit a PromotionRequest (gate-checked)
|
|
2475
|
+
mio mechanism promote approve ... Approve a request (approver must differ from submitter)
|
|
2476
|
+
mio mechanism promote reject ... Reject a request
|
|
2477
|
+
mio mechanism rollback <mechanismId> Roll back the active version to its rollbackTo target
|
|
2478
|
+
|
|
2479
|
+
Options:
|
|
2480
|
+
--json Machine-readable output
|
|
2481
|
+
|
|
2482
|
+
Examples:
|
|
2483
|
+
mio mechanism registry
|
|
2484
|
+
mio mechanism promote submit --mechanism-id m-1 --version 1 --submitted-by codex
|
|
2485
|
+
mio mechanism promote approve --request-id pr-1 --approved-by other-agent
|
|
2486
|
+
mio mechanism rollback m-1`)
|
|
2487
|
+
}
|
|
2488
|
+
|
|
2489
|
+
function mechanismCommand(args, useJson) {
|
|
2490
|
+
const sub = args[1]
|
|
2491
|
+
|
|
2492
|
+
if (!sub || sub === 'help' || sub === '--help' || sub === '-h') {
|
|
2493
|
+
mechanismUsage()
|
|
2494
|
+
if (!sub) process.exitCode = 1
|
|
2495
|
+
return
|
|
2496
|
+
}
|
|
2497
|
+
|
|
2498
|
+
const flags = args.slice(2)
|
|
2499
|
+
|
|
2500
|
+
try {
|
|
2501
|
+
if (sub === 'registry') {
|
|
2502
|
+
const result = mechanismRegistry(
|
|
2503
|
+
{ mechanismId: optionValue(flags, '--mechanism-id'), status: optionValue(flags, '--status') },
|
|
2504
|
+
MIO_HOME,
|
|
2505
|
+
)
|
|
2506
|
+
return jsonOrText(result, useJson)
|
|
2507
|
+
}
|
|
2508
|
+
|
|
2509
|
+
if (sub === 'promote') {
|
|
2510
|
+
const action = flags[0]
|
|
2511
|
+
const result = mechanismPromote(
|
|
2512
|
+
{
|
|
2513
|
+
action,
|
|
2514
|
+
mechanismId: optionValue(flags, '--mechanism-id'),
|
|
2515
|
+
version: parseNumberOption(flags, '--version'),
|
|
2516
|
+
hypothesisId: optionValue(flags, '--hypothesis-id'),
|
|
2517
|
+
experimentRunIds: optionValues(flags, '--experiment-run-ids'),
|
|
2518
|
+
submittedBy: optionValue(flags, '--submitted-by'),
|
|
2519
|
+
requestId: optionValue(flags, '--request-id'),
|
|
2520
|
+
approvedBy: optionValue(flags, '--approved-by'),
|
|
2521
|
+
reason: optionValue(flags, '--reason'),
|
|
2522
|
+
},
|
|
2523
|
+
MIO_HOME,
|
|
2524
|
+
)
|
|
2525
|
+
return jsonOrText(result, useJson)
|
|
2526
|
+
}
|
|
2527
|
+
|
|
2528
|
+
if (sub === 'rollback') {
|
|
2529
|
+
const mechanismId = args[2]
|
|
2530
|
+
if (!mechanismId) {
|
|
2531
|
+
console.error('mio mechanism rollback requires <mechanismId>')
|
|
2532
|
+
console.error('Usage: mio mechanism rollback <mechanismId> [--json]')
|
|
2533
|
+
process.exitCode = 1
|
|
2534
|
+
return
|
|
2535
|
+
}
|
|
2536
|
+
const result = mechanismRollback({ mechanismId }, MIO_HOME)
|
|
2537
|
+
return jsonOrText(result, useJson)
|
|
2538
|
+
}
|
|
2539
|
+
|
|
2540
|
+
console.error(`Unknown mechanism subcommand: ${sub}`)
|
|
2541
|
+
mechanismUsage(console.error)
|
|
2542
|
+
process.exitCode = 1
|
|
2543
|
+
} catch (error) {
|
|
2544
|
+
console.error(error.message || error)
|
|
2545
|
+
process.exitCode = 1
|
|
2546
|
+
}
|
|
2547
|
+
}
|
|
2548
|
+
|
|
2432
2549
|
function readConfig() {
|
|
2433
2550
|
const fallback = { version: 1, home: MIO_HOME, agents: {} }
|
|
2434
2551
|
if (!fs.existsSync(CONFIG_FILE)) return fallback
|
|
@@ -2495,7 +2612,7 @@ function configShowCommand(useJson) {
|
|
|
2495
2612
|
configured: isLlmConfigured(),
|
|
2496
2613
|
},
|
|
2497
2614
|
},
|
|
2498
|
-
true
|
|
2615
|
+
true,
|
|
2499
2616
|
)
|
|
2500
2617
|
}
|
|
2501
2618
|
|
|
@@ -2505,7 +2622,7 @@ function configShowCommand(useJson) {
|
|
|
2505
2622
|
console.log('LLM (effective):')
|
|
2506
2623
|
console.log(` apiUrl: ${effective.apiUrl} [${LLM_SOURCE_LABELS[sources.apiUrl]}]`)
|
|
2507
2624
|
console.log(
|
|
2508
|
-
` apiKey: ${effective.apiKey ? `${maskSecret(effective.apiKey)} [${LLM_SOURCE_LABELS[sources.apiKey]}]` : '(none / unauthenticated)'}
|
|
2625
|
+
` apiKey: ${effective.apiKey ? `${maskSecret(effective.apiKey)} [${LLM_SOURCE_LABELS[sources.apiKey]}]` : '(none / unauthenticated)'}`,
|
|
2509
2626
|
)
|
|
2510
2627
|
console.log(` model: ${effective.model} [${LLM_SOURCE_LABELS[sources.model]}]`)
|
|
2511
2628
|
console.log('')
|
|
@@ -2589,7 +2706,7 @@ function configLlmCommand(flags, useJson) {
|
|
|
2589
2706
|
},
|
|
2590
2707
|
configFile: CONFIG_FILE,
|
|
2591
2708
|
},
|
|
2592
|
-
true
|
|
2709
|
+
true,
|
|
2593
2710
|
)
|
|
2594
2711
|
}
|
|
2595
2712
|
|
|
@@ -2695,11 +2812,8 @@ function statusCommand(useJson) {
|
|
|
2695
2812
|
dataDir: MIO_HOME,
|
|
2696
2813
|
projectName: () => null,
|
|
2697
2814
|
}).listReuse({ status: 'pending', limit: 100 }).records
|
|
2698
|
-
return records.filter(
|
|
2699
|
-
|
|
2700
|
-
String(record.sourceAgent || '').toLowerCase() !==
|
|
2701
|
-
String(record.targetAgent || '').toLowerCase()
|
|
2702
|
-
).length
|
|
2815
|
+
return records.filter((record) => String(record.sourceAgent || '').toLowerCase() !== String(record.targetAgent || '').toLowerCase())
|
|
2816
|
+
.length
|
|
2703
2817
|
} catch {
|
|
2704
2818
|
return 0
|
|
2705
2819
|
}
|
|
@@ -2746,11 +2860,9 @@ function statusCommand(useJson) {
|
|
|
2746
2860
|
console.log(`Observer: ${observer.isRunning(MIO_HOME) ? 'running (pid ' + observer.readPid(MIO_HOME) + ')' : 'not running'}`)
|
|
2747
2861
|
if (pendingAutoClaims > 0) {
|
|
2748
2862
|
console.log(
|
|
2749
|
-
`Pending auto-claims: ${pendingAutoClaims} (${pendingCrossAgent} cross-agent) -- only cross-agent claims whose target output actually cites the source memory may be confirmed; same-agent / weak / self-reported must NOT be (ADR-017)
|
|
2750
|
-
)
|
|
2751
|
-
console.log(
|
|
2752
|
-
` review: \`mio experience list --status pending\` then \`mio experience confirm --ids <id,...>\``
|
|
2863
|
+
`Pending auto-claims: ${pendingAutoClaims} (${pendingCrossAgent} cross-agent) -- only cross-agent claims whose target output actually cites the source memory may be confirmed; same-agent / weak / self-reported must NOT be (ADR-017).`,
|
|
2753
2864
|
)
|
|
2865
|
+
console.log(` review: \`mio experience list --status pending\` then \`mio experience confirm --ids <id,...>\``)
|
|
2754
2866
|
}
|
|
2755
2867
|
}
|
|
2756
2868
|
|
|
@@ -2885,9 +2997,7 @@ function agentsCommand(args, useJson) {
|
|
|
2885
2997
|
}
|
|
2886
2998
|
if (useJson) return jsonOrText(result, true)
|
|
2887
2999
|
console.log(`Registered ${result.agentId} (project=${project})`)
|
|
2888
|
-
console.log(
|
|
2889
|
-
` ${result.registered ? 'created' : `updated (session ${result.sessionCount})`} | host=${result.hostType}`,
|
|
2890
|
-
)
|
|
3000
|
+
console.log(` ${result.registered ? 'created' : `updated (session ${result.sessionCount})`} | host=${result.hostType}`)
|
|
2891
3001
|
if (result.capabilities && result.capabilities.length > 0) {
|
|
2892
3002
|
console.log(` capabilities: ${result.capabilities.join(', ')}`)
|
|
2893
3003
|
}
|
|
@@ -2908,9 +3018,7 @@ function printAgentList(result) {
|
|
|
2908
3018
|
for (const a of result.agents) {
|
|
2909
3019
|
const caps = Array.isArray(a.capabilities) && a.capabilities.length > 0 ? ` [${a.capabilities.join(', ')}]` : ''
|
|
2910
3020
|
console.log(`${a.agentId} (${a.hostType})${caps} project=${a.project || '-'}`)
|
|
2911
|
-
console.log(
|
|
2912
|
-
` sessions=${a.sessionCount || 0} tasks=${a.taskCount} success=${a.successCount} failure=${a.failureCount} | ${a.id}`,
|
|
2913
|
-
)
|
|
3021
|
+
console.log(` sessions=${a.sessionCount || 0} tasks=${a.taskCount} success=${a.successCount} failure=${a.failureCount} | ${a.id}`)
|
|
2914
3022
|
}
|
|
2915
3023
|
}
|
|
2916
3024
|
|
|
@@ -2924,9 +3032,7 @@ function printAgentReport(result) {
|
|
|
2924
3032
|
const o = r.taskOutcomes
|
|
2925
3033
|
const when = r.lastSeenAt ? r.lastSeenAt.slice(0, 19).replace('T', ' ') : 'unknown'
|
|
2926
3034
|
console.log(`${r.agentId} (${r.hostType}) ${r.active ? 'active' : 'idle'}`)
|
|
2927
|
-
console.log(
|
|
2928
|
-
` tasks: ${o.total} total, ${o.success} success, ${o.failure} failure (${o.successRate}% success)`,
|
|
2929
|
-
)
|
|
3035
|
+
console.log(` tasks: ${o.total} total, ${o.success} success, ${o.failure} failure (${o.successRate}% success)`)
|
|
2930
3036
|
console.log(` memories: ${r.memories} experience reuses: ${r.experienceReuses.total} (verified ${r.experienceReuses.verified})`)
|
|
2931
3037
|
console.log(` last seen: ${when} | sessions=${r.sessionCount}`)
|
|
2932
3038
|
}
|
|
@@ -2950,12 +3056,8 @@ function printRate(label, metric, numeratorKey, denominatorKey, unit, rateKey =
|
|
|
2950
3056
|
|
|
2951
3057
|
function printEvaluation(result) {
|
|
2952
3058
|
const s = result.sample
|
|
2953
|
-
console.log(
|
|
2954
|
-
|
|
2955
|
-
)
|
|
2956
|
-
console.log(
|
|
2957
|
-
` sample: queries=${s.queries} routeHits=${s.routeHits} reuses=${s.reuses} traces=${s.traces} agents=${s.agents}`,
|
|
2958
|
-
)
|
|
3059
|
+
console.log(`ADR-017 evaluation${result.project ? ` (project=${result.project})` : ''}${result.since ? ` since ${result.since}` : ''}`)
|
|
3060
|
+
console.log(` sample: queries=${s.queries} routeHits=${s.routeHits} reuses=${s.reuses} traces=${s.traces} agents=${s.agents}`)
|
|
2959
3061
|
console.log(' 1. route adoption rate (hit and acted on / hits)')
|
|
2960
3062
|
printRate('adoption', result.routeAdoption, 'adopted', 'routeHits', 'experience hits')
|
|
2961
3063
|
console.log(' 2. behaviour change rate (confirmed behaviorChanged / reuses)')
|
|
@@ -2969,9 +3071,7 @@ function printEvaluation(result) {
|
|
|
2969
3071
|
if (base) {
|
|
2970
3072
|
const now = result.behaviorChange.verified
|
|
2971
3073
|
const verdict = now >= base.observed ? 'at or above' : now >= base.required ? 'above threshold, below baseline' : 'BELOW BASELINE'
|
|
2972
|
-
console.log(
|
|
2973
|
-
` baseline ${result.baseline.date}: ${base.observed} (required ${base.required}) -- now ${now}, ${verdict}`,
|
|
2974
|
-
)
|
|
3074
|
+
console.log(` baseline ${result.baseline.date}: ${base.observed} (required ${base.required}) -- now ${now}, ${verdict}`)
|
|
2975
3075
|
}
|
|
2976
3076
|
console.log(' 3. recall quality (queries with results that led to a reuse)')
|
|
2977
3077
|
printRate('yield', result.recallQuality, 'queriesLinkedToReuse', 'queriesWithResults', 'queries', 'yield')
|
|
@@ -3350,11 +3450,7 @@ function installCommand(host, useJson) {
|
|
|
3350
3450
|
if (!observerCycleOk) {
|
|
3351
3451
|
console.error('Warning: observer cycle failed during install; run `mio observe --once` manually.')
|
|
3352
3452
|
}
|
|
3353
|
-
console.log(
|
|
3354
|
-
observer.isRunning(MIO_HOME)
|
|
3355
|
-
? 'Observer daemon running.'
|
|
3356
|
-
: 'Observer daemon not running. Run `mio observe --start`.'
|
|
3357
|
-
)
|
|
3453
|
+
console.log(observer.isRunning(MIO_HOME) ? 'Observer daemon running.' : 'Observer daemon not running. Run `mio observe --start`.')
|
|
3358
3454
|
}
|
|
3359
3455
|
|
|
3360
3456
|
function mcpCommand() {
|
|
@@ -3395,7 +3491,8 @@ function observeCommand(args, jsonFlag = false) {
|
|
|
3395
3491
|
console.log(result.started ? 'Observer started.' : 'Observer already running.')
|
|
3396
3492
|
if (researchResult) {
|
|
3397
3493
|
if (researchResult.skipped) console.log('Research scheduler skipped: ' + researchResult.skipped)
|
|
3398
|
-
else if (researchResult.started)
|
|
3494
|
+
else if (researchResult.started)
|
|
3495
|
+
console.log('Research scheduler started (pid ' + researchResult.pid + ', base-dir ' + researchResult.baseDir + ')')
|
|
3399
3496
|
else console.log('Research scheduler already running (pid ' + researchResult.pid + ')')
|
|
3400
3497
|
}
|
|
3401
3498
|
return
|
|
@@ -3404,10 +3501,7 @@ function observeCommand(args, jsonFlag = false) {
|
|
|
3404
3501
|
const result = observer.stopBackground(MIO_HOME)
|
|
3405
3502
|
const researchResult = observer.stopResearchBackground(MIO_HOME)
|
|
3406
3503
|
if (useJson) {
|
|
3407
|
-
return jsonOrText(
|
|
3408
|
-
{ ...result, research: { running: false, stopped: researchResult.stopped, pid: researchResult.pid } },
|
|
3409
|
-
true
|
|
3410
|
-
)
|
|
3504
|
+
return jsonOrText({ ...result, research: { running: false, stopped: researchResult.stopped, pid: researchResult.pid } }, true)
|
|
3411
3505
|
}
|
|
3412
3506
|
console.log(result.stopped ? 'Observer stopped.' : 'Observer was not running.')
|
|
3413
3507
|
console.log(researchResult.stopped ? 'Research scheduler stopped.' : 'Research scheduler was not running.')
|
|
@@ -3421,9 +3515,7 @@ function observeCommand(args, jsonFlag = false) {
|
|
|
3421
3515
|
const researchInfo = { running: researchRunning, pid: researchPid, logFile: observer.researchLogFile(MIO_HOME) }
|
|
3422
3516
|
if (useJson) return jsonOrText({ running, pid, research: researchInfo }, true)
|
|
3423
3517
|
console.log(running ? 'Observer: running (pid ' + pid + ')' : 'Observer: not running')
|
|
3424
|
-
console.log(
|
|
3425
|
-
researchRunning ? 'Research scheduler: running (pid ' + researchPid + ')' : 'Research scheduler: not running'
|
|
3426
|
-
)
|
|
3518
|
+
console.log(researchRunning ? 'Research scheduler: running (pid ' + researchPid + ')' : 'Research scheduler: not running')
|
|
3427
3519
|
return
|
|
3428
3520
|
}
|
|
3429
3521
|
if (flags.includes('--research') && !flags.includes('--start')) {
|
|
@@ -3432,11 +3524,7 @@ function observeCommand(args, jsonFlag = false) {
|
|
|
3432
3524
|
return
|
|
3433
3525
|
}
|
|
3434
3526
|
if (flags.includes('--once')) {
|
|
3435
|
-
const res = observer.runCycle(
|
|
3436
|
-
MIO_HOME,
|
|
3437
|
-
observer.loadState(MIO_HOME),
|
|
3438
|
-
observer.createSinks(MIO_HOME)
|
|
3439
|
-
)
|
|
3527
|
+
const res = observer.runCycle(MIO_HOME, observer.loadState(MIO_HOME), observer.createSinks(MIO_HOME))
|
|
3440
3528
|
if (useJson) return jsonOrText(res, true)
|
|
3441
3529
|
console.log('Observed files=' + res.files + ' lines=' + res.lines + ' outcomes=' + res.outcomes)
|
|
3442
3530
|
return
|
|
@@ -3492,10 +3580,14 @@ Usage:
|
|
|
3492
3580
|
mio experience list List experience reuse (--status pending|confirmed|verified)
|
|
3493
3581
|
mio experience confirm --ids a,b Confirm auto-claimed reuse (bulk supported)
|
|
3494
3582
|
mio experience reuse --source-agent A --target-agent B --experience-id X Record a reuse
|
|
3495
|
-
mio creativity status Show creativity hypothesis counts
|
|
3583
|
+
mio creativity status Show creativity hypothesis counts, recent top ideas, adoption join
|
|
3496
3584
|
mio creativity list List creativity hypotheses (--status active|validated|rejected|draft, --sort novelty, --limit N)
|
|
3497
3585
|
mio creativity generate Generate hypotheses from 2+ --source "name|content" (or --from-insights; calls an LLM)
|
|
3498
3586
|
mio creativity ferment Review and refine active hypotheses (calls an LLM)
|
|
3587
|
+
mio creativity adopt Record an adoption event for a stored hypothesis (writes traces only)
|
|
3588
|
+
mio mechanism registry List mechanism versions and promotion requests
|
|
3589
|
+
mio mechanism promote Submit/approve/reject a PromotionRequest (approver must differ from submitter)
|
|
3590
|
+
mio mechanism rollback Roll back the active version of a mechanism
|
|
3499
3591
|
mio idea generate --goal "..." Grounded idea pipeline: auto sources, novelty gate, persisted (calls an LLM)
|
|
3500
3592
|
mio insight status Insight counts: total, reported, unreported, high-value
|
|
3501
3593
|
mio insight list List insights (--unreported, --min-score N, --detector X, --limit N)
|
|
@@ -3560,6 +3652,8 @@ async function main() {
|
|
|
3560
3652
|
return policyCommand(args, useJson)
|
|
3561
3653
|
case 'creativity':
|
|
3562
3654
|
return creativityCommand(args, useJson)
|
|
3655
|
+
case 'mechanism':
|
|
3656
|
+
return mechanismCommand(args, useJson)
|
|
3563
3657
|
case 'idea':
|
|
3564
3658
|
return ideaCommand(args, useJson)
|
|
3565
3659
|
case 'insight':
|