@memberjunction/cli 5.37.0 → 5.38.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (150) hide show
  1. package/README.md +74 -0
  2. package/dist/baseline/cli-helpers.d.ts +12 -0
  3. package/dist/baseline/cli-helpers.d.ts.map +1 -0
  4. package/dist/baseline/cli-helpers.js +40 -0
  5. package/dist/baseline/cli-helpers.js.map +1 -0
  6. package/dist/baseline/comparator.d.ts +26 -0
  7. package/dist/baseline/comparator.d.ts.map +1 -0
  8. package/dist/baseline/comparator.js +527 -0
  9. package/dist/baseline/comparator.js.map +1 -0
  10. package/dist/baseline/connection.d.ts +39 -0
  11. package/dist/baseline/connection.d.ts.map +1 -0
  12. package/dist/baseline/connection.js +104 -0
  13. package/dist/baseline/connection.js.map +1 -0
  14. package/dist/baseline/data-dumper.d.ts +23 -0
  15. package/dist/baseline/data-dumper.d.ts.map +1 -0
  16. package/dist/baseline/data-dumper.js +94 -0
  17. package/dist/baseline/data-dumper.js.map +1 -0
  18. package/dist/baseline/emitter.d.ts +36 -0
  19. package/dist/baseline/emitter.d.ts.map +1 -0
  20. package/dist/baseline/emitter.js +512 -0
  21. package/dist/baseline/emitter.js.map +1 -0
  22. package/dist/baseline/index.d.ts +18 -0
  23. package/dist/baseline/index.d.ts.map +1 -0
  24. package/dist/baseline/index.js +14 -0
  25. package/dist/baseline/index.js.map +1 -0
  26. package/dist/baseline/introspector-mssql.d.ts +15 -0
  27. package/dist/baseline/introspector-mssql.d.ts.map +1 -0
  28. package/dist/baseline/introspector-mssql.js +673 -0
  29. package/dist/baseline/introspector-mssql.js.map +1 -0
  30. package/dist/baseline/introspector-postgres.d.ts +14 -0
  31. package/dist/baseline/introspector-postgres.d.ts.map +1 -0
  32. package/dist/baseline/introspector-postgres.js +277 -0
  33. package/dist/baseline/introspector-postgres.js.map +1 -0
  34. package/dist/baseline/report.d.ts +7 -0
  35. package/dist/baseline/report.d.ts.map +1 -0
  36. package/dist/baseline/report.js +105 -0
  37. package/dist/baseline/report.js.map +1 -0
  38. package/dist/baseline/types.d.ts +286 -0
  39. package/dist/baseline/types.d.ts.map +1 -0
  40. package/dist/baseline/types.js +10 -0
  41. package/dist/baseline/types.js.map +1 -0
  42. package/dist/baseline/util.d.ts +112 -0
  43. package/dist/baseline/util.d.ts.map +1 -0
  44. package/dist/baseline/util.js +325 -0
  45. package/dist/baseline/util.js.map +1 -0
  46. package/dist/commands/baseline/build.d.ts +29 -0
  47. package/dist/commands/baseline/build.d.ts.map +1 -0
  48. package/dist/commands/baseline/build.js +188 -0
  49. package/dist/commands/baseline/build.js.map +1 -0
  50. package/dist/commands/baseline/compare.d.ts +19 -0
  51. package/dist/commands/baseline/compare.d.ts.map +1 -0
  52. package/dist/commands/baseline/compare.js +133 -0
  53. package/dist/commands/baseline/compare.js.map +1 -0
  54. package/dist/commands/baseline/roundtrip.d.ts +23 -0
  55. package/dist/commands/baseline/roundtrip.d.ts.map +1 -0
  56. package/dist/commands/baseline/roundtrip.js +245 -0
  57. package/dist/commands/baseline/roundtrip.js.map +1 -0
  58. package/dist/commands/test/compare.d.ts +3 -0
  59. package/dist/commands/test/compare.d.ts.map +1 -1
  60. package/dist/commands/test/compare.js +23 -3
  61. package/dist/commands/test/compare.js.map +1 -1
  62. package/dist/commands/test/regression/build.d.ts +14 -0
  63. package/dist/commands/test/regression/build.d.ts.map +1 -0
  64. package/dist/commands/test/regression/build.js +48 -0
  65. package/dist/commands/test/regression/build.js.map +1 -0
  66. package/dist/commands/test/regression/compare.d.ts +15 -0
  67. package/dist/commands/test/regression/compare.d.ts.map +1 -0
  68. package/dist/commands/test/regression/compare.js +66 -0
  69. package/dist/commands/test/regression/compare.js.map +1 -0
  70. package/dist/commands/test/regression/down.d.ts +10 -0
  71. package/dist/commands/test/regression/down.d.ts.map +1 -0
  72. package/dist/commands/test/regression/down.js +29 -0
  73. package/dist/commands/test/regression/down.js.map +1 -0
  74. package/dist/commands/test/regression/export.d.ts +11 -0
  75. package/dist/commands/test/regression/export.d.ts.map +1 -0
  76. package/dist/commands/test/regression/export.js +56 -0
  77. package/dist/commands/test/regression/export.js.map +1 -0
  78. package/dist/commands/test/regression/gen-forms.d.ts +7 -0
  79. package/dist/commands/test/regression/gen-forms.d.ts.map +1 -0
  80. package/dist/commands/test/regression/gen-forms.js +18 -0
  81. package/dist/commands/test/regression/gen-forms.js.map +1 -0
  82. package/dist/commands/test/regression/index.d.ts +7 -0
  83. package/dist/commands/test/regression/index.d.ts.map +1 -0
  84. package/dist/commands/test/regression/index.js +33 -0
  85. package/dist/commands/test/regression/index.js.map +1 -0
  86. package/dist/commands/test/regression/init.d.ts +21 -0
  87. package/dist/commands/test/regression/init.d.ts.map +1 -0
  88. package/dist/commands/test/regression/init.js +111 -0
  89. package/dist/commands/test/regression/init.js.map +1 -0
  90. package/dist/commands/test/regression/remote.d.ts +23 -0
  91. package/dist/commands/test/regression/remote.d.ts.map +1 -0
  92. package/dist/commands/test/regression/remote.js +140 -0
  93. package/dist/commands/test/regression/remote.js.map +1 -0
  94. package/dist/commands/test/regression/up.d.ts +21 -0
  95. package/dist/commands/test/regression/up.d.ts.map +1 -0
  96. package/dist/commands/test/regression/up.js +111 -0
  97. package/dist/commands/test/regression/up.js.map +1 -0
  98. package/dist/commands/test/run.d.ts +1 -0
  99. package/dist/commands/test/run.d.ts.map +1 -1
  100. package/dist/commands/test/run.js +6 -0
  101. package/dist/commands/test/run.js.map +1 -1
  102. package/dist/commands/test/suite.d.ts +5 -0
  103. package/dist/commands/test/suite.d.ts.map +1 -1
  104. package/dist/commands/test/suite.js +27 -0
  105. package/dist/commands/test/suite.js.map +1 -1
  106. package/dist/commands/translate-sql/index.d.ts.map +1 -1
  107. package/dist/commands/translate-sql/index.js +3 -2
  108. package/dist/commands/translate-sql/index.js.map +1 -1
  109. package/dist/init-templates/bring-your-own-app/README.md +74 -0
  110. package/dist/init-templates/bring-your-own-app/byo-metadata/.mj-sync.json +10 -0
  111. package/dist/init-templates/bring-your-own-app/byo-metadata/test-suites/.byo-suite.json +51 -0
  112. package/dist/init-templates/bring-your-own-app/byo-metadata/test-suites/.mj-sync.json +12 -0
  113. package/dist/init-templates/bring-your-own-app/byo-metadata/tests/.T01-counter-increment.json +63 -0
  114. package/dist/init-templates/bring-your-own-app/byo-metadata/tests/.T02-contact-form-submit.json +63 -0
  115. package/dist/init-templates/bring-your-own-app/byo-metadata/tests/.mj-sync.json +12 -0
  116. package/dist/init-templates/bring-your-own-app/docker-compose.app.yml +76 -0
  117. package/dist/init-templates/bring-your-own-app/target.json +23 -0
  118. package/dist/init-templates/generic-web/README.md +115 -0
  119. package/dist/init-templates/generic-web/metadata/.mj-sync.json +10 -0
  120. package/dist/init-templates/generic-web/metadata/test-suites/.generic-web-suite.json +48 -0
  121. package/dist/init-templates/generic-web/metadata/test-suites/.mj-sync.json +12 -0
  122. package/dist/init-templates/generic-web/metadata/tests/.GW01-home-loads.json +74 -0
  123. package/dist/init-templates/generic-web/metadata/tests/.GW02-search-array-map.json +82 -0
  124. package/dist/init-templates/generic-web/metadata/tests/.mj-sync.json +12 -0
  125. package/dist/init-templates/generic-web/oracles/mdn-oracles.cjs +121 -0
  126. package/dist/init-templates/generic-web/target.json +25 -0
  127. package/dist/init-templates/github-actions/README.md +26 -0
  128. package/dist/init-templates/github-actions/regression.yml +52 -0
  129. package/dist/init-templates/remote-mj/README.md +95 -0
  130. package/dist/init-templates/remote-mj/target.json +22 -0
  131. package/dist/init-templates/static-file-server/Dockerfile +23 -0
  132. package/dist/init-templates/static-file-server/README.md +88 -0
  133. package/dist/init-templates/static-file-server/docker-compose.app.yml +44 -0
  134. package/dist/init-templates/static-file-server/metadata/.mj-sync.json +10 -0
  135. package/dist/init-templates/static-file-server/metadata/test-suites/.mj-sync.json +12 -0
  136. package/dist/init-templates/static-file-server/metadata/test-suites/.static-server-suite.json +27 -0
  137. package/dist/init-templates/static-file-server/metadata/tests/.SS01-home-loads.json +45 -0
  138. package/dist/init-templates/static-file-server/metadata/tests/.SS02-navigate-about.json +45 -0
  139. package/dist/init-templates/static-file-server/metadata/tests/.mj-sync.json +12 -0
  140. package/dist/init-templates/static-file-server/public/about.html +12 -0
  141. package/dist/init-templates/static-file-server/public/index.html +27 -0
  142. package/dist/init-templates/static-file-server/target.json +16 -0
  143. package/dist/lib/regression/docker-helpers.d.ts +98 -0
  144. package/dist/lib/regression/docker-helpers.d.ts.map +1 -0
  145. package/dist/lib/regression/docker-helpers.js +184 -0
  146. package/dist/lib/regression/docker-helpers.js.map +1 -0
  147. package/oclif.manifest.json +1356 -509
  148. package/package.json +22 -17
  149. package/regression-compose/docker-compose.bacpac-standalone.yml +109 -0
  150. package/regression-compose/docker-compose.standalone.yml +50 -0
@@ -338,65 +338,92 @@
338
338
  "upgrade.js"
339
339
  ]
340
340
  },
