@memberjunction/cli 6.1.0-edge.0 → 6.1.0-edge.2

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.
@@ -38,15 +38,92 @@
38
38
  "usage.js"
39
39
  ]
40
40
  },
41
- "ai": {
41
+ "baseline:build": {
42
42
  "aliases": [],
43
43
  "args": {},
44
- "description": "Execute AI agents and actions",
45
- "flags": {},
44
+ "description": "Generate a deterministic baseline SQL script from the END-STATE of a migrated MSSQL database.",
45
+ "examples": [
46
+ "<%= config.bin %> <%= command.id %> --out ./migrations/v5/ # auto: within-major rebaseline",
47
+ "<%= config.bin %> <%= command.id %> --source-dir ./migrations/v5 --out ./migrations/v5/",
48
+ "<%= config.bin %> <%= command.id %> --baseline-version 6.0 --out ./migrations/v6/ # explicit major-boundary",
49
+ "<%= config.bin %> <%= command.id %> --baseline-version 5.32 --database MJ_BL_Stack --out /tmp/baseline/"
50
+ ],
51
+ "flags": {
52
+ "baseline-version": {
53
+ "description": "Baseline version stamp in Major.Minor format (literal x is appended for patch, matching the V-file convention). Omit to auto-detect from --source-dir (within-major rebaseline mode).",
54
+ "name": "baseline-version",
55
+ "hasDynamicHelp": false,
56
+ "multiple": false,
57
+ "type": "option"
58
+ },
59
+ "source-dir": {
60
+ "description": "Migrations source directory (e.g. ./migrations/v5). Used to auto-detect the next baseline version + timestamp when --baseline-version is omitted. Defaults to the highest migrations/v*/ directory walked up from cwd.",
61
+ "name": "source-dir",
62
+ "hasDynamicHelp": false,
63
+ "multiple": false,
64
+ "type": "option"
65
+ },
66
+ "description": {
67
+ "description": "Human-readable description embedded in the file header.",
68
+ "name": "description",
69
+ "default": "MemberJunction Baseline",
70
+ "hasDynamicHelp": false,
71
+ "multiple": false,
72
+ "type": "option"
73
+ },
74
+ "database": {
75
+ "description": "Override database name (host/user/password come from MJ config).",
76
+ "name": "database",
77
+ "hasDynamicHelp": false,
78
+ "multiple": false,
79
+ "type": "option"
80
+ },
81
+ "out": {
82
+ "description": "Output directory. Filename is auto-generated.",
83
+ "name": "out",
84
+ "default": ".",
85
+ "hasDynamicHelp": false,
86
+ "multiple": false,
87
+ "type": "option"
88
+ },
89
+ "exclude-data": {
90
+ "description": "Comma-separated list of tables (schema-qualified or not) to skip data dump for.",
91
+ "name": "exclude-data",
92
+ "default": "",
93
+ "hasDynamicHelp": false,
94
+ "multiple": false,
95
+ "type": "option"
96
+ },
97
+ "batch-size": {
98
+ "description": "Rows per INSERT batch.",
99
+ "name": "batch-size",
100
+ "default": 1000,
101
+ "hasDynamicHelp": false,
102
+ "multiple": false,
103
+ "type": "option"
104
+ },
105
+ "no-data": {
106
+ "description": "Emit schema only, no data inserts.",
107
+ "name": "no-data",
108
+ "allowNo": false,
109
+ "type": "boolean"
110
+ },
111
+ "verbose": {
112
+ "description": "Print per-object progress.",
113
+ "name": "verbose",
114
+ "allowNo": false,
115
+ "type": "boolean"
116
+ },
117
+ "dry-run": {
118
+ "description": "Print to stdout instead of writing a file.",
119
+ "name": "dry-run",
120
+ "allowNo": false,
121
+ "type": "boolean"
122
+ }
123
+ },
46
124
  "hasDynamicHelp": false,
47
- "hidden": false,
48
125
  "hiddenAliases": [],
49
- "id": "ai",
126
+ "id": "baseline:build",
50
127
  "pluginAlias": "@memberjunction/cli",
51
128
  "pluginName": "@memberjunction/cli",
52
129
  "pluginType": "core",
@@ -56,51 +133,114 @@
56
133
  "relativePath": [
57
134
  "dist",
58
135
  "commands",
59
- "ai",
60
- "index.js"
136
+ "baseline",
137
+ "build.js"
61
138
  ]
62
139
  },
63
- "app:check-updates": {
140
+ "baseline:compare": {
64
141
  "aliases": [],
65
142
  "args": {},
66
- "description": "Check for available upgrades for installed MJ Open Apps",
143
+ "description": "Deterministically compare two databases object-by-object and row-by-row.",
67
144
  "examples": [
68
- "<%= config.bin %> app check-updates"
145
+ "<%= config.bin %> <%= command.id %> --left MJ_BL_Stack --right MJ_BL_New",
146
+ "<%= config.bin %> <%= command.id %> --left A --right B --row-compare counts",
147
+ "<%= config.bin %> <%= command.id %> --left A --right B --fail-on-diff --out ./diffs/"
69
148
  ],
70
- "flags": {},
71
- "hasDynamicHelp": false,
72
- "hiddenAliases": [],
73
- "id": "app:check-updates",
74
- "pluginAlias": "@memberjunction/cli",
75
- "pluginName": "@memberjunction/cli",
76
- "pluginType": "core",
77
- "strict": true,
78
- "enableJsonFlag": false,
79
- "isESM": true,
80
- "relativePath": [
81
- "dist",
82
- "commands",
83
- "app",
84
- "check-updates.js"
85
- ]
86
- },
87
- "app:disable": {
88
- "aliases": [],
89
- "args": {
90
- "name": {
91
- "description": "Name of the installed app to disable",
92
- "name": "name",
93
- "required": true
149
+ "flags": {
150
+ "left": {
151
+ "description": "Left database name (override).",
152
+ "name": "left",
153
+ "required": true,
154
+ "hasDynamicHelp": false,
155
+ "multiple": false,
156
+ "type": "option"
157
+ },
158
+ "right": {
159
+ "description": "Right database name (override).",
160
+ "name": "right",
161
+ "required": true,
162
+ "hasDynamicHelp": false,
163
+ "multiple": false,
164
+ "type": "option"
165
+ },
166
+ "dialect": {
167
+ "description": "Dialect of both DBs (must match).",
168
+ "name": "dialect",
169
+ "default": "mssql",
170
+ "hasDynamicHelp": false,
171
+ "multiple": false,
172
+ "options": [
173
+ "mssql",
174
+ "postgres"
175
+ ],
176
+ "type": "option"
177
+ },
178
+ "row-compare": {
179
+ "description": "Row comparison mode.",
180
+ "name": "row-compare",
181
+ "default": "full",
182
+ "hasDynamicHelp": false,
183
+ "multiple": false,
184
+ "options": [
185
+ "full",
186
+ "hash",
187
+ "counts",
188
+ "none"
189
+ ],
190
+ "type": "option"
191
+ },
192
+ "row-hash-algo": {
193
+ "description": "Hash algorithm when --row-compare hash.",
194
+ "name": "row-hash-algo",
195
+ "default": "sha256",
196
+ "hasDynamicHelp": false,
197
+ "multiple": false,
198
+ "options": [
199
+ "sha256",
200
+ "md5",
201
+ "checksum_agg"
202
+ ],
203
+ "type": "option"
204
+ },
205
+ "ignore": {
206
+ "description": "Regex of object names to skip.",
207
+ "name": "ignore",
208
+ "default": "^flyway_schema_history$",
209
+ "hasDynamicHelp": false,
210
+ "multiple": false,
211
+ "type": "option"
212
+ },
213
+ "sample-limit": {
214
+ "description": "Maximum row diffs to capture per table.",
215
+ "name": "sample-limit",
216
+ "default": 100,
217
+ "hasDynamicHelp": false,
218
+ "multiple": false,
219
+ "type": "option"
220
+ },
221
+ "out": {
222
+ "description": "Directory to write JSON + Markdown reports.",
223
+ "name": "out",
224
+ "hasDynamicHelp": false,
225
+ "multiple": false,
226
+ "type": "option"
227
+ },
228
+ "fail-on-diff": {
229
+ "description": "Exit non-zero if any diff is found.",
230
+ "name": "fail-on-diff",
231
+ "allowNo": false,
232
+ "type": "boolean"
233
+ },
234
+ "verbose": {
235
+ "description": "Print per-phase progress.",
236
+ "name": "verbose",
237
+ "allowNo": false,
238
+ "type": "boolean"
94
239
  }
95
240
  },
96
- "description": "Disable an installed MJ Open App without removing it",
97
- "examples": [
98
- "<%= config.bin %> app disable acme-crm"
99
- ],
100
- "flags": {},
101
241
  "hasDynamicHelp": false,
102
242
  "hiddenAliases": [],
103
- "id": "app:disable",
243
+ "id": "baseline:compare",
104
244
  "pluginAlias": "@memberjunction/cli",
105
245
  "pluginName": "@memberjunction/cli",
106
246
  "pluginType": "core",
@@ -110,57 +250,119 @@
110
250
  "relativePath": [
111
251
  "dist",
112
252
  "commands",
113
- "app",
114
- "disable.js"
253
+ "baseline",
254
+ "compare.js"
115
255
  ]
116
256
  },
117
- "app:enable": {
257
+ "baseline:roundtrip": {
118
258
  "aliases": [],
119
- "args": {
120
- "name": {
121
- "description": "Name of the installed app to enable",
122
- "name": "name",
123
- "required": true
124
- }
125
- },
126
- "description": "Re-enable a disabled MJ Open App",
259
+ "args": {},
260
+ "description": "Build a baseline from a V-stack database, apply it to a fresh DB, and prove byte-equivalence.",
127
261
  "examples": [
128
- "<%= config.bin %> app enable acme-crm"
262
+ "<%= config.bin %> <%= command.id %> --source MJ_BL_Stack --target MJ_BL_New # auto: within-major",
263
+ "<%= config.bin %> <%= command.id %> --baseline-version 6.0 --source MJ_BL_Stack --target MJ_BL_New # explicit major-boundary",
264
+ "<%= config.bin %> <%= command.id %> --source-dir ./migrations/v5 --source MJ_BL_Stack --target MJ_BL_New"
129
265
  ],
130
- "flags": {},
131
- "hasDynamicHelp": false,
132
- "hiddenAliases": [],
133
- "id": "app:enable",
134
- "pluginAlias": "@memberjunction/cli",
135
- "pluginName": "@memberjunction/cli",
136
- "pluginType": "core",
137
- "strict": true,
138
- "enableJsonFlag": false,
139
- "isESM": true,
140
- "relativePath": [
141
- "dist",
142
- "commands",
143
- "app",
144
- "enable.js"
145
- ]
146
- },
147
- "app:info": {
148
- "aliases": [],
149
- "args": {
150
- "name": {
151
- "description": "Name of the installed app",
152
- "name": "name",
153
- "required": true
266
+ "flags": {
267
+ "baseline-version": {
268
+ "description": "Major.Minor version stamp. Omit to auto-detect from --source-dir (within-major rebaseline).",
269
+ "name": "baseline-version",
270
+ "hasDynamicHelp": false,
271
+ "multiple": false,
272
+ "type": "option"
273
+ },
274
+ "source-dir": {
275
+ "description": "Migrations source directory used to auto-detect baseline version + timestamp when --baseline-version is omitted. Defaults to the highest migrations/v*/ near cwd.",
276
+ "name": "source-dir",
277
+ "hasDynamicHelp": false,
278
+ "multiple": false,
279
+ "type": "option"
280
+ },
281
+ "description": {
282
+ "description": "Header description.",
283
+ "name": "description",
284
+ "default": "MemberJunction Baseline",
285
+ "hasDynamicHelp": false,
286
+ "multiple": false,
287
+ "type": "option"
288
+ },
289
+ "dialect": {
290
+ "description": "Dialect to test. PG path runs the converter via /pg-migrate first.",
291
+ "name": "dialect",
292
+ "default": "mssql",
293
+ "hasDynamicHelp": false,
294
+ "multiple": false,
295
+ "options": [
296
+ "mssql",
297
+ "postgres"
298
+ ],
299
+ "type": "option"
300
+ },
301
+ "source": {
302
+ "description": "Database name with the V-stack already applied (used as comparison gold standard).",
303
+ "name": "source",
304
+ "required": true,
305
+ "hasDynamicHelp": false,
306
+ "multiple": false,
307
+ "type": "option"
308
+ },
309
+ "target": {
310
+ "description": "Empty database name to apply the new baseline to.",
311
+ "name": "target",
312
+ "required": true,
313
+ "hasDynamicHelp": false,
314
+ "multiple": false,
315
+ "type": "option"
316
+ },
317
+ "out": {
318
+ "description": "Output directory for baseline file + reports.",
319
+ "name": "out",
320
+ "default": ".",
321
+ "hasDynamicHelp": false,
322
+ "multiple": false,
323
+ "type": "option"
324
+ },
325
+ "apply-cmd": {
326
+ "description": "Command template to apply the baseline. Tokens: {file} {database}. Defaults to sqlcmd.",
327
+ "name": "apply-cmd",
328
+ "hasDynamicHelp": false,
329
+ "multiple": false,
330
+ "type": "option"
331
+ },
332
+ "row-compare": {
333
+ "description": "Row compare mode passed to the comparator.",
334
+ "name": "row-compare",
335
+ "default": "full",
336
+ "hasDynamicHelp": false,
337
+ "multiple": false,
338
+ "options": [
339
+ "full",
340
+ "hash",
341
+ "counts",
342
+ "none"
343
+ ],
344
+ "type": "option"
345
+ },
346
+ "fail-on-diff": {
347
+ "name": "fail-on-diff",
348
+ "allowNo": false,
349
+ "type": "boolean"
350
+ },
351
+ "keep-target": {
352
+ "description": "Do not drop the target database after run (useful for debugging diffs).",
353
+ "name": "keep-target",
354
+ "allowNo": false,
355
+ "type": "boolean"
356
+ },
357
+ "verbose": {
358
+ "name": "verbose",
359
+ "allowNo": false,
360
+ "type": "boolean"
154
361
  }
155
362
  },
156
- "description": "Show detailed information about an installed MJ Open App",
157
- "examples": [
158
- "<%= config.bin %> app info acme-crm"
159
- ],
160
- "flags": {},
161
363
  "hasDynamicHelp": false,
162
364
  "hiddenAliases": [],
163
- "id": "app:info",
365
+ "id": "baseline:roundtrip",
164
366
  "pluginAlias": "@memberjunction/cli",
165
367
  "pluginName": "@memberjunction/cli",
166
368
  "pluginType": "core",
@@ -170,58 +372,69 @@
170
372
  "relativePath": [
171
373
  "dist",
172
374
  "commands",
173
- "app",
174
- "info.js"
375
+ "baseline",
376
+ "roundtrip.js"
175
377
  ]
176
378
  },
177
- "app:install": {
379
+ "bump": {
178
380
  "aliases": [],
179
- "args": {
180
- "source": {
181
- "description": "GitHub repository URL of the Open App. For a multi-app repo, append the in-repo path to the app (e.g. https://github.com/MemberJunction/Integrations/CRM/HubSpot).",
182
- "name": "source",
183
- "required": true
184
- }
185
- },
186
- "description": "Install an MJ Open App from a GitHub repository",
381
+ "args": {},
382
+ "description": "Bumps MemberJunction dependency versions",
187
383
  "examples": [
188
- "<%= config.bin %> app install https://github.com/acme/mj-crm",
189
- "<%= config.bin %> app install https://github.com/acme/mj-crm --version 1.2.0",
190
- "<%= config.bin %> app install https://github.com/acme/mj-crm --verbose",
191
- "<%= config.bin %> app install https://github.com/MemberJunction/Integrations/CRM/HubSpot",
192
- "<%= config.bin %> app install https://github.com/acme/mj-crm --non-interactive"
384
+ {
385
+ "command": "<%= config.bin %> <%= command.id %>",
386
+ "description": "Bump all @memberjunction/* dependencies in the current directory's package.json to the CLI version"
387
+ },
388
+ {
389
+ "command": "<%= config.bin %> <%= command.id %> -rdv",
390
+ "description": "Preview all recursive packages bumps without writing any changes."
391
+ },
392
+ {
393
+ "command": "<%= config.bin %> <%= command.id %> -rqt v2.10.0 | xargs -n1 -I{} npm install --prefix {}",
394
+ "description": "Recursively bump all @memberjunction/* dependencies in all packages to version v2.10.0 and output only the paths containing the updated package.json files. Pipe the output to xargs to run npm install in each directory and update the package-lock.json files as well."
395
+ }
193
396
  ],
194
397
  "flags": {
195
- "version": {
196
- "description": "Specific version to install (default: latest)",
197
- "name": "version",
198
- "hasDynamicHelp": false,
199
- "multiple": false,
200
- "type": "option"
201
- },
202
398
  "verbose": {
203
399
  "char": "v",
204
- "description": "Show detailed output",
400
+ "description": "Enable additional logging",
205
401
  "name": "verbose",
206
402
  "allowNo": false,
207
403
  "type": "boolean"
208
404
  },
209
- "non-interactive": {
210
- "description": "Skip interactive setup prompts; post-install hooks use environment variables / defaults (for CI/headless installs)",
211
- "name": "non-interactive",
405
+ "recursive": {
406
+ "char": "r",
407
+ "description": "Bump version in current directory and all subdirectories",
408
+ "name": "recursive",
409
+ "allowNo": false,
410
+ "type": "boolean"
411
+ },
412
+ "tag": {
413
+ "char": "t",
414
+ "description": "Version tag to bump target for bump (e.g. v2.10.0), defaults to the CLI version",
415
+ "name": "tag",
416
+ "hasDynamicHelp": false,
417
+ "multiple": false,
418
+ "type": "option"
419
+ },
420
+ "quiet": {
421
+ "char": "q",
422
+ "description": "Only output paths for updated packages",
423
+ "name": "quiet",
212
424
  "allowNo": false,
213
425
  "type": "boolean"
214
426
  },
215
- "dangerously-ignore-dbl-underscore-schema-rule": {
216
- "hidden": true,
217
- "name": "dangerously-ignore-dbl-underscore-schema-rule",
427
+ "dry": {
428
+ "char": "d",
429
+ "description": "Dry run, do not write changes to package.json files",
430
+ "name": "dry",
218
431
  "allowNo": false,
219
432
  "type": "boolean"
220
433
  }
221
434
  },
222
435
  "hasDynamicHelp": false,
223
436
  "hiddenAliases": [],
224
- "id": "app:install",
437
+ "id": "bump",
225
438
  "pluginAlias": "@memberjunction/cli",
226
439
  "pluginName": "@memberjunction/cli",
227
440
  "pluginType": "core",
@@ -231,29 +444,21 @@
231
444
  "relativePath": [
232
445
  "dist",
233
446
  "commands",
234
- "app",
235
- "install.js"
447
+ "bump",
448
+ "index.js"
236
449
  ]
237
450
  },
238
- "app:list": {
451
+ "app:check-updates": {
239
452
  "aliases": [],
240
453
  "args": {},
241
- "description": "List all installed MJ Open Apps",
454
+ "description": "Check for available upgrades for installed MJ Open Apps",
242
455
  "examples": [
243
- "<%= config.bin %> app list"
456
+ "<%= config.bin %> app check-updates"
244
457
  ],
245
- "flags": {
246
- "verbose": {
247
- "char": "v",
248
- "description": "Show detailed output",
249
- "name": "verbose",
250
- "allowNo": false,
251
- "type": "boolean"
252
- }
253
- },
458
+ "flags": {},
254
459
  "hasDynamicHelp": false,
255
460
  "hiddenAliases": [],
256
- "id": "app:list",
461
+ "id": "app:check-updates",
257
462
  "pluginAlias": "@memberjunction/cli",
258
463
  "pluginName": "@memberjunction/cli",
259
464
  "pluginType": "core",
@@ -264,61 +469,26 @@
264
469
  "dist",
265
470
  "commands",
266
471
  "app",
267
- "list.js"
472
+ "check-updates.js"
268
473
  ]
269
474
  },
270
- "app:remove": {
475
+ "app:disable": {
271
476
  "aliases": [],
272
477
  "args": {
273
478
  "name": {
274
- "description": "Name of the installed app to remove",
479
+ "description": "Name of the installed app to disable",
275
480
  "name": "name",
276
481
  "required": true
277
482
  }
278
483
  },
279
- "description": "Remove an installed MJ Open App",
484
+ "description": "Disable an installed MJ Open App without removing it",
280
485
  "examples": [
281
- "<%= config.bin %> app remove acme-crm",
282
- "<%= config.bin %> app remove acme-crm --keep-data",
283
- "<%= config.bin %> app remove acme-crm --force"
486
+ "<%= config.bin %> app disable acme-crm"
284
487
  ],
285
- "flags": {
286
- "keep-data": {
287
- "description": "Keep the database schema and data",
288
- "name": "keep-data",
289
- "allowNo": false,
290
- "type": "boolean"
291
- },
292
- "force": {
293
- "description": "Force removal even if other apps depend on this one",
294
- "name": "force",
295
- "allowNo": false,
296
- "type": "boolean"
297
- },
298
- "yes": {
299
- "char": "y",
300
- "description": "Skip confirmation prompt",
301
- "name": "yes",
302
- "allowNo": false,
303
- "type": "boolean"
304
- },
305
- "verbose": {
306
- "char": "v",
307
- "description": "Show detailed output",
308
- "name": "verbose",
309
- "allowNo": false,
310
- "type": "boolean"
311
- },
312
- "dangerously-ignore-dbl-underscore-schema-rule": {
313
- "hidden": true,
314
- "name": "dangerously-ignore-dbl-underscore-schema-rule",
315
- "allowNo": false,
316
- "type": "boolean"
317
- }
318
- },
488
+ "flags": {},
319
489
  "hasDynamicHelp": false,
320
490
  "hiddenAliases": [],
321
- "id": "app:remove",
491
+ "id": "app:disable",
322
492
  "pluginAlias": "@memberjunction/cli",
323
493
  "pluginName": "@memberjunction/cli",
324
494
  "pluginType": "core",
@@ -329,54 +499,26 @@
329
499
  "dist",
330
500
  "commands",
331
501
  "app",
332
- "remove.js"
502
+ "disable.js"
333
503
  ]
334
504
  },
335
- "app:upgrade": {
505
+ "app:enable": {
336
506
  "aliases": [],
337
507
  "args": {
338
508
  "name": {
339
- "description": "Name of the installed app to upgrade",
509
+ "description": "Name of the installed app to enable",
340
510
  "name": "name",
341
511
  "required": true
342
512
  }
343
513
  },
344
- "description": "Upgrade an installed MJ Open App to a newer version",
514
+ "description": "Re-enable a disabled MJ Open App",
345
515
  "examples": [
346
- "<%= config.bin %> app upgrade acme-crm",
347
- "<%= config.bin %> app upgrade acme-crm --version 1.3.0"
516
+ "<%= config.bin %> app enable acme-crm"
348
517
  ],
349
- "flags": {
350
- "version": {
351
- "description": "Specific version to upgrade to (default: latest)",
352
- "name": "version",
353
- "hasDynamicHelp": false,
354
- "multiple": false,
355
- "type": "option"
356
- },
357
- "verbose": {
358
- "char": "v",
359
- "description": "Show detailed output",
360
- "name": "verbose",
361
- "allowNo": false,
362
- "type": "boolean"
363
- },
364
- "non-interactive": {
365
- "description": "Skip interactive prompts; post-upgrade hooks use environment variables / defaults (for CI/headless upgrades)",
366
- "name": "non-interactive",
367
- "allowNo": false,
368
- "type": "boolean"
369
- },
370
- "dangerously-ignore-dbl-underscore-schema-rule": {
371
- "hidden": true,
372
- "name": "dangerously-ignore-dbl-underscore-schema-rule",
373
- "allowNo": false,
374
- "type": "boolean"
375
- }
376
- },
518
+ "flags": {},
377
519
  "hasDynamicHelp": false,
378
520
  "hiddenAliases": [],
379
- "id": "app:upgrade",
521
+ "id": "app:enable",
380
522
  "pluginAlias": "@memberjunction/cli",
381
523
  "pluginName": "@memberjunction/cli",
382
524
  "pluginType": "core",
@@ -387,57 +529,26 @@
387
529
  "dist",
388
530
  "commands",
389
531
  "app",
390
- "upgrade.js"
532
+ "enable.js"
391
533
  ]
392
534
  },
393
- "artifacts:reclassify": {
535
+ "app:info": {
394
536
  "aliases": [],
395
- "args": {},
396
- "description": "Upgrade-recovery utility for v5.35 artifact unification. Re-evaluates rows whose TypeID is the deleted JSON fallback but whose actual content does not parse as JSON. Normally a no-op: the v5.35 backfill migration handles this automatically. This command is only relevant when the migration ran BEFORE the artifact-type metadata (Generic Text / Generic Binary) was pushed via `mj sync push`, in which case the migration prints a notice telling you to run this. Reports \"no candidates\" once everything is reconciled. Dry-run by default; --apply writes through Record Changes.",
397
- "examples": [
398
- "<%= config.bin %> <%= command.id %>",
399
- "<%= config.bin %> <%= command.id %> --apply --limit 50"
400
- ],
401
- "flags": {
402
- "conversation-id": {
403
- "description": "Scope to artifacts attached to the given conversation.",
404
- "name": "conversation-id",
405
- "hasDynamicHelp": false,
406
- "multiple": false,
407
- "type": "option"
408
- },
409
- "since": {
410
- "description": "Scope to artifacts created on/after this ISO date.",
411
- "name": "since",
412
- "hasDynamicHelp": false,
413
- "multiple": false,
414
- "type": "option"
415
- },
416
- "limit": {
417
- "description": "Maximum number of rows to inspect.",
418
- "name": "limit",
419
- "default": 100,
420
- "hasDynamicHelp": false,
421
- "multiple": false,
422
- "type": "option"
423
- },
424
- "apply": {
425
- "description": "Write changes. Without this flag, this command only reports what it would do.",
426
- "name": "apply",
427
- "allowNo": false,
428
- "type": "boolean"
429
- },
430
- "verbose": {
431
- "char": "v",
432
- "description": "Print every candidate row, not just the summary.",
433
- "name": "verbose",
434
- "allowNo": false,
435
- "type": "boolean"
537
+ "args": {
538
+ "name": {
539
+ "description": "Name of the installed app",
540
+ "name": "name",
541
+ "required": true
436
542
  }
437
543
  },
544
+ "description": "Show detailed information about an installed MJ Open App",
545
+ "examples": [
546
+ "<%= config.bin %> app info acme-crm"
547
+ ],
548
+ "flags": {},
438
549
  "hasDynamicHelp": false,
439
550
  "hiddenAliases": [],
440
- "id": "artifacts:reclassify",
551
+ "id": "app:info",
441
552
  "pluginAlias": "@memberjunction/cli",
442
553
  "pluginName": "@memberjunction/cli",
443
554
  "pluginType": "core",
@@ -447,96 +558,58 @@
447
558
  "relativePath": [
448
559
  "dist",
449
560
  "commands",
450
- "artifacts",
451
- "reclassify.js"
561
+ "app",
562
+ "info.js"
452
563
  ]
453
564
  },
454
- "baseline:build": {
565
+ "app:install": {
455
566
  "aliases": [],
456
- "args": {},
457
- "description": "Generate a deterministic baseline SQL script from the END-STATE of a migrated MSSQL database.",
567
+ "args": {
568
+ "source": {
569
+ "description": "GitHub repository URL of the Open App. For a multi-app repo, append the in-repo path to the app (e.g. https://github.com/MemberJunction/Integrations/CRM/HubSpot).",
570
+ "name": "source",
571
+ "required": true
572
+ }
573
+ },
574
+ "description": "Install an MJ Open App from a GitHub repository",
458
575
  "examples": [
459
- "<%= config.bin %> <%= command.id %> --out ./migrations/v5/ # auto: within-major rebaseline",
460
- "<%= config.bin %> <%= command.id %> --source-dir ./migrations/v5 --out ./migrations/v5/",
461
- "<%= config.bin %> <%= command.id %> --baseline-version 6.0 --out ./migrations/v6/ # explicit major-boundary",
462
- "<%= config.bin %> <%= command.id %> --baseline-version 5.32 --database MJ_BL_Stack --out /tmp/baseline/"
463
- ],
464
- "flags": {
465
- "baseline-version": {
466
- "description": "Baseline version stamp in Major.Minor format (literal x is appended for patch, matching the V-file convention). Omit to auto-detect from --source-dir (within-major rebaseline mode).",
467
- "name": "baseline-version",
468
- "hasDynamicHelp": false,
469
- "multiple": false,
470
- "type": "option"
471
- },
472
- "source-dir": {
473
- "description": "Migrations source directory (e.g. ./migrations/v5). Used to auto-detect the next baseline version + timestamp when --baseline-version is omitted. Defaults to the highest migrations/v*/ directory walked up from cwd.",
474
- "name": "source-dir",
475
- "hasDynamicHelp": false,
476
- "multiple": false,
477
- "type": "option"
478
- },
479
- "description": {
480
- "description": "Human-readable description embedded in the file header.",
481
- "name": "description",
482
- "default": "MemberJunction Baseline",
483
- "hasDynamicHelp": false,
484
- "multiple": false,
485
- "type": "option"
486
- },
487
- "database": {
488
- "description": "Override database name (host/user/password come from MJ config).",
489
- "name": "database",
490
- "hasDynamicHelp": false,
491
- "multiple": false,
492
- "type": "option"
493
- },
494
- "out": {
495
- "description": "Output directory. Filename is auto-generated.",
496
- "name": "out",
497
- "default": ".",
498
- "hasDynamicHelp": false,
499
- "multiple": false,
500
- "type": "option"
501
- },
502
- "exclude-data": {
503
- "description": "Comma-separated list of tables (schema-qualified or not) to skip data dump for.",
504
- "name": "exclude-data",
505
- "default": "",
506
- "hasDynamicHelp": false,
507
- "multiple": false,
508
- "type": "option"
509
- },
510
- "batch-size": {
511
- "description": "Rows per INSERT batch.",
512
- "name": "batch-size",
513
- "default": 1000,
576
+ "<%= config.bin %> app install https://github.com/acme/mj-crm",
577
+ "<%= config.bin %> app install https://github.com/acme/mj-crm --version 1.2.0",
578
+ "<%= config.bin %> app install https://github.com/acme/mj-crm --verbose",
579
+ "<%= config.bin %> app install https://github.com/MemberJunction/Integrations/CRM/HubSpot",
580
+ "<%= config.bin %> app install https://github.com/acme/mj-crm --non-interactive"
581
+ ],
582
+ "flags": {
583
+ "version": {
584
+ "description": "Specific version to install (default: latest)",
585
+ "name": "version",
514
586
  "hasDynamicHelp": false,
515
587
  "multiple": false,
516
588
  "type": "option"
517
589
  },
518
- "no-data": {
519
- "description": "Emit schema only, no data inserts.",
520
- "name": "no-data",
590
+ "verbose": {
591
+ "char": "v",
592
+ "description": "Show detailed output",
593
+ "name": "verbose",
521
594
  "allowNo": false,
522
595
  "type": "boolean"
523
596
  },
524
- "verbose": {
525
- "description": "Print per-object progress.",
526
- "name": "verbose",
597
+ "non-interactive": {
598
+ "description": "Skip interactive setup prompts; post-install hooks use environment variables / defaults (for CI/headless installs)",
599
+ "name": "non-interactive",
527
600
  "allowNo": false,
528
601
  "type": "boolean"
529
602
  },
530
- "dry-run": {
531
- "description": "Print to stdout instead of writing a file.",
532
- "name": "dry-run",
603
+ "dangerously-ignore-dbl-underscore-schema-rule": {
604
+ "hidden": true,
605
+ "name": "dangerously-ignore-dbl-underscore-schema-rule",
533
606
  "allowNo": false,
534
607
  "type": "boolean"
535
608
  }
536
609
  },
537
610
  "hasDynamicHelp": false,
538
611
  "hiddenAliases": [],
539
- "id": "baseline:build",
612
+ "id": "app:install",
540
613
  "pluginAlias": "@memberjunction/cli",
541
614
  "pluginName": "@memberjunction/cli",
542
615
  "pluginType": "core",
@@ -546,106 +619,21 @@
546
619
  "relativePath": [
547
620
  "dist",
548
621
  "commands",
549
- "baseline",
550
- "build.js"
622
+ "app",
623
+ "install.js"
551
624
  ]
552
625
  },
553
- "baseline:compare": {
626
+ "app:list": {
554
627
  "aliases": [],
555
628
  "args": {},
556
- "description": "Deterministically compare two databases object-by-object and row-by-row.",
629
+ "description": "List all installed MJ Open Apps",
557
630
  "examples": [
558
- "<%= config.bin %> <%= command.id %> --left MJ_BL_Stack --right MJ_BL_New",
559
- "<%= config.bin %> <%= command.id %> --left A --right B --row-compare counts",
560
- "<%= config.bin %> <%= command.id %> --left A --right B --fail-on-diff --out ./diffs/"
631
+ "<%= config.bin %> app list"
561
632
  ],
562
633
  "flags": {
563
- "left": {
564
- "description": "Left database name (override).",
565
- "name": "left",
566
- "required": true,
567
- "hasDynamicHelp": false,
568
- "multiple": false,
569
- "type": "option"
570
- },
571
- "right": {
572
- "description": "Right database name (override).",
573
- "name": "right",
574
- "required": true,
575
- "hasDynamicHelp": false,
576
- "multiple": false,
577
- "type": "option"
578
- },
579
- "dialect": {
580
- "description": "Dialect of both DBs (must match).",
581
- "name": "dialect",
582
- "default": "mssql",
583
- "hasDynamicHelp": false,
584
- "multiple": false,
585
- "options": [
586
- "mssql",
587
- "postgres"
588
- ],
589
- "type": "option"
590
- },
591
- "row-compare": {
592
- "description": "Row comparison mode.",
593
- "name": "row-compare",
594
- "default": "full",
595
- "hasDynamicHelp": false,
596
- "multiple": false,
597
- "options": [
598
- "full",
599
- "hash",
600
- "counts",
601
- "none"
602
- ],
603
- "type": "option"
604
- },
605
- "row-hash-algo": {
606
- "description": "Hash algorithm when --row-compare hash.",
607
- "name": "row-hash-algo",
608
- "default": "sha256",
609
- "hasDynamicHelp": false,
610
- "multiple": false,
611
- "options": [
612
- "sha256",
613
- "md5",
614
- "checksum_agg"
615
- ],
616
- "type": "option"
617
- },
618
- "ignore": {
619
- "description": "Regex of object names to skip.",
620
- "name": "ignore",
621
- "default": "^flyway_schema_history$",
622
- "hasDynamicHelp": false,
623
- "multiple": false,
624
- "type": "option"
625
- },
626
- "sample-limit": {
627
- "description": "Maximum row diffs to capture per table.",
628
- "name": "sample-limit",
629
- "default": 100,
630
- "hasDynamicHelp": false,
631
- "multiple": false,
632
- "type": "option"
633
- },
634
- "out": {
635
- "description": "Directory to write JSON + Markdown reports.",
636
- "name": "out",
637
- "hasDynamicHelp": false,
638
- "multiple": false,
639
- "type": "option"
640
- },
641
- "fail-on-diff": {
642
- "description": "Exit non-zero if any diff is found.",
643
- "name": "fail-on-diff",
644
- "allowNo": false,
645
- "type": "boolean"
646
- },
647
634
  "verbose": {
648
- "description": "Print per-phase progress.",
635
+ "char": "v",
636
+ "description": "Show detailed output",
649
637
  "name": "verbose",
650
638
  "allowNo": false,
651
639
  "type": "boolean"
@@ -653,7 +641,7 @@
653
641
  },
654
642
  "hasDynamicHelp": false,
655
643
  "hiddenAliases": [],
656
- "id": "baseline:compare",
644
+ "id": "app:list",
657
645
  "pluginAlias": "@memberjunction/cli",
658
646
  "pluginName": "@memberjunction/cli",
659
647
  "pluginType": "core",
@@ -663,119 +651,120 @@
663
651
  "relativePath": [
664
652
  "dist",
665
653
  "commands",
666
- "baseline",
667
- "compare.js"
654
+ "app",
655
+ "list.js"
668
656
  ]
669
657
  },
670
- "baseline:roundtrip": {
658
+ "app:remove": {
671
659
  "aliases": [],
672
- "args": {},
673
- "description": "Build a baseline from a V-stack database, apply it to a fresh DB, and prove byte-equivalence.",
660
+ "args": {
661
+ "name": {
662
+ "description": "Name of the installed app to remove",
663
+ "name": "name",
664
+ "required": true
665
+ }
666
+ },
667
+ "description": "Remove an installed MJ Open App",
674
668
  "examples": [
675
- "<%= config.bin %> <%= command.id %> --source MJ_BL_Stack --target MJ_BL_New # auto: within-major",
676
- "<%= config.bin %> <%= command.id %> --baseline-version 6.0 --source MJ_BL_Stack --target MJ_BL_New # explicit major-boundary",
677
- "<%= config.bin %> <%= command.id %> --source-dir ./migrations/v5 --source MJ_BL_Stack --target MJ_BL_New"
669
+ "<%= config.bin %> app remove acme-crm",
670
+ "<%= config.bin %> app remove acme-crm --keep-data",
671
+ "<%= config.bin %> app remove acme-crm --force"
678
672
  ],
679
673
  "flags": {
680
- "baseline-version": {
681
- "description": "Major.Minor version stamp. Omit to auto-detect from --source-dir (within-major rebaseline).",
682
- "name": "baseline-version",
683
- "hasDynamicHelp": false,
684
- "multiple": false,
685
- "type": "option"
686
- },
687
- "source-dir": {
688
- "description": "Migrations source directory used to auto-detect baseline version + timestamp when --baseline-version is omitted. Defaults to the highest migrations/v*/ near cwd.",
689
- "name": "source-dir",
690
- "hasDynamicHelp": false,
691
- "multiple": false,
692
- "type": "option"
693
- },
694
- "description": {
695
- "description": "Header description.",
696
- "name": "description",
697
- "default": "MemberJunction Baseline",
698
- "hasDynamicHelp": false,
699
- "multiple": false,
700
- "type": "option"
701
- },
702
- "dialect": {
703
- "description": "Dialect to test. PG path runs the converter via /pg-migrate first.",
704
- "name": "dialect",
705
- "default": "mssql",
706
- "hasDynamicHelp": false,
707
- "multiple": false,
708
- "options": [
709
- "mssql",
710
- "postgres"
711
- ],
712
- "type": "option"
713
- },
714
- "source": {
715
- "description": "Database name with the V-stack already applied (used as comparison gold standard).",
716
- "name": "source",
717
- "required": true,
718
- "hasDynamicHelp": false,
719
- "multiple": false,
720
- "type": "option"
674
+ "keep-data": {
675
+ "description": "Keep the database schema and data",
676
+ "name": "keep-data",
677
+ "allowNo": false,
678
+ "type": "boolean"
721
679
  },
722
- "target": {
723
- "description": "Empty database name to apply the new baseline to.",
724
- "name": "target",
725
- "required": true,
726
- "hasDynamicHelp": false,
727
- "multiple": false,
728
- "type": "option"
680
+ "force": {
681
+ "description": "Force removal even if other apps depend on this one",
682
+ "name": "force",
683
+ "allowNo": false,
684
+ "type": "boolean"
729
685
  },
730
- "out": {
731
- "description": "Output directory for baseline file + reports.",
732
- "name": "out",
733
- "default": ".",
734
- "hasDynamicHelp": false,
735
- "multiple": false,
736
- "type": "option"
686
+ "yes": {
687
+ "char": "y",
688
+ "description": "Skip confirmation prompt",
689
+ "name": "yes",
690
+ "allowNo": false,
691
+ "type": "boolean"
737
692
  },
738
- "apply-cmd": {
739
- "description": "Command template to apply the baseline. Tokens: {file} {database}. Defaults to sqlcmd.",
740
- "name": "apply-cmd",
741
- "hasDynamicHelp": false,
742
- "multiple": false,
743
- "type": "option"
693
+ "verbose": {
694
+ "char": "v",
695
+ "description": "Show detailed output",
696
+ "name": "verbose",
697
+ "allowNo": false,
698
+ "type": "boolean"
744
699
  },
745
- "row-compare": {
746
- "description": "Row compare mode passed to the comparator.",
747
- "name": "row-compare",
748
- "default": "full",
700
+ "dangerously-ignore-dbl-underscore-schema-rule": {
701
+ "hidden": true,
702
+ "name": "dangerously-ignore-dbl-underscore-schema-rule",
703
+ "allowNo": false,
704
+ "type": "boolean"
705
+ }
706
+ },
707
+ "hasDynamicHelp": false,
708
+ "hiddenAliases": [],
709
+ "id": "app:remove",
710
+ "pluginAlias": "@memberjunction/cli",
711
+ "pluginName": "@memberjunction/cli",
712
+ "pluginType": "core",
713
+ "strict": true,
714
+ "enableJsonFlag": false,
715
+ "isESM": true,
716
+ "relativePath": [
717
+ "dist",
718
+ "commands",
719
+ "app",
720
+ "remove.js"
721
+ ]
722
+ },
723
+ "app:upgrade": {
724
+ "aliases": [],
725
+ "args": {
726
+ "name": {
727
+ "description": "Name of the installed app to upgrade",
728
+ "name": "name",
729
+ "required": true
730
+ }
731
+ },
732
+ "description": "Upgrade an installed MJ Open App to a newer version",
733
+ "examples": [
734
+ "<%= config.bin %> app upgrade acme-crm",
735
+ "<%= config.bin %> app upgrade acme-crm --version 1.3.0"
736
+ ],
737
+ "flags": {
738
+ "version": {
739
+ "description": "Specific version to upgrade to (default: latest)",
740
+ "name": "version",
749
741
  "hasDynamicHelp": false,
750
742
  "multiple": false,
751
- "options": [
752
- "full",
753
- "hash",
754
- "counts",
755
- "none"
756
- ],
757
743
  "type": "option"
758
744
  },
759
- "fail-on-diff": {
760
- "name": "fail-on-diff",
745
+ "verbose": {
746
+ "char": "v",
747
+ "description": "Show detailed output",
748
+ "name": "verbose",
761
749
  "allowNo": false,
762
750
  "type": "boolean"
763
751
  },
764
- "keep-target": {
765
- "description": "Do not drop the target database after run (useful for debugging diffs).",
766
- "name": "keep-target",
752
+ "non-interactive": {
753
+ "description": "Skip interactive prompts; post-upgrade hooks use environment variables / defaults (for CI/headless upgrades)",
754
+ "name": "non-interactive",
767
755
  "allowNo": false,
768
756
  "type": "boolean"
769
757
  },
770
- "verbose": {
771
- "name": "verbose",
758
+ "dangerously-ignore-dbl-underscore-schema-rule": {
759
+ "hidden": true,
760
+ "name": "dangerously-ignore-dbl-underscore-schema-rule",
772
761
  "allowNo": false,
773
762
  "type": "boolean"
774
763
  }
775
764
  },
776
765
  "hasDynamicHelp": false,
777
766
  "hiddenAliases": [],
778
- "id": "baseline:roundtrip",
767
+ "id": "app:upgrade",
779
768
  "pluginAlias": "@memberjunction/cli",
780
769
  "pluginName": "@memberjunction/cli",
781
770
  "pluginType": "core",
@@ -785,69 +774,58 @@
785
774
  "relativePath": [
786
775
  "dist",
787
776
  "commands",
788
- "baseline",
789
- "roundtrip.js"
777
+ "app",
778
+ "upgrade.js"
790
779
  ]
791
780
  },
792
- "bump": {
781
+ "artifacts:reclassify": {
793
782
  "aliases": [],
794
783
  "args": {},
795
- "description": "Bumps MemberJunction dependency versions",
784
+ "description": "Upgrade-recovery utility for v5.35 artifact unification. Re-evaluates rows whose TypeID is the deleted JSON fallback but whose actual content does not parse as JSON. Normally a no-op: the v5.35 backfill migration handles this automatically. This command is only relevant when the migration ran BEFORE the artifact-type metadata (Generic Text / Generic Binary) was pushed via `mj sync push`, in which case the migration prints a notice telling you to run this. Reports \"no candidates\" once everything is reconciled. Dry-run by default; --apply writes through Record Changes.",
796
785
  "examples": [
797
- {
798
- "command": "<%= config.bin %> <%= command.id %>",
799
- "description": "Bump all @memberjunction/* dependencies in the current directory's package.json to the CLI version"
800
- },
801
- {
802
- "command": "<%= config.bin %> <%= command.id %> -rdv",
803
- "description": "Preview all recursive packages bumps without writing any changes."
804
- },
805
- {
806
- "command": "<%= config.bin %> <%= command.id %> -rqt v2.10.0 | xargs -n1 -I{} npm install --prefix {}",
807
- "description": "Recursively bump all @memberjunction/* dependencies in all packages to version v2.10.0 and output only the paths containing the updated package.json files. Pipe the output to xargs to run npm install in each directory and update the package-lock.json files as well."
808
- }
786
+ "<%= config.bin %> <%= command.id %>",
787
+ "<%= config.bin %> <%= command.id %> --apply --limit 50"
809
788
  ],
810
789
  "flags": {
811
- "verbose": {
812
- "char": "v",
813
- "description": "Enable additional logging",
814
- "name": "verbose",
815
- "allowNo": false,
816
- "type": "boolean"
790
+ "conversation-id": {
791
+ "description": "Scope to artifacts attached to the given conversation.",
792
+ "name": "conversation-id",
793
+ "hasDynamicHelp": false,
794
+ "multiple": false,
795
+ "type": "option"
817
796
  },
818
- "recursive": {
819
- "char": "r",
820
- "description": "Bump version in current directory and all subdirectories",
821
- "name": "recursive",
822
- "allowNo": false,
823
- "type": "boolean"
797
+ "since": {
798
+ "description": "Scope to artifacts created on/after this ISO date.",
799
+ "name": "since",
800
+ "hasDynamicHelp": false,
801
+ "multiple": false,
802
+ "type": "option"
824
803
  },
825
- "tag": {
826
- "char": "t",
827
- "description": "Version tag to bump target for bump (e.g. v2.10.0), defaults to the CLI version",
828
- "name": "tag",
804
+ "limit": {
805
+ "description": "Maximum number of rows to inspect.",
806
+ "name": "limit",
807
+ "default": 100,
829
808
  "hasDynamicHelp": false,
830
809
  "multiple": false,
831
810
  "type": "option"
832
811
  },
833
- "quiet": {
834
- "char": "q",
835
- "description": "Only output paths for updated packages",
836
- "name": "quiet",
812
+ "apply": {
813
+ "description": "Write changes. Without this flag, this command only reports what it would do.",
814
+ "name": "apply",
837
815
  "allowNo": false,
838
816
  "type": "boolean"
839
817
  },
840
- "dry": {
841
- "char": "d",
842
- "description": "Dry run, do not write changes to package.json files",
843
- "name": "dry",
818
+ "verbose": {
819
+ "char": "v",
820
+ "description": "Print every candidate row, not just the summary.",
821
+ "name": "verbose",
844
822
  "allowNo": false,
845
823
  "type": "boolean"
846
824
  }
847
825
  },
848
826
  "hasDynamicHelp": false,
849
827
  "hiddenAliases": [],
850
- "id": "bump",
828
+ "id": "artifacts:reclassify",
851
829
  "pluginAlias": "@memberjunction/cli",
852
830
  "pluginName": "@memberjunction/cli",
853
831
  "pluginType": "core",
@@ -857,7 +835,29 @@
857
835
  "relativePath": [
858
836
  "dist",
859
837
  "commands",
860
- "bump",
838
+ "artifacts",
839
+ "reclassify.js"
840
+ ]
841
+ },
842
+ "ai": {
843
+ "aliases": [],
844
+ "args": {},
845
+ "description": "Execute AI agents and actions",
846
+ "flags": {},
847
+ "hasDynamicHelp": false,
848
+ "hidden": false,
849
+ "hiddenAliases": [],
850
+ "id": "ai",
851
+ "pluginAlias": "@memberjunction/cli",
852
+ "pluginName": "@memberjunction/cli",
853
+ "pluginType": "core",
854
+ "strict": true,
855
+ "enableJsonFlag": false,
856
+ "isESM": true,
857
+ "relativePath": [
858
+ "dist",
859
+ "commands",
860
+ "ai",
861
861
  "index.js"
862
862
  ]
863
863
  },
@@ -2454,39 +2454,150 @@
2454
2454
  "multiple": false,
2455
2455
  "type": "option"
2456
2456
  },
2457
- "output-dir": {
2458
- "description": "PG migrations directory (committed files read here + baked output written here)",
2459
- "name": "output-dir",
2460
- "default": "./migrations-pg/v5",
2457
+ "output-dir": {
2458
+ "description": "PG migrations directory (committed files read here + baked output written here)",
2459
+ "name": "output-dir",
2460
+ "default": "./migrations-pg/v5",
2461
+ "hasDynamicHelp": false,
2462
+ "multiple": false,
2463
+ "type": "option"
2464
+ },
2465
+ "schema": {
2466
+ "description": "Target schema name",
2467
+ "name": "schema",
2468
+ "default": "__mj",
2469
+ "hasDynamicHelp": false,
2470
+ "multiple": false,
2471
+ "type": "option"
2472
+ },
2473
+ "baseline-floor": {
2474
+ "description": "Re-bake migrations strictly AFTER this version key (default: the latest B* in output-dir)",
2475
+ "name": "baseline-floor",
2476
+ "hasDynamicHelp": false,
2477
+ "multiple": false,
2478
+ "type": "option"
2479
+ },
2480
+ "dry-run": {
2481
+ "description": "Report what would be re-baked without writing files",
2482
+ "name": "dry-run",
2483
+ "allowNo": false,
2484
+ "type": "boolean"
2485
+ }
2486
+ },
2487
+ "hasDynamicHelp": false,
2488
+ "hiddenAliases": [],
2489
+ "id": "migrate:rebake",
2490
+ "pluginAlias": "@memberjunction/cli",
2491
+ "pluginName": "@memberjunction/cli",
2492
+ "pluginType": "core",
2493
+ "strict": true,
2494
+ "enableJsonFlag": false,
2495
+ "isESM": true,
2496
+ "relativePath": [
2497
+ "dist",
2498
+ "commands",
2499
+ "migrate",
2500
+ "rebake.js"
2501
+ ]
2502
+ },
2503
+ "plugin:add": {
2504
+ "aliases": [],
2505
+ "args": {
2506
+ "package": {
2507
+ "description": "Plugin entry-point specifier (package name, subpath, or relative path)",
2508
+ "name": "package",
2509
+ "required": true
2510
+ }
2511
+ },
2512
+ "description": "Register a CLI plugin package in mj-cli-plugins.json so `mj` loads it at startup.",
2513
+ "examples": [
2514
+ "<%= config.bin %> <%= command.id %> @my-org/mj-plugin/plugins",
2515
+ "<%= config.bin %> <%= command.id %> ./local-plugins/my-tool"
2516
+ ],
2517
+ "flags": {
2518
+ "format": {
2519
+ "description": "Output format",
2520
+ "name": "format",
2521
+ "default": "text",
2522
+ "hasDynamicHelp": false,
2523
+ "multiple": false,
2524
+ "options": [
2525
+ "text",
2526
+ "json"
2527
+ ],
2528
+ "type": "option"
2529
+ }
2530
+ },
2531
+ "hasDynamicHelp": false,
2532
+ "hiddenAliases": [],
2533
+ "id": "plugin:add",
2534
+ "pluginAlias": "@memberjunction/cli",
2535
+ "pluginName": "@memberjunction/cli",
2536
+ "pluginType": "core",
2537
+ "strict": true,
2538
+ "enableJsonFlag": false,
2539
+ "isESM": true,
2540
+ "relativePath": [
2541
+ "dist",
2542
+ "commands",
2543
+ "plugin",
2544
+ "add.js"
2545
+ ]
2546
+ },
2547
+ "sql-audit": {
2548
+ "aliases": [],
2549
+ "args": {},
2550
+ "description": "Compare source and target databases for migration verification",
2551
+ "examples": [
2552
+ "<%= config.bin %> sql-audit --source \"mssql://sa:pass@host/db\" --target \"postgres://user:pass@host:5432/db\"",
2553
+ "<%= config.bin %> sql-audit --source \"mssql://sa:pass@host/db\" --target \"postgres://user:pass@host:5432/db\" --output report.txt",
2554
+ "<%= config.bin %> sql-audit --source \"mssql://sa:pass@host/db\" --target \"postgres://user:pass@host:5432/db\" --source-schema __mj --target-schema __mj"
2555
+ ],
2556
+ "flags": {
2557
+ "source": {
2558
+ "description": "Source database connection string (mssql://... or postgres://...)",
2559
+ "name": "source",
2560
+ "required": true,
2561
+ "hasDynamicHelp": false,
2562
+ "multiple": false,
2563
+ "type": "option"
2564
+ },
2565
+ "target": {
2566
+ "description": "Target database connection string (mssql://... or postgres://...)",
2567
+ "name": "target",
2568
+ "required": true,
2569
+ "hasDynamicHelp": false,
2570
+ "multiple": false,
2571
+ "type": "option"
2572
+ },
2573
+ "source-schema": {
2574
+ "description": "Source schema name",
2575
+ "name": "source-schema",
2576
+ "default": "__mj",
2461
2577
  "hasDynamicHelp": false,
2462
2578
  "multiple": false,
2463
2579
  "type": "option"
2464
2580
  },
2465
- "schema": {
2581
+ "target-schema": {
2466
2582
  "description": "Target schema name",
2467
- "name": "schema",
2583
+ "name": "target-schema",
2468
2584
  "default": "__mj",
2469
2585
  "hasDynamicHelp": false,
2470
2586
  "multiple": false,
2471
2587
  "type": "option"
2472
2588
  },
2473
- "baseline-floor": {
2474
- "description": "Re-bake migrations strictly AFTER this version key (default: the latest B* in output-dir)",
2475
- "name": "baseline-floor",
2589
+ "output": {
2590
+ "char": "o",
2591
+ "description": "Save report to file",
2592
+ "name": "output",
2476
2593
  "hasDynamicHelp": false,
2477
2594
  "multiple": false,
2478
2595
  "type": "option"
2479
- },
2480
- "dry-run": {
2481
- "description": "Report what would be re-baked without writing files",
2482
- "name": "dry-run",
2483
- "allowNo": false,
2484
- "type": "boolean"
2485
2596
  }
2486
2597
  },
2487
2598
  "hasDynamicHelp": false,
2488
2599
  "hiddenAliases": [],
2489
- "id": "migrate:rebake",
2600
+ "id": "sql-audit",
2490
2601
  "pluginAlias": "@memberjunction/cli",
2491
2602
  "pluginName": "@memberjunction/cli",
2492
2603
  "pluginType": "core",
@@ -2496,41 +2607,82 @@
2496
2607
  "relativePath": [
2497
2608
  "dist",
2498
2609
  "commands",
2499
- "migrate",
2500
- "rebake.js"
2610
+ "sql-audit",
2611
+ "index.js"
2501
2612
  ]
2502
2613
  },
2503
- "plugin:add": {
2614
+ "sql-convert": {
2504
2615
  "aliases": [],
2505
2616
  "args": {
2506
- "package": {
2507
- "description": "Plugin entry-point specifier (package name, subpath, or relative path)",
2508
- "name": "package",
2617
+ "source": {
2618
+ "description": "Source SQL file path",
2619
+ "name": "source",
2509
2620
  "required": true
2510
2621
  }
2511
2622
  },
2512
- "description": "Register a CLI plugin package in mj-cli-plugins.json so `mj` loads it at startup.",
2623
+ "description": "Convert SQL files between database dialects using rule-based BatchConverter engine",
2513
2624
  "examples": [
2514
- "<%= config.bin %> <%= command.id %> @my-org/mj-plugin/plugins",
2515
- "<%= config.bin %> <%= command.id %> ./local-plugins/my-tool"
2625
+ "<%= config.bin %> sql-convert ./migration.sql --from tsql --to postgres",
2626
+ "<%= config.bin %> sql-convert ./migration.sql --from tsql --to postgres --output converted.sql",
2627
+ "<%= config.bin %> sql-convert ./migration.sql --from tsql --to postgres --schema my_schema",
2628
+ "<%= config.bin %> sql-convert ./migration.sql --from tsql --to postgres --no-header --verbose"
2516
2629
  ],
2517
2630
  "flags": {
2518
- "format": {
2519
- "description": "Output format",
2520
- "name": "format",
2521
- "default": "text",
2631
+ "from": {
2632
+ "description": "Source SQL dialect",
2633
+ "name": "from",
2634
+ "required": true,
2635
+ "hasDynamicHelp": false,
2636
+ "multiple": false,
2637
+ "type": "option"
2638
+ },
2639
+ "to": {
2640
+ "description": "Target SQL dialect",
2641
+ "name": "to",
2642
+ "required": true,
2643
+ "hasDynamicHelp": false,
2644
+ "multiple": false,
2645
+ "type": "option"
2646
+ },
2647
+ "output": {
2648
+ "char": "o",
2649
+ "description": "Output file path (default: <source>.converted.<ext>)",
2650
+ "name": "output",
2651
+ "hasDynamicHelp": false,
2652
+ "multiple": false,
2653
+ "type": "option"
2654
+ },
2655
+ "schema": {
2656
+ "description": "Target schema name",
2657
+ "name": "schema",
2658
+ "default": "__mj",
2522
2659
  "hasDynamicHelp": false,
2523
2660
  "multiple": false,
2524
- "options": [
2525
- "text",
2526
- "json"
2527
- ],
2528
2661
  "type": "option"
2662
+ },
2663
+ "no-header": {
2664
+ "description": "Skip PG header (extensions, schema, implicit cast)",
2665
+ "name": "no-header",
2666
+ "allowNo": false,
2667
+ "type": "boolean"
2668
+ },
2669
+ "no-post-process": {
2670
+ "description": "Skip post-processing pass",
2671
+ "name": "no-post-process",
2672
+ "allowNo": false,
2673
+ "type": "boolean"
2674
+ },
2675
+ "verbose": {
2676
+ "char": "v",
2677
+ "description": "Show per-statement progress and detailed report",
2678
+ "name": "verbose",
2679
+ "allowNo": false,
2680
+ "type": "boolean"
2529
2681
  }
2530
2682
  },
2531
2683
  "hasDynamicHelp": false,
2532
2684
  "hiddenAliases": [],
2533
- "id": "plugin:add",
2685
+ "id": "sql-convert",
2534
2686
  "pluginAlias": "@memberjunction/cli",
2535
2687
  "pluginName": "@memberjunction/cli",
2536
2688
  "pluginType": "core",
@@ -2540,8 +2692,8 @@
2540
2692
  "relativePath": [
2541
2693
  "dist",
2542
2694
  "commands",
2543
- "plugin",
2544
- "add.js"
2695
+ "sql-convert",
2696
+ "index.js"
2545
2697
  ]
2546
2698
  },
2547
2699
  "querygen:export": {
@@ -2729,167 +2881,15 @@
2729
2881
  "path": {
2730
2882
  "char": "p",
2731
2883
  "description": "Path to queries metadata file or directory",
2732
- "name": "path",
2733
- "default": "./metadata/queries",
2734
- "hasDynamicHelp": false,
2735
- "multiple": false,
2736
- "type": "option"
2737
- },
2738
- "verbose": {
2739
- "char": "v",
2740
- "description": "Verbose output",
2741
- "name": "verbose",
2742
- "allowNo": false,
2743
- "type": "boolean"
2744
- }
2745
- },
2746
- "hasDynamicHelp": false,
2747
- "hiddenAliases": [],
2748
- "id": "querygen:validate",
2749
- "pluginAlias": "@memberjunction/cli",
2750
- "pluginName": "@memberjunction/cli",
2751
- "pluginType": "core",
2752
- "strict": true,
2753
- "enableJsonFlag": false,
2754
- "isESM": true,
2755
- "relativePath": [
2756
- "dist",
2757
- "commands",
2758
- "querygen",
2759
- "validate.js"
2760
- ]
2761
- },
2762
- "sql-audit": {
2763
- "aliases": [],
2764
- "args": {},
2765
- "description": "Compare source and target databases for migration verification",
2766
- "examples": [
2767
- "<%= config.bin %> sql-audit --source \"mssql://sa:pass@host/db\" --target \"postgres://user:pass@host:5432/db\"",
2768
- "<%= config.bin %> sql-audit --source \"mssql://sa:pass@host/db\" --target \"postgres://user:pass@host:5432/db\" --output report.txt",
2769
- "<%= config.bin %> sql-audit --source \"mssql://sa:pass@host/db\" --target \"postgres://user:pass@host:5432/db\" --source-schema __mj --target-schema __mj"
2770
- ],
2771
- "flags": {
2772
- "source": {
2773
- "description": "Source database connection string (mssql://... or postgres://...)",
2774
- "name": "source",
2775
- "required": true,
2776
- "hasDynamicHelp": false,
2777
- "multiple": false,
2778
- "type": "option"
2779
- },
2780
- "target": {
2781
- "description": "Target database connection string (mssql://... or postgres://...)",
2782
- "name": "target",
2783
- "required": true,
2784
- "hasDynamicHelp": false,
2785
- "multiple": false,
2786
- "type": "option"
2787
- },
2788
- "source-schema": {
2789
- "description": "Source schema name",
2790
- "name": "source-schema",
2791
- "default": "__mj",
2792
- "hasDynamicHelp": false,
2793
- "multiple": false,
2794
- "type": "option"
2795
- },
2796
- "target-schema": {
2797
- "description": "Target schema name",
2798
- "name": "target-schema",
2799
- "default": "__mj",
2800
- "hasDynamicHelp": false,
2801
- "multiple": false,
2802
- "type": "option"
2803
- },
2804
- "output": {
2805
- "char": "o",
2806
- "description": "Save report to file",
2807
- "name": "output",
2808
- "hasDynamicHelp": false,
2809
- "multiple": false,
2810
- "type": "option"
2811
- }
2812
- },
2813
- "hasDynamicHelp": false,
2814
- "hiddenAliases": [],
2815
- "id": "sql-audit",
2816
- "pluginAlias": "@memberjunction/cli",
2817
- "pluginName": "@memberjunction/cli",
2818
- "pluginType": "core",
2819
- "strict": true,
2820
- "enableJsonFlag": false,
2821
- "isESM": true,
2822
- "relativePath": [
2823
- "dist",
2824
- "commands",
2825
- "sql-audit",
2826
- "index.js"
2827
- ]
2828
- },
2829
- "sql-convert": {
2830
- "aliases": [],
2831
- "args": {
2832
- "source": {
2833
- "description": "Source SQL file path",
2834
- "name": "source",
2835
- "required": true
2836
- }
2837
- },
2838
- "description": "Convert SQL files between database dialects using rule-based BatchConverter engine",
2839
- "examples": [
2840
- "<%= config.bin %> sql-convert ./migration.sql --from tsql --to postgres",
2841
- "<%= config.bin %> sql-convert ./migration.sql --from tsql --to postgres --output converted.sql",
2842
- "<%= config.bin %> sql-convert ./migration.sql --from tsql --to postgres --schema my_schema",
2843
- "<%= config.bin %> sql-convert ./migration.sql --from tsql --to postgres --no-header --verbose"
2844
- ],
2845
- "flags": {
2846
- "from": {
2847
- "description": "Source SQL dialect",
2848
- "name": "from",
2849
- "required": true,
2850
- "hasDynamicHelp": false,
2851
- "multiple": false,
2852
- "type": "option"
2853
- },
2854
- "to": {
2855
- "description": "Target SQL dialect",
2856
- "name": "to",
2857
- "required": true,
2858
- "hasDynamicHelp": false,
2859
- "multiple": false,
2860
- "type": "option"
2861
- },
2862
- "output": {
2863
- "char": "o",
2864
- "description": "Output file path (default: <source>.converted.<ext>)",
2865
- "name": "output",
2866
- "hasDynamicHelp": false,
2867
- "multiple": false,
2868
- "type": "option"
2869
- },
2870
- "schema": {
2871
- "description": "Target schema name",
2872
- "name": "schema",
2873
- "default": "__mj",
2884
+ "name": "path",
2885
+ "default": "./metadata/queries",
2874
2886
  "hasDynamicHelp": false,
2875
2887
  "multiple": false,
2876
2888
  "type": "option"
2877
2889
  },
2878
- "no-header": {
2879
- "description": "Skip PG header (extensions, schema, implicit cast)",
2880
- "name": "no-header",
2881
- "allowNo": false,
2882
- "type": "boolean"
2883
- },
2884
- "no-post-process": {
2885
- "description": "Skip post-processing pass",
2886
- "name": "no-post-process",
2887
- "allowNo": false,
2888
- "type": "boolean"
2889
- },
2890
2890
  "verbose": {
2891
2891
  "char": "v",
2892
- "description": "Show per-statement progress and detailed report",
2892
+ "description": "Verbose output",
2893
2893
  "name": "verbose",
2894
2894
  "allowNo": false,
2895
2895
  "type": "boolean"
@@ -2897,7 +2897,7 @@
2897
2897
  },
2898
2898
  "hasDynamicHelp": false,
2899
2899
  "hiddenAliases": [],
2900
- "id": "sql-convert",
2900
+ "id": "querygen:validate",
2901
2901
  "pluginAlias": "@memberjunction/cli",
2902
2902
  "pluginName": "@memberjunction/cli",
2903
2903
  "pluginType": "core",
@@ -2907,8 +2907,8 @@
2907
2907
  "relativePath": [
2908
2908
  "dist",
2909
2909
  "commands",
2910
- "sql-convert",
2911
- "index.js"
2910
+ "querygen",
2911
+ "validate.js"
2912
2912
  ]
2913
2913
  },
2914
2914
  "standards:adopt": {
@@ -3099,6 +3099,105 @@
3099
3099
  "list.js"
3100
3100
  ]
3101
3101
  },
3102
+ "translate-sql": {
3103
+ "aliases": [],
3104
+ "args": {},
3105
+ "description": "Translate SQL fragments between database dialects (SQL Server ↔ PostgreSQL)",
3106
+ "examples": [
3107
+ "<%= config.bin %> translate-sql --from sqlserver --to postgresql --dry-run",
3108
+ "<%= config.bin %> translate-sql --from sqlserver --to postgresql --scope queries",
3109
+ "<%= config.bin %> translate-sql --from sqlserver --to postgresql --sql \"SELECT TOP 10 [Name] FROM [Users]\"",
3110
+ "<%= config.bin %> translate-sql --from sqlserver --to postgresql --scope all --output ./reports"
3111
+ ],
3112
+ "flags": {
3113
+ "from": {
3114
+ "description": "Source SQL dialect",
3115
+ "name": "from",
3116
+ "required": true,
3117
+ "hasDynamicHelp": false,
3118
+ "multiple": false,
3119
+ "options": [
3120
+ "sqlserver",
3121
+ "postgresql"
3122
+ ],
3123
+ "type": "option"
3124
+ },
3125
+ "to": {
3126
+ "description": "Target SQL dialect",
3127
+ "name": "to",
3128
+ "required": true,
3129
+ "hasDynamicHelp": false,
3130
+ "multiple": false,
3131
+ "options": [
3132
+ "sqlserver",
3133
+ "postgresql"
3134
+ ],
3135
+ "type": "option"
3136
+ },
3137
+ "scope": {
3138
+ "description": "What to scan for translation",
3139
+ "name": "scope",
3140
+ "default": "all",
3141
+ "hasDynamicHelp": false,
3142
+ "multiple": false,
3143
+ "options": [
3144
+ "queries",
3145
+ "views",
3146
+ "filters",
3147
+ "all"
3148
+ ],
3149
+ "type": "option"
3150
+ },
3151
+ "sql": {
3152
+ "description": "Translate a single SQL fragment (inline mode)",
3153
+ "name": "sql",
3154
+ "hasDynamicHelp": false,
3155
+ "multiple": false,
3156
+ "type": "option"
3157
+ },
3158
+ "dry-run": {
3159
+ "description": "Show what would be translated without making changes",
3160
+ "name": "dry-run",
3161
+ "allowNo": false,
3162
+ "type": "boolean"
3163
+ },
3164
+ "review": {
3165
+ "description": "Generate review report only (no writes to database)",
3166
+ "name": "review",
3167
+ "allowNo": false,
3168
+ "type": "boolean"
3169
+ },
3170
+ "output": {
3171
+ "char": "o",
3172
+ "description": "Output directory for the translation report",
3173
+ "name": "output",
3174
+ "hasDynamicHelp": false,
3175
+ "multiple": false,
3176
+ "type": "option"
3177
+ },
3178
+ "force": {
3179
+ "description": "Re-translate even if platform variants already exist",
3180
+ "name": "force",
3181
+ "allowNo": false,
3182
+ "type": "boolean"
3183
+ }
3184
+ },
3185
+ "hasDynamicHelp": false,
3186
+ "hiddenAliases": [],
3187
+ "id": "translate-sql",
3188
+ "pluginAlias": "@memberjunction/cli",
3189
+ "pluginName": "@memberjunction/cli",
3190
+ "pluginType": "core",
3191
+ "strict": true,
3192
+ "enableJsonFlag": false,
3193
+ "isESM": true,
3194
+ "relativePath": [
3195
+ "dist",
3196
+ "commands",
3197
+ "translate-sql",
3198
+ "index.js"
3199
+ ]
3200
+ },
3102
3201
  "sync:file-reset": {
3103
3202
  "aliases": [],
3104
3203
  "args": {},
@@ -3757,6 +3856,144 @@
3757
3856
  "watch.js"
3758
3857
  ]
3759
3858
  },
3859
+ "update:claude": {
3860
+ "aliases": [],
3861
+ "args": {},
3862
+ "description": "Update the Claude Code pack in the current directory.",
3863
+ "examples": [
3864
+ "<%= config.bin %> update:claude",
3865
+ "<%= config.bin %> update:claude --check",
3866
+ "<%= config.bin %> update:claude --refresh-commands",
3867
+ "<%= config.bin %> update:claude --allow-major",
3868
+ "<%= config.bin %> update:claude --json"
3869
+ ],
3870
+ "flags": {
3871
+ "dir": {
3872
+ "description": "Target directory",
3873
+ "name": "dir",
3874
+ "default": ".",
3875
+ "hasDynamicHelp": false,
3876
+ "multiple": false,
3877
+ "type": "option"
3878
+ },
3879
+ "major": {
3880
+ "description": "Force a specific MJ major (default: detected from package.json)",
3881
+ "name": "major",
3882
+ "hasDynamicHelp": false,
3883
+ "multiple": false,
3884
+ "type": "option"
3885
+ },
3886
+ "ref": {
3887
+ "description": "Git ref to fetch from (branch or tag). Default: main.",
3888
+ "name": "ref",
3889
+ "hasDynamicHelp": false,
3890
+ "multiple": false,
3891
+ "type": "option"
3892
+ },
3893
+ "from": {
3894
+ "description": "Use a local pack source instead of fetching from GitHub",
3895
+ "name": "from",
3896
+ "hasDynamicHelp": false,
3897
+ "multiple": false,
3898
+ "type": "option"
3899
+ },
3900
+ "offline": {
3901
+ "description": "Forbid network; requires --from <path>",
3902
+ "name": "offline",
3903
+ "allowNo": false,
3904
+ "type": "boolean"
3905
+ },
3906
+ "dry-run": {
3907
+ "description": "Print what would be written; change nothing",
3908
+ "name": "dry-run",
3909
+ "allowNo": false,
3910
+ "type": "boolean"
3911
+ },
3912
+ "yes": {
3913
+ "char": "y",
3914
+ "description": "Don't prompt (reserved for future interactive paths; currently no-op)",
3915
+ "name": "yes",
3916
+ "allowNo": false,
3917
+ "type": "boolean"
3918
+ },
3919
+ "force": {
3920
+ "description": "Overwrite user-customized commands/skills (saves .bak files)",
3921
+ "name": "force",
3922
+ "allowNo": false,
3923
+ "type": "boolean"
3924
+ },
3925
+ "skip-commands": {
3926
+ "description": "Skip seeding .claude/commands/",
3927
+ "name": "skip-commands",
3928
+ "allowNo": false,
3929
+ "type": "boolean"
3930
+ },
3931
+ "skip-skills": {
3932
+ "description": "Skip seeding .claude/skills/",
3933
+ "name": "skip-skills",
3934
+ "allowNo": false,
3935
+ "type": "boolean"
3936
+ },
3937
+ "skip-settings": {
3938
+ "description": "Skip merging .claude/settings.json",
3939
+ "name": "skip-settings",
3940
+ "allowNo": false,
3941
+ "type": "boolean"
3942
+ },
3943
+ "check": {
3944
+ "description": "Compare local pack version to remote without writing anything",
3945
+ "name": "check",
3946
+ "allowNo": false,
3947
+ "type": "boolean"
3948
+ },
3949
+ "refresh-commands": {
3950
+ "description": "Force-resync .claude/commands/* from the pack (saves .bak files)",
3951
+ "name": "refresh-commands",
3952
+ "allowNo": false,
3953
+ "type": "boolean"
3954
+ },
3955
+ "refresh-skills": {
3956
+ "description": "Force-resync .claude/skills/** from the pack (saves .bak files)",
3957
+ "name": "refresh-skills",
3958
+ "allowNo": false,
3959
+ "type": "boolean"
3960
+ },
3961
+ "allow-major": {
3962
+ "description": "Allow the remote pack's major to differ from local MJ's major",
3963
+ "name": "allow-major",
3964
+ "allowNo": false,
3965
+ "type": "boolean"
3966
+ },
3967
+ "json": {
3968
+ "description": "Output as JSON (matches plan §7.5 schema)",
3969
+ "name": "json",
3970
+ "allowNo": false,
3971
+ "type": "boolean"
3972
+ },
3973
+ "verbose": {
3974
+ "char": "v",
3975
+ "description": "Show progress messages",
3976
+ "name": "verbose",
3977
+ "allowNo": false,
3978
+ "type": "boolean"
3979
+ }
3980
+ },
3981
+ "hasDynamicHelp": false,
3982
+ "hiddenAliases": [],
3983
+ "id": "update:claude",
3984
+ "pluginAlias": "@memberjunction/cli",
3985
+ "pluginName": "@memberjunction/cli",
3986
+ "pluginType": "core",
3987
+ "strict": true,
3988
+ "enableJsonFlag": false,
3989
+ "isESM": true,
3990
+ "relativePath": [
3991
+ "dist",
3992
+ "commands",
3993
+ "update",
3994
+ "claude.js"
3995
+ ]
3996
+ },
3760
3997
  "test:compare": {
3761
3998
  "aliases": [],
3762
3999
  "args": {
@@ -3905,304 +4142,10 @@
3905
4142
  "multiple": false,
3906
4143
  "type": "option"
3907
4144
  },
3908
- "status": {
3909
- "char": "s",
3910
- "description": "Filter by status",
3911
- "name": "status",
3912
- "hasDynamicHelp": false,
3913
- "multiple": false,
3914
- "type": "option"
3915
- },
3916
- "format": {
3917
- "char": "f",
3918
- "description": "Output format",
3919
- "name": "format",
3920
- "default": "console",
3921
- "hasDynamicHelp": false,
3922
- "multiple": false,
3923
- "options": [
3924
- "console",
3925
- "json",
3926
- "markdown"
3927
- ],
3928
- "type": "option"
3929
- },
3930
- "output": {
3931
- "char": "o",
3932
- "description": "Output file path",
3933
- "name": "output",
3934
- "hasDynamicHelp": false,
3935
- "multiple": false,
3936
- "type": "option"
3937
- },
3938
- "verbose": {
3939
- "char": "v",
3940
- "description": "Show detailed information",
3941
- "name": "verbose",
3942
- "allowNo": false,
3943
- "type": "boolean"
3944
- }
3945
- },
3946
- "hasDynamicHelp": false,
3947
- "hiddenAliases": [],
3948
- "id": "test:history",
3949
- "pluginAlias": "@memberjunction/cli",
3950
- "pluginName": "@memberjunction/cli",
3951
- "pluginType": "core",
3952
- "strict": true,
3953
- "enableJsonFlag": false,
3954
- "isESM": true,
3955
- "relativePath": [
3956
- "dist",
3957
- "commands",
3958
- "test",
3959
- "history.js"
3960
- ]
3961
- },
3962
- "test": {
3963
- "aliases": [],
3964
- "args": {},
3965
- "description": "MemberJunction Testing Framework - Execute and manage tests",
3966
- "examples": [
3967
- "<%= config.bin %> <%= command.id %> run <test-id>",
3968
- "<%= config.bin %> <%= command.id %> run --name=\"Active Members Count\"",
3969
- "<%= config.bin %> <%= command.id %> suite <suite-id>",
3970
- "<%= config.bin %> <%= command.id %> list",
3971
- "<%= config.bin %> <%= command.id %> list --suites",
3972
- "<%= config.bin %> <%= command.id %> validate --all"
3973
- ],
3974
- "flags": {},
3975
- "hasDynamicHelp": false,
3976
- "hiddenAliases": [],
3977
- "id": "test",
3978
- "pluginAlias": "@memberjunction/cli",
3979
- "pluginName": "@memberjunction/cli",
3980
- "pluginType": "core",
3981
- "strict": true,
3982
- "enableJsonFlag": false,
3983
- "isESM": true,
3984
- "relativePath": [
3985
- "dist",
3986
- "commands",
3987
- "test",
3988
- "index.js"
3989
- ]
3990
- },
3991
- "test:list": {
3992
- "aliases": [],
3993
- "args": {},
3994
- "description": "List available tests, suites, and types",
3995
- "examples": [
3996
- "<%= config.bin %> <%= command.id %>",
3997
- "<%= config.bin %> <%= command.id %> --suites",
3998
- "<%= config.bin %> <%= command.id %> --types",
3999
- "<%= config.bin %> <%= command.id %> --type=agent-eval",
4000
- "<%= config.bin %> <%= command.id %> --tag=smoke",
4001
- "<%= config.bin %> <%= command.id %> --status=active --verbose"
4002
- ],
4003
- "flags": {
4004
- "suites": {
4005
- "description": "List test suites instead of tests",
4006
- "name": "suites",
4007
- "allowNo": false,
4008
- "type": "boolean"
4009
- },
4010
- "types": {
4011
- "description": "List test types",
4012
- "name": "types",
4013
- "allowNo": false,
4014
- "type": "boolean"
4015
- },
4016
- "type": {
4017
- "char": "t",
4018
- "description": "Filter by test type",
4019
- "name": "type",
4020
- "hasDynamicHelp": false,
4021
- "multiple": false,
4022
- "type": "option"
4023
- },
4024
- "tag": {
4025
- "description": "Filter by tag",
4026
- "name": "tag",
4027
- "hasDynamicHelp": false,
4028
- "multiple": false,
4029
- "type": "option"
4030
- },
4031
- "status": {
4032
- "char": "s",
4033
- "description": "Filter by status",
4034
- "name": "status",
4035
- "hasDynamicHelp": false,
4036
- "multiple": false,
4037
- "type": "option"
4038
- },
4039
- "format": {
4040
- "char": "f",
4041
- "description": "Output format",
4042
- "name": "format",
4043
- "default": "console",
4044
- "hasDynamicHelp": false,
4045
- "multiple": false,
4046
- "options": [
4047
- "console",
4048
- "json",
4049
- "markdown"
4050
- ],
4051
- "type": "option"
4052
- },
4053
- "output": {
4054
- "char": "o",
4055
- "description": "Output file path",
4056
- "name": "output",
4057
- "hasDynamicHelp": false,
4058
- "multiple": false,
4059
- "type": "option"
4060
- },
4061
- "verbose": {
4062
- "char": "v",
4063
- "description": "Show detailed information",
4064
- "name": "verbose",
4065
- "allowNo": false,
4066
- "type": "boolean"
4067
- }
4068
- },
4069
- "hasDynamicHelp": false,
4070
- "hiddenAliases": [],
4071
- "id": "test:list",
4072
- "pluginAlias": "@memberjunction/cli",
4073
- "pluginName": "@memberjunction/cli",
4074
- "pluginType": "core",
4075
- "strict": true,
4076
- "enableJsonFlag": false,
4077
- "isESM": true,
4078
- "relativePath": [
4079
- "dist",
4080
- "commands",
4081
- "test",
4082
- "list.js"
4083
- ]
4084
- },
4085
- "test:run": {
4086
- "aliases": [],
4087
- "args": {
4088
- "testId": {
4089
- "description": "Test ID to execute",
4090
- "name": "testId",
4091
- "required": false
4092
- }
4093
- },
4094
- "description": "Execute a single test by ID or name",
4095
- "examples": [
4096
- "<%= config.bin %> <%= command.id %> <test-id>",
4097
- "<%= config.bin %> <%= command.id %> --name=\"Active Members Count\"",
4098
- "<%= config.bin %> <%= command.id %> <test-id> --environment=staging",
4099
- "<%= config.bin %> <%= command.id %> <test-id> --format=json --output=results.json",
4100
- "<%= config.bin %> <%= command.id %> <test-id> --dry-run"
4101
- ],
4102
- "flags": {
4103
- "name": {
4104
- "char": "n",
4105
- "description": "Test name to execute",
4106
- "name": "name",
4107
- "hasDynamicHelp": false,
4108
- "multiple": false,
4109
- "type": "option"
4110
- },
4111
- "environment": {
4112
- "char": "e",
4113
- "description": "Environment context (dev, staging, prod)",
4114
- "name": "environment",
4115
- "hasDynamicHelp": false,
4116
- "multiple": false,
4117
- "type": "option"
4118
- },
4119
- "format": {
4120
- "char": "f",
4121
- "description": "Output format",
4122
- "name": "format",
4123
- "default": "console",
4124
- "hasDynamicHelp": false,
4125
- "multiple": false,
4126
- "options": [
4127
- "console",
4128
- "json",
4129
- "markdown"
4130
- ],
4131
- "type": "option"
4132
- },
4133
- "output": {
4134
- "char": "o",
4135
- "description": "Output file path",
4136
- "name": "output",
4137
- "hasDynamicHelp": false,
4138
- "multiple": false,
4139
- "type": "option"
4140
- },
4141
- "dry-run": {
4142
- "description": "Validate without executing",
4143
- "name": "dry-run",
4144
- "allowNo": false,
4145
- "type": "boolean"
4146
- },
4147
- "verbose": {
4148
- "char": "v",
4149
- "description": "Show detailed execution information",
4150
- "name": "verbose",
4151
- "allowNo": false,
4152
- "type": "boolean"
4153
- },
4154
- "checks-module": {
4155
- "description": "Module specifier (package name or path) side-effect-imported before the run so its integration check bundles register on the IntegrationCheckRegistry. Durable form: mj.config.cjs `testing.checkModules` (this repo loads '@memberjunction/integration-test-suite' that way).",
4156
- "name": "checks-module",
4157
- "hasDynamicHelp": false,
4158
- "multiple": false,
4159
- "type": "option"
4160
- },
4161
- "oracles-module": {
4162
- "description": "Path to a JS/TS module that exports custom IOracle classes or instances. Each export is registered on the engine before the test runs — used by non-MJ adopters to plug app-specific oracle types without modifying TestingFramework.",
4163
- "name": "oracles-module",
4164
- "hasDynamicHelp": false,
4165
- "multiple": false,
4166
- "type": "option"
4167
- }
4168
- },
4169
- "hasDynamicHelp": false,
4170
- "hiddenAliases": [],
4171
- "id": "test:run",
4172
- "pluginAlias": "@memberjunction/cli",
4173
- "pluginName": "@memberjunction/cli",
4174
- "pluginType": "core",
4175
- "strict": true,
4176
- "enableJsonFlag": false,
4177
- "isESM": true,
4178
- "relativePath": [
4179
- "dist",
4180
- "commands",
4181
- "test",
4182
- "run.js"
4183
- ]
4184
- },
4185
- "test:suite": {
4186
- "aliases": [],
4187
- "args": {
4188
- "suiteId": {
4189
- "description": "Test suite ID to execute",
4190
- "name": "suiteId",
4191
- "required": false
4192
- }
4193
- },
4194
- "description": "Execute a test suite",
4195
- "examples": [
4196
- "<%= config.bin %> <%= command.id %> <suite-id>",
4197
- "<%= config.bin %> <%= command.id %> --name=\"Agent Quality Suite\"",
4198
- "<%= config.bin %> <%= command.id %> <suite-id> --format=json",
4199
- "<%= config.bin %> <%= command.id %> <suite-id> --output=suite-results.json"
4200
- ],
4201
- "flags": {
4202
- "name": {
4203
- "char": "n",
4204
- "description": "Test suite name to execute",
4205
- "name": "name",
4145
+ "status": {
4146
+ "char": "s",
4147
+ "description": "Filter by status",
4148
+ "name": "status",
4206
4149
  "hasDynamicHelp": false,
4207
4150
  "multiple": false,
4208
4151
  "type": "option"
@@ -4231,60 +4174,15 @@
4231
4174
  },
4232
4175
  "verbose": {
4233
4176
  "char": "v",
4234
- "description": "Show detailed execution information",
4177
+ "description": "Show detailed information",
4235
4178
  "name": "verbose",
4236
4179
  "allowNo": false,
4237
4180
  "type": "boolean"
4238
- },
4239
- "delay": {
4240
- "char": "d",
4241
- "description": "Delay in milliseconds between test executions (avoids Auth0 rate limits)",
4242
- "name": "delay",
4243
- "default": 0,
4244
- "hasDynamicHelp": false,
4245
- "multiple": false,
4246
- "type": "option"
4247
- },
4248
- "parallel": {
4249
- "char": "p",
4250
- "description": "Run tests in parallel with shared browser sessions",
4251
- "name": "parallel",
4252
- "allowNo": false,
4253
- "type": "boolean"
4254
- },
4255
- "max-parallel": {
4256
- "description": "Maximum number of parallel workers (default 4)",
4257
- "name": "max-parallel",
4258
- "default": 4,
4259
- "hasDynamicHelp": false,
4260
- "multiple": false,
4261
- "type": "option"
4262
- },
4263
- "flaky-check": {
4264
- "description": "Run each test N times to detect flakiness (variance > 0.3 or mixed pass/fail = flaky). Recommended: 3 or 5",
4265
- "name": "flaky-check",
4266
- "hasDynamicHelp": false,
4267
- "multiple": false,
4268
- "type": "option"
4269
- },
4270
- "checks-module": {
4271
- "description": "Module specifier (package name or path) side-effect-imported before the run so its integration check bundles register on the IntegrationCheckRegistry. Durable form: mj.config.cjs `testing.checkModules` (this repo loads '@memberjunction/integration-test-suite' that way).",
4272
- "name": "checks-module",
4273
- "hasDynamicHelp": false,
4274
- "multiple": false,
4275
- "type": "option"
4276
- },
4277
- "oracles-module": {
4278
- "description": "Path to a JS/TS module that exports custom IOracle classes or instances. Each export is registered on the engine before the suite runs — used by non-MJ adopters to plug app-specific oracle types without modifying TestingFramework.",
4279
- "name": "oracles-module",
4280
- "hasDynamicHelp": false,
4281
- "multiple": false,
4282
- "type": "option"
4283
4181
  }
4284
4182
  },
4285
4183
  "hasDynamicHelp": false,
4286
4184
  "hiddenAliases": [],
4287
- "id": "test:suite",
4185
+ "id": "test:history",
4288
4186
  "pluginAlias": "@memberjunction/cli",
4289
4187
  "pluginName": "@memberjunction/cli",
4290
4188
  "pluginType": "core",
@@ -4295,47 +4193,85 @@
4295
4193
  "dist",
4296
4194
  "commands",
4297
4195
  "test",
4298
- "suite.js"
4196
+ "history.js"
4299
4197
  ]
4300
4198
  },
4301
- "test:validate": {
4199
+ "test": {
4302
4200
  "aliases": [],
4303
- "args": {
4304
- "testId": {
4305
- "description": "Test ID to validate",
4306
- "name": "testId",
4307
- "required": false
4308
- }
4309
- },
4310
- "description": "Validate test definitions without executing",
4201
+ "args": {},
4202
+ "description": "MemberJunction Testing Framework - Execute and manage tests",
4311
4203
  "examples": [
4312
- "<%= config.bin %> <%= command.id %> <test-id>",
4313
- "<%= config.bin %> <%= command.id %> --all",
4204
+ "<%= config.bin %> <%= command.id %> run <test-id>",
4205
+ "<%= config.bin %> <%= command.id %> run --name=\"Active Members Count\"",
4206
+ "<%= config.bin %> <%= command.id %> suite <suite-id>",
4207
+ "<%= config.bin %> <%= command.id %> list",
4208
+ "<%= config.bin %> <%= command.id %> list --suites",
4209
+ "<%= config.bin %> <%= command.id %> validate --all"
4210
+ ],
4211
+ "flags": {},
4212
+ "hasDynamicHelp": false,
4213
+ "hiddenAliases": [],
4214
+ "id": "test",
4215
+ "pluginAlias": "@memberjunction/cli",
4216
+ "pluginName": "@memberjunction/cli",
4217
+ "pluginType": "core",
4218
+ "strict": true,
4219
+ "enableJsonFlag": false,
4220
+ "isESM": true,
4221
+ "relativePath": [
4222
+ "dist",
4223
+ "commands",
4224
+ "test",
4225
+ "index.js"
4226
+ ]
4227
+ },
4228
+ "test:list": {
4229
+ "aliases": [],
4230
+ "args": {},
4231
+ "description": "List available tests, suites, and types",
4232
+ "examples": [
4233
+ "<%= config.bin %> <%= command.id %>",
4234
+ "<%= config.bin %> <%= command.id %> --suites",
4235
+ "<%= config.bin %> <%= command.id %> --types",
4314
4236
  "<%= config.bin %> <%= command.id %> --type=agent-eval",
4315
- "<%= config.bin %> <%= command.id %> --all --save-report",
4316
- "<%= config.bin %> <%= command.id %> --all --output=validation-report.md"
4237
+ "<%= config.bin %> <%= command.id %> --tag=smoke",
4238
+ "<%= config.bin %> <%= command.id %> --status=active --verbose"
4317
4239
  ],
4318
4240
  "flags": {
4319
- "all": {
4320
- "char": "a",
4321
- "description": "Validate all tests",
4322
- "name": "all",
4241
+ "suites": {
4242
+ "description": "List test suites instead of tests",
4243
+ "name": "suites",
4244
+ "allowNo": false,
4245
+ "type": "boolean"
4246
+ },
4247
+ "types": {
4248
+ "description": "List test types",
4249
+ "name": "types",
4323
4250
  "allowNo": false,
4324
4251
  "type": "boolean"
4325
4252
  },
4326
4253
  "type": {
4327
4254
  "char": "t",
4328
- "description": "Validate tests by type",
4255
+ "description": "Filter by test type",
4329
4256
  "name": "type",
4330
4257
  "hasDynamicHelp": false,
4331
4258
  "multiple": false,
4332
4259
  "type": "option"
4333
4260
  },
4334
- "save-report": {
4335
- "description": "Save validation report to file",
4336
- "name": "save-report",
4337
- "allowNo": false,
4338
- "type": "boolean"
4261
+ "tag": {
4262
+ "description": "Filter by tag",
4263
+ "name": "tag",
4264
+ "hasDynamicHelp": false,
4265
+ "multiple": false,
4266
+ "type": "option"
4267
+ },
4268
+ "status": {
4269
+ "char": "s",
4270
+ "description": "Filter by status",
4271
+ "name": "status",
4272
+ "hasDynamicHelp": false,
4273
+ "multiple": false,
4274
+ "type": "option"
4339
4275
  },
4340
4276
  "format": {
4341
4277
  "char": "f",
@@ -4369,7 +4305,7 @@
4369
4305
  },
4370
4306
  "hasDynamicHelp": false,
4371
4307
  "hiddenAliases": [],
4372
- "id": "test:validate",
4308
+ "id": "test:list",
4373
4309
  "pluginAlias": "@memberjunction/cli",
4374
4310
  "pluginName": "@memberjunction/cli",
4375
4311
  "pluginType": "core",
@@ -4380,95 +4316,96 @@
4380
4316
  "dist",
4381
4317
  "commands",
4382
4318
  "test",
4383
- "validate.js"
4319
+ "list.js"
4384
4320
  ]
4385
4321
  },
4386
- "translate-sql": {
4322
+ "test:run": {
4387
4323
  "aliases": [],
4388
- "args": {},
4389
- "description": "Translate SQL fragments between database dialects (SQL Server ↔ PostgreSQL)",
4324
+ "args": {
4325
+ "testId": {
4326
+ "description": "Test ID to execute",
4327
+ "name": "testId",
4328
+ "required": false
4329
+ }
4330
+ },
4331
+ "description": "Execute a single test by ID or name",
4390
4332
  "examples": [
4391
- "<%= config.bin %> translate-sql --from sqlserver --to postgresql --dry-run",
4392
- "<%= config.bin %> translate-sql --from sqlserver --to postgresql --scope queries",
4393
- "<%= config.bin %> translate-sql --from sqlserver --to postgresql --sql \"SELECT TOP 10 [Name] FROM [Users]\"",
4394
- "<%= config.bin %> translate-sql --from sqlserver --to postgresql --scope all --output ./reports"
4333
+ "<%= config.bin %> <%= command.id %> <test-id>",
4334
+ "<%= config.bin %> <%= command.id %> --name=\"Active Members Count\"",
4335
+ "<%= config.bin %> <%= command.id %> <test-id> --environment=staging",
4336
+ "<%= config.bin %> <%= command.id %> <test-id> --format=json --output=results.json",
4337
+ "<%= config.bin %> <%= command.id %> <test-id> --dry-run"
4395
4338
  ],
4396
4339
  "flags": {
4397
- "from": {
4398
- "description": "Source SQL dialect",
4399
- "name": "from",
4400
- "required": true,
4340
+ "name": {
4341
+ "char": "n",
4342
+ "description": "Test name to execute",
4343
+ "name": "name",
4401
4344
  "hasDynamicHelp": false,
4402
4345
  "multiple": false,
4403
- "options": [
4404
- "sqlserver",
4405
- "postgresql"
4406
- ],
4407
4346
  "type": "option"
4408
4347
  },
4409
- "to": {
4410
- "description": "Target SQL dialect",
4411
- "name": "to",
4412
- "required": true,
4348
+ "environment": {
4349
+ "char": "e",
4350
+ "description": "Environment context (dev, staging, prod)",
4351
+ "name": "environment",
4413
4352
  "hasDynamicHelp": false,
4414
4353
  "multiple": false,
4415
- "options": [
4416
- "sqlserver",
4417
- "postgresql"
4418
- ],
4419
4354
  "type": "option"
4420
4355
  },
4421
- "scope": {
4422
- "description": "What to scan for translation",
4423
- "name": "scope",
4424
- "default": "all",
4356
+ "format": {
4357
+ "char": "f",
4358
+ "description": "Output format",
4359
+ "name": "format",
4360
+ "default": "console",
4425
4361
  "hasDynamicHelp": false,
4426
4362
  "multiple": false,
4427
4363
  "options": [
4428
- "queries",
4429
- "views",
4430
- "filters",
4431
- "all"
4364
+ "console",
4365
+ "json",
4366
+ "markdown"
4432
4367
  ],
4433
4368
  "type": "option"
4434
4369
  },
4435
- "sql": {
4436
- "description": "Translate a single SQL fragment (inline mode)",
4437
- "name": "sql",
4370
+ "output": {
4371
+ "char": "o",
4372
+ "description": "Output file path",
4373
+ "name": "output",
4438
4374
  "hasDynamicHelp": false,
4439
4375
  "multiple": false,
4440
4376
  "type": "option"
4441
4377
  },
4442
4378
  "dry-run": {
4443
- "description": "Show what would be translated without making changes",
4379
+ "description": "Validate without executing",
4444
4380
  "name": "dry-run",
4445
4381
  "allowNo": false,
4446
4382
  "type": "boolean"
4447
4383
  },
4448
- "review": {
4449
- "description": "Generate review report only (no writes to database)",
4450
- "name": "review",
4384
+ "verbose": {
4385
+ "char": "v",
4386
+ "description": "Show detailed execution information",
4387
+ "name": "verbose",
4451
4388
  "allowNo": false,
4452
4389
  "type": "boolean"
4453
4390
  },
4454
- "output": {
4455
- "char": "o",
4456
- "description": "Output directory for the translation report",
4457
- "name": "output",
4391
+ "checks-module": {
4392
+ "description": "Module specifier (package name or path) side-effect-imported before the run so its integration check bundles register on the IntegrationCheckRegistry. Durable form: mj.config.cjs `testing.checkModules` (this repo loads '@memberjunction/integration-test-suite' that way).",
4393
+ "name": "checks-module",
4458
4394
  "hasDynamicHelp": false,
4459
4395
  "multiple": false,
4460
4396
  "type": "option"
4461
4397
  },
4462
- "force": {
4463
- "description": "Re-translate even if platform variants already exist",
4464
- "name": "force",
4465
- "allowNo": false,
4466
- "type": "boolean"
4398
+ "oracles-module": {
4399
+ "description": "Path to a JS/TS module that exports custom IOracle classes or instances. Each export is registered on the engine before the test runs — used by non-MJ adopters to plug app-specific oracle types without modifying TestingFramework.",
4400
+ "name": "oracles-module",
4401
+ "hasDynamicHelp": false,
4402
+ "multiple": false,
4403
+ "type": "option"
4467
4404
  }
4468
4405
  },
4469
4406
  "hasDynamicHelp": false,
4470
4407
  "hiddenAliases": [],
4471
- "id": "translate-sql",
4408
+ "id": "test:run",
4472
4409
  "pluginAlias": "@memberjunction/cli",
4473
4410
  "pluginName": "@memberjunction/cli",
4474
4411
  "pluginType": "core",
@@ -4478,176 +4415,113 @@
4478
4415
  "relativePath": [
4479
4416
  "dist",
4480
4417
  "commands",
4481
- "translate-sql",
4482
- "index.js"
4418
+ "test",
4419
+ "run.js"
4483
4420
  ]
4484
4421
  },
4485
- "update:claude": {
4422
+ "test:suite": {
4486
4423
  "aliases": [],
4487
- "args": {},
4488
- "description": "Update the Claude Code pack in the current directory.",
4424
+ "args": {
4425
+ "suiteId": {
4426
+ "description": "Test suite ID to execute",
4427
+ "name": "suiteId",
4428
+ "required": false
4429
+ }
4430
+ },
4431
+ "description": "Execute a test suite",
4489
4432
  "examples": [
4490
- "<%= config.bin %> update:claude",
4491
- "<%= config.bin %> update:claude --check",
4492
- "<%= config.bin %> update:claude --refresh-commands",
4493
- "<%= config.bin %> update:claude --allow-major",
4494
- "<%= config.bin %> update:claude --json"
4433
+ "<%= config.bin %> <%= command.id %> <suite-id>",
4434
+ "<%= config.bin %> <%= command.id %> --name=\"Agent Quality Suite\"",
4435
+ "<%= config.bin %> <%= command.id %> <suite-id> --format=json",
4436
+ "<%= config.bin %> <%= command.id %> <suite-id> --output=suite-results.json"
4495
4437
  ],
4496
4438
  "flags": {
4497
- "dir": {
4498
- "description": "Target directory",
4499
- "name": "dir",
4500
- "default": ".",
4501
- "hasDynamicHelp": false,
4502
- "multiple": false,
4503
- "type": "option"
4504
- },
4505
- "major": {
4506
- "description": "Force a specific MJ major (default: detected from package.json)",
4507
- "name": "major",
4439
+ "name": {
4440
+ "char": "n",
4441
+ "description": "Test suite name to execute",
4442
+ "name": "name",
4508
4443
  "hasDynamicHelp": false,
4509
4444
  "multiple": false,
4510
4445
  "type": "option"
4511
4446
  },
4512
- "ref": {
4513
- "description": "Git ref to fetch from (branch or tag). Default: main.",
4514
- "name": "ref",
4447
+ "format": {
4448
+ "char": "f",
4449
+ "description": "Output format",
4450
+ "name": "format",
4451
+ "default": "console",
4515
4452
  "hasDynamicHelp": false,
4516
4453
  "multiple": false,
4454
+ "options": [
4455
+ "console",
4456
+ "json",
4457
+ "markdown"
4458
+ ],
4517
4459
  "type": "option"
4518
4460
  },
4519
- "from": {
4520
- "description": "Use a local pack source instead of fetching from GitHub",
4521
- "name": "from",
4461
+ "output": {
4462
+ "char": "o",
4463
+ "description": "Output file path",
4464
+ "name": "output",
4522
4465
  "hasDynamicHelp": false,
4523
4466
  "multiple": false,
4524
4467
  "type": "option"
4525
4468
  },
4526
- "offline": {
4527
- "description": "Forbid network; requires --from <path>",
4528
- "name": "offline",
4529
- "allowNo": false,
4530
- "type": "boolean"
4531
- },
4532
- "dry-run": {
4533
- "description": "Print what would be written; change nothing",
4534
- "name": "dry-run",
4535
- "allowNo": false,
4536
- "type": "boolean"
4537
- },
4538
- "yes": {
4539
- "char": "y",
4540
- "description": "Don't prompt (reserved for future interactive paths; currently no-op)",
4541
- "name": "yes",
4542
- "allowNo": false,
4543
- "type": "boolean"
4544
- },
4545
- "force": {
4546
- "description": "Overwrite user-customized commands/skills (saves .bak files)",
4547
- "name": "force",
4548
- "allowNo": false,
4549
- "type": "boolean"
4550
- },
4551
- "skip-commands": {
4552
- "description": "Skip seeding .claude/commands/",
4553
- "name": "skip-commands",
4554
- "allowNo": false,
4555
- "type": "boolean"
4556
- },
4557
- "skip-skills": {
4558
- "description": "Skip seeding .claude/skills/",
4559
- "name": "skip-skills",
4560
- "allowNo": false,
4561
- "type": "boolean"
4562
- },
4563
- "skip-settings": {
4564
- "description": "Skip merging .claude/settings.json",
4565
- "name": "skip-settings",
4469
+ "verbose": {
4470
+ "char": "v",
4471
+ "description": "Show detailed execution information",
4472
+ "name": "verbose",
4566
4473
  "allowNo": false,
4567
4474
  "type": "boolean"
4568
4475
  },
4569
- "check": {
4570
- "description": "Compare local pack version to remote without writing anything",
4571
- "name": "check",
4572
- "allowNo": false,
4573
- "type": "boolean"
4476
+ "delay": {
4477
+ "char": "d",
4478
+ "description": "Delay in milliseconds between test executions (avoids Auth0 rate limits)",
4479
+ "name": "delay",
4480
+ "default": 0,
4481
+ "hasDynamicHelp": false,
4482
+ "multiple": false,
4483
+ "type": "option"
4574
4484
  },
4575
- "refresh-commands": {
4576
- "description": "Force-resync .claude/commands/* from the pack (saves .bak files)",
4577
- "name": "refresh-commands",
4485
+ "parallel": {
4486
+ "char": "p",
4487
+ "description": "Run tests in parallel with shared browser sessions",
4488
+ "name": "parallel",
4578
4489
  "allowNo": false,
4579
4490
  "type": "boolean"
4580
4491
  },
4581
- "refresh-skills": {
4582
- "description": "Force-resync .claude/skills/** from the pack (saves .bak files)",
4583
- "name": "refresh-skills",
4584
- "allowNo": false,
4585
- "type": "boolean"
4492
+ "max-parallel": {
4493
+ "description": "Maximum number of parallel workers (default 4)",
4494
+ "name": "max-parallel",
4495
+ "default": 4,
4496
+ "hasDynamicHelp": false,
4497
+ "multiple": false,
4498
+ "type": "option"
4586
4499
  },
4587
- "allow-major": {
4588
- "description": "Allow the remote pack's major to differ from local MJ's major",
4589
- "name": "allow-major",
4590
- "allowNo": false,
4591
- "type": "boolean"
4500
+ "flaky-check": {
4501
+ "description": "Run each test N times to detect flakiness (variance > 0.3 or mixed pass/fail = flaky). Recommended: 3 or 5",
4502
+ "name": "flaky-check",
4503
+ "hasDynamicHelp": false,
4504
+ "multiple": false,
4505
+ "type": "option"
4592
4506
  },
4593
- "json": {
4594
- "description": "Output as JSON (matches plan §7.5 schema)",
4595
- "name": "json",
4596
- "allowNo": false,
4597
- "type": "boolean"
4507
+ "checks-module": {
4508
+ "description": "Module specifier (package name or path) side-effect-imported before the run so its integration check bundles register on the IntegrationCheckRegistry. Durable form: mj.config.cjs `testing.checkModules` (this repo loads '@memberjunction/integration-test-suite' that way).",
4509
+ "name": "checks-module",
4510
+ "hasDynamicHelp": false,
4511
+ "multiple": false,
4512
+ "type": "option"
4598
4513
  },
4599
- "verbose": {
4600
- "char": "v",
4601
- "description": "Show progress messages",
4602
- "name": "verbose",
4603
- "allowNo": false,
4604
- "type": "boolean"
4605
- }
4606
- },
4607
- "hasDynamicHelp": false,
4608
- "hiddenAliases": [],
4609
- "id": "update:claude",
4610
- "pluginAlias": "@memberjunction/cli",
4611
- "pluginName": "@memberjunction/cli",
4612
- "pluginType": "core",
4613
- "strict": true,
4614
- "enableJsonFlag": false,
4615
- "isESM": true,
4616
- "relativePath": [
4617
- "dist",
4618
- "commands",
4619
- "update",
4620
- "claude.js"
4621
- ]
4622
- },
4623
- "ai:actions:list": {
4624
- "aliases": [],
4625
- "args": {},
4626
- "description": "List available AI actions",
4627
- "examples": [
4628
- "<%= config.bin %> <%= command.id %>",
4629
- "<%= config.bin %> <%= command.id %> --output=table",
4630
- "<%= config.bin %> <%= command.id %> --output=json"
4631
- ],
4632
- "flags": {
4633
- "output": {
4634
- "char": "o",
4635
- "description": "Output format",
4636
- "name": "output",
4637
- "default": "compact",
4514
+ "oracles-module": {
4515
+ "description": "Path to a JS/TS module that exports custom IOracle classes or instances. Each export is registered on the engine before the suite runs — used by non-MJ adopters to plug app-specific oracle types without modifying TestingFramework.",
4516
+ "name": "oracles-module",
4638
4517
  "hasDynamicHelp": false,
4639
4518
  "multiple": false,
4640
- "options": [
4641
- "compact",
4642
- "json",
4643
- "table"
4644
- ],
4645
4519
  "type": "option"
4646
4520
  }
4647
4521
  },
4648
4522
  "hasDynamicHelp": false,
4649
4523
  "hiddenAliases": [],
4650
- "id": "ai:actions:list",
4524
+ "id": "test:suite",
4651
4525
  "pluginAlias": "@memberjunction/cli",
4652
4526
  "pluginName": "@memberjunction/cli",
4653
4527
  "pluginType": "core",
@@ -4657,78 +4531,82 @@
4657
4531
  "relativePath": [
4658
4532
  "dist",
4659
4533
  "commands",
4660
- "ai",
4661
- "actions",
4662
- "list.js"
4534
+ "test",
4535
+ "suite.js"
4663
4536
  ]
4664
4537
  },
4665
- "ai:actions:run": {
4538
+ "test:validate": {
4666
4539
  "aliases": [],
4667
- "args": {},
4668
- "description": "Execute an AI action with parameters",
4669
- "examples": [
4670
- "<%= config.bin %> <%= command.id %> -n \"Get Weather\" --param \"Location=Boston\"",
4671
- "<%= config.bin %> <%= command.id %> -n \"Get Stock Price\" --param \"Ticker=AAPL\"",
4672
- "<%= config.bin %> <%= command.id %> -n \"Send Single Message\" --param \"To=user@example.com\" --param \"Subject=Test\" --param \"Body=Hello\" --param \"MessageType=Email\" --param \"Provider=SendGrid\"",
4673
- "<%= config.bin %> <%= command.id %> -n \"Calculate Expression\" --param \"Expression=2+2*3\" --dry-run"
4540
+ "args": {
4541
+ "testId": {
4542
+ "description": "Test ID to validate",
4543
+ "name": "testId",
4544
+ "required": false
4545
+ }
4546
+ },
4547
+ "description": "Validate test definitions without executing",
4548
+ "examples": [
4549
+ "<%= config.bin %> <%= command.id %> <test-id>",
4550
+ "<%= config.bin %> <%= command.id %> --all",
4551
+ "<%= config.bin %> <%= command.id %> --type=agent-eval",
4552
+ "<%= config.bin %> <%= command.id %> --all --save-report",
4553
+ "<%= config.bin %> <%= command.id %> --all --output=validation-report.md"
4674
4554
  ],
4675
4555
  "flags": {
4676
- "name": {
4677
- "char": "n",
4678
- "description": "Action name",
4679
- "name": "name",
4680
- "required": true,
4681
- "hasDynamicHelp": false,
4682
- "multiple": false,
4683
- "type": "option"
4556
+ "all": {
4557
+ "char": "a",
4558
+ "description": "Validate all tests",
4559
+ "name": "all",
4560
+ "allowNo": false,
4561
+ "type": "boolean"
4684
4562
  },
4685
- "param": {
4686
- "char": "p",
4687
- "description": "Action parameters in key=value format",
4688
- "name": "param",
4563
+ "type": {
4564
+ "char": "t",
4565
+ "description": "Validate tests by type",
4566
+ "name": "type",
4689
4567
  "hasDynamicHelp": false,
4690
- "multiple": true,
4568
+ "multiple": false,
4691
4569
  "type": "option"
4692
4570
  },
4693
- "dry-run": {
4694
- "description": "Validate without executing",
4695
- "name": "dry-run",
4571
+ "save-report": {
4572
+ "description": "Save validation report to file",
4573
+ "name": "save-report",
4696
4574
  "allowNo": false,
4697
4575
  "type": "boolean"
4698
4576
  },
4699
- "output": {
4700
- "char": "o",
4577
+ "format": {
4578
+ "char": "f",
4701
4579
  "description": "Output format",
4702
- "name": "output",
4703
- "default": "compact",
4580
+ "name": "format",
4581
+ "default": "console",
4704
4582
  "hasDynamicHelp": false,
4705
4583
  "multiple": false,
4706
4584
  "options": [
4707
- "compact",
4585
+ "console",
4708
4586
  "json",
4709
- "table"
4587
+ "markdown"
4710
4588
  ],
4711
4589
  "type": "option"
4712
4590
  },
4591
+ "output": {
4592
+ "char": "o",
4593
+ "description": "Output file path",
4594
+ "name": "output",
4595
+ "hasDynamicHelp": false,
4596
+ "multiple": false,
4597
+ "type": "option"
4598
+ },
4713
4599
  "verbose": {
4714
4600
  "char": "v",
4715
- "description": "Show detailed execution information",
4601
+ "description": "Show detailed information",
4716
4602
  "name": "verbose",
4717
4603
  "allowNo": false,
4718
4604
  "type": "boolean"
4719
- },
4720
- "timeout": {
4721
- "description": "Execution timeout in milliseconds",
4722
- "name": "timeout",
4723
- "default": 300000,
4724
- "hasDynamicHelp": false,
4725
- "multiple": false,
4726
- "type": "option"
4727
4605
  }
4728
4606
  },
4729
4607
  "hasDynamicHelp": false,
4730
4608
  "hiddenAliases": [],
4731
- "id": "ai:actions:run",
4609
+ "id": "test:validate",
4732
4610
  "pluginAlias": "@memberjunction/cli",
4733
4611
  "pluginName": "@memberjunction/cli",
4734
4612
  "pluginType": "core",
@@ -4738,15 +4616,14 @@
4738
4616
  "relativePath": [
4739
4617
  "dist",
4740
4618
  "commands",
4741
- "ai",
4742
- "actions",
4743
- "run.js"
4619
+ "test",
4620
+ "validate.js"
4744
4621
  ]
4745
4622
  },
4746
- "ai:agents:list": {
4623
+ "ai:actions:list": {
4747
4624
  "aliases": [],
4748
4625
  "args": {},
4749
- "description": "List available AI agents",
4626
+ "description": "List available AI actions",
4750
4627
  "examples": [
4751
4628
  "<%= config.bin %> <%= command.id %>",
4752
4629
  "<%= config.bin %> <%= command.id %> --output=table",
@@ -4770,7 +4647,7 @@
4770
4647
  },
4771
4648
  "hasDynamicHelp": false,
4772
4649
  "hiddenAliases": [],
4773
- "id": "ai:agents:list",
4650
+ "id": "ai:actions:list",
4774
4651
  "pluginAlias": "@memberjunction/cli",
4775
4652
  "pluginName": "@memberjunction/cli",
4776
4653
  "pluginType": "core",
@@ -4781,47 +4658,41 @@
4781
4658
  "dist",
4782
4659
  "commands",
4783
4660
  "ai",
4784
- "agents",
4661
+ "actions",
4785
4662
  "list.js"
4786
4663
  ]
4787
4664
  },
4788
- "ai:agents:run": {
4665
+ "ai:actions:run": {
4789
4666
  "aliases": [],
4790
4667
  "args": {},
4791
- "description": "Execute an AI agent with a prompt or start interactive chat",
4668
+ "description": "Execute an AI action with parameters",
4792
4669
  "examples": [
4793
- "<%= config.bin %> <%= command.id %> -a \"Skip: Requirements Expert\" -p \"Create a dashboard for sales metrics\"",
4794
- "<%= config.bin %> <%= command.id %> -a \"Child Component Generator Sub-agent\" --chat",
4795
- "<%= config.bin %> <%= command.id %> -a \"Skip: Technical Design Expert\" -p \"Build a React component\" --verbose --timeout=600000"
4670
+ "<%= config.bin %> <%= command.id %> -n \"Get Weather\" --param \"Location=Boston\"",
4671
+ "<%= config.bin %> <%= command.id %> -n \"Get Stock Price\" --param \"Ticker=AAPL\"",
4672
+ "<%= config.bin %> <%= command.id %> -n \"Send Single Message\" --param \"To=user@example.com\" --param \"Subject=Test\" --param \"Body=Hello\" --param \"MessageType=Email\" --param \"Provider=SendGrid\"",
4673
+ "<%= config.bin %> <%= command.id %> -n \"Calculate Expression\" --param \"Expression=2+2*3\" --dry-run"
4796
4674
  ],
4797
4675
  "flags": {
4798
- "agent": {
4799
- "char": "a",
4800
- "description": "Agent name",
4801
- "name": "agent",
4676
+ "name": {
4677
+ "char": "n",
4678
+ "description": "Action name",
4679
+ "name": "name",
4802
4680
  "required": true,
4803
4681
  "hasDynamicHelp": false,
4804
4682
  "multiple": false,
4805
4683
  "type": "option"
4806
4684
  },
4807
- "prompt": {
4685
+ "param": {
4808
4686
  "char": "p",
4809
- "description": "Prompt to execute",
4810
- "exclusive": [
4811
- "chat"
4812
- ],
4813
- "name": "prompt",
4687
+ "description": "Action parameters in key=value format",
4688
+ "name": "param",
4814
4689
  "hasDynamicHelp": false,
4815
- "multiple": false,
4690
+ "multiple": true,
4816
4691
  "type": "option"
4817
4692
  },
4818
- "chat": {
4819
- "char": "c",
4820
- "description": "Start interactive chat mode",
4821
- "exclusive": [
4822
- "prompt"
4823
- ],
4824
- "name": "chat",
4693
+ "dry-run": {
4694
+ "description": "Validate without executing",
4695
+ "name": "dry-run",
4825
4696
  "allowNo": false,
4826
4697
  "type": "boolean"
4827
4698
  },
@@ -4857,7 +4728,7 @@
4857
4728
  },
4858
4729
  "hasDynamicHelp": false,
4859
4730
  "hiddenAliases": [],
4860
- "id": "ai:agents:run",
4731
+ "id": "ai:actions:run",
4861
4732
  "pluginAlias": "@memberjunction/cli",
4862
4733
  "pluginName": "@memberjunction/cli",
4863
4734
  "pluginType": "core",
@@ -4868,7 +4739,7 @@
4868
4739
  "dist",
4869
4740
  "commands",
4870
4741
  "ai",
4871
- "agents",
4742
+ "actions",
4872
4743
  "run.js"
4873
4744
  ]
4874
4745
  },
@@ -5088,6 +4959,135 @@
5088
4959
  "index.js"
5089
4960
  ]
5090
4961
  },
4962
+ "ai:agents:list": {
4963
+ "aliases": [],
4964
+ "args": {},
4965
+ "description": "List available AI agents",
4966
+ "examples": [
4967
+ "<%= config.bin %> <%= command.id %>",
4968
+ "<%= config.bin %> <%= command.id %> --output=table",
4969
+ "<%= config.bin %> <%= command.id %> --output=json"
4970
+ ],
4971
+ "flags": {
4972
+ "output": {
4973
+ "char": "o",
4974
+ "description": "Output format",
4975
+ "name": "output",
4976
+ "default": "compact",
4977
+ "hasDynamicHelp": false,
4978
+ "multiple": false,
4979
+ "options": [
4980
+ "compact",
4981
+ "json",
4982
+ "table"
4983
+ ],
4984
+ "type": "option"
4985
+ }
4986
+ },
4987
+ "hasDynamicHelp": false,
4988
+ "hiddenAliases": [],
4989
+ "id": "ai:agents:list",
4990
+ "pluginAlias": "@memberjunction/cli",
4991
+ "pluginName": "@memberjunction/cli",
4992
+ "pluginType": "core",
4993
+ "strict": true,
4994
+ "enableJsonFlag": false,
4995
+ "isESM": true,
4996
+ "relativePath": [
4997
+ "dist",
4998
+ "commands",
4999
+ "ai",
5000
+ "agents",
5001
+ "list.js"
5002
+ ]
5003
+ },
5004
+ "ai:agents:run": {
5005
+ "aliases": [],
5006
+ "args": {},
5007
+ "description": "Execute an AI agent with a prompt or start interactive chat",
5008
+ "examples": [
5009
+ "<%= config.bin %> <%= command.id %> -a \"Skip: Requirements Expert\" -p \"Create a dashboard for sales metrics\"",
5010
+ "<%= config.bin %> <%= command.id %> -a \"Child Component Generator Sub-agent\" --chat",
5011
+ "<%= config.bin %> <%= command.id %> -a \"Skip: Technical Design Expert\" -p \"Build a React component\" --verbose --timeout=600000"
5012
+ ],
5013
+ "flags": {
5014
+ "agent": {
5015
+ "char": "a",
5016
+ "description": "Agent name",
5017
+ "name": "agent",
5018
+ "required": true,
5019
+ "hasDynamicHelp": false,
5020
+ "multiple": false,
5021
+ "type": "option"
5022
+ },
5023
+ "prompt": {
5024
+ "char": "p",
5025
+ "description": "Prompt to execute",
5026
+ "exclusive": [
5027
+ "chat"
5028
+ ],
5029
+ "name": "prompt",
5030
+ "hasDynamicHelp": false,
5031
+ "multiple": false,
5032
+ "type": "option"
5033
+ },
5034
+ "chat": {
5035
+ "char": "c",
5036
+ "description": "Start interactive chat mode",
5037
+ "exclusive": [
5038
+ "prompt"
5039
+ ],
5040
+ "name": "chat",
5041
+ "allowNo": false,
5042
+ "type": "boolean"
5043
+ },
5044
+ "output": {
5045
+ "char": "o",
5046
+ "description": "Output format",
5047
+ "name": "output",
5048
+ "default": "compact",
5049
+ "hasDynamicHelp": false,
5050
+ "multiple": false,
5051
+ "options": [
5052
+ "compact",
5053
+ "json",
5054
+ "table"
5055
+ ],
5056
+ "type": "option"
5057
+ },
5058
+ "verbose": {
5059
+ "char": "v",
5060
+ "description": "Show detailed execution information",
5061
+ "name": "verbose",
5062
+ "allowNo": false,
5063
+ "type": "boolean"
5064
+ },
5065
+ "timeout": {
5066
+ "description": "Execution timeout in milliseconds",
5067
+ "name": "timeout",
5068
+ "default": 300000,
5069
+ "hasDynamicHelp": false,
5070
+ "multiple": false,
5071
+ "type": "option"
5072
+ }
5073
+ },
5074
+ "hasDynamicHelp": false,
5075
+ "hiddenAliases": [],
5076
+ "id": "ai:agents:run",
5077
+ "pluginAlias": "@memberjunction/cli",
5078
+ "pluginName": "@memberjunction/cli",
5079
+ "pluginType": "core",
5080
+ "strict": true,
5081
+ "enableJsonFlag": false,
5082
+ "isESM": true,
5083
+ "relativePath": [
5084
+ "dist",
5085
+ "commands",
5086
+ "ai",
5087
+ "agents",
5088
+ "run.js"
5089
+ ]
5090
+ },
5091
5091
  "ai:prompts:list": {
5092
5092
  "aliases": [],
5093
5093
  "args": {},
@@ -5668,5 +5668,5 @@
5668
5668
  ]
5669
5669
  }
5670
5670
  },
5671
- "version": "6.1.0-edge.0"
5671
+ "version": "6.1.0-edge.2"
5672
5672
  }