@memberjunction/cli 5.37.0 → 5.39.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 (177) 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 +519 -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/bundle/index.d.ts +21 -0
  59. package/dist/commands/bundle/index.d.ts.map +1 -0
  60. package/dist/commands/bundle/index.js +62 -0
  61. package/dist/commands/bundle/index.js.map +1 -0
  62. package/dist/commands/migrate/index.d.ts +29 -0
  63. package/dist/commands/migrate/index.d.ts.map +1 -1
  64. package/dist/commands/migrate/index.js +111 -5
  65. package/dist/commands/migrate/index.js.map +1 -1
  66. package/dist/commands/test/compare.d.ts +3 -0
  67. package/dist/commands/test/compare.d.ts.map +1 -1
  68. package/dist/commands/test/compare.js +23 -3
  69. package/dist/commands/test/compare.js.map +1 -1
  70. package/dist/commands/test/regression/build.d.ts +14 -0
  71. package/dist/commands/test/regression/build.d.ts.map +1 -0
  72. package/dist/commands/test/regression/build.js +48 -0
  73. package/dist/commands/test/regression/build.js.map +1 -0
  74. package/dist/commands/test/regression/compare.d.ts +15 -0
  75. package/dist/commands/test/regression/compare.d.ts.map +1 -0
  76. package/dist/commands/test/regression/compare.js +66 -0
  77. package/dist/commands/test/regression/compare.js.map +1 -0
  78. package/dist/commands/test/regression/down.d.ts +10 -0
  79. package/dist/commands/test/regression/down.d.ts.map +1 -0
  80. package/dist/commands/test/regression/down.js +29 -0
  81. package/dist/commands/test/regression/down.js.map +1 -0
  82. package/dist/commands/test/regression/export.d.ts +11 -0
  83. package/dist/commands/test/regression/export.d.ts.map +1 -0
  84. package/dist/commands/test/regression/export.js +56 -0
  85. package/dist/commands/test/regression/export.js.map +1 -0
  86. package/dist/commands/test/regression/gen-forms.d.ts +7 -0
  87. package/dist/commands/test/regression/gen-forms.d.ts.map +1 -0
  88. package/dist/commands/test/regression/gen-forms.js +18 -0
  89. package/dist/commands/test/regression/gen-forms.js.map +1 -0
  90. package/dist/commands/test/regression/index.d.ts +7 -0
  91. package/dist/commands/test/regression/index.d.ts.map +1 -0
  92. package/dist/commands/test/regression/index.js +33 -0
  93. package/dist/commands/test/regression/index.js.map +1 -0
  94. package/dist/commands/test/regression/init.d.ts +21 -0
  95. package/dist/commands/test/regression/init.d.ts.map +1 -0
  96. package/dist/commands/test/regression/init.js +111 -0
  97. package/dist/commands/test/regression/init.js.map +1 -0
  98. package/dist/commands/test/regression/remote.d.ts +23 -0
  99. package/dist/commands/test/regression/remote.d.ts.map +1 -0
  100. package/dist/commands/test/regression/remote.js +140 -0
  101. package/dist/commands/test/regression/remote.js.map +1 -0
  102. package/dist/commands/test/regression/up.d.ts +21 -0
  103. package/dist/commands/test/regression/up.d.ts.map +1 -0
  104. package/dist/commands/test/regression/up.js +111 -0
  105. package/dist/commands/test/regression/up.js.map +1 -0
  106. package/dist/commands/test/run.d.ts +1 -0
  107. package/dist/commands/test/run.d.ts.map +1 -1
  108. package/dist/commands/test/run.js +6 -0
  109. package/dist/commands/test/run.js.map +1 -1
  110. package/dist/commands/test/suite.d.ts +5 -0
  111. package/dist/commands/test/suite.d.ts.map +1 -1
  112. package/dist/commands/test/suite.js +27 -0
  113. package/dist/commands/test/suite.js.map +1 -1
  114. package/dist/commands/translate-sql/index.d.ts.map +1 -1
  115. package/dist/commands/translate-sql/index.js +3 -2
  116. package/dist/commands/translate-sql/index.js.map +1 -1
  117. package/dist/config.d.ts +6 -0
  118. package/dist/config.d.ts.map +1 -1
  119. package/dist/config.js +13 -0
  120. package/dist/config.js.map +1 -1
  121. package/dist/init-templates/bring-your-own-app/README.md +74 -0
  122. package/dist/init-templates/bring-your-own-app/byo-metadata/.mj-sync.json +10 -0
  123. package/dist/init-templates/bring-your-own-app/byo-metadata/test-suites/.byo-suite.json +51 -0
  124. package/dist/init-templates/bring-your-own-app/byo-metadata/test-suites/.mj-sync.json +12 -0
  125. package/dist/init-templates/bring-your-own-app/byo-metadata/tests/.T01-counter-increment.json +63 -0
  126. package/dist/init-templates/bring-your-own-app/byo-metadata/tests/.T02-contact-form-submit.json +63 -0
  127. package/dist/init-templates/bring-your-own-app/byo-metadata/tests/.mj-sync.json +12 -0
  128. package/dist/init-templates/bring-your-own-app/docker-compose.app.yml +76 -0
  129. package/dist/init-templates/bring-your-own-app/target.json +23 -0
  130. package/dist/init-templates/generic-web/README.md +115 -0
  131. package/dist/init-templates/generic-web/metadata/.mj-sync.json +10 -0
  132. package/dist/init-templates/generic-web/metadata/test-suites/.generic-web-suite.json +48 -0
  133. package/dist/init-templates/generic-web/metadata/test-suites/.mj-sync.json +12 -0
  134. package/dist/init-templates/generic-web/metadata/tests/.GW01-home-loads.json +74 -0
  135. package/dist/init-templates/generic-web/metadata/tests/.GW02-search-array-map.json +82 -0
  136. package/dist/init-templates/generic-web/metadata/tests/.mj-sync.json +12 -0
  137. package/dist/init-templates/generic-web/oracles/mdn-oracles.cjs +121 -0
  138. package/dist/init-templates/generic-web/target.json +25 -0
  139. package/dist/init-templates/github-actions/README.md +26 -0
  140. package/dist/init-templates/github-actions/regression.yml +52 -0
  141. package/dist/init-templates/remote-mj/README.md +95 -0
  142. package/dist/init-templates/remote-mj/target.json +22 -0
  143. package/dist/init-templates/static-file-server/Dockerfile +23 -0
  144. package/dist/init-templates/static-file-server/README.md +88 -0
  145. package/dist/init-templates/static-file-server/docker-compose.app.yml +44 -0
  146. package/dist/init-templates/static-file-server/metadata/.mj-sync.json +10 -0
  147. package/dist/init-templates/static-file-server/metadata/test-suites/.mj-sync.json +12 -0
  148. package/dist/init-templates/static-file-server/metadata/test-suites/.static-server-suite.json +27 -0
  149. package/dist/init-templates/static-file-server/metadata/tests/.SS01-home-loads.json +45 -0
  150. package/dist/init-templates/static-file-server/metadata/tests/.SS02-navigate-about.json +45 -0
  151. package/dist/init-templates/static-file-server/metadata/tests/.mj-sync.json +12 -0
  152. package/dist/init-templates/static-file-server/public/about.html +12 -0
  153. package/dist/init-templates/static-file-server/public/index.html +27 -0
  154. package/dist/init-templates/static-file-server/target.json +16 -0
  155. package/dist/lib/db-preflight.d.ts +42 -0
  156. package/dist/lib/db-preflight.d.ts.map +1 -0
  157. package/dist/lib/db-preflight.js +113 -0
  158. package/dist/lib/db-preflight.js.map +1 -0
  159. package/dist/lib/db-version.d.ts +36 -0
  160. package/dist/lib/db-version.d.ts.map +1 -0
  161. package/dist/lib/db-version.js +45 -0
  162. package/dist/lib/db-version.js.map +1 -0
  163. package/dist/lib/migration-fetch.d.ts +49 -0
  164. package/dist/lib/migration-fetch.d.ts.map +1 -0
  165. package/dist/lib/migration-fetch.js +152 -0
  166. package/dist/lib/migration-fetch.js.map +1 -0
  167. package/dist/lib/regression/docker-helpers.d.ts +98 -0
  168. package/dist/lib/regression/docker-helpers.d.ts.map +1 -0
  169. package/dist/lib/regression/docker-helpers.js +184 -0
  170. package/dist/lib/regression/docker-helpers.js.map +1 -0
  171. package/dist/light-commands.d.ts.map +1 -1
  172. package/dist/light-commands.js +2 -0
  173. package/dist/light-commands.js.map +1 -1
  174. package/oclif.manifest.json +1635 -702
  175. package/package.json +22 -17
  176. package/regression-compose/docker-compose.bacpac-standalone.yml +109 -0
  177. package/regression-compose/docker-compose.standalone.yml +50 -0
@@ -338,78 +338,6 @@
338
338
  "upgrade.js"
339
339
  ]
340
340
  },
341
- "bump": {
342
- "aliases": [],
343
- "args": {},
344
- "description": "Bumps MemberJunction dependency versions",
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
- }
358
- ],
359
- "flags": {
360
- "verbose": {
361
- "char": "v",
362
- "description": "Enable additional logging",
363
- "name": "verbose",
364
- "allowNo": false,
365
- "type": "boolean"
366
- },
367
- "recursive": {
368
- "char": "r",
369
- "description": "Bump version in current directory and all subdirectories",
370
- "name": "recursive",
371
- "allowNo": false,
372
- "type": "boolean"
373
- },
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",
378
- "hasDynamicHelp": false,
379
- "multiple": false,
380
- "type": "option"
381
- },
382
- "quiet": {
383
- "char": "q",
384
- "description": "Only output paths for updated packages",
385
- "name": "quiet",
386
- "allowNo": false,
387
- "type": "boolean"
388
- },
389
- "dry": {
390
- "char": "d",
391
- "description": "Dry run, do not write changes to package.json files",
392
- "name": "dry",
393
- "allowNo": false,
394
- "type": "boolean"
395
- }
396
- },
397
- "hasDynamicHelp": false,
398
- "hiddenAliases": [],
399
- "id": "bump",
400
- "pluginAlias": "@memberjunction/cli",
401
- "pluginName": "@memberjunction/cli",
402
- "pluginType": "core",
403
- "strict": true,
404
- "enableJsonFlag": false,
405
- "isESM": true,
406
- "relativePath": [
407
- "dist",
408
- "commands",
409
- "bump",
410
- "index.js"
411
- ]
412
- },
413
341
  "artifacts:reclassify": {
414
342
  "aliases": [],
415
343
  "args": {},
@@ -471,100 +399,92 @@
471
399
  "reclassify.js"
472
400
  ]
473
401
  },
