mio-agent-runtime 0.15.0 → 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.
@@ -0,0 +1,99 @@
1
+ 'use strict'
2
+
3
+ const path = require('path')
4
+
5
+ // Re-export the pure TS helpers from the creativity package so CLI and MCP
6
+ // share one implementation of the A5 gate, promotion gate, and state machine.
7
+ // The JSONL store itself is the same MechanismRegistryStore the TS tests use.
8
+ let _registry = null
9
+ let _registryDir = null
10
+
11
+ function ensureRegistry(dataDir) {
12
+ if (_registry && _registryDir === dataDir) return _registry
13
+ const { MechanismRegistryStore } = require('@akemi-mio/creativity/MechanismRegistry')
14
+ const base = path.join(dataDir, 'creativity')
15
+ _registry = new MechanismRegistryStore(path.join(base, 'mechanisms.jsonl'))
16
+ _registryDir = dataDir
17
+ return _registry
18
+ }
19
+
20
+ function resetRegistryCache() {
21
+ _registry = null
22
+ _registryDir = null
23
+ }
24
+
25
+ /**
26
+ * Query the mechanism registry: active/rolled_back versions and promotion requests.
27
+ */
28
+ function mechanismRegistry(args = {}, dataDir) {
29
+ const registry = ensureRegistry(dataDir)
30
+ const mechanismId = args.mechanismId || undefined
31
+ const versions = mechanismId ? registry.listVersions(mechanismId) : registry.listVersions()
32
+ const requests = args.status ? registry.listRequests(args.status) : registry.listRequests()
33
+ return { versions, requests }
34
+ }
35
+
36
+ /**
37
+ * Submit a PromotionRequest. Gate is provided by the caller (checkSubmitGate).
38
+ * A5 is enforced inside MechanismRegistryStore.approve.
39
+ */
40
+ function mechanismPromote(args = {}, dataDir) {
41
+ const registry = ensureRegistry(dataDir)
42
+ const action = args.action || 'submit'
43
+
44
+ if (action === 'submit') {
45
+ const { checkSubmitGate } = require('@akemi-mio/creativity/MechanismRegistry')
46
+ const { DEFAULT_STOPPING_RULE } = require('@akemi-mio/creativity/ExperimentRunStore')
47
+ // Build a minimal gate from provided experimentRunIds length; full gate
48
+ // wiring is in the TS layer. For CLI/MCP thin surface we accept an
49
+ // explicit gate override or compute from runs.length vs minSamples.
50
+ const runs = (args.experimentRunIds || []).map((id, i) => ({
51
+ id,
52
+ assignment: 'candidate',
53
+ outcome: 'success',
54
+ metrics: {},
55
+ evidenceIds: [],
56
+ createdAt: Date.now() - i,
57
+ }))
58
+ const gate = args.gateOverride
59
+ ? { allowed: !!args.gateOverride.allowed, reason: args.gateOverride.reason || 'ok' }
60
+ : checkSubmitGate(DEFAULT_STOPPING_RULE, runs, args.currentSnapshotId)
61
+ const result = registry.submit(
62
+ {
63
+ mechanismId: args.mechanismId,
64
+ version: args.version,
65
+ hypothesisId: args.hypothesisId,
66
+ experimentRunIds: args.experimentRunIds,
67
+ submittedBy: args.submittedBy,
68
+ },
69
+ gate,
70
+ )
71
+ return result
72
+ }
73
+
74
+ if (action === 'approve') {
75
+ return registry.approve(args.requestId, args.approvedBy)
76
+ }
77
+
78
+ if (action === 'reject') {
79
+ return registry.reject(args.requestId, args.approvedBy, args.reason || 'rejected')
80
+ }
81
+
82
+ return { ok: false, reason: 'unknown_action' }
83
+ }
84
+
85
+ /**
86
+ * Rollback the active version of a mechanism to its rollbackTo target.
87
+ */
88
+ function mechanismRollback(args = {}, dataDir) {
89
+ const registry = ensureRegistry(dataDir)
90
+ return registry.rollback(args.mechanismId)
91
+ }
92
+
93
+ module.exports = {
94
+ mechanismRegistry,
95
+ mechanismPromote,
96
+ mechanismRollback,
97
+ ensureRegistry,
98
+ resetRegistryCache,
99
+ }