341
- "bump": {
341
+ "baseline:build": {
342
342
  "aliases": [],
343
343
  "args": {},
344
- "description": "Bumps MemberJunction dependency versions",
344
+ "description": "Generate a deterministic baseline SQL script from the END-STATE of a migrated MSSQL database.",
345
345
  "examples": [
346
- {
347
- "command": "<%= config.bin %> <%= command.id %>",
348
- "description": "Bump all @memberjunction/* dependencies in the current directory's package.json to the CLI version"
349
- },
350
- {
351
- "command": "<%= config.bin %> <%= command.id %> -rdv",
352
- "description": "Preview all recursive packages bumps without writing any changes."
353
- },
354
- {
355
- "command": "<%= config.bin %> <%= command.id %> -rqt v2.10.0 | xargs -n1 -I{} npm install --prefix {}",
356
- "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."
357
- }
346
+ "<%= config.bin %> <%= command.id %> --out ./migrations/v5/ # auto: within-major rebaseline",
347
+ "<%= config.bin %> <%= command.id %> --source-dir ./migrations/v5 --out ./migrations/v5/",
348
+ "<%= config.bin %> <%= command.id %> --baseline-version 6.0 --out ./migrations/v6/ # explicit major-boundary",
349
+ "<%= config.bin %> <%= command.id %> --baseline-version 5.32 --database MJ_BL_Stack --out /tmp/baseline/"
358
350
  ],
359
351
  "flags": {
360
- "verbose": {
361
- "char": "v",
362
- "description": "Enable additional logging",
363
- "name": "verbose",
364
- "allowNo": false,
365
- "type": "boolean"
352
+ "baseline-version": {
353
+ "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).",
354
+ "name": "baseline-version",
355
+ "hasDynamicHelp": false,
356
+ "multiple": false,
357
+ "type": "option"
366
358
  },
367
- "recursive": {
368
- "char": "r",
369
- "description": "Bump version in current directory and all subdirectories",
370
- "name": "recursive",
371
- "allowNo": false,
372
- "type": "boolean"
359
+ "source-dir": {
360
+ "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.",
361
+ "name": "source-dir",
362
+ "hasDynamicHelp": false,
363
+ "multiple": false,
364
+ "type": "option"
373
365
  },
374
- "tag": {
375
- "char": "t",
376
- "description": "Version tag to bump target for bump (e.g. v2.10.0), defaults to the CLI version",
377
- "name": "tag",
366
+ "description": {
367
+ "description": "Human-readable description embedded in the file header.",
368
+ "name": "description",
369
+ "default": "MemberJunction Baseline",
378
370
  "hasDynamicHelp": false,
379
371
  "multiple": false,
380
372
  "type": "option"
381
373
  },
382
- "quiet": {
383
- "char": "q",
384
- "description": "Only output paths for updated packages",
385
- "name": "quiet",
374
+ "database": {
375
+ "description": "Override database name (host/user/password come from MJ config).",
376
+ "name": "database",
377
+ "hasDynamicHelp": false,
378
+ "multiple": false,
379
+ "type": "option"
380
+ },
381
+ "out": {
382
+ "description": "Output directory. Filename is auto-generated.",
383
+ "name": "out",
384
+ "default": ".",
385
+ "hasDynamicHelp": false,
386
+ "multiple": false,
387
+ "type": "option"
388
+ },
389
+ "exclude-data": {
390
+ "description": "Comma-separated list of tables (schema-qualified or not) to skip data dump for.",
391
+ "name": "exclude-data",
392
+ "default": "",
393
+ "hasDynamicHelp": false,
394
+ "multiple": false,
395
+ "type": "option"
396
+ },
397
+ "batch-size": {
398
+ "description": "Rows per INSERT batch.",
399
+ "name": "batch-size",
400
+ "default": 1000,
401
+ "hasDynamicHelp": false,
402
+ "multiple": false,
403
+ "type": "option"
404
+ },
405
+ "no-data": {
406
+ "description": "Emit schema only, no data inserts.",
407
+ "name": "no-data",
386
408
  "allowNo": false,
387
409
  "type": "boolean"
388
410
  },
389
- "dry": {
390
- "char": "d",
391
- "description": "Dry run, do not write changes to package.json files",
392
- "name": "dry",
411
+ "verbose": {
412
+ "description": "Print per-object progress.",
413
+ "name": "verbose",
414
+ "allowNo": false,
415
+ "type": "boolean"
416
+ },
417
+ "dry-run": {
418
+ "description": "Print to stdout instead of writing a file.",
419
+ "name": "dry-run",
393
420
  "allowNo": false,
394
421
  "type": "boolean"
395
422
  }
396
423
  },
397
424
  "hasDynamicHelp": false,
398
425
  "hiddenAliases": [],
399
- "id": "bump",
426
+ "id": "baseline:build",
400
427
  "pluginAlias": "@memberjunction/cli",
401
428
  "pluginName": "@memberjunction/cli",
402
429
  "pluginType": "core",
@@ -406,50 +433,106 @@
406
433
  "relativePath": [
407
434
  "dist",
408
435
  "commands",
409
- "bump",
410
- "index.js"
436
+ "baseline",
437
+ "build.js"
411
438
  ]
412
439
  },
413
- "artifacts:reclassify": {
440
+ "baseline:compare": {
414
441
  "aliases": [],
415
442
  "args": {},
416
- "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.",
443
+ "description": "Deterministically compare two databases object-by-object and row-by-row.",
417
444
  "examples": [
418
- "<%= config.bin %> <%= command.id %>",
419
- "<%= config.bin %> <%= command.id %> --apply --limit 50"
445
+ "<%= config.bin %> <%= command.id %> --left MJ_BL_Stack --right MJ_BL_New",
446
+ "<%= config.bin %> <%= command.id %> --left A --right B --row-compare counts",
447
+ "<%= config.bin %> <%= command.id %> --left A --right B --fail-on-diff --out ./diffs/"
420
448
  ],
421
449
  "flags": {
422
- "conversation-id": {
423
- "description": "Scope to artifacts attached to the given conversation.",
424
- "name": "conversation-id",
450
+ "left": {
451
+ "description": "Left database name (override).",
452
+ "name": "left",
453
+ "required": true,
425
454
  "hasDynamicHelp": false,
426
455
  "multiple": false,
427
456
  "type": "option"
428
457
  },
429
- "since": {
430
- "description": "Scope to artifacts created on/after this ISO date.",
431
- "name": "since",
458
+ "right": {
459
+ "description": "Right database name (override).",
460
+ "name": "right",
461
+ "required": true,
432
462
  "hasDynamicHelp": false,
433
463
  "multiple": false,
434
464
  "type": "option"
435
465
  },
436
- "limit": {
437
- "description": "Maximum number of rows to inspect.",
438
- "name": "limit",
466
+ "dialect": {
467
+ "description": "Dialect of both DBs (must match).",
468
+ "name": "dialect",
469
+ "default": "mssql",
470
+ "hasDynamicHelp": false,
471
+ "multiple": false,
472
+ "options": [
473
+ "mssql",
474
+ "postgres"
475
+ ],
476
+ "type": "option"
477
+ },
478
+ "row-compare": {
479
+ "description": "Row comparison mode.",
480
+ "name": "row-compare",
481
+ "default": "full",
482
+ "hasDynamicHelp": false,
483
+ "multiple": false,
484
+ "options": [
485
+ "full",
486
+ "hash",
487
+ "counts",
488
+ "none"
489
+ ],
490
+ "type": "option"
491
+ },
492
+ "row-hash-algo": {
493
+ "description": "Hash algorithm when --row-compare hash.",
494
+ "name": "row-hash-algo",
495
+ "default": "sha256",
496
+ "hasDynamicHelp": false,
497
+ "multiple": false,
498
+ "options": [
499
+ "sha256",
500
+ "md5",
501
+ "checksum_agg"
502
+ ],
503
+ "type": "option"
504
+ },
505
+ "ignore": {
506
+ "description": "Regex of object names to skip.",
507
+ "name": "ignore",
508
+ "default": "^flyway_schema_history$",
509
+ "hasDynamicHelp": false,
510
+ "multiple": false,
511
+ "type": "option"
512
+ },
513
+ "sample-limit": {
514
+ "description": "Maximum row diffs to capture per table.",
515
+ "name": "sample-limit",
439
516
  "default": 100,
440
517
  "hasDynamicHelp": false,
441
518
  "multiple": false,
442
519
  "type": "option"
443
520
  },
444
- "apply": {
445
- "description": "Write changes. Without this flag, this command only reports what it would do.",
446
- "name": "apply",
521
+ "out": {
522
+ "description": "Directory to write JSON + Markdown reports.",
523
+ "name": "out",
524
+ "hasDynamicHelp": false,
525
+ "multiple": false,
526
+ "type": "option"
527
+ },
528
+ "fail-on-diff": {
529
+ "description": "Exit non-zero if any diff is found.",
530
+ "name": "fail-on-diff",
447
531
  "allowNo": false,
448
532
  "type": "boolean"
449
533
  },
450
534
  "verbose": {
451
- "char": "v",
452
- "description": "Print every candidate row, not just the summary.",
535
+ "description": "Print per-phase progress.",
453
536
  "name": "verbose",
454
537
  "allowNo": false,
455
538
  "type": "boolean"
@@ -457,7 +540,7 @@
457
540
  },
458
541
  "hasDynamicHelp": false,
459
542
  "hiddenAliases": [],
460
- "id": "artifacts:reclassify",
543
+ "id": "baseline:compare",
461
544
  "pluginAlias": "@memberjunction/cli",
462
545
  "pluginName": "@memberjunction/cli",
463
546
  "pluginType": "core",
@@ -467,21 +550,111 @@
467
550
  "relativePath": [
468
551
  "dist",
469
552
  "commands",
470
- "artifacts",
471
- "reclassify.js"
553
+ "baseline",
554
+ "compare.js"
472
555
  ]
473
556
  },
474
- "clean": {
557
+ "baseline:roundtrip": {
475
558
  "aliases": [],
476
559
  "args": {},
477
- "description": "Resets the MemberJunction database to a pre-installation state",
560
+ "description": "Build a baseline from a V-stack database, apply it to a fresh DB, and prove byte-equivalence.",
478
561
  "examples": [
479
- "<%= config.bin %> <%= command.id %>\n"
562
+ "<%= config.bin %> <%= command.id %> --source MJ_BL_Stack --target MJ_BL_New # auto: within-major",
563
+ "<%= config.bin %> <%= command.id %> --baseline-version 6.0 --source MJ_BL_Stack --target MJ_BL_New # explicit major-boundary",
564
+ "<%= config.bin %> <%= command.id %> --source-dir ./migrations/v5 --source MJ_BL_Stack --target MJ_BL_New"
480
565
  ],
481
566
  "flags": {
567
+ "baseline-version": {
568
+ "description": "Major.Minor version stamp. Omit to auto-detect from --source-dir (within-major rebaseline).",
569
+ "name": "baseline-version",
570
+ "hasDynamicHelp": false,
571
+ "multiple": false,
572
+ "type": "option"
573
+ },
574
+ "source-dir": {
575
+ "description": "Migrations source directory used to auto-detect baseline version + timestamp when --baseline-version is omitted. Defaults to the highest migrations/v*/ near cwd.",
576
+ "name": "source-dir",
577
+ "hasDynamicHelp": false,
578
+ "multiple": false,
579
+ "type": "option"
580
+ },
581
+ "description": {
582
+ "description": "Header description.",
583
+ "name": "description",
584
+ "default": "MemberJunction Baseline",
585
+ "hasDynamicHelp": false,
586
+ "multiple": false,
587
+ "type": "option"
588
+ },
589
+ "dialect": {
590
+ "description": "Dialect to test. PG path runs the converter via /pg-migrate first.",
591
+ "name": "dialect",
592
+ "default": "mssql",
593
+ "hasDynamicHelp": false,
594
+ "multiple": false,
595
+ "options": [
596
+ "mssql",
597
+ "postgres"
598
+ ],
599
+ "type": "option"
600
+ },
601
+ "source": {
602
+ "description": "Database name with the V-stack already applied (used as comparison gold standard).",
603
+ "name": "source",
604
+ "required": true,
605
+ "hasDynamicHelp": false,
606
+ "multiple": false,
607
+ "type": "option"
608
+ },
609
+ "target": {
610
+ "description": "Empty database name to apply the new baseline to.",
611
+ "name": "target",
612
+ "required": true,
613
+ "hasDynamicHelp": false,
614
+ "multiple": false,
615
+ "type": "option"
616
+ },
617
+ "out": {
618
+ "description": "Output directory for baseline file + reports.",
619
+ "name": "out",
620
+ "default": ".",
621
+ "hasDynamicHelp": false,
622
+ "multiple": false,
623
+ "type": "option"
624
+ },
625
+ "apply-cmd": {
626
+ "description": "Command template to apply the baseline. Tokens: {file} {database}. Defaults to sqlcmd.",
627
+ "name": "apply-cmd",
628
+ "hasDynamicHelp": false,
629
+ "multiple": false,
630
+ "type": "option"
631
+ },
632
+ "row-compare": {
633
+ "description": "Row compare mode passed to the comparator.",
634
+ "name": "row-compare",
635
+ "default": "full",
636
+ "hasDynamicHelp": false,
637
+ "multiple": false,
638
+ "options": [
639
+ "full",
640
+ "hash",
641
+ "counts",
642
+ "none"
643
+ ],
644
+ "type": "option"
645
+ },
646
+ "fail-on-diff": {
647
+ "name": "fail-on-diff",
648
+ "allowNo": false,
649
+ "type": "boolean"
650
+ },
651
+ "keep-target": {
652
+ "description": "Do not drop the target database after run (useful for debugging diffs).",
653
+ "name": "keep-target",
654
+ "allowNo": false,
655
+ "type": "boolean"
656
+ },
482
657
  "verbose": {
483
- "char": "v",
484
- "description": "Enable additional logging",
485
658
  "name": "verbose",
486
659
  "allowNo": false,
487
660
  "type": "boolean"
@@ -489,7 +662,7 @@
489
662
  },
490
663
  "hasDynamicHelp": false,
491
664
  "hiddenAliases": [],
492
- "id": "clean",
665
+ "id": "baseline:roundtrip",
493
666
  "pluginAlias": "@memberjunction/cli",
494
667
  "pluginName": "@memberjunction/cli",
495
668
  "pluginType": "core",
@@ -499,64 +672,50 @@
499
672
  "relativePath": [
500
673
  "dist",
501
674
  "commands",
502
- "clean",
503
- "index.js"
675
+ "baseline",
676
+ "roundtrip.js"
504
677
  ]
505
678
  },
506
- "codegen:5-0-fix-entity-names": {
679
+ "artifacts:reclassify": {
507
680
  "aliases": [],
508
681
  "args": {},
509
- "description": "[v5.0 Migration] Scan TypeScript files for entity names AND class names that need updating.\n\nThree strategies are applied:\n 1. Class name renames (regex) ActionEntity -> MJActionEntity, ActionSchema -> MJActionSchema,\n ActionEntityExtended -> MJActionEntityExtended (extended subclasses),\n ActionEntityServerEntity -> MJActionEntityServer (server subclass suffix standardization),\n ActionFormComponentExtended -> MJActionFormComponentExtended (Angular form components).\n Explicit subclass mappings (57 entries from subclass-rename-map.json) take priority over\n auto-generated suffix rules, enabling suffix changes (e.g., _Server -> Server, ServerEntity -> Server).\n 2. Multi-word entity name renames (regex) 'AI Models' -> 'MJ: AI Models'\n 3. Single-word entity name renames (AST) 'Actions' -> 'MJ: Actions' in GetEntityObject, OpenEntityRecord,\n navigateToEntity, EntityName: assignments, .Name === comparisons, @RegisterClass decorators.\n\nThe rename map (272 entity entries + 57 subclass entries) is built from entity_subclasses.ts @RegisterClass\ndecorators plus embedded rename maps. Runs in dry-run mode by default; use --fix to apply.",
682
+ "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.",
510
683
  "examples": [
511
- {
512
- "description": "Dry-run scan of the packages directory",
513
- "command": "<%= config.bin %> <%= command.id %> --path packages/"
514
- },
515
- {
516
- "description": "Scan a single file",
517
- "command": "<%= config.bin %> <%= command.id %> --path packages/Angular/Explorer/dashboards/src/Actions/components/actions-overview.component.ts"
518
- },
519
- {
520
- "description": "Apply fixes across the codebase",
521
- "command": "<%= config.bin %> <%= command.id %> --path packages/ --fix"
522
- },
523
- {
524
- "description": "Quiet mode (summary only)",
525
- "command": "<%= config.bin %> <%= command.id %> --path packages/ -q"
526
- }
684
+ "<%= config.bin %> <%= command.id %>",
685
+ "<%= config.bin %> <%= command.id %> --apply --limit 50"
527
686
  ],
528
687
  "flags": {
529
- "path": {
530
- "char": "p",
531
- "description": "File or directory to scan. Accepts a single .ts file or a directory (scanned recursively). Defaults to the current working directory.",
532
- "name": "path",
688
+ "conversation-id": {
689
+ "description": "Scope to artifacts attached to the given conversation.",
690
+ "name": "conversation-id",
533
691
  "hasDynamicHelp": false,
534
692
  "multiple": false,
535
693
  "type": "option"
536
694
  },
537
- "fix": {
538
- "description": "Apply fixes in place. Without this flag, the command runs in dry-run mode and only reports findings.",
539
- "name": "fix",
540
- "allowNo": false,
541
- "type": "boolean"
695
+ "since": {
696
+ "description": "Scope to artifacts created on/after this ISO date.",
697
+ "name": "since",
698
+ "hasDynamicHelp": false,
699
+ "multiple": false,
700
+ "type": "option"
542
701
  },
543
- "entity-subclasses": {
544
- "description": "Explicit path to entity_subclasses.ts for building the rename map. If omitted, the tool searches common locations relative to the target path.",
545
- "name": "entity-subclasses",
702
+ "limit": {
703
+ "description": "Maximum number of rows to inspect.",
704
+ "name": "limit",
705
+ "default": 100,
546
706
  "hasDynamicHelp": false,
547
707
  "multiple": false,
548
708
  "type": "option"
549
709
  },
550
- "quiet": {
551
- "char": "q",
552
- "description": "Suppress detailed per-file output; only show the final summary counts.",
553
- "name": "quiet",
710
+ "apply": {
711
+ "description": "Write changes. Without this flag, this command only reports what it would do.",
712
+ "name": "apply",
554
713
  "allowNo": false,
555
714
  "type": "boolean"
556
715
  },
557
716
  "verbose": {
558
717
  "char": "v",
559
- "description": "Show detailed progress including each file being scanned.",
718
+ "description": "Print every candidate row, not just the summary.",
560
719
  "name": "verbose",
561
720
  "allowNo": false,
562
721
  "type": "boolean"
@@ -564,7 +723,7 @@
564
723
  },
565
724
  "hasDynamicHelp": false,
566
725
  "hiddenAliases": [],
567
- "id": "codegen:5-0-fix-entity-names",
726
+ "id": "artifacts:reclassify",
568
727
  "pluginAlias": "@memberjunction/cli",
569
728
  "pluginName": "@memberjunction/cli",
570
729
  "pluginType": "core",
@@ -574,11 +733,190 @@
574
733
  "relativePath": [
575
734
  "dist",
576
735
  "commands",
577
- "codegen",
578
- "5-0-fix-entity-names.js"
736
+ "artifacts",
737
+ "reclassify.js"
579
738
  ]
580
739
  },
581
- "codegen:5-0-fix-html-entity-names": {
740
+ "bump": {
741
+ "aliases": [],
742
+ "args": {},
743
+ "description": "Bumps MemberJunction dependency versions",
744
+ "examples": [
745
+ {
746
+ "command": "<%= config.bin %> <%= command.id %>",
747
+ "description": "Bump all @memberjunction/* dependencies in the current directory's package.json to the CLI version"
748
+ },
749
+ {
750
+ "command": "<%= config.bin %> <%= command.id %> -rdv",
751
+ "description": "Preview all recursive packages bumps without writing any changes."
752
+ },
753
+ {
754
+ "command": "<%= config.bin %> <%= command.id %> -rqt v2.10.0 | xargs -n1 -I{} npm install --prefix {}",
755
+ "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."
756
+ }
757
+ ],
758
+ "flags": {
759
+ "verbose": {
760
+ "char": "v",
761
+ "description": "Enable additional logging",
762
+ "name": "verbose",
763
+ "allowNo": false,
764
+ "type": "boolean"
765
+ },
766
+ "recursive": {
767
+ "char": "r",
768
+ "description": "Bump version in current directory and all subdirectories",
769
+ "name": "recursive",
770
+ "allowNo": false,
771
+ "type": "boolean"
772
+ },
773
+ "tag": {
774
+ "char": "t",
775
+ "description": "Version tag to bump target for bump (e.g. v2.10.0), defaults to the CLI version",
776
+ "name": "tag",
777
+ "hasDynamicHelp": false,
778
+ "multiple": false,
779
+ "type": "option"
780
+ },
781
+ "quiet": {
782
+ "char": "q",
783
+ "description": "Only output paths for updated packages",
784
+ "name": "quiet",
785
+ "allowNo": false,
786
+ "type": "boolean"
787
+ },
788
+ "dry": {
789
+ "char": "d",
790
+ "description": "Dry run, do not write changes to package.json files",
791
+ "name": "dry",
792
+ "allowNo": false,
793
+ "type": "boolean"
794
+ }
795
+ },
796
+ "hasDynamicHelp": false,
797
+ "hiddenAliases": [],
798
+ "id": "bump",
799
+ "pluginAlias": "@memberjunction/cli",
800
+ "pluginName": "@memberjunction/cli",
801
+ "pluginType": "core",
802
+ "strict": true,
803
+ "enableJsonFlag": false,
804
+ "isESM": true,
805
+ "relativePath": [
806
+ "dist",
807
+ "commands",
808
+ "bump",
809
+ "index.js"
810
+ ]
811
+ },
812
+ "clean": {
813
+ "aliases": [],
814
+ "args": {},
815
+ "description": "Resets the MemberJunction database to a pre-installation state",
816
+ "examples": [
817
+ "<%= config.bin %> <%= command.id %>\n"
818
+ ],
819
+ "flags": {
820
+ "verbose": {
821
+ "char": "v",
822
+ "description": "Enable additional logging",
823
+ "name": "verbose",
824
+ "allowNo": false,
825
+ "type": "boolean"
826
+ }
827
+ },
828
+ "hasDynamicHelp": false,
829
+ "hiddenAliases": [],
830
+ "id": "clean",
831
+ "pluginAlias": "@memberjunction/cli",
832
+ "pluginName": "@memberjunction/cli",
833
+ "pluginType": "core",
834
+ "strict": true,
835
+ "enableJsonFlag": false,
836
+ "isESM": true,
837
+ "relativePath": [
838
+ "dist",
839
+ "commands",
840
+ "clean",
841
+ "index.js"
842
+ ]
843
+ },
844
+ "codegen:5-0-fix-entity-names": {
845
+ "aliases": [],
846
+ "args": {},
847
+ "description": "[v5.0 Migration] Scan TypeScript files for entity names AND class names that need updating.\n\nThree strategies are applied:\n 1. Class name renames (regex) — ActionEntity -> MJActionEntity, ActionSchema -> MJActionSchema,\n ActionEntityExtended -> MJActionEntityExtended (extended subclasses),\n ActionEntityServerEntity -> MJActionEntityServer (server subclass suffix standardization),\n ActionFormComponentExtended -> MJActionFormComponentExtended (Angular form components).\n Explicit subclass mappings (57 entries from subclass-rename-map.json) take priority over\n auto-generated suffix rules, enabling suffix changes (e.g., _Server -> Server, ServerEntity -> Server).\n 2. Multi-word entity name renames (regex) — 'AI Models' -> 'MJ: AI Models'\n 3. Single-word entity name renames (AST) — 'Actions' -> 'MJ: Actions' in GetEntityObject, OpenEntityRecord,\n navigateToEntity, EntityName: assignments, .Name === comparisons, @RegisterClass decorators.\n\nThe rename map (272 entity entries + 57 subclass entries) is built from entity_subclasses.ts @RegisterClass\ndecorators plus embedded rename maps. Runs in dry-run mode by default; use --fix to apply.",
848
+ "examples": [
849
+ {
850
+ "description": "Dry-run scan of the packages directory",
851
+ "command": "<%= config.bin %> <%= command.id %> --path packages/"
852
+ },
853
+ {
854
+ "description": "Scan a single file",
855
+ "command": "<%= config.bin %> <%= command.id %> --path packages/Angular/Explorer/dashboards/src/Actions/components/actions-overview.component.ts"
856
+ },
857
+ {
858
+ "description": "Apply fixes across the codebase",
859
+ "command": "<%= config.bin %> <%= command.id %> --path packages/ --fix"
860
+ },
861
+ {
862
+ "description": "Quiet mode (summary only)",
863
+ "command": "<%= config.bin %> <%= command.id %> --path packages/ -q"
864
+ }
865
+ ],
866
+ "flags": {
867
+ "path": {
868
+ "char": "p",
869
+ "description": "File or directory to scan. Accepts a single .ts file or a directory (scanned recursively). Defaults to the current working directory.",
870
+ "name": "path",
871
+ "hasDynamicHelp": false,
872
+ "multiple": false,
873
+ "type": "option"
874
+ },
875
+ "fix": {
876
+ "description": "Apply fixes in place. Without this flag, the command runs in dry-run mode and only reports findings.",
877
+ "name": "fix",
878
+ "allowNo": false,
879
+ "type": "boolean"
880
+ },
881
+ "entity-subclasses": {
882
+ "description": "Explicit path to entity_subclasses.ts for building the rename map. If omitted, the tool searches common locations relative to the target path.",
883
+ "name": "entity-subclasses",
884
+ "hasDynamicHelp": false,
885
+ "multiple": false,
886
+ "type": "option"
887
+ },
888
+ "quiet": {
889
+ "char": "q",
890
+ "description": "Suppress detailed per-file output; only show the final summary counts.",
891
+ "name": "quiet",
892
+ "allowNo": false,
893
+ "type": "boolean"
894
+ },
895
+ "verbose": {
896
+ "char": "v",
897
+ "description": "Show detailed progress including each file being scanned.",
898
+ "name": "verbose",
899
+ "allowNo": false,
900
+ "type": "boolean"
901
+ }
902
+ },
903
+ "hasDynamicHelp": false,
904
+ "hiddenAliases": [],
905
+ "id": "codegen:5-0-fix-entity-names",
906
+ "pluginAlias": "@memberjunction/cli",
907
+ "pluginName": "@memberjunction/cli",
908
+ "pluginType": "core",
909
+ "strict": true,
910
+ "enableJsonFlag": false,
911
+ "isESM": true,
912
+ "relativePath": [
913
+ "dist",
914
+ "commands",
915
+ "codegen",
916
+ "5-0-fix-entity-names.js"
917
+ ]
918
+ },
919
+ "codegen:5-0-fix-html-entity-names": {
582
920
  "aliases": [],
583
921
  "args": {},
584
922
  "description": "[v5.0 Migration] Scan Angular HTML template files for hardcoded entity names that need \"MJ: \" prefix updates.\n\nUses targeted regex patterns to find entity name references in template expressions\nand attribute values. Detects method calls like navigateToEntity('Actions'),\nOpenEntityRecord('Entities', id), and attribute values like RowsEntityName=\"Users\".\nRuns in dry-run mode by default; use --fix to apply.\n\nThe rename map is built dynamically from entity_subclasses.ts by parsing all\n@RegisterClass(BaseEntity, 'MJ: XYZ') decorators (~272 entries).",
@@ -906,6 +1244,63 @@
906
1244
  "manifest.js"
907
1245
  ]
908
1246
  },
1247
+ "doctor": {
1248
+ "aliases": [],
1249
+ "args": {},
1250
+ "description": "Diagnose a MemberJunction installation",
1251
+ "examples": [
1252
+ "<%= config.bin %> <%= command.id %>",
1253
+ "<%= config.bin %> <%= command.id %> --dir ./my-mj-project",
1254
+ "<%= config.bin %> <%= command.id %> --verbose",
1255
+ "<%= config.bin %> <%= command.id %> --report",
1256
+ "<%= config.bin %> <%= command.id %> --report_extended"
1257
+ ],
1258
+ "flags": {
1259
+ "dir": {
1260
+ "description": "Target directory to diagnose",
1261
+ "name": "dir",
1262
+ "default": ".",
1263
+ "hasDynamicHelp": false,
1264
+ "multiple": false,
1265
+ "type": "option"
1266
+ },
1267
+ "verbose": {
1268
+ "char": "v",
1269
+ "description": "Show detailed output including suggested fixes inline",
1270
+ "name": "verbose",
1271
+ "allowNo": false,
1272
+ "type": "boolean"
1273
+ },
1274
+ "report": {
1275
+ "char": "r",
1276
+ "description": "Generate a diagnostic report file (mj-diagnostic-report.md) for sharing with support",
1277
+ "name": "report",
1278
+ "allowNo": false,
1279
+ "type": "boolean"
1280
+ },
1281
+ "report_extended": {
1282
+ "description": "Generate an extended report with config file snapshots and service startup log capture (~60s longer)",
1283
+ "name": "report_extended",
1284
+ "allowNo": false,
1285
+ "type": "boolean"
1286
+ }
1287
+ },
1288
+ "hasDynamicHelp": false,
1289
+ "hiddenAliases": [],
1290
+ "id": "doctor",
1291
+ "pluginAlias": "@memberjunction/cli",
1292
+ "pluginName": "@memberjunction/cli",
1293
+ "pluginType": "core",
1294
+ "strict": true,
1295
+ "enableJsonFlag": false,
1296
+ "isESM": true,
1297
+ "relativePath": [
1298
+ "dist",
1299
+ "commands",
1300
+ "doctor",
1301
+ "index.js"
1302
+ ]
1303
+ },
909
1304
  "dbdoc:analyze": {
910
1305
  "aliases": [],
911
1306
  "args": {},
@@ -1343,188 +1738,16 @@
1343
1738
  "status.js"
1344
1739
  ]
1345
1740
  },
1346
- "doctor": {
1741
+ "migrate:convert": {
1347
1742
  "aliases": [],
1348
1743
  "args": {},
1349
- "description": "Diagnose a MemberJunction installation",
1744
+ "description": "Convert T-SQL migrations to PostgreSQL using the BatchConverter pipeline",
1350
1745
  "examples": [
1351
- "<%= config.bin %> <%= command.id %>",
1352
- "<%= config.bin %> <%= command.id %> --dir ./my-mj-project",
1353
- "<%= config.bin %> <%= command.id %> --verbose",
1354
- "<%= config.bin %> <%= command.id %> --report",
1355
- "<%= config.bin %> <%= command.id %> --report_extended"
1356
- ],
1357
- "flags": {
1358
- "dir": {
1359
- "description": "Target directory to diagnose",
1360
- "name": "dir",
1361
- "default": ".",
1362
- "hasDynamicHelp": false,
1363
- "multiple": false,
1364
- "type": "option"
1365
- },
1366
- "verbose": {
1367
- "char": "v",
1368
- "description": "Show detailed output including suggested fixes inline",
1369
- "name": "verbose",
1370
- "allowNo": false,
1371
- "type": "boolean"
1372
- },
1373
- "report": {
1374
- "char": "r",
1375
- "description": "Generate a diagnostic report file (mj-diagnostic-report.md) for sharing with support",
1376
- "name": "report",
1377
- "allowNo": false,
1378
- "type": "boolean"
1379
- },
1380
- "report_extended": {
1381
- "description": "Generate an extended report with config file snapshots and service startup log capture (~60s longer)",
1382
- "name": "report_extended",
1383
- "allowNo": false,
1384
- "type": "boolean"
1385
- }
1386
- },
1387
- "hasDynamicHelp": false,
1388
- "hiddenAliases": [],
1389
- "id": "doctor",
1390
- "pluginAlias": "@memberjunction/cli",
1391
- "pluginName": "@memberjunction/cli",
1392
- "pluginType": "core",
1393
- "strict": true,
1394
- "enableJsonFlag": false,
1395
- "isESM": true,
1396
- "relativePath": [
1397
- "dist",
1398
- "commands",
1399
- "doctor",
1400
- "index.js"
1401
- ]
1402
- },
1403
- "install": {
1404
- "aliases": [],
1405
- "args": {},
1406
- "description": "Install MemberJunction from a GitHub release",
1407
- "examples": [
1408
- "<%= config.bin %> <%= command.id %>",
1409
- "<%= config.bin %> <%= command.id %> -t v4.3.0",
1410
- "<%= config.bin %> <%= command.id %> --dry-run",
1411
- "<%= config.bin %> <%= command.id %> --yes"
1412
- ],
1413
- "flags": {
1414
- "tag": {
1415
- "char": "t",
1416
- "description": "Release tag to install (e.g. v4.3.0). If omitted, shows a version picker.",
1417
- "name": "tag",
1418
- "hasDynamicHelp": false,
1419
- "multiple": false,
1420
- "type": "option"
1421
- },
1422
- "dir": {
1423
- "description": "Target directory for the installation",
1424
- "name": "dir",
1425
- "default": ".",
1426
- "hasDynamicHelp": false,
1427
- "multiple": false,
1428
- "type": "option"
1429
- },
1430
- "config": {
1431
- "char": "c",
1432
- "description": "Path to JSON config file with install settings (database, auth, ports, etc.)",
1433
- "name": "config",
1434
- "hasDynamicHelp": false,
1435
- "multiple": false,
1436
- "type": "option"
1437
- },
1438
- "legacy": {
1439
- "description": "Use the legacy interactive installer (ZIP-only distribution)",
1440
- "hidden": true,
1441
- "name": "legacy",
1442
- "allowNo": false,
1443
- "type": "boolean"
1444
- },
1445
- "dry-run": {
1446
- "description": "Show the install plan without executing it",
1447
- "name": "dry-run",
1448
- "allowNo": false,
1449
- "type": "boolean"
1450
- },
1451
- "yes": {
1452
- "char": "y",
1453
- "description": "Non-interactive mode: auto-select latest version and accept defaults",
1454
- "name": "yes",
1455
- "allowNo": false,
1456
- "type": "boolean"
1457
- },
1458
- "verbose": {
1459
- "char": "v",
1460
- "description": "Show detailed output",
1461
- "name": "verbose",
1462
- "allowNo": false,
1463
- "type": "boolean"
1464
- },
1465
- "skip-db": {
1466
- "description": "Skip database provisioning phases",
1467
- "name": "skip-db",
1468
- "allowNo": false,
1469
- "type": "boolean"
1470
- },
1471
- "skip-start": {
1472
- "description": "Skip service startup and smoke tests",
1473
- "name": "skip-start",
1474
- "allowNo": false,
1475
- "type": "boolean"
1476
- },
1477
- "no-resume": {
1478
- "description": "Ignore any existing checkpoint and start fresh",
1479
- "name": "no-resume",
1480
- "allowNo": false,
1481
- "type": "boolean"
1482
- },
1483
- "fast": {
1484
- "description": "Fast mode: skip smoke test and optimize post-codegen steps. Re-run without --fast if you encounter issues.",
1485
- "name": "fast",
1486
- "allowNo": false,
1487
- "type": "boolean"
1488
- },
1489
- "overwrite-config": {
1490
- "description": "Overwrite existing config files (.env, mj.config.cjs, environment.ts) instead of preserving them",
1491
- "name": "overwrite-config",
1492
- "allowNo": false,
1493
- "type": "boolean"
1494
- },
1495
- "monorepo": {
1496
- "description": "Install the full MemberJunction source repository instead of the lightweight distribution. Use this for MJ framework development.",
1497
- "name": "monorepo",
1498
- "allowNo": false,
1499
- "type": "boolean"
1500
- }
1501
- },
1502
- "hasDynamicHelp": false,
1503
- "hiddenAliases": [],
1504
- "id": "install",
1505
- "pluginAlias": "@memberjunction/cli",
1506
- "pluginName": "@memberjunction/cli",
1507
- "pluginType": "core",
1508
- "strict": true,
1509
- "enableJsonFlag": false,
1510
- "isESM": true,
1511
- "relativePath": [
1512
- "dist",
1513
- "commands",
1514
- "install",
1515
- "index.js"
1516
- ]
1517
- },
1518
- "migrate:convert": {
1519
- "aliases": [],
1520
- "args": {},
1521
- "description": "Convert T-SQL migrations to PostgreSQL using the BatchConverter pipeline",
1522
- "examples": [
1523
- "<%= config.bin %> migrate convert",
1524
- "<%= config.bin %> migrate convert --dry-run",
1525
- "<%= config.bin %> migrate convert --file V202604060452__v5.24.x__KnowledgeHub.sql",
1526
- "<%= config.bin %> migrate convert --source-dir ./migrations/v5 --output-dir ./migrations-pg/v5",
1527
- "<%= config.bin %> migrate convert --verbose"
1746
+ "<%= config.bin %> migrate convert",
1747
+ "<%= config.bin %> migrate convert --dry-run",
1748
+ "<%= config.bin %> migrate convert --file V202604060452__v5.24.x__KnowledgeHub.sql",
1749
+ "<%= config.bin %> migrate convert --source-dir ./migrations/v5 --output-dir ./migrations-pg/v5",
1750
+ "<%= config.bin %> migrate convert --verbose"
1528
1751
  ],
1529
1752
  "flags": {
1530
1753
  "source-dir": {
@@ -2577,176 +2800,101 @@
2577
2800
  "watch.js"
2578
2801
  ]
2579
2802
  },
2580
- "translate-sql": {
2803
+ "test:compare": {
2581
2804
  "aliases": [],
2582
- "args": {},
2583
- "description": "Translate SQL fragments between database dialects (SQL Server ↔ PostgreSQL)",
2805
+ "args": {
2806
+ "runId1": {
2807
+ "description": "First test run ID to compare",
2808
+ "name": "runId1",
2809
+ "required": false
2810
+ },
2811
+ "runId2": {
2812
+ "description": "Second test run ID to compare",
2813
+ "name": "runId2",
2814
+ "required": false
2815
+ }
2816
+ },
2817
+ "description": "Compare test runs for regression detection",
2584
2818
  "examples": [
2585
- "<%= config.bin %> translate-sql --from sqlserver --to postgresql --dry-run",
2586
- "<%= config.bin %> translate-sql --from sqlserver --to postgresql --scope queries",
2587
- "<%= config.bin %> translate-sql --from sqlserver --to postgresql --sql \"SELECT TOP 10 [Name] FROM [Users]\"",
2588
- "<%= config.bin %> translate-sql --from sqlserver --to postgresql --scope all --output ./reports"
2819
+ "<%= config.bin %> <%= command.id %>",
2820
+ "<%= config.bin %> <%= command.id %> --latest",
2821
+ "<%= config.bin %> <%= command.id %> <run-id-1> <run-id-2>",
2822
+ "<%= config.bin %> <%= command.id %> -v 5.17.0 -v 5.18.0",
2823
+ "<%= config.bin %> <%= command.id %> -c abc1234 -c def5678",
2824
+ "<%= config.bin %> <%= command.id %> --from-json baseline.json latest.json",
2825
+ "<%= config.bin %> <%= command.id %> --latest --format=markdown --output=report.md"
2589
2826
  ],
2590
2827
  "flags": {
2591
- "from": {
2592
- "description": "Source SQL dialect",
2593
- "name": "from",
2594
- "required": true,
2828
+ "version": {
2829
+ "char": "v",
2830
+ "description": "Compare runs by version",
2831
+ "name": "version",
2595
2832
  "hasDynamicHelp": false,
2596
- "multiple": false,
2597
- "options": [
2598
- "sqlserver",
2599
- "postgresql"
2600
- ],
2833
+ "multiple": true,
2601
2834
  "type": "option"
2602
2835
  },
2603
- "to": {
2604
- "description": "Target SQL dialect",
2605
- "name": "to",
2606
- "required": true,
2836
+ "commit": {
2837
+ "char": "c",
2838
+ "description": "Compare runs by git commit",
2839
+ "name": "commit",
2607
2840
  "hasDynamicHelp": false,
2608
- "multiple": false,
2609
- "options": [
2610
- "sqlserver",
2611
- "postgresql"
2612
- ],
2841
+ "multiple": true,
2613
2842
  "type": "option"
2614
2843
  },
2615
- "scope": {
2616
- "description": "What to scan for translation",
2617
- "name": "scope",
2618
- "default": "all",
2844
+ "diff-only": {
2845
+ "description": "Show only differences",
2846
+ "name": "diff-only",
2847
+ "allowNo": false,
2848
+ "type": "boolean"
2849
+ },
2850
+ "latest": {
2851
+ "char": "l",
2852
+ "description": "Compare the two most recent completed suite runs",
2853
+ "name": "latest",
2854
+ "allowNo": false,
2855
+ "type": "boolean"
2856
+ },
2857
+ "from-json": {
2858
+ "description": "Compare two results.json files directly (no DB). Pass twice: --from-json PREV --from-json CURR",
2859
+ "name": "from-json",
2860
+ "hasDynamicHelp": false,
2861
+ "multiple": true,
2862
+ "type": "option"
2863
+ },
2864
+ "format": {
2865
+ "char": "f",
2866
+ "description": "Output format",
2867
+ "name": "format",
2868
+ "default": "console",
2619
2869
  "hasDynamicHelp": false,
2620
2870
  "multiple": false,
2621
2871
  "options": [
2622
- "queries",
2623
- "views",
2624
- "filters",
2625
- "all"
2872
+ "console",
2873
+ "json",
2874
+ "markdown"
2626
2875
  ],
2627
2876
  "type": "option"
2628
2877
  },
2629
- "sql": {
2630
- "description": "Translate a single SQL fragment (inline mode)",
2631
- "name": "sql",
2878
+ "output": {
2879
+ "char": "o",
2880
+ "description": "Output file path",
2881
+ "name": "output",
2632
2882
  "hasDynamicHelp": false,
2633
2883
  "multiple": false,
2634
2884
  "type": "option"
2635
2885
  },
2636
- "dry-run": {
2637
- "description": "Show what would be translated without making changes",
2638
- "name": "dry-run",
2639
- "allowNo": false,
2640
- "type": "boolean"
2641
- },
2642
- "review": {
2643
- "description": "Generate review report only (no writes to database)",
2644
- "name": "review",
2645
- "allowNo": false,
2646
- "type": "boolean"
2647
- },
2648
- "output": {
2649
- "char": "o",
2650
- "description": "Output directory for the translation report",
2651
- "name": "output",
2652
- "hasDynamicHelp": false,
2653
- "multiple": false,
2654
- "type": "option"
2655
- },
2656
- "force": {
2657
- "description": "Re-translate even if platform variants already exist",
2658
- "name": "force",
2659
- "allowNo": false,
2660
- "type": "boolean"
2661
- }
2662
- },
2663
- "hasDynamicHelp": false,
2664
- "hiddenAliases": [],
2665
- "id": "translate-sql",
2666
- "pluginAlias": "@memberjunction/cli",
2667
- "pluginName": "@memberjunction/cli",
2668
- "pluginType": "core",
2669
- "strict": true,
2670
- "enableJsonFlag": false,
2671
- "isESM": true,
2672
- "relativePath": [
2673
- "dist",
2674
- "commands",
2675
- "translate-sql",
2676
- "index.js"
2677
- ]
2678
- },
2679
- "test:compare": {
2680
- "aliases": [],
2681
- "args": {
2682
- "runId1": {
2683
- "description": "First test run ID to compare",
2684
- "name": "runId1",
2685
- "required": false
2686
- },
2687
- "runId2": {
2688
- "description": "Second test run ID to compare",
2689
- "name": "runId2",
2690
- "required": false
2691
- }
2692
- },
2693
- "description": "Compare test runs for regression detection",
2694
- "examples": [
2695
- "<%= config.bin %> <%= command.id %> <run-id-1> <run-id-2>",
2696
- "<%= config.bin %> <%= command.id %> --baseline=<run-id> --current=<run-id>",
2697
- "<%= config.bin %> <%= command.id %> --suite=<suite-id> --since=\"2024-01-01\"",
2698
- "<%= config.bin %> <%= command.id %> <run-id-1> <run-id-2> --format=json"
2699
- ],
2700
- "flags": {
2701
- "version": {
2702
- "char": "v",
2703
- "description": "Compare runs by version",
2704
- "name": "version",
2705
- "hasDynamicHelp": false,
2706
- "multiple": true,
2707
- "type": "option"
2708
- },
2709
- "commit": {
2710
- "char": "c",
2711
- "description": "Compare runs by git commit",
2712
- "name": "commit",
2713
- "hasDynamicHelp": false,
2714
- "multiple": true,
2715
- "type": "option"
2716
- },
2717
- "diff-only": {
2718
- "description": "Show only differences",
2719
- "name": "diff-only",
2886
+ "verbose": {
2887
+ "description": "Show detailed information",
2888
+ "name": "verbose",
2720
2889
  "allowNo": false,
2721
2890
  "type": "boolean"
2722
2891
  },
2723
- "format": {
2724
- "char": "f",
2725
- "description": "Output format",
2726
- "name": "format",
2727
- "default": "console",
2728
- "hasDynamicHelp": false,
2729
- "multiple": false,
2730
- "options": [
2731
- "console",
2732
- "json",
2733
- "markdown"
2734
- ],
2735
- "type": "option"
2736
- },
2737
- "output": {
2738
- "char": "o",
2739
- "description": "Output file path",
2740
- "name": "output",
2892
+ "tag": {
2893
+ "description": "Filter suite runs by tag (matches against MJTestSuiteRunEntity.Tags). Useful for isolating runs from a specific source environment in an archive MJ. DB mode only — --from-json ignores this flag.",
2894
+ "name": "tag",
2741
2895
  "hasDynamicHelp": false,
2742
2896
  "multiple": false,
2743
2897
  "type": "option"
2744
- },
2745
- "verbose": {
2746
- "description": "Show detailed information",
2747
- "name": "verbose",
2748
- "allowNo": false,
2749
- "type": "boolean"
2750
2898
  }
2751
2899
  },
2752
2900
  "hasDynamicHelp": false,
@@ -3045,6 +3193,13 @@
3045
3193
  "name": "verbose",
3046
3194
  "allowNo": false,
3047
3195
  "type": "boolean"
3196
+ },
3197
+ "oracles-module": {
3198
+ "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.",
3199
+ "name": "oracles-module",
3200
+ "hasDynamicHelp": false,
3201
+ "multiple": false,
3202
+ "type": "option"
3048
3203
  }
3049
3204
  },
3050
3205
  "hasDynamicHelp": false,
@@ -3116,6 +3271,44 @@
3116
3271
  "name": "verbose",
3117
3272
  "allowNo": false,
3118
3273
  "type": "boolean"
3274
+ },
3275
+ "delay": {
3276
+ "char": "d",
3277
+ "description": "Delay in milliseconds between test executions (avoids Auth0 rate limits)",
3278
+ "name": "delay",
3279
+ "default": 0,
3280
+ "hasDynamicHelp": false,
3281
+ "multiple": false,
3282
+ "type": "option"
3283
+ },
3284
+ "parallel": {
3285
+ "char": "p",
3286
+ "description": "Run tests in parallel with shared browser sessions",
3287
+ "name": "parallel",
3288
+ "allowNo": false,
3289
+ "type": "boolean"
3290
+ },
3291
+ "max-parallel": {
3292
+ "description": "Maximum number of parallel workers (default 4)",
3293
+ "name": "max-parallel",
3294
+ "default": 4,
3295
+ "hasDynamicHelp": false,
3296
+ "multiple": false,
3297
+ "type": "option"
3298
+ },
3299
+ "flaky-check": {
3300
+ "description": "Run each test N times to detect flakiness (variance > 0.3 or mixed pass/fail = flaky). Recommended: 3 or 5",
3301
+ "name": "flaky-check",
3302
+ "hasDynamicHelp": false,
3303
+ "multiple": false,
3304
+ "type": "option"
3305
+ },
3306
+ "oracles-module": {
3307
+ "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.",
3308
+ "name": "oracles-module",
3309
+ "hasDynamicHelp": false,
3310
+ "multiple": false,
3311
+ "type": "option"
3119
3312
  }
3120
3313
  },
3121
3314
  "hasDynamicHelp": false,
@@ -3219,115 +3412,92 @@
3219
3412
  "validate.js"
3220
3413
  ]
3221
3414
  },
3222
- "ai:actions:list": {
3415
+ "translate-sql": {
3223
3416
  "aliases": [],
3224
3417
  "args": {},
3225
- "description": "List available AI actions",
3418
+ "description": "Translate SQL fragments between database dialects (SQL Server ↔ PostgreSQL)",
3226
3419
  "examples": [
3227
- "<%= config.bin %> <%= command.id %>",
3228
- "<%= config.bin %> <%= command.id %> --output=table",
3229
- "<%= config.bin %> <%= command.id %> --output=json"
3420
+ "<%= config.bin %> translate-sql --from sqlserver --to postgresql --dry-run",
3421
+ "<%= config.bin %> translate-sql --from sqlserver --to postgresql --scope queries",
3422
+ "<%= config.bin %> translate-sql --from sqlserver --to postgresql --sql \"SELECT TOP 10 [Name] FROM [Users]\"",
3423
+ "<%= config.bin %> translate-sql --from sqlserver --to postgresql --scope all --output ./reports"
3230
3424
  ],
3231
3425
  "flags": {
3232
- "output": {
3233
- "char": "o",
3234
- "description": "Output format",
3235
- "name": "output",
3236
- "default": "compact",
3426
+ "from": {
3427
+ "description": "Source SQL dialect",
3428
+ "name": "from",
3429
+ "required": true,
3237
3430
  "hasDynamicHelp": false,
3238
3431
  "multiple": false,
3239
3432
  "options": [
3240
- "compact",
3241
- "json",
3242
- "table"
3433
+ "sqlserver",
3434
+ "postgresql"
3243
3435
  ],
3244
3436
  "type": "option"
3245
- }
3246
- },
3247
- "hasDynamicHelp": false,
3248
- "hiddenAliases": [],
3249
- "id": "ai:actions:list",
3250
- "pluginAlias": "@memberjunction/cli",
3251
- "pluginName": "@memberjunction/cli",
3252
- "pluginType": "core",
3253
- "strict": true,
3254
- "enableJsonFlag": false,
3255
- "isESM": true,
3256
- "relativePath": [
3257
- "dist",
3258
- "commands",
3259
- "ai",
3260
- "actions",
3261
- "list.js"
3262
- ]
3263
- },
3264
- "ai:actions:run": {
3265
- "aliases": [],
3266
- "args": {},
3267
- "description": "Execute an AI action with parameters",
3268
- "examples": [
3269
- "<%= config.bin %> <%= command.id %> -n \"Get Weather\" --param \"Location=Boston\"",
3270
- "<%= config.bin %> <%= command.id %> -n \"Get Stock Price\" --param \"Ticker=AAPL\"",
3271
- "<%= 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\"",
3272
- "<%= config.bin %> <%= command.id %> -n \"Calculate Expression\" --param \"Expression=2+2*3\" --dry-run"
3273
- ],
3274
- "flags": {
3275
- "name": {
3276
- "char": "n",
3277
- "description": "Action name",
3278
- "name": "name",
3437
+ },
3438
+ "to": {
3439
+ "description": "Target SQL dialect",
3440
+ "name": "to",
3279
3441
  "required": true,
3280
3442
  "hasDynamicHelp": false,
3281
3443
  "multiple": false,
3444
+ "options": [
3445
+ "sqlserver",
3446
+ "postgresql"
3447
+ ],
3282
3448
  "type": "option"
3283
3449
  },
3284
- "param": {
3285
- "char": "p",
3286
- "description": "Action parameters in key=value format",
3287
- "name": "param",
3450
+ "scope": {
3451
+ "description": "What to scan for translation",
3452
+ "name": "scope",
3453
+ "default": "all",
3288
3454
  "hasDynamicHelp": false,
3289
- "multiple": true,
3455
+ "multiple": false,
3456
+ "options": [
3457
+ "queries",
3458
+ "views",
3459
+ "filters",
3460
+ "all"
3461
+ ],
3462
+ "type": "option"
3463
+ },
3464
+ "sql": {
3465
+ "description": "Translate a single SQL fragment (inline mode)",
3466
+ "name": "sql",
3467
+ "hasDynamicHelp": false,
3468
+ "multiple": false,
3290
3469
  "type": "option"
3291
3470
  },
3292
3471
  "dry-run": {
3293
- "description": "Validate without executing",
3472
+ "description": "Show what would be translated without making changes",
3294
3473
  "name": "dry-run",
3295
3474
  "allowNo": false,
3296
3475
  "type": "boolean"
3297
3476
  },
3477
+ "review": {
3478
+ "description": "Generate review report only (no writes to database)",
3479
+ "name": "review",
3480
+ "allowNo": false,
3481
+ "type": "boolean"
3482
+ },
3298
3483
  "output": {
3299
3484
  "char": "o",
3300
- "description": "Output format",
3485
+ "description": "Output directory for the translation report",
3301
3486
  "name": "output",
3302
- "default": "compact",
3303
3487
  "hasDynamicHelp": false,
3304
3488
  "multiple": false,
3305
- "options": [
3306
- "compact",
3307
- "json",
3308
- "table"
3309
- ],
3310
3489
  "type": "option"
3311
3490
  },
3312
- "verbose": {
3313
- "char": "v",
3314
- "description": "Show detailed execution information",
3315
- "name": "verbose",
3491
+ "force": {
3492
+ "description": "Re-translate even if platform variants already exist",
3493
+ "name": "force",
3316
3494
  "allowNo": false,
3317
3495
  "type": "boolean"
3318
- },
3319
- "timeout": {
3320
- "description": "Execution timeout in milliseconds",
3321
- "name": "timeout",
3322
- "default": 300000,
3323
- "hasDynamicHelp": false,
3324
- "multiple": false,
3325
- "type": "option"
3326
3496
  }
3327
3497
  },
3328
3498
  "hasDynamicHelp": false,
3329
3499
  "hiddenAliases": [],
3330
- "id": "ai:actions:run",
3500
+ "id": "translate-sql",
3331
3501
  "pluginAlias": "@memberjunction/cli",
3332
3502
  "pluginName": "@memberjunction/cli",
3333
3503
  "pluginType": "core",
@@ -3337,9 +3507,123 @@
3337
3507
  "relativePath": [
3338
3508
  "dist",
3339
3509
  "commands",
3340
- "ai",
3341
- "actions",
3342
- "run.js"
3510
+ "translate-sql",
3511
+ "index.js"
3512
+ ]
3513
+ },
3514
+ "install": {
3515
+ "aliases": [],
3516
+ "args": {},
3517
+ "description": "Install MemberJunction from a GitHub release",
3518
+ "examples": [
3519
+ "<%= config.bin %> <%= command.id %>",
3520
+ "<%= config.bin %> <%= command.id %> -t v4.3.0",
3521
+ "<%= config.bin %> <%= command.id %> --dry-run",
3522
+ "<%= config.bin %> <%= command.id %> --yes"
3523
+ ],
3524
+ "flags": {
3525
+ "tag": {
3526
+ "char": "t",
3527
+ "description": "Release tag to install (e.g. v4.3.0). If omitted, shows a version picker.",
3528
+ "name": "tag",
3529
+ "hasDynamicHelp": false,
3530
+ "multiple": false,
3531
+ "type": "option"
3532
+ },
3533
+ "dir": {
3534
+ "description": "Target directory for the installation",
3535
+ "name": "dir",
3536
+ "default": ".",
3537
+ "hasDynamicHelp": false,
3538
+ "multiple": false,
3539
+ "type": "option"
3540
+ },
3541
+ "config": {
3542
+ "char": "c",
3543
+ "description": "Path to JSON config file with install settings (database, auth, ports, etc.)",
3544
+ "name": "config",
3545
+ "hasDynamicHelp": false,
3546
+ "multiple": false,
3547
+ "type": "option"
3548
+ },
3549
+ "legacy": {
3550
+ "description": "Use the legacy interactive installer (ZIP-only distribution)",
3551
+ "hidden": true,
3552
+ "name": "legacy",
3553
+ "allowNo": false,
3554
+ "type": "boolean"
3555
+ },
3556
+ "dry-run": {
3557
+ "description": "Show the install plan without executing it",
3558
+ "name": "dry-run",
3559
+ "allowNo": false,
3560
+ "type": "boolean"
3561
+ },
3562
+ "yes": {
3563
+ "char": "y",
3564
+ "description": "Non-interactive mode: auto-select latest version and accept defaults",
3565
+ "name": "yes",
3566
+ "allowNo": false,
3567
+ "type": "boolean"
3568
+ },
3569
+ "verbose": {
3570
+ "char": "v",
3571
+ "description": "Show detailed output",
3572
+ "name": "verbose",
3573
+ "allowNo": false,
3574
+ "type": "boolean"
3575
+ },
3576
+ "skip-db": {
3577
+ "description": "Skip database provisioning phases",
3578
+ "name": "skip-db",
3579
+ "allowNo": false,
3580
+ "type": "boolean"
3581
+ },
3582
+ "skip-start": {
3583
+ "description": "Skip service startup and smoke tests",
3584
+ "name": "skip-start",
3585
+ "allowNo": false,
3586
+ "type": "boolean"
3587
+ },
3588
+ "no-resume": {
3589
+ "description": "Ignore any existing checkpoint and start fresh",
3590
+ "name": "no-resume",
3591
+ "allowNo": false,
3592
+ "type": "boolean"
3593
+ },
3594
+ "fast": {
3595
+ "description": "Fast mode: skip smoke test and optimize post-codegen steps. Re-run without --fast if you encounter issues.",
3596
+ "name": "fast",
3597
+ "allowNo": false,
3598
+ "type": "boolean"
3599
+ },
3600
+ "overwrite-config": {
3601
+ "description": "Overwrite existing config files (.env, mj.config.cjs, environment.ts) instead of preserving them",
3602
+ "name": "overwrite-config",
3603
+ "allowNo": false,
3604
+ "type": "boolean"
3605
+ },
3606
+ "monorepo": {
3607
+ "description": "Install the full MemberJunction source repository instead of the lightweight distribution. Use this for MJ framework development.",
3608
+ "name": "monorepo",
3609
+ "allowNo": false,
3610
+ "type": "boolean"
3611
+ }
3612
+ },
3613
+ "hasDynamicHelp": false,
3614
+ "hiddenAliases": [],
3615
+ "id": "install",
3616
+ "pluginAlias": "@memberjunction/cli",
3617
+ "pluginName": "@memberjunction/cli",
3618
+ "pluginType": "core",
3619
+ "strict": true,
3620
+ "enableJsonFlag": false,
3621
+ "isESM": true,
3622
+ "relativePath": [
3623
+ "dist",
3624
+ "commands",
3625
+ "install",
3626
+ "index.js"
3343
3627
  ]
3344
3628
  },
3345
3629
  "ai:agents:list": {
@@ -3687,6 +3971,129 @@
3687
3971
  "index.js"
3688
3972
  ]
3689
3973
  },
3974
+ "ai:actions:list": {
3975
+ "aliases": [],
3976
+ "args": {},
3977
+ "description": "List available AI actions",
3978
+ "examples": [
3979
+ "<%= config.bin %> <%= command.id %>",
3980
+ "<%= config.bin %> <%= command.id %> --output=table",
3981
+ "<%= config.bin %> <%= command.id %> --output=json"
3982
+ ],
3983
+ "flags": {
3984
+ "output": {
3985
+ "char": "o",
3986
+ "description": "Output format",
3987
+ "name": "output",
3988
+ "default": "compact",
3989
+ "hasDynamicHelp": false,
3990
+ "multiple": false,
3991
+ "options": [
3992
+ "compact",
3993
+ "json",
3994
+ "table"
3995
+ ],
3996
+ "type": "option"
3997
+ }
3998
+ },
3999
+ "hasDynamicHelp": false,
4000
+ "hiddenAliases": [],
4001
+ "id": "ai:actions:list",
4002
+ "pluginAlias": "@memberjunction/cli",
4003
+ "pluginName": "@memberjunction/cli",
4004
+ "pluginType": "core",
4005
+ "strict": true,
4006
+ "enableJsonFlag": false,
4007
+ "isESM": true,
4008
+ "relativePath": [
4009
+ "dist",
4010
+ "commands",
4011
+ "ai",
4012
+ "actions",
4013
+ "list.js"
4014
+ ]
4015
+ },
4016
+ "ai:actions:run": {
4017
+ "aliases": [],
4018
+ "args": {},
4019
+ "description": "Execute an AI action with parameters",
4020
+ "examples": [
4021
+ "<%= config.bin %> <%= command.id %> -n \"Get Weather\" --param \"Location=Boston\"",
4022
+ "<%= config.bin %> <%= command.id %> -n \"Get Stock Price\" --param \"Ticker=AAPL\"",
4023
+ "<%= 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\"",
4024
+ "<%= config.bin %> <%= command.id %> -n \"Calculate Expression\" --param \"Expression=2+2*3\" --dry-run"
4025
+ ],
4026
+ "flags": {
4027
+ "name": {
4028
+ "char": "n",
4029
+ "description": "Action name",
4030
+ "name": "name",
4031
+ "required": true,
4032
+ "hasDynamicHelp": false,
4033
+ "multiple": false,
4034
+ "type": "option"
4035
+ },
4036
+ "param": {
4037
+ "char": "p",
4038
+ "description": "Action parameters in key=value format",
4039
+ "name": "param",
4040
+ "hasDynamicHelp": false,
4041
+ "multiple": true,
4042
+ "type": "option"
4043
+ },
4044
+ "dry-run": {
4045
+ "description": "Validate without executing",
4046
+ "name": "dry-run",
4047
+ "allowNo": false,
4048
+ "type": "boolean"
4049
+ },
4050
+ "output": {
4051
+ "char": "o",
4052
+ "description": "Output format",
4053
+ "name": "output",
4054
+ "default": "compact",
4055
+ "hasDynamicHelp": false,
4056
+ "multiple": false,
4057
+ "options": [
4058
+ "compact",
4059
+ "json",
4060
+ "table"
4061
+ ],
4062
+ "type": "option"
4063
+ },
4064
+ "verbose": {
4065
+ "char": "v",
4066
+ "description": "Show detailed execution information",
4067
+ "name": "verbose",
4068
+ "allowNo": false,
4069
+ "type": "boolean"
4070
+ },
4071
+ "timeout": {
4072
+ "description": "Execution timeout in milliseconds",
4073
+ "name": "timeout",
4074
+ "default": 300000,
4075
+ "hasDynamicHelp": false,
4076
+ "multiple": false,
4077
+ "type": "option"
4078
+ }
4079
+ },
4080
+ "hasDynamicHelp": false,
4081
+ "hiddenAliases": [],
4082
+ "id": "ai:actions:run",
4083
+ "pluginAlias": "@memberjunction/cli",
4084
+ "pluginName": "@memberjunction/cli",
4085
+ "pluginType": "core",
4086
+ "strict": true,
4087
+ "enableJsonFlag": false,
4088
+ "isESM": true,
4089
+ "relativePath": [
4090
+ "dist",
4091
+ "commands",
4092
+ "ai",
4093
+ "actions",
4094
+ "run.js"
4095
+ ]
4096
+ },
3690
4097
  "ai:prompts:list": {
3691
4098
  "aliases": [],
3692
4099
  "args": {},
@@ -3825,7 +4232,447 @@
3825
4232
  "prompts",
3826
4233
  "run.js"
3827
4234
  ]
4235
+ },
4236
+ "test:regression:build": {
4237
+ "aliases": [],
4238
+ "args": {
4239
+ "service": {
4240
+ "description": "Optional service name(s) to rebuild (e.g. mjexplorer, test-runner).",
4241
+ "name": "service",
4242
+ "required": false
4243
+ }
4244
+ },
4245
+ "description": "Build Docker images for the regression stack. On first run (or whenever .docker-generated/ is empty) this also invokes `gen-forms` to generate Angular entity forms — that step takes ~5 minutes but only happens when the form output is missing.",
4246
+ "examples": [
4247
+ "<%= config.bin %> <%= command.id %>",
4248
+ "<%= config.bin %> <%= command.id %> mjexplorer # rebuild a specific service",
4249
+ "<%= config.bin %> <%= command.id %> --skip-gen-forms"
4250
+ ],
4251
+ "flags": {
4252
+ "skip-gen-forms": {
4253
+ "description": "Skip the gen-forms guard, even when .docker-generated/ is empty. Use when you know the entity forms are already generated.",
4254
+ "name": "skip-gen-forms",
4255
+ "allowNo": false,
4256
+ "type": "boolean"
4257
+ }
4258
+ },
4259
+ "hasDynamicHelp": false,
4260
+ "hiddenAliases": [],
4261
+ "id": "test:regression:build",
4262
+ "pluginAlias": "@memberjunction/cli",
4263
+ "pluginName": "@memberjunction/cli",
4264
+ "pluginType": "core",
4265
+ "strict": false,
4266
+ "enableJsonFlag": false,
4267
+ "isESM": true,
4268
+ "relativePath": [
4269
+ "dist",
4270
+ "commands",
4271
+ "test",
4272
+ "regression",
4273
+ "build.js"
4274
+ ]
4275
+ },
4276
+ "test:regression:compare": {
4277
+ "aliases": [],
4278
+ "args": {},
4279
+ "description": "Diff the two most recent regression runs from docker/regression/test-results/. Thin alias for `mj test compare --from-json <dir>` that handles the path.",
4280
+ "examples": [
4281
+ "<%= config.bin %> <%= command.id %>",
4282
+ "<%= config.bin %> <%= command.id %> --diff-only",
4283
+ "<%= config.bin %> <%= command.id %> --format=markdown --output=delta.md"
4284
+ ],
4285
+ "flags": {
4286
+ "diff-only": {
4287
+ "description": "Show only differences.",
4288
+ "name": "diff-only",
4289
+ "allowNo": false,
4290
+ "type": "boolean"
4291
+ },
4292
+ "format": {
4293
+ "char": "f",
4294
+ "description": "Output format.",
4295
+ "name": "format",
4296
+ "default": "console",
4297
+ "hasDynamicHelp": false,
4298
+ "multiple": false,
4299
+ "options": [
4300
+ "console",
4301
+ "json",
4302
+ "markdown"
4303
+ ],
4304
+ "type": "option"
4305
+ },
4306
+ "output": {
4307
+ "char": "o",
4308
+ "description": "Output file path.",
4309
+ "name": "output",
4310
+ "hasDynamicHelp": false,
4311
+ "multiple": false,
4312
+ "type": "option"
4313
+ },
4314
+ "verbose": {
4315
+ "description": "Show detailed information.",
4316
+ "name": "verbose",
4317
+ "allowNo": false,
4318
+ "type": "boolean"
4319
+ },
4320
+ "tag": {
4321
+ "description": "Filter suite runs by tag. Compares the two most recent runs whose Tags array contains the tag — useful when an archive MJ holds runs from multiple environments.",
4322
+ "name": "tag",
4323
+ "hasDynamicHelp": false,
4324
+ "multiple": false,
4325
+ "type": "option"
4326
+ }
4327
+ },
4328
+ "hasDynamicHelp": false,
4329
+ "hiddenAliases": [],
4330
+ "id": "test:regression:compare",
4331
+ "pluginAlias": "@memberjunction/cli",
4332
+ "pluginName": "@memberjunction/cli",
4333
+ "pluginType": "core",
4334
+ "strict": false,
4335
+ "enableJsonFlag": false,
4336
+ "isESM": true,
4337
+ "relativePath": [
4338
+ "dist",
4339
+ "commands",
4340
+ "test",
4341
+ "regression",
4342
+ "compare.js"
4343
+ ]
4344
+ },
4345
+ "test:regression:down": {
4346
+ "aliases": [],
4347
+ "args": {},
4348
+ "description": "Stop the regression stack and wipe DB volumes (docker compose down -v).",
4349
+ "examples": [
4350
+ "<%= config.bin %> <%= command.id %>",
4351
+ "<%= config.bin %> <%= command.id %> --keep-volumes"
4352
+ ],
4353
+ "flags": {
4354
+ "keep-volumes": {
4355
+ "description": "Skip the `-v` flag — preserves the ephemeral DB volume.",
4356
+ "name": "keep-volumes",
4357
+ "allowNo": false,
4358
+ "type": "boolean"
4359
+ }
4360
+ },
4361
+ "hasDynamicHelp": false,
4362
+ "hiddenAliases": [],
4363
+ "id": "test:regression:down",
4364
+ "pluginAlias": "@memberjunction/cli",
4365
+ "pluginName": "@memberjunction/cli",
4366
+ "pluginType": "core",
4367
+ "strict": true,
4368
+ "enableJsonFlag": false,
4369
+ "isESM": true,
4370
+ "relativePath": [
4371
+ "dist",
4372
+ "commands",
4373
+ "test",
4374
+ "regression",
4375
+ "down.js"
4376
+ ]
4377
+ },
4378
+ "test:regression:export": {
4379
+ "aliases": [],
4380
+ "args": {},
4381
+ "description": "Export a regression run's HTML report as a single self-contained file (screenshots inlined as base64), producing report.standalone.html. Portable for sharing or attaching as a CI artifact.",
4382
+ "examples": [
4383
+ "<%= config.bin %> <%= command.id %>",
4384
+ "<%= config.bin %> <%= command.id %> --run=run-20260526T220118Z",
4385
+ "<%= config.bin %> <%= command.id %> --run=./some/other/run-dir"
4386
+ ],
4387
+ "flags": {
4388
+ "run": {
4389
+ "char": "r",
4390
+ "description": "Which run to export. A folder name (under test-results/) or a path. Defaults to the latest run.",
4391
+ "name": "run",
4392
+ "hasDynamicHelp": false,
4393
+ "multiple": false,
4394
+ "type": "option"
4395
+ },
4396
+ "image": {
4397
+ "description": "(external) Published image used to inline reports. Default: memberjunction/agentic-test-runner:latest.",
4398
+ "name": "image",
4399
+ "hasDynamicHelp": false,
4400
+ "multiple": false,
4401
+ "type": "option"
4402
+ }
4403
+ },
4404
+ "hasDynamicHelp": false,
4405
+ "hiddenAliases": [],
4406
+ "id": "test:regression:export",
4407
+ "pluginAlias": "@memberjunction/cli",
4408
+ "pluginName": "@memberjunction/cli",
4409
+ "pluginType": "core",
4410
+ "strict": true,
4411
+ "enableJsonFlag": false,
4412
+ "isESM": true,
4413
+ "relativePath": [
4414
+ "dist",
4415
+ "commands",
4416
+ "test",
4417
+ "regression",
4418
+ "export.js"
4419
+ ]
4420
+ },
4421
+ "test:regression:gen-forms": {
4422
+ "aliases": [],
4423
+ "args": {},
4424
+ "description": "Regenerate Angular entity forms used by the regression MJExplorer image. Slow (~5 min) — only required after schema or codegen changes.",
4425
+ "examples": [
4426
+ "<%= config.bin %> <%= command.id %>"
4427
+ ],
4428
+ "flags": {},
4429
+ "hasDynamicHelp": false,
4430
+ "hiddenAliases": [],
4431
+ "id": "test:regression:gen-forms",
4432
+ "pluginAlias": "@memberjunction/cli",
4433
+ "pluginName": "@memberjunction/cli",
4434
+ "pluginType": "core",
4435
+ "strict": true,
4436
+ "enableJsonFlag": false,
4437
+ "isESM": true,
4438
+ "relativePath": [
4439
+ "dist",
4440
+ "commands",
4441
+ "test",
4442
+ "regression",
4443
+ "gen-forms.js"
4444
+ ]
4445
+ },
4446
+ "test:regression": {
4447
+ "aliases": [],
4448
+ "args": {},
4449
+ "description": "MJ Explorer regression test suite — Docker-based LLM-driven browser tests",
4450
+ "examples": [
4451
+ "<%= config.bin %> <%= command.id %> build # Build images (incl. gen-forms on first run)",
4452
+ "<%= config.bin %> <%= command.id %> up # Run the full self-contained MJ stack (Mode A)",
4453
+ "<%= config.bin %> <%= command.id %> down # Tear down + wipe DB volumes",
4454
+ "<%= config.bin %> <%= command.id %> gen-forms # Regenerate Angular entity forms",
4455
+ "<%= config.bin %> <%= command.id %> compare # Diff the two most recent runs",
4456
+ "<%= config.bin %> <%= command.id %> export # Export a run as a portable standalone HTML",
4457
+ "<%= config.bin %> <%= command.id %> remote --target=staging-mj # Mode B/C/D against a remote URL",
4458
+ "<%= config.bin %> <%= command.id %> init generic-web # Scaffold one of the example dirs"
4459
+ ],
4460
+ "flags": {},
4461
+ "hasDynamicHelp": false,
4462
+ "hiddenAliases": [],
4463
+ "id": "test:regression",
4464
+ "pluginAlias": "@memberjunction/cli",
4465
+ "pluginName": "@memberjunction/cli",
4466
+ "pluginType": "core",
4467
+ "strict": true,
4468
+ "enableJsonFlag": false,
4469
+ "isESM": true,
4470
+ "relativePath": [
4471
+ "dist",
4472
+ "commands",
4473
+ "test",
4474
+ "regression",
4475
+ "index.js"
4476
+ ]
4477
+ },
4478
+ "test:regression:init": {
4479
+ "aliases": [],
4480
+ "args": {
4481
+ "name": {
4482
+ "description": "Template name to scaffold (run with --list to see available).",
4483
+ "name": "name",
4484
+ "required": false
4485
+ }
4486
+ },
4487
+ "description": "Scaffold one of the bundled regression-suite mode templates into the current directory. Adapt the generated files (target profile + optional compose overlay + tests) to point at your app, then run `mj test regression remote --target=...` to execute the suite against it.",
4488
+ "examples": [
4489
+ "<%= config.bin %> <%= command.id %> generic-web",
4490
+ "<%= config.bin %> <%= command.id %> static-file-server",
4491
+ "<%= config.bin %> <%= command.id %> remote-mj",
4492
+ "<%= config.bin %> <%= command.id %> bring-your-own-app",
4493
+ "<%= config.bin %> <%= command.id %> --list"
4494
+ ],
4495
+ "flags": {
4496
+ "list": {
4497
+ "description": "List available templates and exit.",
4498
+ "name": "list",
4499
+ "allowNo": false,
4500
+ "type": "boolean"
4501
+ }
4502
+ },
4503
+ "hasDynamicHelp": false,
4504
+ "hiddenAliases": [],
4505
+ "id": "test:regression:init",
4506
+ "pluginAlias": "@memberjunction/cli",
4507
+ "pluginName": "@memberjunction/cli",
4508
+ "pluginType": "core",
4509
+ "strict": true,
4510
+ "enableJsonFlag": false,
4511
+ "isESM": true,
4512
+ "relativePath": [
4513
+ "dist",
4514
+ "commands",
4515
+ "test",
4516
+ "regression",
4517
+ "init.js"
4518
+ ]
4519
+ },
4520
+ "test:regression:remote": {
4521
+ "aliases": [],
4522
+ "args": {},
4523
+ "description": "Run the regression suite against a remote URL (Mode B/C/D). Inside the MJ monorepo it drives the local compose stack; outside it runs the published agentic-test-runner image (no monorepo needed).",
4524
+ "examples": [
4525
+ "<%= config.bin %> <%= command.id %> --target=staging-mj",
4526
+ "<%= config.bin %> <%= command.id %> --target=./my/custom.target.json",
4527
+ "<%= config.bin %> <%= command.id %> --target=./app/target.json --overlay=./app/docker-compose.app.yml",
4528
+ "<%= config.bin %> <%= command.id %> --target=./t.json --image=memberjunction/agentic-test-runner:v5.30.0 --env-file=./.env"
4529
+ ],
4530
+ "flags": {
4531
+ "target": {
4532
+ "char": "t",
4533
+ "description": "Target profile. Bare name (monorepo: docker/regression/targets/<name>.target.json) or a path.",
4534
+ "name": "target",
4535
+ "required": true,
4536
+ "hasDynamicHelp": false,
4537
+ "multiple": false,
4538
+ "type": "option"
4539
+ },
4540
+ "no-local-stack": {
4541
+ "description": "(monorepo only) Use the lean `remote-target` profile (test-runner only) instead of the full local stack.",
4542
+ "name": "no-local-stack",
4543
+ "allowNo": false,
4544
+ "type": "boolean"
4545
+ },
4546
+ "overlay": {
4547
+ "description": "docker-compose overlay (Mode D) that boots your app alongside the runner on the same network. May repeat.",
4548
+ "name": "overlay",
4549
+ "hasDynamicHelp": false,
4550
+ "multiple": true,
4551
+ "type": "option"
4552
+ },
4553
+ "image": {
4554
+ "description": "(external) Published image tag to run. Default: memberjunction/agentic-test-runner:latest. Pin for reproducibility.",
4555
+ "name": "image",
4556
+ "hasDynamicHelp": false,
4557
+ "multiple": false,
4558
+ "type": "option"
4559
+ },
4560
+ "env-file": {
4561
+ "description": "(external) Path to a .env injected into the runner (DB_*, AI_VENDOR_API_KEY__GeminiLLM, auth env: refs).",
4562
+ "name": "env-file",
4563
+ "hasDynamicHelp": false,
4564
+ "multiple": false,
4565
+ "type": "option"
4566
+ },
4567
+ "detach": {
4568
+ "char": "d",
4569
+ "description": "(monorepo) Run in the background (docker compose up -d).",
4570
+ "name": "detach",
4571
+ "allowNo": false,
4572
+ "type": "boolean"
4573
+ }
4574
+ },
4575
+ "hasDynamicHelp": false,
4576
+ "hiddenAliases": [],
4577
+ "id": "test:regression:remote",
4578
+ "pluginAlias": "@memberjunction/cli",
4579
+ "pluginName": "@memberjunction/cli",
4580
+ "pluginType": "core",
4581
+ "strict": true,
4582
+ "enableJsonFlag": false,
4583
+ "isESM": true,
4584
+ "relativePath": [
4585
+ "dist",
4586
+ "commands",
4587
+ "test",
4588
+ "regression",
4589
+ "remote.js"
4590
+ ]
4591
+ },
4592
+ "test:regression:up": {
4593
+ "aliases": [],
4594
+ "args": {},
4595
+ "description": "Run the self-contained MJ regression stack (Mode A). With --bacpac, the DB is imported from a .bacpac. Inside the monorepo this builds from source; outside, --bacpac runs the published-image stack (plain `up` is monorepo-only).",
4596
+ "examples": [
4597
+ "<%= config.bin %> <%= command.id %>",
4598
+ "<%= config.bin %> <%= command.id %> --detach",
4599
+ "<%= config.bin %> <%= command.id %> --bacpac=./db.bacpac --suite=\"My Suite\" --metadata=./my-suite-metadata",
4600
+ "<%= config.bin %> <%= command.id %> --bacpac=./db.bacpac --bacpac-no-upgrade"
4601
+ ],
4602
+ "flags": {
4603
+ "detach": {
4604
+ "char": "d",
4605
+ "description": "Run containers in the background (docker compose up -d).",
4606
+ "name": "detach",
4607
+ "allowNo": false,
4608
+ "type": "boolean"
4609
+ },
4610
+ "bacpac": {
4611
+ "description": "Path to a .bacpac of a real MJ database to import and test against.",
4612
+ "name": "bacpac",
4613
+ "hasDynamicHelp": false,
4614
+ "multiple": false,
4615
+ "type": "option"
4616
+ },
4617
+ "bacpac-no-upgrade": {
4618
+ "description": "Import the bacpac as-is — skip migrate/codegen. Only safe at the current MJ version. Requires --bacpac.",
4619
+ "name": "bacpac-no-upgrade",
4620
+ "allowNo": false,
4621
+ "type": "boolean"
4622
+ },
4623
+ "suite": {
4624
+ "description": "Test suite to run (TEST_SUITE_NAME). Use with --bacpac + --metadata.",
4625
+ "name": "suite",
4626
+ "hasDynamicHelp": false,
4627
+ "multiple": false,
4628
+ "type": "option"
4629
+ },
4630
+ "metadata": {
4631
+ "description": "Directory of your test + test-suite metadata (pushed before the run). Requires --bacpac.",
4632
+ "name": "metadata",
4633
+ "hasDynamicHelp": false,
4634
+ "multiple": false,
4635
+ "type": "option"
4636
+ },
4637
+ "image": {
4638
+ "description": "(external) Published agentic-test-runner image. Default: memberjunction/agentic-test-runner:latest.",
4639
+ "name": "image",
4640
+ "hasDynamicHelp": false,
4641
+ "multiple": false,
4642
+ "type": "option"
4643
+ },
4644
+ "explorer-image": {
4645
+ "description": "(external bacpac) Published Explorer image (prerequisite). Default: memberjunction/explorer:latest.",
4646
+ "name": "explorer-image",
4647
+ "hasDynamicHelp": false,
4648
+ "multiple": false,
4649
+ "type": "option"
4650
+ },
4651
+ "env-file": {
4652
+ "description": "(external) .env injected into the runner (auth env: refs).",
4653
+ "name": "env-file",
4654
+ "hasDynamicHelp": false,
4655
+ "multiple": false,
4656
+ "type": "option"
4657
+ }
4658
+ },
4659
+ "hasDynamicHelp": false,
4660
+ "hiddenAliases": [],
4661
+ "id": "test:regression:up",
4662
+ "pluginAlias": "@memberjunction/cli",
4663
+ "pluginName": "@memberjunction/cli",
4664
+ "pluginType": "core",
4665
+ "strict": true,
4666
+ "enableJsonFlag": false,
4667
+ "isESM": true,
4668
+ "relativePath": [
4669
+ "dist",
4670
+ "commands",
4671
+ "test",
4672
+ "regression",
4673
+ "up.js"
4674
+ ]
3828
4675
  }
3829
4676
  },
3830
- "version": "5.37.0"
4677
+ "version": "5.38.0"
3831
4678
  }