474
- "clean": {
402
+ "baseline:build": {
475
403
  "aliases": [],
476
404
  "args": {},
477
- "description": "Resets the MemberJunction database to a pre-installation state",
405
+ "description": "Generate a deterministic baseline SQL script from the END-STATE of a migrated MSSQL database.",
478
406
  "examples": [
479
- "<%= config.bin %> <%= command.id %>\n"
407
+ "<%= config.bin %> <%= command.id %> --out ./migrations/v5/ # auto: within-major rebaseline",
408
+ "<%= config.bin %> <%= command.id %> --source-dir ./migrations/v5 --out ./migrations/v5/",
409
+ "<%= config.bin %> <%= command.id %> --baseline-version 6.0 --out ./migrations/v6/ # explicit major-boundary",
410
+ "<%= config.bin %> <%= command.id %> --baseline-version 5.32 --database MJ_BL_Stack --out /tmp/baseline/"
480
411
  ],
481
412
  "flags": {
482
- "verbose": {
483
- "char": "v",
484
- "description": "Enable additional logging",
485
- "name": "verbose",
486
- "allowNo": false,
487
- "type": "boolean"
488
- }
489
- },
490
- "hasDynamicHelp": false,
491
- "hiddenAliases": [],
492
- "id": "clean",
493
- "pluginAlias": "@memberjunction/cli",
494
- "pluginName": "@memberjunction/cli",
495
- "pluginType": "core",
496
- "strict": true,
497
- "enableJsonFlag": false,
498
- "isESM": true,
499
- "relativePath": [
500
- "dist",
501
- "commands",
502
- "clean",
503
- "index.js"
504
- ]
505
- },
506
- "codegen:5-0-fix-entity-names": {
507
- "aliases": [],
508
- "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.",
510
- "examples": [
511
- {
512
- "description": "Dry-run scan of the packages directory",
513
- "command": "<%= config.bin %> <%= command.id %> --path packages/"
413
+ "baseline-version": {
414
+ "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).",
415
+ "name": "baseline-version",
416
+ "hasDynamicHelp": false,
417
+ "multiple": false,
418
+ "type": "option"
514
419
  },
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"
420
+ "source-dir": {
421
+ "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.",
422
+ "name": "source-dir",
423
+ "hasDynamicHelp": false,
424
+ "multiple": false,
425
+ "type": "option"
518
426
  },
519
- {
520
- "description": "Apply fixes across the codebase",
521
- "command": "<%= config.bin %> <%= command.id %> --path packages/ --fix"
427
+ "description": {
428
+ "description": "Human-readable description embedded in the file header.",
429
+ "name": "description",
430
+ "default": "MemberJunction Baseline",
431
+ "hasDynamicHelp": false,
432
+ "multiple": false,
433
+ "type": "option"
522
434
  },
523
- {
524
- "description": "Quiet mode (summary only)",
525
- "command": "<%= config.bin %> <%= command.id %> --path packages/ -q"
526
- }
527
- ],
528
- "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",
435
+ "database": {
436
+ "description": "Override database name (host/user/password come from MJ config).",
437
+ "name": "database",
533
438
  "hasDynamicHelp": false,
534
439
  "multiple": false,
535
440
  "type": "option"
536
441
  },
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"
442
+ "out": {
443
+ "description": "Output directory. Filename is auto-generated.",
444
+ "name": "out",
445
+ "default": ".",
446
+ "hasDynamicHelp": false,
447
+ "multiple": false,
448
+ "type": "option"
542
449
  },
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",
450
+ "exclude-data": {
451
+ "description": "Comma-separated list of tables (schema-qualified or not) to skip data dump for.",
452
+ "name": "exclude-data",
453
+ "default": "",
546
454
  "hasDynamicHelp": false,
547
455
  "multiple": false,
548
456
  "type": "option"
549
457
  },
550
- "quiet": {
551
- "char": "q",
552
- "description": "Suppress detailed per-file output; only show the final summary counts.",
553
- "name": "quiet",
458
+ "batch-size": {
459
+ "description": "Rows per INSERT batch.",
460
+ "name": "batch-size",
461
+ "default": 1000,
462
+ "hasDynamicHelp": false,
463
+ "multiple": false,
464
+ "type": "option"
465
+ },
466
+ "no-data": {
467
+ "description": "Emit schema only, no data inserts.",
468
+ "name": "no-data",
554
469
  "allowNo": false,
555
470
  "type": "boolean"
556
471
  },
557
472
  "verbose": {
558
- "char": "v",
559
- "description": "Show detailed progress including each file being scanned.",
473
+ "description": "Print per-object progress.",
560
474
  "name": "verbose",
561
475
  "allowNo": false,
562
476
  "type": "boolean"
477
+ },
478
+ "dry-run": {
479
+ "description": "Print to stdout instead of writing a file.",
480
+ "name": "dry-run",
481
+ "allowNo": false,
482
+ "type": "boolean"
563
483
  }
564
484
  },
565
485
  "hasDynamicHelp": false,
566
486
  "hiddenAliases": [],
567
- "id": "codegen:5-0-fix-entity-names",
487
+ "id": "baseline:build",
568
488
  "pluginAlias": "@memberjunction/cli",
569
489
  "pluginName": "@memberjunction/cli",
570
490
  "pluginType": "core",
@@ -574,64 +494,106 @@
574
494
  "relativePath": [
575
495
  "dist",
576
496
  "commands",
577
- "codegen",
578
- "5-0-fix-entity-names.js"
497
+ "baseline",
498
+ "build.js"
579
499
  ]
580
500
  },
581
- "codegen:5-0-fix-html-entity-names": {
501
+ "baseline:compare": {
582
502
  "aliases": [],
583
503
  "args": {},
584
- "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).",
504
+ "description": "Deterministically compare two databases object-by-object and row-by-row.",
585
505
  "examples": [
586
- {
587
- "description": "Dry-run scan of Angular templates",
588
- "command": "<%= config.bin %> <%= command.id %> --path packages/Angular/"
506
+ "<%= config.bin %> <%= command.id %> --left MJ_BL_Stack --right MJ_BL_New",
507
+ "<%= config.bin %> <%= command.id %> --left A --right B --row-compare counts",
508
+ "<%= config.bin %> <%= command.id %> --left A --right B --fail-on-diff --out ./diffs/"
509
+ ],
510
+ "flags": {
511
+ "left": {
512
+ "description": "Left database name (override).",
513
+ "name": "left",
514
+ "required": true,
515
+ "hasDynamicHelp": false,
516
+ "multiple": false,
517
+ "type": "option"
589
518
  },
590
- {
591
- "description": "Apply fixes to HTML templates",
592
- "command": "<%= config.bin %> <%= command.id %> --path packages/Angular/ --fix"
519
+ "right": {
520
+ "description": "Right database name (override).",
521
+ "name": "right",
522
+ "required": true,
523
+ "hasDynamicHelp": false,
524
+ "multiple": false,
525
+ "type": "option"
593
526
  },
594
- {
595
- "description": "Scan with verbose output",
596
- "command": "<%= config.bin %> <%= command.id %> --path packages/ -v"
527
+ "dialect": {
528
+ "description": "Dialect of both DBs (must match).",
529
+ "name": "dialect",
530
+ "default": "mssql",
531
+ "hasDynamicHelp": false,
532
+ "multiple": false,
533
+ "options": [
534
+ "mssql",
535
+ "postgres"
536
+ ],
537
+ "type": "option"
597
538
  },
598
- {
599
- "description": "Scan a single template file",
600
- "command": "<%= config.bin %> <%= command.id %> --path packages/Angular/Explorer/dashboards/src/Actions/actions-dashboard.component.html"
601
- }
602
- ],
603
- "flags": {
604
- "path": {
605
- "char": "p",
606
- "description": "File or directory to scan. Accepts a single .html file or a directory (scanned recursively). Defaults to the current working directory.",
607
- "name": "path",
539
+ "row-compare": {
540
+ "description": "Row comparison mode.",
541
+ "name": "row-compare",
542
+ "default": "full",
608
543
  "hasDynamicHelp": false,
609
544
  "multiple": false,
545
+ "options": [
546
+ "full",
547
+ "hash",
548
+ "counts",
549
+ "none"
550
+ ],
610
551
  "type": "option"
611
552
  },
612
- "fix": {
613
- "description": "Apply fixes in place. Without this flag, the command runs in dry-run mode and only reports findings.",
614
- "name": "fix",
615
- "allowNo": false,
616
- "type": "boolean"
553
+ "row-hash-algo": {
554
+ "description": "Hash algorithm when --row-compare hash.",
555
+ "name": "row-hash-algo",
556
+ "default": "sha256",
557
+ "hasDynamicHelp": false,
558
+ "multiple": false,
559
+ "options": [
560
+ "sha256",
561
+ "md5",
562
+ "checksum_agg"
563
+ ],
564
+ "type": "option"
617
565
  },
618
- "entity-subclasses": {
619
- "description": "Explicit path to entity_subclasses.ts for building the rename map. If omitted, the tool searches common locations relative to the target path.",
620
- "name": "entity-subclasses",
566
+ "ignore": {
567
+ "description": "Regex of object names to skip.",
568
+ "name": "ignore",
569
+ "default": "^flyway_schema_history$",
621
570
  "hasDynamicHelp": false,
622
571
  "multiple": false,
623
572
  "type": "option"
624
573
  },
625
- "quiet": {
626
- "char": "q",
627
- "description": "Suppress detailed per-file output; only show the final summary counts.",
628
- "name": "quiet",
574
+ "sample-limit": {
575
+ "description": "Maximum row diffs to capture per table.",
576
+ "name": "sample-limit",
577
+ "default": 100,
578
+ "hasDynamicHelp": false,
579
+ "multiple": false,
580
+ "type": "option"
581
+ },
582
+ "out": {
583
+ "description": "Directory to write JSON + Markdown reports.",
584
+ "name": "out",
585
+ "hasDynamicHelp": false,
586
+ "multiple": false,
587
+ "type": "option"
588
+ },
589
+ "fail-on-diff": {
590
+ "description": "Exit non-zero if any diff is found.",
591
+ "name": "fail-on-diff",
629
592
  "allowNo": false,
630
593
  "type": "boolean"
631
594
  },
632
595
  "verbose": {
633
- "char": "v",
634
- "description": "Show detailed progress including each file being scanned.",
596
+ "description": "Print per-phase progress.",
635
597
  "name": "verbose",
636
598
  "allowNo": false,
637
599
  "type": "boolean"
@@ -639,7 +601,7 @@
639
601
  },
640
602
  "hasDynamicHelp": false,
641
603
  "hiddenAliases": [],
642
- "id": "codegen:5-0-fix-html-entity-names",
604
+ "id": "baseline:compare",
643
605
  "pluginAlias": "@memberjunction/cli",
644
606
  "pluginName": "@memberjunction/cli",
645
607
  "pluginType": "core",
@@ -649,64 +611,111 @@
649
611
  "relativePath": [
650
612
  "dist",
651
613
  "commands",
652
- "codegen",
653
- "5-0-fix-html-entity-names.js"
614
+ "baseline",
615
+ "compare.js"
654
616
  ]
655
617
  },
656
- "codegen:5-0-fix-metadata-names": {
618
+ "baseline:roundtrip": {
657
619
  "aliases": [],
658
620
  "args": {},
659
- "description": "[v5.0 Migration] Scan metadata JSON files for entity names that need \"MJ: \" prefix updates.\n\nTargets the metadata/ directory used by \"mj sync\". Detects entity name references in\n@lookup: directives (both the entity name and lookup value), .mj-sync.json and\n.mj-folder.json config files (entity/entityName fields), relatedEntities object keys,\nand fields.Name values in Entities-managing folders. Runs in dry-run mode by default;\nuse --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).",
621
+ "description": "Build a baseline from a V-stack database, apply it to a fresh DB, and prove byte-equivalence.",
660
622
  "examples": [
661
- {
662
- "description": "Dry-run scan of the metadata directory",
663
- "command": "<%= config.bin %> <%= command.id %> --path metadata/"
664
- },
665
- {
666
- "description": "Apply fixes to metadata files",
667
- "command": "<%= config.bin %> <%= command.id %> --path metadata/ --fix"
668
- },
669
- {
670
- "description": "Scan a specific subdirectory",
671
- "command": "<%= config.bin %> <%= command.id %> --path metadata/resource-types"
672
- },
673
- {
674
- "description": "Scan and fix a single metadata file",
675
- "command": "<%= config.bin %> <%= command.id %> --path metadata/entities/.audit-related-entities.json --fix"
676
- }
623
+ "<%= config.bin %> <%= command.id %> --source MJ_BL_Stack --target MJ_BL_New # auto: within-major",
624
+ "<%= config.bin %> <%= command.id %> --baseline-version 6.0 --source MJ_BL_Stack --target MJ_BL_New # explicit major-boundary",
625
+ "<%= config.bin %> <%= command.id %> --source-dir ./migrations/v5 --source MJ_BL_Stack --target MJ_BL_New"
677
626
  ],
678
627
  "flags": {
679
- "path": {
680
- "char": "p",
681
- "description": "File or directory to scan. Accepts a single .json file or a directory (scanned recursively, including dotfiles like .mj-sync.json). Defaults to the current working directory.",
682
- "name": "path",
628
+ "baseline-version": {
629
+ "description": "Major.Minor version stamp. Omit to auto-detect from --source-dir (within-major rebaseline).",
630
+ "name": "baseline-version",
683
631
  "hasDynamicHelp": false,
684
632
  "multiple": false,
685
633
  "type": "option"
686
634
  },
687
- "fix": {
688
- "description": "Apply fixes in place. Without this flag, the command runs in dry-run mode and only reports findings.",
689
- "name": "fix",
690
- "allowNo": false,
691
- "type": "boolean"
635
+ "source-dir": {
636
+ "description": "Migrations source directory used to auto-detect baseline version + timestamp when --baseline-version is omitted. Defaults to the highest migrations/v*/ near cwd.",
637
+ "name": "source-dir",
638
+ "hasDynamicHelp": false,
639
+ "multiple": false,
640
+ "type": "option"
692
641
  },
693
- "entity-subclasses": {
694
- "description": "Explicit path to entity_subclasses.ts for building the rename map. If omitted, the tool searches common locations relative to the target path.",
695
- "name": "entity-subclasses",
642
+ "description": {
643
+ "description": "Header description.",
644
+ "name": "description",
645
+ "default": "MemberJunction Baseline",
696
646
  "hasDynamicHelp": false,
697
647
  "multiple": false,
698
648
  "type": "option"
699
649
  },
700
- "quiet": {
701
- "char": "q",
702
- "description": "Suppress detailed per-file output; only show the final summary counts.",
703
- "name": "quiet",
650
+ "dialect": {
651
+ "description": "Dialect to test. PG path runs the converter via /pg-migrate first.",
652
+ "name": "dialect",
653
+ "default": "mssql",
654
+ "hasDynamicHelp": false,
655
+ "multiple": false,
656
+ "options": [
657
+ "mssql",
658
+ "postgres"
659
+ ],
660
+ "type": "option"
661
+ },
662
+ "source": {
663
+ "description": "Database name with the V-stack already applied (used as comparison gold standard).",
664
+ "name": "source",
665
+ "required": true,
666
+ "hasDynamicHelp": false,
667
+ "multiple": false,
668
+ "type": "option"
669
+ },
670
+ "target": {
671
+ "description": "Empty database name to apply the new baseline to.",
672
+ "name": "target",
673
+ "required": true,
674
+ "hasDynamicHelp": false,
675
+ "multiple": false,
676
+ "type": "option"
677
+ },
678
+ "out": {
679
+ "description": "Output directory for baseline file + reports.",
680
+ "name": "out",
681
+ "default": ".",
682
+ "hasDynamicHelp": false,
683
+ "multiple": false,
684
+ "type": "option"
685
+ },
686
+ "apply-cmd": {
687
+ "description": "Command template to apply the baseline. Tokens: {file} {database}. Defaults to sqlcmd.",
688
+ "name": "apply-cmd",
689
+ "hasDynamicHelp": false,
690
+ "multiple": false,
691
+ "type": "option"
692
+ },
693
+ "row-compare": {
694
+ "description": "Row compare mode passed to the comparator.",
695
+ "name": "row-compare",
696
+ "default": "full",
697
+ "hasDynamicHelp": false,
698
+ "multiple": false,
699
+ "options": [
700
+ "full",
701
+ "hash",
702
+ "counts",
703
+ "none"
704
+ ],
705
+ "type": "option"
706
+ },
707
+ "fail-on-diff": {
708
+ "name": "fail-on-diff",
709
+ "allowNo": false,
710
+ "type": "boolean"
711
+ },
712
+ "keep-target": {
713
+ "description": "Do not drop the target database after run (useful for debugging diffs).",
714
+ "name": "keep-target",
704
715
  "allowNo": false,
705
716
  "type": "boolean"
706
717
  },
707
718
  "verbose": {
708
- "char": "v",
709
- "description": "Show detailed progress including each file being scanned.",
710
719
  "name": "verbose",
711
720
  "allowNo": false,
712
721
  "type": "boolean"
@@ -714,7 +723,7 @@
714
723
  },
715
724
  "hasDynamicHelp": false,
716
725
  "hiddenAliases": [],
717
- "id": "codegen:5-0-fix-metadata-names",
726
+ "id": "baseline:roundtrip",
718
727
  "pluginAlias": "@memberjunction/cli",
719
728
  "pluginName": "@memberjunction/cli",
720
729
  "pluginType": "core",
@@ -724,55 +733,69 @@
724
733
  "relativePath": [
725
734
  "dist",
726
735
  "commands",
727
- "codegen",
728
- "5-0-fix-metadata-names.js"
736
+ "baseline",
737
+ "roundtrip.js"
729
738
  ]
730
739
  },
731
- "codegen": {
740
+ "bump": {
732
741
  "aliases": [],
733
742
  "args": {},
734
- "description": "Run the full MemberJunction code generation pipeline.\n\nAnalyzes your SQL Server database schema, updates MemberJunction metadata, and\ngenerates synchronized code across the entire stack:\n\n - SQL views, stored procedures, indexes, and permissions\n - TypeScript entity classes with Zod validation schemas\n - Angular form components with AI-driven layouts\n - GraphQL resolvers and type definitions\n - Action subclasses and DB schema JSON\n\nConfiguration is loaded from mj.config.cjs in the current directory (or parent\ndirectories). Database connection can also be set via environment variables:\nDB_HOST, DB_DATABASE, CODEGEN_DB_USERNAME, CODEGEN_DB_PASSWORD.\n\nUse --skipdb to skip all database operations (metadata sync, SQL object\ngeneration) and only regenerate TypeScript, Angular, and GraphQL output from\nexisting metadata.\n\nUse --skipfiles to skip all file-generation operations (TypeScript entities,\nAngular components, GraphQL resolvers, action subclasses, DB schema JSON) and\nonly run database-side operations (metadata sync, SQL object generation,\npermissions, custom SQL scripts).\n\n--skipdb and --skipfiles are independent and can be combined in any mix.\n\nUse --force-advanced-gen to bypass Pass 2 entity scoping and re-run the LLM-driven\nadvanced generation (smart fields, form layout) for ALL entities. Useful when AI\nprompts have changed and you want unchanged entities re-evaluated.",
743
+ "description": "Bumps MemberJunction dependency versions",
735
744
  "examples": [
736
745
  {
737
746
  "command": "<%= config.bin %> <%= command.id %>",
738
- "description": "Run the full code generation pipeline"
739
- },
740
- {
741
- "command": "<%= config.bin %> <%= command.id %> --skipdb",
742
- "description": "Regenerate code files without touching the database"
747
+ "description": "Bump all @memberjunction/* dependencies in the current directory's package.json to the CLI version"
743
748
  },
744
749
  {
745
- "command": "<%= config.bin %> <%= command.id %> --skipfiles",
746
- "description": "Run database-side operations only, without regenerating any code files"
750
+ "command": "<%= config.bin %> <%= command.id %> -rdv",
751
+ "description": "Preview all recursive packages bumps without writing any changes."
747
752
  },
748
753
  {
749
- "command": "<%= config.bin %> <%= command.id %> --force-advanced-gen",
750
- "description": "Re-run advanced generation for all entities (bypasses changed-entity scoping)"
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."
751
756
  }
752
757
  ],
753
758
  "flags": {
754
- "skipdb": {
755
- "description": "Skip database operations (metadata sync, SQL generation). Only regenerate TypeScript entities, Angular components, and GraphQL resolvers from existing metadata.",
756
- "name": "skipdb",
759
+ "verbose": {
760
+ "char": "v",
761
+ "description": "Enable additional logging",
762
+ "name": "verbose",
757
763
  "allowNo": false,
758
764
  "type": "boolean"
759
765
  },
760
- "skipfiles": {
761
- "description": "Skip file-generation operations (TypeScript entities, Angular components, GraphQL resolvers, action subclasses, DB schema JSON). Only run database-side operations.",
762
- "name": "skipfiles",
766
+ "recursive": {
767
+ "char": "r",
768
+ "description": "Bump version in current directory and all subdirectories",
769
+ "name": "recursive",
763
770
  "allowNo": false,
764
771
  "type": "boolean"
765
772
  },
766
- "force-advanced-gen": {
767
- "description": "Bypass entity scoping in Pass 2 and force advanced generation to re-run for all entities. Used when AI prompts have changed and unchanged entities should be re-evaluated.",
768
- "name": "force-advanced-gen",
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",
769
792
  "allowNo": false,
770
793
  "type": "boolean"
771
794
  }
772
795
  },
773
796
  "hasDynamicHelp": false,
774
797
  "hiddenAliases": [],
775
- "id": "codegen",
798
+ "id": "bump",
776
799
  "pluginAlias": "@memberjunction/cli",
777
800
  "pluginName": "@memberjunction/cli",
778
801
  "pluginType": "core",
@@ -782,117 +805,77 @@
782
805
  "relativePath": [
783
806
  "dist",
784
807
  "commands",
785
- "codegen",
808
+ "bump",
786
809
  "index.js"
787
810
  ]
788
811
  },
789
- "codegen:manifest": {
812
+ "bundle": {
790
813
  "aliases": [],
791
814
  "args": {},
792
- "description": "Generate a class registration manifest to prevent tree-shaking.\n\nMemberJunction uses @RegisterClass decorators with a dynamic class factory.\nModern bundlers (ESBuild, Vite) cannot detect dynamic instantiation and will\ntree-shake these classes out of production builds. This command scans the\ndependency tree for all @RegisterClass-decorated classes and emits a manifest\nfile with static imports that the bundler cannot eliminate.\n\nTypically used as a prebuild/prestart script for MJAPI and MJExplorer. For\nMJ distribution users, pre-built manifests ship inside @memberjunction/server-bootstrap\nand @memberjunction/ng-bootstrap -- use --exclude-packages @memberjunction to\ngenerate a supplemental manifest covering only your own application classes.",
815
+ "description": "Create a self-contained MemberJunction distribution zip for offline/air-gapped installs",
793
816
  "examples": [
794
- {
795
- "command": "<%= config.bin %> <%= command.id %>",
796
- "description": "Generate manifest with default output path"
797
- },
798
- {
799
- "command": "<%= config.bin %> <%= command.id %> --appDir ./packages/MJAPI --output ./packages/MJAPI/src/generated/class-registrations-manifest.ts",
800
- "description": "Generate manifest for a specific application directory"
801
- },
802
- {
803
- "command": "<%= config.bin %> <%= command.id %> --exclude-packages @memberjunction",
804
- "description": "Exclude MJ packages (use pre-built bootstrap manifests instead)"
805
- },
806
- {
807
- "command": "<%= config.bin %> <%= command.id %> --exclude-packages @memberjunction --no-sync-deps",
808
- "description": "Exclude MJ packages and skip dependency reconciliation"
809
- },
810
- {
811
- "command": "<%= config.bin %> <%= command.id %> --filter BaseEngine --filter BaseAction --verbose",
812
- "description": "Only include specific base classes with detailed progress"
813
- },
814
- {
815
- "command": "<%= config.bin %> <%= command.id %> --scan-dist",
816
- "description": "Include dist/ scanning for npm-published packages without src/"
817
- }
817
+ "<%= config.bin %> <%= command.id %> --out ./mj-install.zip",
818
+ "<%= config.bin %> <%= command.id %> --tag v5.38.0 --out ./mj-install.zip",
819
+ "<%= config.bin %> <%= command.id %> --source . --out ./mj-install.zip",
820
+ "<%= config.bin %> <%= command.id %> --tag v5.38.0 --with-migrations --out ./mj-install.zip",
821
+ "<%= config.bin %> <%= command.id %> --with-migrations --db-platform postgresql --out ./mj-install.zip"
818
822
  ],
819
823
  "flags": {
820
- "output": {
824
+ "out": {
821
825
  "char": "o",
822
- "description": "Output file path for the generated manifest. The file will contain named imports and a CLASS_REGISTRATIONS array.",
823
- "name": "output",
824
- "default": "./src/generated/class-registrations-manifest.ts",
826
+ "description": "Output zip path",
827
+ "name": "out",
828
+ "required": true,
825
829
  "hasDynamicHelp": false,
826
830
  "multiple": false,
827
831
  "type": "option"
828
832
  },
829
- "appDir": {
830
- "char": "a",
831
- "description": "Root directory of the application whose package.json dependency tree will be scanned. Defaults to the current working directory.",
832
- "name": "appDir",
833
+ "tag": {
834
+ "char": "t",
835
+ "description": "Release tag to bundle (e.g. v5.38.0). Defaults to the latest branch tip.",
836
+ "name": "tag",
833
837
  "hasDynamicHelp": false,
834
838
  "multiple": false,
835
839
  "type": "option"
836
840
  },
837
- "filter": {
838
- "char": "f",
839
- "description": "Only include classes extending this base class. Can be repeated (e.g., --filter BaseEngine --filter BaseAction).",
840
- "name": "filter",
841
- "hasDynamicHelp": false,
842
- "multiple": true,
843
- "type": "option"
844
- },
845
- "exclude-packages": {
846
- "char": "e",
847
- "description": "Skip packages whose name starts with this prefix. Useful for excluding @memberjunction packages when using pre-built bootstrap manifests. Can be repeated.",
848
- "name": "exclude-packages",
841
+ "source": {
842
+ "description": "Bundle from a local working-tree directory instead of fetching from the repo",
843
+ "name": "source",
849
844
  "hasDynamicHelp": false,
850
- "multiple": true,
845
+ "multiple": false,
851
846
  "type": "option"
852
847
  },
853
- "no-sync-deps": {
854
- "description": "Skip automatic dependency reconciliation. By default, the manifest generator adds any manifest-imported packages that are missing from package.json dependencies. Use this flag when generating supplemental manifests with --exclude-packages, where excluded packages are already covered by a pre-built bootstrap manifest.",
855
- "name": "no-sync-deps",
856
- "allowNo": false,
857
- "type": "boolean"
858
- },
859
- "quiet": {
860
- "char": "q",
861
- "description": "Suppress all output except errors.",
862
- "name": "quiet",
863
- "allowNo": false,
864
- "type": "boolean"
865
- },
866
- "verbose": {
867
- "char": "v",
868
- "description": "Show detailed progress including per-package scanning info and skipped classes.",
869
- "name": "verbose",
870
- "allowNo": false,
871
- "type": "boolean"
872
- },
873
- "scan-dist": {
874
- "description": "Scan compiled JavaScript files in dist/ directories for packages without src/. Use this when your dependency tree includes npm-published packages that contain @RegisterClass decorators. Without this flag, only TypeScript source in src/ is scanned.",
875
- "name": "scan-dist",
848
+ "with-migrations": {
849
+ "description": "Include the migration tree(s) so an air-gapped \"mj migrate\" can run offline. Ships both SQL Server and PostgreSQL trees by default.",
850
+ "name": "with-migrations",
876
851
  "allowNo": false,
877
852
  "type": "boolean"
878
853
  },
879
- "lazy-config": {
880
- "description": "Output path for a generated lazy-loading feature config file. Maps @RegisterClass keys from excluded packages to dynamic import() loaders based on package.json subpath exports. Only packages with subpath exports in their package.json are included. Requires --exclude-packages.",
881
- "name": "lazy-config",
854
+ "db-platform": {
855
+ "dependsOn": [
856
+ "with-migrations"
857
+ ],
858
+ "description": "With --with-migrations, ship only this platform's migration tree instead of both",
859
+ "name": "db-platform",
882
860
  "hasDynamicHelp": false,
883
861
  "multiple": false,
862
+ "options": [
863
+ "sqlserver",
864
+ "postgresql"
865
+ ],
884
866
  "type": "option"
885
867
  },
886
- "strict": {
887
- "description": "Treat coverage audit gaps as fatal errors. A gap is a @RegisterClass class in an excluded package that is not reachable from any lazy chunk subpath export. Use in CI to catch tree-shaking issues before merge.",
888
- "name": "strict",
868
+ "verbose": {
869
+ "char": "v",
870
+ "description": "Show detailed output",
871
+ "name": "verbose",
889
872
  "allowNo": false,
890
873
  "type": "boolean"
891
874
  }
892
875
  },
893
876
  "hasDynamicHelp": false,
894
877
  "hiddenAliases": [],
895
- "id": "codegen:manifest",
878
+ "id": "bundle",
896
879
  "pluginAlias": "@memberjunction/cli",
897
880
  "pluginName": "@memberjunction/cli",
898
881
  "pluginType": "core",
@@ -902,42 +885,29 @@
902
885
  "relativePath": [
903
886
  "dist",
904
887
  "commands",
905
- "codegen",
906
- "manifest.js"
888
+ "bundle",
889
+ "index.js"
907
890
  ]
908
891
  },
909
- "dbdoc:analyze": {
892
+ "clean": {
910
893
  "aliases": [],
911
894
  "args": {},
912
- "description": "Analyze database and generate documentation (delegates to db-auto-doc analyze)",
895
+ "description": "Resets the MemberJunction database to a pre-installation state",
913
896
  "examples": [
914
- "<%= config.bin %> <%= command.id %>",
915
- "<%= config.bin %> <%= command.id %> --resume ./output/run-6/state.json",
916
- "<%= config.bin %> <%= command.id %> --config ./my-config.json"
897
+ "<%= config.bin %> <%= command.id %>\n"
917
898
  ],
918
899
  "flags": {
919
- "resume": {
920
- "char": "r",
921
- "description": "Resume from an existing state file",
922
- "name": "resume",
923
- "required": false,
924
- "hasDynamicHelp": false,
925
- "multiple": false,
926
- "type": "option"
927
- },
928
- "config": {
929
- "char": "c",
930
- "description": "Path to config file",
931
- "name": "config",
932
- "default": "./config.json",
933
- "hasDynamicHelp": false,
934
- "multiple": false,
935
- "type": "option"
900
+ "verbose": {
901
+ "char": "v",
902
+ "description": "Enable additional logging",
903
+ "name": "verbose",
904
+ "allowNo": false,
905
+ "type": "boolean"
936
906
  }
937
907
  },
938
908
  "hasDynamicHelp": false,
939
909
  "hiddenAliases": [],
940
- "id": "dbdoc:analyze",
910
+ "id": "clean",
941
911
  "pluginAlias": "@memberjunction/cli",
942
912
  "pluginName": "@memberjunction/cli",
943
913
  "pluginType": "core",
@@ -947,8 +917,456 @@
947
917
  "relativePath": [
948
918
  "dist",
949
919
  "commands",
950
- "dbdoc",
951
- "analyze.js"
920
+ "clean",
921
+ "index.js"
922
+ ]
923
+ },
924
+ "codegen:5-0-fix-entity-names": {
925
+ "aliases": [],
926
+ "args": {},
927
+ "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.",
928
+ "examples": [
929
+ {
930
+ "description": "Dry-run scan of the packages directory",
931
+ "command": "<%= config.bin %> <%= command.id %> --path packages/"
932
+ },
933
+ {
934
+ "description": "Scan a single file",
935
+ "command": "<%= config.bin %> <%= command.id %> --path packages/Angular/Explorer/dashboards/src/Actions/components/actions-overview.component.ts"
936
+ },
937
+ {
938
+ "description": "Apply fixes across the codebase",
939
+ "command": "<%= config.bin %> <%= command.id %> --path packages/ --fix"
940
+ },
941
+ {
942
+ "description": "Quiet mode (summary only)",
943
+ "command": "<%= config.bin %> <%= command.id %> --path packages/ -q"
944
+ }
945
+ ],
946
+ "flags": {
947
+ "path": {
948
+ "char": "p",
949
+ "description": "File or directory to scan. Accepts a single .ts file or a directory (scanned recursively). Defaults to the current working directory.",
950
+ "name": "path",
951
+ "hasDynamicHelp": false,
952
+ "multiple": false,
953
+ "type": "option"
954
+ },
955
+ "fix": {
956
+ "description": "Apply fixes in place. Without this flag, the command runs in dry-run mode and only reports findings.",
957
+ "name": "fix",
958
+ "allowNo": false,
959
+ "type": "boolean"
960
+ },
961
+ "entity-subclasses": {
962
+ "description": "Explicit path to entity_subclasses.ts for building the rename map. If omitted, the tool searches common locations relative to the target path.",
963
+ "name": "entity-subclasses",
964
+ "hasDynamicHelp": false,
965
+ "multiple": false,
966
+ "type": "option"
967
+ },
968
+ "quiet": {
969
+ "char": "q",
970
+ "description": "Suppress detailed per-file output; only show the final summary counts.",
971
+ "name": "quiet",
972
+ "allowNo": false,
973
+ "type": "boolean"
974
+ },
975
+ "verbose": {
976
+ "char": "v",
977
+ "description": "Show detailed progress including each file being scanned.",
978
+ "name": "verbose",
979
+ "allowNo": false,
980
+ "type": "boolean"
981
+ }
982
+ },
983
+ "hasDynamicHelp": false,
984
+ "hiddenAliases": [],
985
+ "id": "codegen:5-0-fix-entity-names",
986
+ "pluginAlias": "@memberjunction/cli",
987
+ "pluginName": "@memberjunction/cli",
988
+ "pluginType": "core",
989
+ "strict": true,
990
+ "enableJsonFlag": false,
991
+ "isESM": true,
992
+ "relativePath": [
993
+ "dist",
994
+ "commands",
995
+ "codegen",
996
+ "5-0-fix-entity-names.js"
997
+ ]
998
+ },
999
+ "codegen:5-0-fix-html-entity-names": {
1000
+ "aliases": [],
1001
+ "args": {},
1002
+ "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).",
1003
+ "examples": [
1004
+ {
1005
+ "description": "Dry-run scan of Angular templates",
1006
+ "command": "<%= config.bin %> <%= command.id %> --path packages/Angular/"
1007
+ },
1008
+ {
1009
+ "description": "Apply fixes to HTML templates",
1010
+ "command": "<%= config.bin %> <%= command.id %> --path packages/Angular/ --fix"
1011
+ },
1012
+ {
1013
+ "description": "Scan with verbose output",
1014
+ "command": "<%= config.bin %> <%= command.id %> --path packages/ -v"
1015
+ },
1016
+ {
1017
+ "description": "Scan a single template file",
1018
+ "command": "<%= config.bin %> <%= command.id %> --path packages/Angular/Explorer/dashboards/src/Actions/actions-dashboard.component.html"
1019
+ }
1020
+ ],
1021
+ "flags": {
1022
+ "path": {
1023
+ "char": "p",
1024
+ "description": "File or directory to scan. Accepts a single .html file or a directory (scanned recursively). Defaults to the current working directory.",
1025
+ "name": "path",
1026
+ "hasDynamicHelp": false,
1027
+ "multiple": false,
1028
+ "type": "option"
1029
+ },
1030
+ "fix": {
1031
+ "description": "Apply fixes in place. Without this flag, the command runs in dry-run mode and only reports findings.",
1032
+ "name": "fix",
1033
+ "allowNo": false,
1034
+ "type": "boolean"
1035
+ },
1036
+ "entity-subclasses": {
1037
+ "description": "Explicit path to entity_subclasses.ts for building the rename map. If omitted, the tool searches common locations relative to the target path.",
1038
+ "name": "entity-subclasses",
1039
+ "hasDynamicHelp": false,
1040
+ "multiple": false,
1041
+ "type": "option"
1042
+ },
1043
+ "quiet": {
1044
+ "char": "q",
1045
+ "description": "Suppress detailed per-file output; only show the final summary counts.",
1046
+ "name": "quiet",
1047
+ "allowNo": false,
1048
+ "type": "boolean"
1049
+ },
1050
+ "verbose": {
1051
+ "char": "v",
1052
+ "description": "Show detailed progress including each file being scanned.",
1053
+ "name": "verbose",
1054
+ "allowNo": false,
1055
+ "type": "boolean"
1056
+ }
1057
+ },
1058
+ "hasDynamicHelp": false,
1059
+ "hiddenAliases": [],
1060
+ "id": "codegen:5-0-fix-html-entity-names",
1061
+ "pluginAlias": "@memberjunction/cli",
1062
+ "pluginName": "@memberjunction/cli",
1063
+ "pluginType": "core",
1064
+ "strict": true,
1065
+ "enableJsonFlag": false,
1066
+ "isESM": true,
1067
+ "relativePath": [
1068
+ "dist",
1069
+ "commands",
1070
+ "codegen",
1071
+ "5-0-fix-html-entity-names.js"
1072
+ ]
1073
+ },
1074
+ "codegen:5-0-fix-metadata-names": {
1075
+ "aliases": [],
1076
+ "args": {},
1077
+ "description": "[v5.0 Migration] Scan metadata JSON files for entity names that need \"MJ: \" prefix updates.\n\nTargets the metadata/ directory used by \"mj sync\". Detects entity name references in\n@lookup: directives (both the entity name and lookup value), .mj-sync.json and\n.mj-folder.json config files (entity/entityName fields), relatedEntities object keys,\nand fields.Name values in Entities-managing folders. Runs in dry-run mode by default;\nuse --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).",
1078
+ "examples": [
1079
+ {
1080
+ "description": "Dry-run scan of the metadata directory",
1081
+ "command": "<%= config.bin %> <%= command.id %> --path metadata/"
1082
+ },
1083
+ {
1084
+ "description": "Apply fixes to metadata files",
1085
+ "command": "<%= config.bin %> <%= command.id %> --path metadata/ --fix"
1086
+ },
1087
+ {
1088
+ "description": "Scan a specific subdirectory",
1089
+ "command": "<%= config.bin %> <%= command.id %> --path metadata/resource-types"
1090
+ },
1091
+ {
1092
+ "description": "Scan and fix a single metadata file",
1093
+ "command": "<%= config.bin %> <%= command.id %> --path metadata/entities/.audit-related-entities.json --fix"
1094
+ }
1095
+ ],
1096
+ "flags": {
1097
+ "path": {
1098
+ "char": "p",
1099
+ "description": "File or directory to scan. Accepts a single .json file or a directory (scanned recursively, including dotfiles like .mj-sync.json). Defaults to the current working directory.",
1100
+ "name": "path",
1101
+ "hasDynamicHelp": false,
1102
+ "multiple": false,
1103
+ "type": "option"
1104
+ },
1105
+ "fix": {
1106
+ "description": "Apply fixes in place. Without this flag, the command runs in dry-run mode and only reports findings.",
1107
+ "name": "fix",
1108
+ "allowNo": false,
1109
+ "type": "boolean"
1110
+ },
1111
+ "entity-subclasses": {
1112
+ "description": "Explicit path to entity_subclasses.ts for building the rename map. If omitted, the tool searches common locations relative to the target path.",
1113
+ "name": "entity-subclasses",
1114
+ "hasDynamicHelp": false,
1115
+ "multiple": false,
1116
+ "type": "option"
1117
+ },
1118
+ "quiet": {
1119
+ "char": "q",
1120
+ "description": "Suppress detailed per-file output; only show the final summary counts.",
1121
+ "name": "quiet",
1122
+ "allowNo": false,
1123
+ "type": "boolean"
1124
+ },
1125
+ "verbose": {
1126
+ "char": "v",
1127
+ "description": "Show detailed progress including each file being scanned.",
1128
+ "name": "verbose",
1129
+ "allowNo": false,
1130
+ "type": "boolean"
1131
+ }
1132
+ },
1133
+ "hasDynamicHelp": false,
1134
+ "hiddenAliases": [],
1135
+ "id": "codegen:5-0-fix-metadata-names",
1136
+ "pluginAlias": "@memberjunction/cli",
1137
+ "pluginName": "@memberjunction/cli",
1138
+ "pluginType": "core",
1139
+ "strict": true,
1140
+ "enableJsonFlag": false,
1141
+ "isESM": true,
1142
+ "relativePath": [
1143
+ "dist",
1144
+ "commands",
1145
+ "codegen",
1146
+ "5-0-fix-metadata-names.js"
1147
+ ]
1148
+ },
1149
+ "codegen": {
1150
+ "aliases": [],
1151
+ "args": {},
1152
+ "description": "Run the full MemberJunction code generation pipeline.\n\nAnalyzes your SQL Server database schema, updates MemberJunction metadata, and\ngenerates synchronized code across the entire stack:\n\n - SQL views, stored procedures, indexes, and permissions\n - TypeScript entity classes with Zod validation schemas\n - Angular form components with AI-driven layouts\n - GraphQL resolvers and type definitions\n - Action subclasses and DB schema JSON\n\nConfiguration is loaded from mj.config.cjs in the current directory (or parent\ndirectories). Database connection can also be set via environment variables:\nDB_HOST, DB_DATABASE, CODEGEN_DB_USERNAME, CODEGEN_DB_PASSWORD.\n\nUse --skipdb to skip all database operations (metadata sync, SQL object\ngeneration) and only regenerate TypeScript, Angular, and GraphQL output from\nexisting metadata.\n\nUse --skipfiles to skip all file-generation operations (TypeScript entities,\nAngular components, GraphQL resolvers, action subclasses, DB schema JSON) and\nonly run database-side operations (metadata sync, SQL object generation,\npermissions, custom SQL scripts).\n\n--skipdb and --skipfiles are independent and can be combined in any mix.\n\nUse --force-advanced-gen to bypass Pass 2 entity scoping and re-run the LLM-driven\nadvanced generation (smart fields, form layout) for ALL entities. Useful when AI\nprompts have changed and you want unchanged entities re-evaluated.",
1153
+ "examples": [
1154
+ {
1155
+ "command": "<%= config.bin %> <%= command.id %>",
1156
+ "description": "Run the full code generation pipeline"
1157
+ },
1158
+ {
1159
+ "command": "<%= config.bin %> <%= command.id %> --skipdb",
1160
+ "description": "Regenerate code files without touching the database"
1161
+ },
1162
+ {
1163
+ "command": "<%= config.bin %> <%= command.id %> --skipfiles",
1164
+ "description": "Run database-side operations only, without regenerating any code files"
1165
+ },
1166
+ {
1167
+ "command": "<%= config.bin %> <%= command.id %> --force-advanced-gen",
1168
+ "description": "Re-run advanced generation for all entities (bypasses changed-entity scoping)"
1169
+ }
1170
+ ],
1171
+ "flags": {
1172
+ "skipdb": {
1173
+ "description": "Skip database operations (metadata sync, SQL generation). Only regenerate TypeScript entities, Angular components, and GraphQL resolvers from existing metadata.",
1174
+ "name": "skipdb",
1175
+ "allowNo": false,
1176
+ "type": "boolean"
1177
+ },
1178
+ "skipfiles": {
1179
+ "description": "Skip file-generation operations (TypeScript entities, Angular components, GraphQL resolvers, action subclasses, DB schema JSON). Only run database-side operations.",
1180
+ "name": "skipfiles",
1181
+ "allowNo": false,
1182
+ "type": "boolean"
1183
+ },
1184
+ "force-advanced-gen": {
1185
+ "description": "Bypass entity scoping in Pass 2 and force advanced generation to re-run for all entities. Used when AI prompts have changed and unchanged entities should be re-evaluated.",
1186
+ "name": "force-advanced-gen",
1187
+ "allowNo": false,
1188
+ "type": "boolean"
1189
+ }
1190
+ },
1191
+ "hasDynamicHelp": false,
1192
+ "hiddenAliases": [],
1193
+ "id": "codegen",
1194
+ "pluginAlias": "@memberjunction/cli",
1195
+ "pluginName": "@memberjunction/cli",
1196
+ "pluginType": "core",
1197
+ "strict": true,
1198
+ "enableJsonFlag": false,
1199
+ "isESM": true,
1200
+ "relativePath": [
1201
+ "dist",
1202
+ "commands",
1203
+ "codegen",
1204
+ "index.js"
1205
+ ]
1206
+ },
1207
+ "codegen:manifest": {
1208
+ "aliases": [],
1209
+ "args": {},
1210
+ "description": "Generate a class registration manifest to prevent tree-shaking.\n\nMemberJunction uses @RegisterClass decorators with a dynamic class factory.\nModern bundlers (ESBuild, Vite) cannot detect dynamic instantiation and will\ntree-shake these classes out of production builds. This command scans the\ndependency tree for all @RegisterClass-decorated classes and emits a manifest\nfile with static imports that the bundler cannot eliminate.\n\nTypically used as a prebuild/prestart script for MJAPI and MJExplorer. For\nMJ distribution users, pre-built manifests ship inside @memberjunction/server-bootstrap\nand @memberjunction/ng-bootstrap -- use --exclude-packages @memberjunction to\ngenerate a supplemental manifest covering only your own application classes.",
1211
+ "examples": [
1212
+ {
1213
+ "command": "<%= config.bin %> <%= command.id %>",
1214
+ "description": "Generate manifest with default output path"
1215
+ },
1216
+ {
1217
+ "command": "<%= config.bin %> <%= command.id %> --appDir ./packages/MJAPI --output ./packages/MJAPI/src/generated/class-registrations-manifest.ts",
1218
+ "description": "Generate manifest for a specific application directory"
1219
+ },
1220
+ {
1221
+ "command": "<%= config.bin %> <%= command.id %> --exclude-packages @memberjunction",
1222
+ "description": "Exclude MJ packages (use pre-built bootstrap manifests instead)"
1223
+ },
1224
+ {
1225
+ "command": "<%= config.bin %> <%= command.id %> --exclude-packages @memberjunction --no-sync-deps",
1226
+ "description": "Exclude MJ packages and skip dependency reconciliation"
1227
+ },
1228
+ {
1229
+ "command": "<%= config.bin %> <%= command.id %> --filter BaseEngine --filter BaseAction --verbose",
1230
+ "description": "Only include specific base classes with detailed progress"
1231
+ },
1232
+ {
1233
+ "command": "<%= config.bin %> <%= command.id %> --scan-dist",
1234
+ "description": "Include dist/ scanning for npm-published packages without src/"
1235
+ }
1236
+ ],
1237
+ "flags": {
1238
+ "output": {
1239
+ "char": "o",
1240
+ "description": "Output file path for the generated manifest. The file will contain named imports and a CLASS_REGISTRATIONS array.",
1241
+ "name": "output",
1242
+ "default": "./src/generated/class-registrations-manifest.ts",
1243
+ "hasDynamicHelp": false,
1244
+ "multiple": false,
1245
+ "type": "option"
1246
+ },
1247
+ "appDir": {
1248
+ "char": "a",
1249
+ "description": "Root directory of the application whose package.json dependency tree will be scanned. Defaults to the current working directory.",
1250
+ "name": "appDir",
1251
+ "hasDynamicHelp": false,
1252
+ "multiple": false,
1253
+ "type": "option"
1254
+ },
1255
+ "filter": {
1256
+ "char": "f",
1257
+ "description": "Only include classes extending this base class. Can be repeated (e.g., --filter BaseEngine --filter BaseAction).",
1258
+ "name": "filter",
1259
+ "hasDynamicHelp": false,
1260
+ "multiple": true,
1261
+ "type": "option"
1262
+ },
1263
+ "exclude-packages": {
1264
+ "char": "e",
1265
+ "description": "Skip packages whose name starts with this prefix. Useful for excluding @memberjunction packages when using pre-built bootstrap manifests. Can be repeated.",
1266
+ "name": "exclude-packages",
1267
+ "hasDynamicHelp": false,
1268
+ "multiple": true,
1269
+ "type": "option"
1270
+ },
1271
+ "no-sync-deps": {
1272
+ "description": "Skip automatic dependency reconciliation. By default, the manifest generator adds any manifest-imported packages that are missing from package.json dependencies. Use this flag when generating supplemental manifests with --exclude-packages, where excluded packages are already covered by a pre-built bootstrap manifest.",
1273
+ "name": "no-sync-deps",
1274
+ "allowNo": false,
1275
+ "type": "boolean"
1276
+ },
1277
+ "quiet": {
1278
+ "char": "q",
1279
+ "description": "Suppress all output except errors.",
1280
+ "name": "quiet",
1281
+ "allowNo": false,
1282
+ "type": "boolean"
1283
+ },
1284
+ "verbose": {
1285
+ "char": "v",
1286
+ "description": "Show detailed progress including per-package scanning info and skipped classes.",
1287
+ "name": "verbose",
1288
+ "allowNo": false,
1289
+ "type": "boolean"
1290
+ },
1291
+ "scan-dist": {
1292
+ "description": "Scan compiled JavaScript files in dist/ directories for packages without src/. Use this when your dependency tree includes npm-published packages that contain @RegisterClass decorators. Without this flag, only TypeScript source in src/ is scanned.",
1293
+ "name": "scan-dist",
1294
+ "allowNo": false,
1295
+ "type": "boolean"
1296
+ },
1297
+ "lazy-config": {
1298
+ "description": "Output path for a generated lazy-loading feature config file. Maps @RegisterClass keys from excluded packages to dynamic import() loaders based on package.json subpath exports. Only packages with subpath exports in their package.json are included. Requires --exclude-packages.",
1299
+ "name": "lazy-config",
1300
+ "hasDynamicHelp": false,
1301
+ "multiple": false,
1302
+ "type": "option"
1303
+ },
1304
+ "strict": {
1305
+ "description": "Treat coverage audit gaps as fatal errors. A gap is a @RegisterClass class in an excluded package that is not reachable from any lazy chunk subpath export. Use in CI to catch tree-shaking issues before merge.",
1306
+ "name": "strict",
1307
+ "allowNo": false,
1308
+ "type": "boolean"
1309
+ }
1310
+ },
1311
+ "hasDynamicHelp": false,
1312
+ "hiddenAliases": [],
1313
+ "id": "codegen:manifest",
1314
+ "pluginAlias": "@memberjunction/cli",
1315
+ "pluginName": "@memberjunction/cli",
1316
+ "pluginType": "core",
1317
+ "strict": true,
1318
+ "enableJsonFlag": false,
1319
+ "isESM": true,
1320
+ "relativePath": [
1321
+ "dist",
1322
+ "commands",
1323
+ "codegen",
1324
+ "manifest.js"
1325
+ ]
1326
+ },
1327
+ "dbdoc:analyze": {
1328
+ "aliases": [],
1329
+ "args": {},
1330
+ "description": "Analyze database and generate documentation (delegates to db-auto-doc analyze)",
1331
+ "examples": [
1332
+ "<%= config.bin %> <%= command.id %>",
1333
+ "<%= config.bin %> <%= command.id %> --resume ./output/run-6/state.json",
1334
+ "<%= config.bin %> <%= command.id %> --config ./my-config.json"
1335
+ ],
1336
+ "flags": {
1337
+ "resume": {
1338
+ "char": "r",
1339
+ "description": "Resume from an existing state file",
1340
+ "name": "resume",
1341
+ "required": false,
1342
+ "hasDynamicHelp": false,
1343
+ "multiple": false,
1344
+ "type": "option"
1345
+ },
1346
+ "config": {
1347
+ "char": "c",
1348
+ "description": "Path to config file",
1349
+ "name": "config",
1350
+ "default": "./config.json",
1351
+ "hasDynamicHelp": false,
1352
+ "multiple": false,
1353
+ "type": "option"
1354
+ }
1355
+ },
1356
+ "hasDynamicHelp": false,
1357
+ "hiddenAliases": [],
1358
+ "id": "dbdoc:analyze",
1359
+ "pluginAlias": "@memberjunction/cli",
1360
+ "pluginName": "@memberjunction/cli",
1361
+ "pluginType": "core",
1362
+ "strict": true,
1363
+ "enableJsonFlag": false,
1364
+ "isESM": true,
1365
+ "relativePath": [
1366
+ "dist",
1367
+ "commands",
1368
+ "dbdoc",
1369
+ "analyze.js"
952
1370
  ]
953
1371
  },
954
1372
  "dbdoc:export-sample-queries": {
@@ -1318,75 +1736,18 @@
1318
1736
  "<%= config.bin %> <%= command.id %> --state-file ./custom-state.json"
1319
1737
  ],
1320
1738
  "flags": {
1321
- "state-file": {
1322
- "char": "s",
1323
- "description": "Path to state JSON file",
1324
- "name": "state-file",
1325
- "hasDynamicHelp": false,
1326
- "multiple": false,
1327
- "type": "option"
1328
- }
1329
- },
1330
- "hasDynamicHelp": false,
1331
- "hiddenAliases": [],
1332
- "id": "dbdoc:status",
1333
- "pluginAlias": "@memberjunction/cli",
1334
- "pluginName": "@memberjunction/cli",
1335
- "pluginType": "core",
1336
- "strict": true,
1337
- "enableJsonFlag": false,
1338
- "isESM": true,
1339
- "relativePath": [
1340
- "dist",
1341
- "commands",
1342
- "dbdoc",
1343
- "status.js"
1344
- ]
1345
- },
1346
- "doctor": {
1347
- "aliases": [],
1348
- "args": {},
1349
- "description": "Diagnose a MemberJunction installation",
1350
- "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": ".",
1739
+ "state-file": {
1740
+ "char": "s",
1741
+ "description": "Path to state JSON file",
1742
+ "name": "state-file",
1362
1743
  "hasDynamicHelp": false,
1363
1744
  "multiple": false,
1364
1745
  "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
1746
  }
1386
1747
  },
1387
1748
  "hasDynamicHelp": false,
1388
1749
  "hiddenAliases": [],
1389
- "id": "doctor",
1750
+ "id": "dbdoc:status",
1390
1751
  "pluginAlias": "@memberjunction/cli",
1391
1752
  "pluginName": "@memberjunction/cli",
1392
1753
  "pluginType": "core",
@@ -1396,8 +1757,8 @@
1396
1757
  "relativePath": [
1397
1758
  "dist",
1398
1759
  "commands",
1399
- "doctor",
1400
- "index.js"
1760
+ "dbdoc",
1761
+ "status.js"
1401
1762
  ]
1402
1763
  },
1403
1764
  "install": {
@@ -1699,6 +2060,12 @@
1699
2060
  "hasDynamicHelp": false,
1700
2061
  "multiple": false,
1701
2062
  "type": "option"
2063
+ },
2064
+ "check-connection": {
2065
+ "description": "Verify the database connection (including TLS) and exit without migrating",
2066
+ "name": "check-connection",
2067
+ "allowNo": false,
2068
+ "type": "boolean"
1702
2069
  }
1703
2070
  },
1704
2071
  "hasDynamicHelp": false,
@@ -1932,6 +2299,63 @@
1932
2299
  "validate.js"
1933
2300
  ]
1934
2301
  },
2302
+ "doctor": {
2303
+ "aliases": [],
2304
+ "args": {},
2305
+ "description": "Diagnose a MemberJunction installation",
2306
+ "examples": [
2307
+ "<%= config.bin %> <%= command.id %>",
2308
+ "<%= config.bin %> <%= command.id %> --dir ./my-mj-project",
2309
+ "<%= config.bin %> <%= command.id %> --verbose",
2310
+ "<%= config.bin %> <%= command.id %> --report",
2311
+ "<%= config.bin %> <%= command.id %> --report_extended"
2312
+ ],
2313
+ "flags": {
2314
+ "dir": {
2315
+ "description": "Target directory to diagnose",
2316
+ "name": "dir",
2317
+ "default": ".",
2318
+ "hasDynamicHelp": false,
2319
+ "multiple": false,
2320
+ "type": "option"
2321
+ },
2322
+ "verbose": {
2323
+ "char": "v",
2324
+ "description": "Show detailed output including suggested fixes inline",
2325
+ "name": "verbose",
2326
+ "allowNo": false,
2327
+ "type": "boolean"
2328
+ },
2329
+ "report": {
2330
+ "char": "r",
2331
+ "description": "Generate a diagnostic report file (mj-diagnostic-report.md) for sharing with support",
2332
+ "name": "report",
2333
+ "allowNo": false,
2334
+ "type": "boolean"
2335
+ },
2336
+ "report_extended": {
2337
+ "description": "Generate an extended report with config file snapshots and service startup log capture (~60s longer)",
2338
+ "name": "report_extended",
2339
+ "allowNo": false,
2340
+ "type": "boolean"
2341
+ }
2342
+ },
2343
+ "hasDynamicHelp": false,
2344
+ "hiddenAliases": [],
2345
+ "id": "doctor",
2346
+ "pluginAlias": "@memberjunction/cli",
2347
+ "pluginName": "@memberjunction/cli",
2348
+ "pluginType": "core",
2349
+ "strict": true,
2350
+ "enableJsonFlag": false,
2351
+ "isESM": true,
2352
+ "relativePath": [
2353
+ "dist",
2354
+ "commands",
2355
+ "doctor",
2356
+ "index.js"
2357
+ ]
2358
+ },
1935
2359
  "sql-audit": {
1936
2360
  "aliases": [],
1937
2361
  "args": {},
@@ -2692,10 +3116,13 @@
2692
3116
  },
2693
3117
  "description": "Compare test runs for regression detection",
2694
3118
  "examples": [
3119
+ "<%= config.bin %> <%= command.id %>",
3120
+ "<%= config.bin %> <%= command.id %> --latest",
2695
3121
  "<%= 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"
3122
+ "<%= config.bin %> <%= command.id %> -v 5.17.0 -v 5.18.0",
3123
+ "<%= config.bin %> <%= command.id %> -c abc1234 -c def5678",
3124
+ "<%= config.bin %> <%= command.id %> --from-json baseline.json latest.json",
3125
+ "<%= config.bin %> <%= command.id %> --latest --format=markdown --output=report.md"
2699
3126
  ],
2700
3127
  "flags": {
2701
3128
  "version": {
@@ -2720,6 +3147,20 @@
2720
3147
  "allowNo": false,
2721
3148
  "type": "boolean"
2722
3149
  },
3150
+ "latest": {
3151
+ "char": "l",
3152
+ "description": "Compare the two most recent completed suite runs",
3153
+ "name": "latest",
3154
+ "allowNo": false,
3155
+ "type": "boolean"
3156
+ },
3157
+ "from-json": {
3158
+ "description": "Compare two results.json files directly (no DB). Pass twice: --from-json PREV --from-json CURR",
3159
+ "name": "from-json",
3160
+ "hasDynamicHelp": false,
3161
+ "multiple": true,
3162
+ "type": "option"
3163
+ },
2723
3164
  "format": {
2724
3165
  "char": "f",
2725
3166
  "description": "Output format",
@@ -2747,6 +3188,13 @@
2747
3188
  "name": "verbose",
2748
3189
  "allowNo": false,
2749
3190
  "type": "boolean"
3191
+ },
3192
+ "tag": {
3193
+ "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.",
3194
+ "name": "tag",
3195
+ "hasDynamicHelp": false,
3196
+ "multiple": false,
3197
+ "type": "option"
2750
3198
  }
2751
3199
  },
2752
3200
  "hasDynamicHelp": false,
@@ -3045,6 +3493,13 @@
3045
3493
  "name": "verbose",
3046
3494
  "allowNo": false,
3047
3495
  "type": "boolean"
3496
+ },
3497
+ "oracles-module": {
3498
+ "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.",
3499
+ "name": "oracles-module",
3500
+ "hasDynamicHelp": false,
3501
+ "multiple": false,
3502
+ "type": "option"
3048
3503
  }
3049
3504
  },
3050
3505
  "hasDynamicHelp": false,
@@ -3116,6 +3571,44 @@
3116
3571
  "name": "verbose",
3117
3572
  "allowNo": false,
3118
3573
  "type": "boolean"
3574
+ },
3575
+ "delay": {
3576
+ "char": "d",
3577
+ "description": "Delay in milliseconds between test executions (avoids Auth0 rate limits)",
3578
+ "name": "delay",
3579
+ "default": 0,
3580
+ "hasDynamicHelp": false,
3581
+ "multiple": false,
3582
+ "type": "option"
3583
+ },
3584
+ "parallel": {
3585
+ "char": "p",
3586
+ "description": "Run tests in parallel with shared browser sessions",
3587
+ "name": "parallel",
3588
+ "allowNo": false,
3589
+ "type": "boolean"
3590
+ },
3591
+ "max-parallel": {
3592
+ "description": "Maximum number of parallel workers (default 4)",
3593
+ "name": "max-parallel",
3594
+ "default": 4,
3595
+ "hasDynamicHelp": false,
3596
+ "multiple": false,
3597
+ "type": "option"
3598
+ },
3599
+ "flaky-check": {
3600
+ "description": "Run each test N times to detect flakiness (variance > 0.3 or mixed pass/fail = flaky). Recommended: 3 or 5",
3601
+ "name": "flaky-check",
3602
+ "hasDynamicHelp": false,
3603
+ "multiple": false,
3604
+ "type": "option"
3605
+ },
3606
+ "oracles-module": {
3607
+ "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.",
3608
+ "name": "oracles-module",
3609
+ "hasDynamicHelp": false,
3610
+ "multiple": false,
3611
+ "type": "option"
3119
3612
  }
3120
3613
  },
3121
3614
  "hasDynamicHelp": false,
@@ -3205,7 +3698,129 @@
3205
3698
  },
3206
3699
  "hasDynamicHelp": false,
3207
3700
  "hiddenAliases": [],
3208
- "id": "test:validate",
3701
+ "id": "test:validate",
3702
+ "pluginAlias": "@memberjunction/cli",
3703
+ "pluginName": "@memberjunction/cli",
3704
+ "pluginType": "core",
3705
+ "strict": true,
3706
+ "enableJsonFlag": false,
3707
+ "isESM": true,
3708
+ "relativePath": [
3709
+ "dist",
3710
+ "commands",
3711
+ "test",
3712
+ "validate.js"
3713
+ ]
3714
+ },
3715
+ "ai:actions:list": {
3716
+ "aliases": [],
3717
+ "args": {},
3718
+ "description": "List available AI actions",
3719
+ "examples": [
3720
+ "<%= config.bin %> <%= command.id %>",
3721
+ "<%= config.bin %> <%= command.id %> --output=table",
3722
+ "<%= config.bin %> <%= command.id %> --output=json"
3723
+ ],
3724
+ "flags": {
3725
+ "output": {
3726
+ "char": "o",
3727
+ "description": "Output format",
3728
+ "name": "output",
3729
+ "default": "compact",
3730
+ "hasDynamicHelp": false,
3731
+ "multiple": false,
3732
+ "options": [
3733
+ "compact",
3734
+ "json",
3735
+ "table"
3736
+ ],
3737
+ "type": "option"
3738
+ }
3739
+ },
3740
+ "hasDynamicHelp": false,
3741
+ "hiddenAliases": [],
3742
+ "id": "ai:actions:list",
3743
+ "pluginAlias": "@memberjunction/cli",
3744
+ "pluginName": "@memberjunction/cli",
3745
+ "pluginType": "core",
3746
+ "strict": true,
3747
+ "enableJsonFlag": false,
3748
+ "isESM": true,
3749
+ "relativePath": [
3750
+ "dist",
3751
+ "commands",
3752
+ "ai",
3753
+ "actions",
3754
+ "list.js"
3755
+ ]
3756
+ },
3757
+ "ai:actions:run": {
3758
+ "aliases": [],
3759
+ "args": {},
3760
+ "description": "Execute an AI action with parameters",
3761
+ "examples": [
3762
+ "<%= config.bin %> <%= command.id %> -n \"Get Weather\" --param \"Location=Boston\"",
3763
+ "<%= config.bin %> <%= command.id %> -n \"Get Stock Price\" --param \"Ticker=AAPL\"",
3764
+ "<%= 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\"",
3765
+ "<%= config.bin %> <%= command.id %> -n \"Calculate Expression\" --param \"Expression=2+2*3\" --dry-run"
3766
+ ],
3767
+ "flags": {
3768
+ "name": {
3769
+ "char": "n",
3770
+ "description": "Action name",
3771
+ "name": "name",
3772
+ "required": true,
3773
+ "hasDynamicHelp": false,
3774
+ "multiple": false,
3775
+ "type": "option"
3776
+ },
3777
+ "param": {
3778
+ "char": "p",
3779
+ "description": "Action parameters in key=value format",
3780
+ "name": "param",
3781
+ "hasDynamicHelp": false,
3782
+ "multiple": true,
3783
+ "type": "option"
3784
+ },
3785
+ "dry-run": {
3786
+ "description": "Validate without executing",
3787
+ "name": "dry-run",
3788
+ "allowNo": false,
3789
+ "type": "boolean"
3790
+ },
3791
+ "output": {
3792
+ "char": "o",
3793
+ "description": "Output format",
3794
+ "name": "output",
3795
+ "default": "compact",
3796
+ "hasDynamicHelp": false,
3797
+ "multiple": false,
3798
+ "options": [
3799
+ "compact",
3800
+ "json",
3801
+ "table"
3802
+ ],
3803
+ "type": "option"
3804
+ },
3805
+ "verbose": {
3806
+ "char": "v",
3807
+ "description": "Show detailed execution information",
3808
+ "name": "verbose",
3809
+ "allowNo": false,
3810
+ "type": "boolean"
3811
+ },
3812
+ "timeout": {
3813
+ "description": "Execution timeout in milliseconds",
3814
+ "name": "timeout",
3815
+ "default": 300000,
3816
+ "hasDynamicHelp": false,
3817
+ "multiple": false,
3818
+ "type": "option"
3819
+ }
3820
+ },
3821
+ "hasDynamicHelp": false,
3822
+ "hiddenAliases": [],
3823
+ "id": "ai:actions:run",
3209
3824
  "pluginAlias": "@memberjunction/cli",
3210
3825
  "pluginName": "@memberjunction/cli",
3211
3826
  "pluginType": "core",
@@ -3215,14 +3830,15 @@
3215
3830
  "relativePath": [
3216
3831
  "dist",
3217
3832
  "commands",
3218
- "test",
3219
- "validate.js"
3833
+ "ai",
3834
+ "actions",
3835
+ "run.js"
3220
3836
  ]
3221
3837
  },
3222
- "ai:actions:list": {
3838
+ "ai:agents:list": {
3223
3839
  "aliases": [],
3224
3840
  "args": {},
3225
- "description": "List available AI actions",
3841
+ "description": "List available AI agents",
3226
3842
  "examples": [
3227
3843
  "<%= config.bin %> <%= command.id %>",
3228
3844
  "<%= config.bin %> <%= command.id %> --output=table",
@@ -3246,7 +3862,7 @@
3246
3862
  },
3247
3863
  "hasDynamicHelp": false,
3248
3864
  "hiddenAliases": [],
3249
- "id": "ai:actions:list",
3865
+ "id": "ai:agents:list",
3250
3866
  "pluginAlias": "@memberjunction/cli",
3251
3867
  "pluginName": "@memberjunction/cli",
3252
3868
  "pluginType": "core",
@@ -3257,41 +3873,47 @@
3257
3873
  "dist",
3258
3874
  "commands",
3259
3875
  "ai",
3260
- "actions",
3876
+ "agents",
3261
3877
  "list.js"
3262
3878
  ]
3263
3879
  },
3264
- "ai:actions:run": {
3880
+ "ai:agents:run": {
3265
3881
  "aliases": [],
3266
3882
  "args": {},
3267
- "description": "Execute an AI action with parameters",
3883
+ "description": "Execute an AI agent with a prompt or start interactive chat",
3268
3884
  "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"
3885
+ "<%= config.bin %> <%= command.id %> -a \"Skip: Requirements Expert\" -p \"Create a dashboard for sales metrics\"",
3886
+ "<%= config.bin %> <%= command.id %> -a \"Child Component Generator Sub-agent\" --chat",
3887
+ "<%= config.bin %> <%= command.id %> -a \"Skip: Technical Design Expert\" -p \"Build a React component\" --verbose --timeout=600000"
3273
3888
  ],
3274
3889
  "flags": {
3275
- "name": {
3276
- "char": "n",
3277
- "description": "Action name",
3278
- "name": "name",
3890
+ "agent": {
3891
+ "char": "a",
3892
+ "description": "Agent name",
3893
+ "name": "agent",
3279
3894
  "required": true,
3280
3895
  "hasDynamicHelp": false,
3281
3896
  "multiple": false,
3282
3897
  "type": "option"
3283
3898
  },
3284
- "param": {
3899
+ "prompt": {
3285
3900
  "char": "p",
3286
- "description": "Action parameters in key=value format",
3287
- "name": "param",
3901
+ "description": "Prompt to execute",
3902
+ "exclusive": [
3903
+ "chat"
3904
+ ],
3905
+ "name": "prompt",
3288
3906
  "hasDynamicHelp": false,
3289
- "multiple": true,
3907
+ "multiple": false,
3290
3908
  "type": "option"
3291
3909
  },
3292
- "dry-run": {
3293
- "description": "Validate without executing",
3294
- "name": "dry-run",
3910
+ "chat": {
3911
+ "char": "c",
3912
+ "description": "Start interactive chat mode",
3913
+ "exclusive": [
3914
+ "prompt"
3915
+ ],
3916
+ "name": "chat",
3295
3917
  "allowNo": false,
3296
3918
  "type": "boolean"
3297
3919
  },
@@ -3327,7 +3949,223 @@
3327
3949
  },
3328
3950
  "hasDynamicHelp": false,
3329
3951
  "hiddenAliases": [],
3330
- "id": "ai:actions:run",
3952
+ "id": "ai:agents:run",
3953
+ "pluginAlias": "@memberjunction/cli",
3954
+ "pluginName": "@memberjunction/cli",
3955
+ "pluginType": "core",
3956
+ "strict": true,
3957
+ "enableJsonFlag": false,
3958
+ "isESM": true,
3959
+ "relativePath": [
3960
+ "dist",
3961
+ "commands",
3962
+ "ai",
3963
+ "agents",
3964
+ "run.js"
3965
+ ]
3966
+ },
3967
+ "ai:audit:agent-run": {
3968
+ "aliases": [],
3969
+ "args": {
3970
+ "runId": {
3971
+ "description": "AI Agent Run ID to audit (UUID)",
3972
+ "name": "runId",
3973
+ "required": false
3974
+ }
3975
+ },
3976
+ "description": "Audit and analyze AI agent execution runs for debugging and performance analysis",
3977
+ "examples": [
3978
+ "<%= config.bin %> <%= command.id %> abc-123-def-456",
3979
+ "<%= config.bin %> <%= command.id %> abc-123-def-456 --output=markdown",
3980
+ "<%= config.bin %> <%= command.id %> abc-123-def-456 --step 3",
3981
+ "<%= config.bin %> <%= command.id %> abc-123-def-456 --step 3 --detail full",
3982
+ "<%= config.bin %> <%= command.id %> abc-123-def-456 --errors",
3983
+ "<%= config.bin %> <%= command.id %> --list --agent \"Skip: Requirements Expert\"",
3984
+ "<%= config.bin %> <%= command.id %> --list --status failed --days 7",
3985
+ "<%= config.bin %> <%= command.id %> abc-123-def-456 --export full --file report.json"
3986
+ ],
3987
+ "flags": {
3988
+ "output": {
3989
+ "char": "o",
3990
+ "description": "Output format",
3991
+ "name": "output",
3992
+ "default": "compact",
3993
+ "hasDynamicHelp": false,
3994
+ "multiple": false,
3995
+ "options": [
3996
+ "compact",
3997
+ "json",
3998
+ "table",
3999
+ "markdown"
4000
+ ],
4001
+ "type": "option"
4002
+ },
4003
+ "step": {
4004
+ "char": "s",
4005
+ "description": "Show details for specific step number (1-based index)",
4006
+ "exclusive": [
4007
+ "list",
4008
+ "errors"
4009
+ ],
4010
+ "name": "step",
4011
+ "hasDynamicHelp": false,
4012
+ "multiple": false,
4013
+ "type": "option"
4014
+ },
4015
+ "detail": {
4016
+ "char": "d",
4017
+ "dependsOn": [
4018
+ "step"
4019
+ ],
4020
+ "description": "Detail level for step output (default: standard)",
4021
+ "name": "detail",
4022
+ "hasDynamicHelp": false,
4023
+ "multiple": false,
4024
+ "options": [
4025
+ "minimal",
4026
+ "standard",
4027
+ "detailed",
4028
+ "full"
4029
+ ],
4030
+ "type": "option"
4031
+ },
4032
+ "errors": {
4033
+ "char": "e",
4034
+ "description": "Show only error details and context",
4035
+ "exclusive": [
4036
+ "step",
4037
+ "list"
4038
+ ],
4039
+ "name": "errors",
4040
+ "allowNo": false,
4041
+ "type": "boolean"
4042
+ },
4043
+ "list": {
4044
+ "char": "l",
4045
+ "description": "List recent agent runs",
4046
+ "exclusive": [
4047
+ "step",
4048
+ "errors"
4049
+ ],
4050
+ "name": "list",
4051
+ "allowNo": false,
4052
+ "type": "boolean"
4053
+ },
4054
+ "agent": {
4055
+ "char": "a",
4056
+ "dependsOn": [
4057
+ "list"
4058
+ ],
4059
+ "description": "Filter by agent name",
4060
+ "name": "agent",
4061
+ "hasDynamicHelp": false,
4062
+ "multiple": false,
4063
+ "type": "option"
4064
+ },
4065
+ "status": {
4066
+ "dependsOn": [
4067
+ "list"
4068
+ ],
4069
+ "description": "Filter by run status",
4070
+ "name": "status",
4071
+ "default": "all",
4072
+ "hasDynamicHelp": false,
4073
+ "multiple": false,
4074
+ "options": [
4075
+ "success",
4076
+ "failed",
4077
+ "running",
4078
+ "all"
4079
+ ],
4080
+ "type": "option"
4081
+ },
4082
+ "days": {
4083
+ "dependsOn": [
4084
+ "list"
4085
+ ],
4086
+ "description": "Number of days to look back",
4087
+ "name": "days",
4088
+ "default": 7,
4089
+ "hasDynamicHelp": false,
4090
+ "multiple": false,
4091
+ "type": "option"
4092
+ },
4093
+ "limit": {
4094
+ "dependsOn": [
4095
+ "list"
4096
+ ],
4097
+ "description": "Maximum number of runs to return",
4098
+ "name": "limit",
4099
+ "default": 50,
4100
+ "hasDynamicHelp": false,
4101
+ "multiple": false,
4102
+ "type": "option"
4103
+ },
4104
+ "export": {
4105
+ "dependsOn": [
4106
+ "file"
4107
+ ],
4108
+ "description": "Export full data to file",
4109
+ "name": "export",
4110
+ "hasDynamicHelp": false,
4111
+ "multiple": false,
4112
+ "options": [
4113
+ "full",
4114
+ "summary",
4115
+ "steps"
4116
+ ],
4117
+ "type": "option"
4118
+ },
4119
+ "file": {
4120
+ "char": "f",
4121
+ "description": "Output file path for export",
4122
+ "name": "file",
4123
+ "hasDynamicHelp": false,
4124
+ "multiple": false,
4125
+ "type": "option"
4126
+ },
4127
+ "max-tokens": {
4128
+ "description": "Maximum tokens per field (0 = no limit)",
4129
+ "name": "max-tokens",
4130
+ "default": 5000,
4131
+ "hasDynamicHelp": false,
4132
+ "multiple": false,
4133
+ "type": "option"
4134
+ },
4135
+ "verbose": {
4136
+ "char": "v",
4137
+ "description": "Show detailed diagnostic information",
4138
+ "name": "verbose",
4139
+ "allowNo": false,
4140
+ "type": "boolean"
4141
+ }
4142
+ },
4143
+ "hasDynamicHelp": false,
4144
+ "hiddenAliases": [],
4145
+ "id": "ai:audit:agent-run",
4146
+ "pluginAlias": "@memberjunction/cli",
4147
+ "pluginName": "@memberjunction/cli",
4148
+ "pluginType": "core",
4149
+ "strict": true,
4150
+ "enableJsonFlag": false,
4151
+ "isESM": true,
4152
+ "relativePath": [
4153
+ "dist",
4154
+ "commands",
4155
+ "ai",
4156
+ "audit",
4157
+ "agent-run.js"
4158
+ ]
4159
+ },
4160
+ "ai:audit": {
4161
+ "aliases": [],
4162
+ "args": {},
4163
+ "description": "Analyze and audit AI agent runs, prompts, and actions for debugging and performance analysis",
4164
+ "flags": {},
4165
+ "hasDynamicHelp": false,
4166
+ "hidden": false,
4167
+ "hiddenAliases": [],
4168
+ "id": "ai:audit",
3331
4169
  "pluginAlias": "@memberjunction/cli",
3332
4170
  "pluginName": "@memberjunction/cli",
3333
4171
  "pluginType": "core",
@@ -3338,38 +4176,29 @@
3338
4176
  "dist",
3339
4177
  "commands",
3340
4178
  "ai",
3341
- "actions",
3342
- "run.js"
4179
+ "audit",
4180
+ "index.js"
3343
4181
  ]
3344
4182
  },
3345
- "ai:agents:list": {
4183
+ "ai:prompts:list": {
3346
4184
  "aliases": [],
3347
4185
  "args": {},
3348
- "description": "List available AI agents",
4186
+ "description": "List available models for prompt execution",
3349
4187
  "examples": [
3350
- "<%= config.bin %> <%= command.id %>",
3351
- "<%= config.bin %> <%= command.id %> --output=table",
3352
- "<%= config.bin %> <%= command.id %> --output=json"
4188
+ "<%= config.bin %> <%= command.id %>"
3353
4189
  ],
3354
4190
  "flags": {
3355
- "output": {
3356
- "char": "o",
3357
- "description": "Output format",
3358
- "name": "output",
3359
- "default": "compact",
3360
- "hasDynamicHelp": false,
3361
- "multiple": false,
3362
- "options": [
3363
- "compact",
3364
- "json",
3365
- "table"
3366
- ],
3367
- "type": "option"
4191
+ "verbose": {
4192
+ "char": "v",
4193
+ "description": "Show detailed model information",
4194
+ "name": "verbose",
4195
+ "allowNo": false,
4196
+ "type": "boolean"
3368
4197
  }
3369
4198
  },
3370
4199
  "hasDynamicHelp": false,
3371
4200
  "hiddenAliases": [],
3372
- "id": "ai:agents:list",
4201
+ "id": "ai:prompts:list",
3373
4202
  "pluginAlias": "@memberjunction/cli",
3374
4203
  "pluginName": "@memberjunction/cli",
3375
4204
  "pluginType": "core",
@@ -3380,49 +4209,68 @@
3380
4209
  "dist",
3381
4210
  "commands",
3382
4211
  "ai",
3383
- "agents",
4212
+ "prompts",
3384
4213
  "list.js"
3385
4214
  ]
3386
4215
  },
3387
- "ai:agents:run": {
4216
+ "ai:prompts:run": {
3388
4217
  "aliases": [],
3389
4218
  "args": {},
3390
- "description": "Execute an AI agent with a prompt or start interactive chat",
4219
+ "description": "Execute a direct prompt with an AI model",
3391
4220
  "examples": [
3392
- "<%= config.bin %> <%= command.id %> -a \"Skip: Requirements Expert\" -p \"Create a dashboard for sales metrics\"",
3393
- "<%= config.bin %> <%= command.id %> -a \"Child Component Generator Sub-agent\" --chat",
3394
- "<%= config.bin %> <%= command.id %> -a \"Skip: Technical Design Expert\" -p \"Build a React component\" --verbose --timeout=600000"
4221
+ "<%= config.bin %> <%= command.id %> -p \"Explain quantum computing in simple terms\"",
4222
+ "<%= config.bin %> <%= command.id %> -p \"Write a Python function to sort a list\" --model \"gpt-4\"",
4223
+ "<%= config.bin %> <%= command.id %> -p \"Translate to French: Hello world\" --temperature 0.3",
4224
+ "<%= config.bin %> <%= command.id %> -p \"Generate a haiku\" --system \"You are a poet\" --max-tokens 100"
3395
4225
  ],
3396
4226
  "flags": {
3397
- "agent": {
3398
- "char": "a",
3399
- "description": "Agent name",
3400
- "name": "agent",
4227
+ "prompt": {
4228
+ "char": "p",
4229
+ "description": "The prompt to execute",
4230
+ "name": "prompt",
3401
4231
  "required": true,
3402
4232
  "hasDynamicHelp": false,
3403
4233
  "multiple": false,
3404
4234
  "type": "option"
3405
4235
  },
3406
- "prompt": {
3407
- "char": "p",
3408
- "description": "Prompt to execute",
3409
- "exclusive": [
3410
- "chat"
3411
- ],
3412
- "name": "prompt",
4236
+ "model": {
4237
+ "char": "m",
4238
+ "description": "AI model to use (e.g., gpt-4, claude-3-opus)",
4239
+ "name": "model",
3413
4240
  "hasDynamicHelp": false,
3414
4241
  "multiple": false,
3415
4242
  "type": "option"
3416
4243
  },
3417
- "chat": {
4244
+ "system": {
4245
+ "char": "s",
4246
+ "description": "System prompt to set context",
4247
+ "name": "system",
4248
+ "hasDynamicHelp": false,
4249
+ "multiple": false,
4250
+ "type": "option"
4251
+ },
4252
+ "temperature": {
4253
+ "char": "t",
4254
+ "description": "Temperature for response creativity (0.0-2.0)",
4255
+ "name": "temperature",
4256
+ "hasDynamicHelp": false,
4257
+ "multiple": false,
4258
+ "type": "option"
4259
+ },
4260
+ "max-tokens": {
4261
+ "description": "Maximum tokens for the response",
4262
+ "name": "max-tokens",
4263
+ "hasDynamicHelp": false,
4264
+ "multiple": false,
4265
+ "type": "option"
4266
+ },
4267
+ "configuration": {
3418
4268
  "char": "c",
3419
- "description": "Start interactive chat mode",
3420
- "exclusive": [
3421
- "prompt"
3422
- ],
3423
- "name": "chat",
3424
- "allowNo": false,
3425
- "type": "boolean"
4269
+ "description": "AI Configuration ID to use",
4270
+ "name": "configuration",
4271
+ "hasDynamicHelp": false,
4272
+ "multiple": false,
4273
+ "type": "option"
3426
4274
  },
3427
4275
  "output": {
3428
4276
  "char": "o",
@@ -3456,7 +4304,7 @@
3456
4304
  },
3457
4305
  "hasDynamicHelp": false,
3458
4306
  "hiddenAliases": [],
3459
- "id": "ai:agents:run",
4307
+ "id": "ai:prompts:run",
3460
4308
  "pluginAlias": "@memberjunction/cli",
3461
4309
  "pluginName": "@memberjunction/cli",
3462
4310
  "pluginType": "core",
@@ -3467,189 +4315,181 @@
3467
4315
  "dist",
3468
4316
  "commands",
3469
4317
  "ai",
3470
- "agents",
4318
+ "prompts",
3471
4319
  "run.js"
3472
4320
  ]
3473
4321
  },
3474
- "ai:audit:agent-run": {
4322
+ "test:regression:build": {
3475
4323
  "aliases": [],
3476
4324
  "args": {
3477
- "runId": {
3478
- "description": "AI Agent Run ID to audit (UUID)",
3479
- "name": "runId",
4325
+ "service": {
4326
+ "description": "Optional service name(s) to rebuild (e.g. mjexplorer, test-runner).",
4327
+ "name": "service",
3480
4328
  "required": false
3481
4329
  }
3482
4330
  },
3483
- "description": "Audit and analyze AI agent execution runs for debugging and performance analysis",
4331
+ "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.",
3484
4332
  "examples": [
3485
- "<%= config.bin %> <%= command.id %> abc-123-def-456",
3486
- "<%= config.bin %> <%= command.id %> abc-123-def-456 --output=markdown",
3487
- "<%= config.bin %> <%= command.id %> abc-123-def-456 --step 3",
3488
- "<%= config.bin %> <%= command.id %> abc-123-def-456 --step 3 --detail full",
3489
- "<%= config.bin %> <%= command.id %> abc-123-def-456 --errors",
3490
- "<%= config.bin %> <%= command.id %> --list --agent \"Skip: Requirements Expert\"",
3491
- "<%= config.bin %> <%= command.id %> --list --status failed --days 7",
3492
- "<%= config.bin %> <%= command.id %> abc-123-def-456 --export full --file report.json"
4333
+ "<%= config.bin %> <%= command.id %>",
4334
+ "<%= config.bin %> <%= command.id %> mjexplorer # rebuild a specific service",
4335
+ "<%= config.bin %> <%= command.id %> --skip-gen-forms"
3493
4336
  ],
3494
4337
  "flags": {
3495
- "output": {
3496
- "char": "o",
3497
- "description": "Output format",
3498
- "name": "output",
3499
- "default": "compact",
3500
- "hasDynamicHelp": false,
3501
- "multiple": false,
3502
- "options": [
3503
- "compact",
3504
- "json",
3505
- "table",
3506
- "markdown"
3507
- ],
3508
- "type": "option"
3509
- },
3510
- "step": {
3511
- "char": "s",
3512
- "description": "Show details for specific step number (1-based index)",
3513
- "exclusive": [
3514
- "list",
3515
- "errors"
3516
- ],
3517
- "name": "step",
3518
- "hasDynamicHelp": false,
3519
- "multiple": false,
3520
- "type": "option"
3521
- },
3522
- "detail": {
3523
- "char": "d",
3524
- "dependsOn": [
3525
- "step"
3526
- ],
3527
- "description": "Detail level for step output (default: standard)",
3528
- "name": "detail",
3529
- "hasDynamicHelp": false,
3530
- "multiple": false,
3531
- "options": [
3532
- "minimal",
3533
- "standard",
3534
- "detailed",
3535
- "full"
3536
- ],
3537
- "type": "option"
3538
- },
3539
- "errors": {
3540
- "char": "e",
3541
- "description": "Show only error details and context",
3542
- "exclusive": [
3543
- "step",
3544
- "list"
3545
- ],
3546
- "name": "errors",
4338
+ "skip-gen-forms": {
4339
+ "description": "Skip the gen-forms guard, even when .docker-generated/ is empty. Use when you know the entity forms are already generated.",
4340
+ "name": "skip-gen-forms",
3547
4341
  "allowNo": false,
3548
4342
  "type": "boolean"
3549
- },
3550
- "list": {
3551
- "char": "l",
3552
- "description": "List recent agent runs",
3553
- "exclusive": [
3554
- "step",
3555
- "errors"
3556
- ],
3557
- "name": "list",
4343
+ }
4344
+ },
4345
+ "hasDynamicHelp": false,
4346
+ "hiddenAliases": [],
4347
+ "id": "test:regression:build",
4348
+ "pluginAlias": "@memberjunction/cli",
4349
+ "pluginName": "@memberjunction/cli",
4350
+ "pluginType": "core",
4351
+ "strict": false,
4352
+ "enableJsonFlag": false,
4353
+ "isESM": true,
4354
+ "relativePath": [
4355
+ "dist",
4356
+ "commands",
4357
+ "test",
4358
+ "regression",
4359
+ "build.js"
4360
+ ]
4361
+ },
4362
+ "test:regression:compare": {
4363
+ "aliases": [],
4364
+ "args": {},
4365
+ "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.",
4366
+ "examples": [
4367
+ "<%= config.bin %> <%= command.id %>",
4368
+ "<%= config.bin %> <%= command.id %> --diff-only",
4369
+ "<%= config.bin %> <%= command.id %> --format=markdown --output=delta.md"
4370
+ ],
4371
+ "flags": {
4372
+ "diff-only": {
4373
+ "description": "Show only differences.",
4374
+ "name": "diff-only",
3558
4375
  "allowNo": false,
3559
4376
  "type": "boolean"
3560
4377
  },
3561
- "agent": {
3562
- "char": "a",
3563
- "dependsOn": [
3564
- "list"
3565
- ],
3566
- "description": "Filter by agent name",
3567
- "name": "agent",
3568
- "hasDynamicHelp": false,
3569
- "multiple": false,
3570
- "type": "option"
3571
- },
3572
- "status": {
3573
- "dependsOn": [
3574
- "list"
3575
- ],
3576
- "description": "Filter by run status",
3577
- "name": "status",
3578
- "default": "all",
3579
- "hasDynamicHelp": false,
3580
- "multiple": false,
3581
- "options": [
3582
- "success",
3583
- "failed",
3584
- "running",
3585
- "all"
3586
- ],
3587
- "type": "option"
3588
- },
3589
- "days": {
3590
- "dependsOn": [
3591
- "list"
3592
- ],
3593
- "description": "Number of days to look back",
3594
- "name": "days",
3595
- "default": 7,
4378
+ "format": {
4379
+ "char": "f",
4380
+ "description": "Output format.",
4381
+ "name": "format",
4382
+ "default": "console",
3596
4383
  "hasDynamicHelp": false,
3597
4384
  "multiple": false,
4385
+ "options": [
4386
+ "console",
4387
+ "json",
4388
+ "markdown"
4389
+ ],
3598
4390
  "type": "option"
3599
4391
  },
3600
- "limit": {
3601
- "dependsOn": [
3602
- "list"
3603
- ],
3604
- "description": "Maximum number of runs to return",
3605
- "name": "limit",
3606
- "default": 50,
4392
+ "output": {
4393
+ "char": "o",
4394
+ "description": "Output file path.",
4395
+ "name": "output",
3607
4396
  "hasDynamicHelp": false,
3608
4397
  "multiple": false,
3609
4398
  "type": "option"
3610
4399
  },
3611
- "export": {
3612
- "dependsOn": [
3613
- "file"
3614
- ],
3615
- "description": "Export full data to file",
3616
- "name": "export",
4400
+ "verbose": {
4401
+ "description": "Show detailed information.",
4402
+ "name": "verbose",
4403
+ "allowNo": false,
4404
+ "type": "boolean"
4405
+ },
4406
+ "tag": {
4407
+ "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.",
4408
+ "name": "tag",
3617
4409
  "hasDynamicHelp": false,
3618
4410
  "multiple": false,
3619
- "options": [
3620
- "full",
3621
- "summary",
3622
- "steps"
3623
- ],
3624
4411
  "type": "option"
3625
- },
3626
- "file": {
3627
- "char": "f",
3628
- "description": "Output file path for export",
3629
- "name": "file",
4412
+ }
4413
+ },
4414
+ "hasDynamicHelp": false,
4415
+ "hiddenAliases": [],
4416
+ "id": "test:regression:compare",
4417
+ "pluginAlias": "@memberjunction/cli",
4418
+ "pluginName": "@memberjunction/cli",
4419
+ "pluginType": "core",
4420
+ "strict": false,
4421
+ "enableJsonFlag": false,
4422
+ "isESM": true,
4423
+ "relativePath": [
4424
+ "dist",
4425
+ "commands",
4426
+ "test",
4427
+ "regression",
4428
+ "compare.js"
4429
+ ]
4430
+ },
4431
+ "test:regression:down": {
4432
+ "aliases": [],
4433
+ "args": {},
4434
+ "description": "Stop the regression stack and wipe DB volumes (docker compose down -v).",
4435
+ "examples": [
4436
+ "<%= config.bin %> <%= command.id %>",
4437
+ "<%= config.bin %> <%= command.id %> --keep-volumes"
4438
+ ],
4439
+ "flags": {
4440
+ "keep-volumes": {
4441
+ "description": "Skip the `-v` flag — preserves the ephemeral DB volume.",
4442
+ "name": "keep-volumes",
4443
+ "allowNo": false,
4444
+ "type": "boolean"
4445
+ }
4446
+ },
4447
+ "hasDynamicHelp": false,
4448
+ "hiddenAliases": [],
4449
+ "id": "test:regression:down",
4450
+ "pluginAlias": "@memberjunction/cli",
4451
+ "pluginName": "@memberjunction/cli",
4452
+ "pluginType": "core",
4453
+ "strict": true,
4454
+ "enableJsonFlag": false,
4455
+ "isESM": true,
4456
+ "relativePath": [
4457
+ "dist",
4458
+ "commands",
4459
+ "test",
4460
+ "regression",
4461
+ "down.js"
4462
+ ]
4463
+ },
4464
+ "test:regression:export": {
4465
+ "aliases": [],
4466
+ "args": {},
4467
+ "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.",
4468
+ "examples": [
4469
+ "<%= config.bin %> <%= command.id %>",
4470
+ "<%= config.bin %> <%= command.id %> --run=run-20260526T220118Z",
4471
+ "<%= config.bin %> <%= command.id %> --run=./some/other/run-dir"
4472
+ ],
4473
+ "flags": {
4474
+ "run": {
4475
+ "char": "r",
4476
+ "description": "Which run to export. A folder name (under test-results/) or a path. Defaults to the latest run.",
4477
+ "name": "run",
3630
4478
  "hasDynamicHelp": false,
3631
4479
  "multiple": false,
3632
4480
  "type": "option"
3633
4481
  },
3634
- "max-tokens": {
3635
- "description": "Maximum tokens per field (0 = no limit)",
3636
- "name": "max-tokens",
3637
- "default": 5000,
4482
+ "image": {
4483
+ "description": "(external) Published image used to inline reports. Default: memberjunction/agentic-test-runner:latest.",
4484
+ "name": "image",
3638
4485
  "hasDynamicHelp": false,
3639
4486
  "multiple": false,
3640
4487
  "type": "option"
3641
- },
3642
- "verbose": {
3643
- "char": "v",
3644
- "description": "Show detailed diagnostic information",
3645
- "name": "verbose",
3646
- "allowNo": false,
3647
- "type": "boolean"
3648
4488
  }
3649
4489
  },
3650
4490
  "hasDynamicHelp": false,
3651
4491
  "hiddenAliases": [],
3652
- "id": "ai:audit:agent-run",
4492
+ "id": "test:regression:export",
3653
4493
  "pluginAlias": "@memberjunction/cli",
3654
4494
  "pluginName": "@memberjunction/cli",
3655
4495
  "pluginType": "core",
@@ -3659,20 +4499,22 @@
3659
4499
  "relativePath": [
3660
4500
  "dist",
3661
4501
  "commands",
3662
- "ai",
3663
- "audit",
3664
- "agent-run.js"
4502
+ "test",
4503
+ "regression",
4504
+ "export.js"
3665
4505
  ]
3666
4506
  },
3667
- "ai:audit": {
4507
+ "test:regression:gen-forms": {
3668
4508
  "aliases": [],
3669
4509
  "args": {},
3670
- "description": "Analyze and audit AI agent runs, prompts, and actions for debugging and performance analysis",
4510
+ "description": "Regenerate Angular entity forms used by the regression MJExplorer image. Slow (~5 min) — only required after schema or codegen changes.",
4511
+ "examples": [
4512
+ "<%= config.bin %> <%= command.id %>"
4513
+ ],
3671
4514
  "flags": {},
3672
4515
  "hasDynamicHelp": false,
3673
- "hidden": false,
3674
4516
  "hiddenAliases": [],
3675
- "id": "ai:audit",
4517
+ "id": "test:regression:gen-forms",
3676
4518
  "pluginAlias": "@memberjunction/cli",
3677
4519
  "pluginName": "@memberjunction/cli",
3678
4520
  "pluginType": "core",
@@ -3682,30 +4524,71 @@
3682
4524
  "relativePath": [
3683
4525
  "dist",
3684
4526
  "commands",
3685
- "ai",
3686
- "audit",
3687
- "index.js"
4527
+ "test",
4528
+ "regression",
4529
+ "gen-forms.js"
3688
4530
  ]
3689
4531
  },
3690
- "ai:prompts:list": {
4532
+ "test:regression": {
3691
4533
  "aliases": [],
3692
4534
  "args": {},
3693
- "description": "List available models for prompt execution",
4535
+ "description": "MJ Explorer regression test suite — Docker-based LLM-driven browser tests",
3694
4536
  "examples": [
3695
- "<%= config.bin %> <%= command.id %>"
4537
+ "<%= config.bin %> <%= command.id %> build # Build images (incl. gen-forms on first run)",
4538
+ "<%= config.bin %> <%= command.id %> up # Run the full self-contained MJ stack (Mode A)",
4539
+ "<%= config.bin %> <%= command.id %> down # Tear down + wipe DB volumes",
4540
+ "<%= config.bin %> <%= command.id %> gen-forms # Regenerate Angular entity forms",
4541
+ "<%= config.bin %> <%= command.id %> compare # Diff the two most recent runs",
4542
+ "<%= config.bin %> <%= command.id %> export # Export a run as a portable standalone HTML",
4543
+ "<%= config.bin %> <%= command.id %> remote --target=staging-mj # Mode B/C/D against a remote URL",
4544
+ "<%= config.bin %> <%= command.id %> init generic-web # Scaffold one of the example dirs"
4545
+ ],
4546
+ "flags": {},
4547
+ "hasDynamicHelp": false,
4548
+ "hiddenAliases": [],
4549
+ "id": "test:regression",
4550
+ "pluginAlias": "@memberjunction/cli",
4551
+ "pluginName": "@memberjunction/cli",
4552
+ "pluginType": "core",
4553
+ "strict": true,
4554
+ "enableJsonFlag": false,
4555
+ "isESM": true,
4556
+ "relativePath": [
4557
+ "dist",
4558
+ "commands",
4559
+ "test",
4560
+ "regression",
4561
+ "index.js"
4562
+ ]
4563
+ },
4564
+ "test:regression:init": {
4565
+ "aliases": [],
4566
+ "args": {
4567
+ "name": {
4568
+ "description": "Template name to scaffold (run with --list to see available).",
4569
+ "name": "name",
4570
+ "required": false
4571
+ }
4572
+ },
4573
+ "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.",
4574
+ "examples": [
4575
+ "<%= config.bin %> <%= command.id %> generic-web",
4576
+ "<%= config.bin %> <%= command.id %> static-file-server",
4577
+ "<%= config.bin %> <%= command.id %> remote-mj",
4578
+ "<%= config.bin %> <%= command.id %> bring-your-own-app",
4579
+ "<%= config.bin %> <%= command.id %> --list"
3696
4580
  ],
3697
4581
  "flags": {
3698
- "verbose": {
3699
- "char": "v",
3700
- "description": "Show detailed model information",
3701
- "name": "verbose",
4582
+ "list": {
4583
+ "description": "List available templates and exit.",
4584
+ "name": "list",
3702
4585
  "allowNo": false,
3703
4586
  "type": "boolean"
3704
4587
  }
3705
4588
  },
3706
4589
  "hasDynamicHelp": false,
3707
4590
  "hiddenAliases": [],
3708
- "id": "ai:prompts:list",
4591
+ "id": "test:regression:init",
3709
4592
  "pluginAlias": "@memberjunction/cli",
3710
4593
  "pluginName": "@memberjunction/cli",
3711
4594
  "pluginType": "core",
@@ -3715,95 +4598,145 @@
3715
4598
  "relativePath": [
3716
4599
  "dist",
3717
4600
  "commands",
3718
- "ai",
3719
- "prompts",
3720
- "list.js"
4601
+ "test",
4602
+ "regression",
4603
+ "init.js"
3721
4604
  ]
3722
4605
  },
3723
- "ai:prompts:run": {
4606
+ "test:regression:remote": {
3724
4607
  "aliases": [],
3725
4608
  "args": {},
3726
- "description": "Execute a direct prompt with an AI model",
4609
+ "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).",
3727
4610
  "examples": [
3728
- "<%= config.bin %> <%= command.id %> -p \"Explain quantum computing in simple terms\"",
3729
- "<%= config.bin %> <%= command.id %> -p \"Write a Python function to sort a list\" --model \"gpt-4\"",
3730
- "<%= config.bin %> <%= command.id %> -p \"Translate to French: Hello world\" --temperature 0.3",
3731
- "<%= config.bin %> <%= command.id %> -p \"Generate a haiku\" --system \"You are a poet\" --max-tokens 100"
4611
+ "<%= config.bin %> <%= command.id %> --target=staging-mj",
4612
+ "<%= config.bin %> <%= command.id %> --target=./my/custom.target.json",
4613
+ "<%= config.bin %> <%= command.id %> --target=./app/target.json --overlay=./app/docker-compose.app.yml",
4614
+ "<%= config.bin %> <%= command.id %> --target=./t.json --image=memberjunction/agentic-test-runner:v5.30.0 --env-file=./.env"
3732
4615
  ],
3733
4616
  "flags": {
3734
- "prompt": {
3735
- "char": "p",
3736
- "description": "The prompt to execute",
3737
- "name": "prompt",
4617
+ "target": {
4618
+ "char": "t",
4619
+ "description": "Target profile. Bare name (monorepo: docker/regression/targets/<name>.target.json) or a path.",
4620
+ "name": "target",
3738
4621
  "required": true,
3739
4622
  "hasDynamicHelp": false,
3740
4623
  "multiple": false,
3741
4624
  "type": "option"
3742
4625
  },
3743
- "model": {
3744
- "char": "m",
3745
- "description": "AI model to use (e.g., gpt-4, claude-3-opus)",
3746
- "name": "model",
4626
+ "no-local-stack": {
4627
+ "description": "(monorepo only) Use the lean `remote-target` profile (test-runner only) instead of the full local stack.",
4628
+ "name": "no-local-stack",
4629
+ "allowNo": false,
4630
+ "type": "boolean"
4631
+ },
4632
+ "overlay": {
4633
+ "description": "docker-compose overlay (Mode D) that boots your app alongside the runner on the same network. May repeat.",
4634
+ "name": "overlay",
4635
+ "hasDynamicHelp": false,
4636
+ "multiple": true,
4637
+ "type": "option"
4638
+ },
4639
+ "image": {
4640
+ "description": "(external) Published image tag to run. Default: memberjunction/agentic-test-runner:latest. Pin for reproducibility.",
4641
+ "name": "image",
3747
4642
  "hasDynamicHelp": false,
3748
4643
  "multiple": false,
3749
4644
  "type": "option"
3750
4645
  },
3751
- "system": {
3752
- "char": "s",
3753
- "description": "System prompt to set context",
3754
- "name": "system",
4646
+ "env-file": {
4647
+ "description": "(external) Path to a .env injected into the runner (DB_*, AI_VENDOR_API_KEY__GeminiLLM, auth env: refs).",
4648
+ "name": "env-file",
3755
4649
  "hasDynamicHelp": false,
3756
4650
  "multiple": false,
3757
4651
  "type": "option"
3758
4652
  },
3759
- "temperature": {
3760
- "char": "t",
3761
- "description": "Temperature for response creativity (0.0-2.0)",
3762
- "name": "temperature",
4653
+ "detach": {
4654
+ "char": "d",
4655
+ "description": "(monorepo) Run in the background (docker compose up -d).",
4656
+ "name": "detach",
4657
+ "allowNo": false,
4658
+ "type": "boolean"
4659
+ }
4660
+ },
4661
+ "hasDynamicHelp": false,
4662
+ "hiddenAliases": [],
4663
+ "id": "test:regression:remote",
4664
+ "pluginAlias": "@memberjunction/cli",
4665
+ "pluginName": "@memberjunction/cli",
4666
+ "pluginType": "core",
4667
+ "strict": true,
4668
+ "enableJsonFlag": false,
4669
+ "isESM": true,
4670
+ "relativePath": [
4671
+ "dist",
4672
+ "commands",
4673
+ "test",
4674
+ "regression",
4675
+ "remote.js"
4676
+ ]
4677
+ },
4678
+ "test:regression:up": {
4679
+ "aliases": [],
4680
+ "args": {},
4681
+ "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).",
4682
+ "examples": [
4683
+ "<%= config.bin %> <%= command.id %>",
4684
+ "<%= config.bin %> <%= command.id %> --detach",
4685
+ "<%= config.bin %> <%= command.id %> --bacpac=./db.bacpac --suite=\"My Suite\" --metadata=./my-suite-metadata",
4686
+ "<%= config.bin %> <%= command.id %> --bacpac=./db.bacpac --bacpac-no-upgrade"
4687
+ ],
4688
+ "flags": {
4689
+ "detach": {
4690
+ "char": "d",
4691
+ "description": "Run containers in the background (docker compose up -d).",
4692
+ "name": "detach",
4693
+ "allowNo": false,
4694
+ "type": "boolean"
4695
+ },
4696
+ "bacpac": {
4697
+ "description": "Path to a .bacpac of a real MJ database to import and test against.",
4698
+ "name": "bacpac",
3763
4699
  "hasDynamicHelp": false,
3764
4700
  "multiple": false,
3765
4701
  "type": "option"
3766
4702
  },
3767
- "max-tokens": {
3768
- "description": "Maximum tokens for the response",
3769
- "name": "max-tokens",
4703
+ "bacpac-no-upgrade": {
4704
+ "description": "Import the bacpac as-is — skip migrate/codegen. Only safe at the current MJ version. Requires --bacpac.",
4705
+ "name": "bacpac-no-upgrade",
4706
+ "allowNo": false,
4707
+ "type": "boolean"
4708
+ },
4709
+ "suite": {
4710
+ "description": "Test suite to run (TEST_SUITE_NAME). Use with --bacpac + --metadata.",
4711
+ "name": "suite",
3770
4712
  "hasDynamicHelp": false,
3771
4713
  "multiple": false,
3772
4714
  "type": "option"
3773
4715
  },
3774
- "configuration": {
3775
- "char": "c",
3776
- "description": "AI Configuration ID to use",
3777
- "name": "configuration",
4716
+ "metadata": {
4717
+ "description": "Directory of your test + test-suite metadata (pushed before the run). Requires --bacpac.",
4718
+ "name": "metadata",
3778
4719
  "hasDynamicHelp": false,
3779
4720
  "multiple": false,
3780
4721
  "type": "option"
3781
4722
  },
3782
- "output": {
3783
- "char": "o",
3784
- "description": "Output format",
3785
- "name": "output",
3786
- "default": "compact",
4723
+ "image": {
4724
+ "description": "(external) Published agentic-test-runner image. Default: memberjunction/agentic-test-runner:latest.",
4725
+ "name": "image",
3787
4726
  "hasDynamicHelp": false,
3788
4727
  "multiple": false,
3789
- "options": [
3790
- "compact",
3791
- "json",
3792
- "table"
3793
- ],
3794
4728
  "type": "option"
3795
4729
  },
3796
- "verbose": {
3797
- "char": "v",
3798
- "description": "Show detailed execution information",
3799
- "name": "verbose",
3800
- "allowNo": false,
3801
- "type": "boolean"
4730
+ "explorer-image": {
4731
+ "description": "(external bacpac) Published Explorer image (prerequisite). Default: memberjunction/explorer:latest.",
4732
+ "name": "explorer-image",
4733
+ "hasDynamicHelp": false,
4734
+ "multiple": false,
4735
+ "type": "option"
3802
4736
  },
3803
- "timeout": {
3804
- "description": "Execution timeout in milliseconds",
3805
- "name": "timeout",
3806
- "default": 300000,
4737
+ "env-file": {
4738
+ "description": "(external) .env injected into the runner (auth env: refs).",
4739
+ "name": "env-file",
3807
4740
  "hasDynamicHelp": false,
3808
4741
  "multiple": false,
3809
4742
  "type": "option"
@@ -3811,7 +4744,7 @@
3811
4744
  },
3812
4745
  "hasDynamicHelp": false,
3813
4746
  "hiddenAliases": [],
3814
- "id": "ai:prompts:run",
4747
+ "id": "test:regression:up",
3815
4748
  "pluginAlias": "@memberjunction/cli",
3816
4749
  "pluginName": "@memberjunction/cli",
3817
4750
  "pluginType": "core",
@@ -3821,11 +4754,11 @@
3821
4754
  "relativePath": [
3822
4755
  "dist",
3823
4756
  "commands",
3824
- "ai",
3825
- "prompts",
3826
- "run.js"
4757
+ "test",
4758
+ "regression",
4759
+ "up.js"
3827
4760
  ]
3828
4761
  }
3829
4762
  },
3830
- "version": "5.37.0"
4763
+ "version": "5.39.0"
3831
4764
  }