mio-agent-runtime 0.5.15 → 0.5.17
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 +144 -236
- package/adapters/codex.js +122 -134
- package/adapters/hermes.js +122 -140
- package/adapters/host-utils.js +61 -61
- package/adapters/opencode.js +176 -215
- package/adapters/workbuddy.js +196 -242
- package/bin/mio.js +423 -424
- package/observe/observer.js +1326 -1335
- package/package.json +38 -25
- package/scripts/verify-packed-runtime.js +371 -0
- package/server/creativity-engine.js +397 -0
- package/server/evolution-cutover.js +119 -0
- package/server/host-capabilities.js +50 -0
- package/server/mio-intelligence-mcp/README.md +184 -173
- package/server/mio-intelligence-mcp/index.js +621 -300
- package/server/mio-intelligence-mcp/package.json +17 -17
- package/server/mio-intelligence-mcp/phase0.js +381 -381
- package/server/runtime-modules.js +111 -0
- package/server/mio-intelligence-mcp/dashboard-server.js +0 -171
package/package.json
CHANGED
|
@@ -1,25 +1,38 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "mio-agent-runtime",
|
|
3
|
-
"version": "0.5.
|
|
4
|
-
"description": "Mio Agent Runtime installer and MCP intelligence layer",
|
|
5
|
-
"license": "MIT",
|
|
6
|
-
"type": "commonjs",
|
|
7
|
-
"bin": {
|
|
8
|
-
"mio": "bin/mio.js"
|
|
9
|
-
},
|
|
10
|
-
"files": [
|
|
11
|
-
"bin/",
|
|
12
|
-
"server/",
|
|
13
|
-
"adapters/",
|
|
14
|
-
"observe/",
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
"
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "mio-agent-runtime",
|
|
3
|
+
"version": "0.5.17",
|
|
4
|
+
"description": "Mio Agent Runtime installer and MCP intelligence layer",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "commonjs",
|
|
7
|
+
"bin": {
|
|
8
|
+
"mio": "bin/mio.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"bin/",
|
|
12
|
+
"server/",
|
|
13
|
+
"adapters/",
|
|
14
|
+
"observe/",
|
|
15
|
+
"scripts/",
|
|
16
|
+
"README.md",
|
|
17
|
+
"!server/mio-intelligence-mcp/__tests__"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"check": "node --check bin/mio.js && node --check adapters/host-utils.js && node --check adapters/codex.js && node --check adapters/opencode.js && node --check adapters/workbuddy.js && node --check adapters/hermes.js && node --check server/runtime-modules.js && node --check server/host-capabilities.js && node --check server/evolution-cutover.js && node --check server/mio-intelligence-mcp/index.js && node --check server/mio-intelligence-mcp/phase0.js && node --check observe/observer.js && node --check scripts/verify-packed-runtime.js",
|
|
21
|
+
"prepack": "npm run check",
|
|
22
|
+
"verify:pack-install": "node scripts/verify-packed-runtime.js"
|
|
23
|
+
},
|
|
24
|
+
"engines": {
|
|
25
|
+
"node": ">=18"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"@akemi-mio/runtime-contracts": "^0.1.0",
|
|
29
|
+
"@akemi-mio/runtime-foundation": "^0.1.0",
|
|
30
|
+
"@akemi-mio/experience-memory": "^0.1.0",
|
|
31
|
+
"@akemi-mio/evolution-learning": "^0.1.0",
|
|
32
|
+
"@akemi-mio/evolution-strategy": "^0.1.0",
|
|
33
|
+
"@akemi-mio/evolution-safety": "^0.1.0",
|
|
34
|
+
"@akemi-mio/evolution-scheduler": "^0.1.0",
|
|
35
|
+
"@akemi-mio/observer": "^0.1.0",
|
|
36
|
+
"@akemi-mio/insight": "^0.1.0"
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict'
|
|
3
|
+
|
|
4
|
+
const fs = require('node:fs')
|
|
5
|
+
const os = require('node:os')
|
|
6
|
+
const path = require('node:path')
|
|
7
|
+
const crypto = require('node:crypto')
|
|
8
|
+
const { execFileSync } = require('node:child_process')
|
|
9
|
+
|
|
10
|
+
const RUNTIME_PACKAGE_NAMES = [
|
|
11
|
+
'@akemi-mio/runtime-contracts',
|
|
12
|
+
'@akemi-mio/runtime-foundation',
|
|
13
|
+
'@akemi-mio/experience-memory',
|
|
14
|
+
'@akemi-mio/evolution-learning',
|
|
15
|
+
'@akemi-mio/evolution-strategy',
|
|
16
|
+
'@akemi-mio/evolution-safety',
|
|
17
|
+
'@akemi-mio/evolution-scheduler',
|
|
18
|
+
'mio-agent-runtime',
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
function runtimePackageNames() {
|
|
22
|
+
return [...RUNTIME_PACKAGE_NAMES]
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function usage() {
|
|
26
|
+
return [
|
|
27
|
+
'Usage: node scripts/verify-packed-runtime.js [options]',
|
|
28
|
+
'',
|
|
29
|
+
'Options:',
|
|
30
|
+
' --workspace-root <path> Workspace root that contains packages/',
|
|
31
|
+
' --artifact-dir <path> Directory where npm pack writes tarballs',
|
|
32
|
+
' --install-dir <path> Clean temporary npm project directory',
|
|
33
|
+
' --report-path <path> Optional JSON evidence report path; must not exist',
|
|
34
|
+
' --help Show this help message',
|
|
35
|
+
].join('\n')
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function parseVerifyPackedRuntimeArgs(argv) {
|
|
39
|
+
const options = { help: false }
|
|
40
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
41
|
+
const option = argv[index]
|
|
42
|
+
if (option === '--help' || option === '-h') return { help: true }
|
|
43
|
+
if (!['--workspace-root', '--artifact-dir', '--install-dir', '--report-path'].includes(option)) {
|
|
44
|
+
throw new Error(`Unknown option: ${option}`)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const value = argv[index + 1]
|
|
48
|
+
if (!value || value.startsWith('--')) {
|
|
49
|
+
throw new Error(`Missing value for ${option}`)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (option === '--workspace-root') options.workspaceRoot = value
|
|
53
|
+
if (option === '--artifact-dir') options.artifactDir = value
|
|
54
|
+
if (option === '--install-dir') options.installDir = value
|
|
55
|
+
if (option === '--report-path') options.reportPath = value
|
|
56
|
+
index += 1
|
|
57
|
+
}
|
|
58
|
+
return options
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function createVerifyPackedRuntimeOptions(argv, env = process.env) {
|
|
62
|
+
const envOptions = {}
|
|
63
|
+
if (env.MIO_PACK_WORKSPACE_ROOT) envOptions.workspaceRoot = env.MIO_PACK_WORKSPACE_ROOT
|
|
64
|
+
if (env.MIO_PACK_ARTIFACT_DIR) envOptions.artifactDir = env.MIO_PACK_ARTIFACT_DIR
|
|
65
|
+
if (env.MIO_PACK_INSTALL_DIR) envOptions.installDir = env.MIO_PACK_INSTALL_DIR
|
|
66
|
+
if (env.MIO_PACK_REPORT_PATH) envOptions.reportPath = env.MIO_PACK_REPORT_PATH
|
|
67
|
+
|
|
68
|
+
const cliOptions = parseVerifyPackedRuntimeArgs(argv)
|
|
69
|
+
if (cliOptions.help) return { help: true }
|
|
70
|
+
return { ...envOptions, ...cliOptions, help: false }
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function npmCommand(platform = process.platform) {
|
|
74
|
+
return platform === 'win32' ? 'npm.cmd' : 'npm'
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function npmInvocation(args, env = process.env, platform = process.platform, node = process.execPath) {
|
|
78
|
+
if (env.npm_execpath) {
|
|
79
|
+
return { command: node, args: [env.npm_execpath, ...args] }
|
|
80
|
+
}
|
|
81
|
+
if (platform === 'win32') {
|
|
82
|
+
return { command: 'cmd.exe', args: ['/d', '/s', '/c', 'npm', ...args] }
|
|
83
|
+
}
|
|
84
|
+
return { command: npmCommand(platform), args }
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function packageDirName(name) {
|
|
88
|
+
if (name === 'mio-agent-runtime') return 'mio-cli'
|
|
89
|
+
return name.replace('@akemi-mio/', '')
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function tarballFileName(name, version) {
|
|
93
|
+
return `${name.replace(/^@/, '').replace('/', '-')}-${version}.tgz`
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function readPackageJson(workspaceRoot, name) {
|
|
97
|
+
const packageDir = path.join(workspaceRoot, 'packages', packageDirName(name))
|
|
98
|
+
return {
|
|
99
|
+
packageDir,
|
|
100
|
+
manifest: JSON.parse(fs.readFileSync(path.join(packageDir, 'package.json'), 'utf8')),
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function createPackedRuntimeInstallPlan(input = {}) {
|
|
105
|
+
const workspaceRoot = path.resolve(input.workspaceRoot || path.join(__dirname, '..', '..', '..'))
|
|
106
|
+
const artifactDir = path.resolve(input.artifactDir || fs.mkdtempSync(path.join(os.tmpdir(), 'mio-pack-artifacts-')))
|
|
107
|
+
const installDir = path.resolve(input.installDir || fs.mkdtempSync(path.join(os.tmpdir(), 'mio-pack-install-')))
|
|
108
|
+
const cli = path.join(installDir, 'node_modules', 'mio-agent-runtime', 'bin', 'mio.js')
|
|
109
|
+
const packages = RUNTIME_PACKAGE_NAMES.map((name) => {
|
|
110
|
+
const { packageDir, manifest } = readPackageJson(workspaceRoot, name)
|
|
111
|
+
return {
|
|
112
|
+
name,
|
|
113
|
+
version: manifest.version,
|
|
114
|
+
packageDir,
|
|
115
|
+
tarball: path.join(artifactDir, tarballFileName(name, manifest.version)),
|
|
116
|
+
}
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
return {
|
|
120
|
+
workspaceRoot,
|
|
121
|
+
artifactDir,
|
|
122
|
+
installDir,
|
|
123
|
+
packages,
|
|
124
|
+
install: {
|
|
125
|
+
cwd: installDir,
|
|
126
|
+
args: ['install', '--ignore-scripts', '--no-audit', '--no-fund', ...packages.map((pkg) => pkg.tarball)],
|
|
127
|
+
},
|
|
128
|
+
smoke: {
|
|
129
|
+
cwd: installDir,
|
|
130
|
+
args: [cli, '--json', 'evolution', 'status'],
|
|
131
|
+
status: {
|
|
132
|
+
cwd: installDir,
|
|
133
|
+
args: [cli, '--json', 'evolution', 'status'],
|
|
134
|
+
},
|
|
135
|
+
cutover: [
|
|
136
|
+
{
|
|
137
|
+
cwd: installDir,
|
|
138
|
+
args: [
|
|
139
|
+
cli,
|
|
140
|
+
'--json',
|
|
141
|
+
'evolution',
|
|
142
|
+
'shadow',
|
|
143
|
+
'record',
|
|
144
|
+
'--project',
|
|
145
|
+
'pack-install-smoke',
|
|
146
|
+
'--label',
|
|
147
|
+
'installed status parity',
|
|
148
|
+
'--legacy',
|
|
149
|
+
'{"modules":7}',
|
|
150
|
+
'--modular',
|
|
151
|
+
'{"modules":7}',
|
|
152
|
+
],
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
cwd: installDir,
|
|
156
|
+
args: [
|
|
157
|
+
cli,
|
|
158
|
+
'--json',
|
|
159
|
+
'evolution',
|
|
160
|
+
'dual-write',
|
|
161
|
+
'record',
|
|
162
|
+
'--project',
|
|
163
|
+
'pack-install-smoke',
|
|
164
|
+
'--label',
|
|
165
|
+
'installed memory parity',
|
|
166
|
+
'--authoritative',
|
|
167
|
+
'legacy',
|
|
168
|
+
'--legacy-result',
|
|
169
|
+
'{"id":"sample","ok":true}',
|
|
170
|
+
'--modular-result',
|
|
171
|
+
'{"id":"sample","ok":true}',
|
|
172
|
+
],
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
cwd: installDir,
|
|
176
|
+
args: [
|
|
177
|
+
cli,
|
|
178
|
+
'--json',
|
|
179
|
+
'evolution',
|
|
180
|
+
'cutover',
|
|
181
|
+
'readiness',
|
|
182
|
+
'--project',
|
|
183
|
+
'pack-install-smoke',
|
|
184
|
+
'--min-shadow-runs',
|
|
185
|
+
'1',
|
|
186
|
+
],
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
cwd: installDir,
|
|
190
|
+
args: [
|
|
191
|
+
cli,
|
|
192
|
+
'--json',
|
|
193
|
+
'evolution',
|
|
194
|
+
'cutover',
|
|
195
|
+
'apply',
|
|
196
|
+
'--dry-run',
|
|
197
|
+
'--project',
|
|
198
|
+
'pack-install-smoke',
|
|
199
|
+
'--plan',
|
|
200
|
+
'{"approved":true,"from":"legacy","to":"modular","actions":[{"type":"set_authority","from":"legacy","to":"modular"}]}',
|
|
201
|
+
],
|
|
202
|
+
},
|
|
203
|
+
],
|
|
204
|
+
},
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function run(command, args, options = {}) {
|
|
209
|
+
const output = execFileSync(command, args, {
|
|
210
|
+
cwd: options.cwd,
|
|
211
|
+
env: options.env || process.env,
|
|
212
|
+
encoding: 'utf8',
|
|
213
|
+
stdio: options.stdio || ['ignore', 'pipe', 'pipe'],
|
|
214
|
+
})
|
|
215
|
+
return output ? output.trim() : ''
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
function packageArtifactEvidence(pkg) {
|
|
219
|
+
if (!fs.existsSync(pkg.tarball)) {
|
|
220
|
+
throw new Error(`Expected tarball was not created: ${pkg.tarball}`)
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
const content = fs.readFileSync(pkg.tarball)
|
|
224
|
+
return {
|
|
225
|
+
name: pkg.name,
|
|
226
|
+
version: pkg.version,
|
|
227
|
+
tarball: pkg.tarball,
|
|
228
|
+
sizeBytes: fs.statSync(pkg.tarball).size,
|
|
229
|
+
sha512: crypto.createHash('sha512').update(content).digest('hex'),
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
function writeVerificationReport(result, reportPath) {
|
|
234
|
+
const resolvedReportPath = path.resolve(reportPath)
|
|
235
|
+
if (fs.existsSync(resolvedReportPath)) {
|
|
236
|
+
throw new Error(`Verification report already exists: ${resolvedReportPath}`)
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
fs.mkdirSync(path.dirname(resolvedReportPath), { recursive: true })
|
|
240
|
+
fs.writeFileSync(resolvedReportPath, `${JSON.stringify(result, null, 2)}\n`)
|
|
241
|
+
return resolvedReportPath
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
function summarizeInstalledSmoke(status, cutover) {
|
|
245
|
+
const modules = Array.isArray(status.modules) ? status.modules : []
|
|
246
|
+
const moduleNames = new Set(modules.map((module) => module.name))
|
|
247
|
+
const expectedModules = RUNTIME_PACKAGE_NAMES.filter((name) => name.startsWith('@akemi-mio/'))
|
|
248
|
+
const missingModules = expectedModules.filter((name) => !moduleNames.has(name))
|
|
249
|
+
if (missingModules.length > 0) {
|
|
250
|
+
throw new Error(`Installed runtime status is missing modules: ${missingModules.join(', ')}`)
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
const failedModules = modules.filter((module) => module.loaded !== true || module.healthy !== true)
|
|
254
|
+
if (failedModules.length > 0) {
|
|
255
|
+
throw new Error(
|
|
256
|
+
`Installed runtime modules failed health check: ${failedModules.map((module) => module.name).join(', ')}`,
|
|
257
|
+
)
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
const shadow = cutover[0]
|
|
261
|
+
const dualWrite = cutover[1]
|
|
262
|
+
const readiness = cutover.find((entry) => entry && entry.status === 'pass')
|
|
263
|
+
const apply = cutover.find((entry) => entry && entry.dryRun === true)
|
|
264
|
+
|
|
265
|
+
if (!shadow || shadow.matched !== true) throw new Error('Installed shadow smoke did not match')
|
|
266
|
+
if (!dualWrite || !dualWrite.shadow || dualWrite.shadow.matched !== true) {
|
|
267
|
+
throw new Error('Installed dual-write smoke did not match')
|
|
268
|
+
}
|
|
269
|
+
if (!readiness) throw new Error('Installed cutover readiness smoke did not pass')
|
|
270
|
+
if (!apply || apply.applied !== false) throw new Error('Installed cutover apply smoke did not stay dry-run')
|
|
271
|
+
|
|
272
|
+
return {
|
|
273
|
+
runtime: status.runtime,
|
|
274
|
+
version: status.version,
|
|
275
|
+
modules: modules.map((module) => ({
|
|
276
|
+
name: module.name,
|
|
277
|
+
loaded: module.loaded,
|
|
278
|
+
healthy: module.healthy,
|
|
279
|
+
})),
|
|
280
|
+
cutover: {
|
|
281
|
+
shadowMatched: shadow.matched === true,
|
|
282
|
+
dualWriteMatched: dualWrite.shadow.matched === true,
|
|
283
|
+
readiness: readiness.status,
|
|
284
|
+
applied: apply.applied,
|
|
285
|
+
},
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
function verifyPackedRuntimeInstall(input = {}) {
|
|
290
|
+
const plan = createPackedRuntimeInstallPlan(input)
|
|
291
|
+
fs.mkdirSync(plan.artifactDir, { recursive: true })
|
|
292
|
+
fs.mkdirSync(plan.installDir, { recursive: true })
|
|
293
|
+
|
|
294
|
+
for (const pkg of plan.packages) {
|
|
295
|
+
const pack = npmInvocation(['pack', '--pack-destination', plan.artifactDir])
|
|
296
|
+
run(pack.command, pack.args, {
|
|
297
|
+
cwd: pkg.packageDir,
|
|
298
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
299
|
+
})
|
|
300
|
+
packageArtifactEvidence(pkg)
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
const init = npmInvocation(['init', '-y'])
|
|
304
|
+
run(init.command, init.args, { cwd: plan.installDir, stdio: ['ignore', 'pipe', 'pipe'] })
|
|
305
|
+
const install = npmInvocation(plan.install.args)
|
|
306
|
+
run(install.command, install.args, { cwd: plan.install.cwd, stdio: ['ignore', 'pipe', 'pipe'] })
|
|
307
|
+
const smokeEnv = {
|
|
308
|
+
...process.env,
|
|
309
|
+
MIO_HOME: path.join(plan.installDir, '.mio-home'),
|
|
310
|
+
}
|
|
311
|
+
const smokeStdout = run(process.execPath, plan.smoke.status.args, {
|
|
312
|
+
cwd: plan.smoke.status.cwd,
|
|
313
|
+
env: smokeEnv,
|
|
314
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
315
|
+
})
|
|
316
|
+
const cutover = plan.smoke.cutover.map((command) => {
|
|
317
|
+
const stdout = run(process.execPath, command.args, {
|
|
318
|
+
cwd: command.cwd,
|
|
319
|
+
env: smokeEnv,
|
|
320
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
321
|
+
})
|
|
322
|
+
return JSON.parse(stdout)
|
|
323
|
+
})
|
|
324
|
+
const status = JSON.parse(smokeStdout)
|
|
325
|
+
const smoke = summarizeInstalledSmoke(status, cutover)
|
|
326
|
+
return {
|
|
327
|
+
ok: true,
|
|
328
|
+
artifactDir: plan.artifactDir,
|
|
329
|
+
installDir: plan.installDir,
|
|
330
|
+
packages: plan.packages.map(packageArtifactEvidence),
|
|
331
|
+
smoke,
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
function main() {
|
|
336
|
+
const options = createVerifyPackedRuntimeOptions(process.argv.slice(2))
|
|
337
|
+
if (options.help) {
|
|
338
|
+
console.log(usage())
|
|
339
|
+
return
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
const result = verifyPackedRuntimeInstall(options)
|
|
343
|
+
if (options.reportPath) {
|
|
344
|
+
result.reportPath = path.resolve(options.reportPath)
|
|
345
|
+
writeVerificationReport(result, result.reportPath)
|
|
346
|
+
}
|
|
347
|
+
console.log(JSON.stringify(result, null, 2))
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
if (require.main === module) {
|
|
351
|
+
try {
|
|
352
|
+
main()
|
|
353
|
+
} catch (error) {
|
|
354
|
+
console.error(error && error.stack ? error.stack : error)
|
|
355
|
+
process.exitCode = 1
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
module.exports = {
|
|
360
|
+
createVerifyPackedRuntimeOptions,
|
|
361
|
+
createPackedRuntimeInstallPlan,
|
|
362
|
+
packageArtifactEvidence,
|
|
363
|
+
npmInvocation,
|
|
364
|
+
npmCommand,
|
|
365
|
+
parseVerifyPackedRuntimeArgs,
|
|
366
|
+
runtimePackageNames,
|
|
367
|
+
summarizeInstalledSmoke,
|
|
368
|
+
usage,
|
|
369
|
+
verifyPackedRuntimeInstall,
|
|
370
|
+
writeVerificationReport,
|
|
371
|
+
}
|