@memberjunction/cli 5.44.0 → 5.45.1

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.
@@ -188,7 +188,8 @@
188
188
  "<%= config.bin %> app install https://github.com/acme/mj-crm",
189
189
  "<%= config.bin %> app install https://github.com/acme/mj-crm --version 1.2.0",
190
190
  "<%= config.bin %> app install https://github.com/acme/mj-crm --verbose",
191
- "<%= config.bin %> app install https://github.com/MemberJunction/Integrations/CRM/HubSpot"
191
+ "<%= config.bin %> app install https://github.com/MemberJunction/Integrations/CRM/HubSpot",
192
+ "<%= config.bin %> app install https://github.com/acme/mj-crm --non-interactive"
192
193
  ],
193
194
  "flags": {
194
195
  "version": {
@@ -205,6 +206,12 @@
205
206
  "allowNo": false,
206
207
  "type": "boolean"
207
208
  },
209
+ "non-interactive": {
210
+ "description": "Skip interactive setup prompts; post-install hooks use environment variables / defaults (for CI/headless installs)",
211
+ "name": "non-interactive",
212
+ "allowNo": false,
213
+ "type": "boolean"
214
+ },
208
215
  "dangerously-ignore-dbl-underscore-schema-rule": {
209
216
  "hidden": true,
210
217
  "name": "dangerously-ignore-dbl-underscore-schema-rule",
@@ -354,6 +361,12 @@
354
361
  "allowNo": false,
355
362
  "type": "boolean"
356
363
  },
364
+ "non-interactive": {
365
+ "description": "Skip interactive prompts; post-upgrade hooks use environment variables / defaults (for CI/headless upgrades)",
366
+ "name": "non-interactive",
367
+ "allowNo": false,
368
+ "type": "boolean"
369
+ },
357
370
  "dangerously-ignore-dbl-underscore-schema-rule": {
358
371
  "hidden": true,
359
372
  "name": "dangerously-ignore-dbl-underscore-schema-rule",
@@ -715,6 +728,67 @@
715
728
  "roundtrip.js"
716
729
  ]
717
730
  },
731
+ "artifacts:reclassify": {
732
+ "aliases": [],
733
+ "args": {},
734
+ "description": "Upgrade-recovery utility for v5.35 artifact unification. Re-evaluates rows whose TypeID is the deleted JSON fallback but whose actual content does not parse as JSON. Normally a no-op: the v5.35 backfill migration handles this automatically. This command is only relevant when the migration ran BEFORE the artifact-type metadata (Generic Text / Generic Binary) was pushed via `mj sync push`, in which case the migration prints a notice telling you to run this. Reports \"no candidates\" once everything is reconciled. Dry-run by default; --apply writes through Record Changes.",
735
+ "examples": [
736
+ "<%= config.bin %> <%= command.id %>",
737
+ "<%= config.bin %> <%= command.id %> --apply --limit 50"
738
+ ],
739
+ "flags": {
740
+ "conversation-id": {
741
+ "description": "Scope to artifacts attached to the given conversation.",
742
+ "name": "conversation-id",
743
+ "hasDynamicHelp": false,
744
+ "multiple": false,
745
+ "type": "option"
746
+ },
747
+ "since": {
748
+ "description": "Scope to artifacts created on/after this ISO date.",
749
+ "name": "since",
750
+ "hasDynamicHelp": false,
751
+ "multiple": false,
752
+ "type": "option"
753
+ },
754
+ "limit": {
755
+ "description": "Maximum number of rows to inspect.",
756
+ "name": "limit",
757
+ "default": 100,
758
+ "hasDynamicHelp": false,
759
+ "multiple": false,
760
+ "type": "option"
761
+ },
762
+ "apply": {
763
+ "description": "Write changes. Without this flag, this command only reports what it would do.",
764
+ "name": "apply",
765
+ "allowNo": false,
766
+ "type": "boolean"
767
+ },
768
+ "verbose": {
769
+ "char": "v",
770
+ "description": "Print every candidate row, not just the summary.",
771
+ "name": "verbose",
772
+ "allowNo": false,
773
+ "type": "boolean"
774
+ }
775
+ },
776
+ "hasDynamicHelp": false,
777
+ "hiddenAliases": [],
778
+ "id": "artifacts:reclassify",
779
+ "pluginAlias": "@memberjunction/cli",
780
+ "pluginName": "@memberjunction/cli",
781
+ "pluginType": "core",
782
+ "strict": true,
783
+ "enableJsonFlag": false,
784
+ "isESM": true,
785
+ "relativePath": [
786
+ "dist",
787
+ "commands",
788
+ "artifacts",
789
+ "reclassify.js"
790
+ ]
791
+ },
718
792
  "bump": {
719
793
  "aliases": [],
720
794
  "args": {},
@@ -905,67 +979,6 @@
905
979
  "index.js"
906
980
  ]
907
981
  },
908
- "artifacts:reclassify": {
909
- "aliases": [],
910
- "args": {},
911
- "description": "Upgrade-recovery utility for v5.35 artifact unification. Re-evaluates rows whose TypeID is the deleted JSON fallback but whose actual content does not parse as JSON. Normally a no-op: the v5.35 backfill migration handles this automatically. This command is only relevant when the migration ran BEFORE the artifact-type metadata (Generic Text / Generic Binary) was pushed via `mj sync push`, in which case the migration prints a notice telling you to run this. Reports \"no candidates\" once everything is reconciled. Dry-run by default; --apply writes through Record Changes.",
912
- "examples": [
913
- "<%= config.bin %> <%= command.id %>",
914
- "<%= config.bin %> <%= command.id %> --apply --limit 50"
915
- ],
916
- "flags": {
917
- "conversation-id": {
918
- "description": "Scope to artifacts attached to the given conversation.",
919
- "name": "conversation-id",
920
- "hasDynamicHelp": false,
921
- "multiple": false,
922
- "type": "option"
923
- },
924
- "since": {
925
- "description": "Scope to artifacts created on/after this ISO date.",
926
- "name": "since",
927
- "hasDynamicHelp": false,
928
- "multiple": false,
929
- "type": "option"
930
- },
931
- "limit": {
932
- "description": "Maximum number of rows to inspect.",
933
- "name": "limit",
934
- "default": 100,
935
- "hasDynamicHelp": false,
936
- "multiple": false,
937
- "type": "option"
938
- },
939
- "apply": {
940
- "description": "Write changes. Without this flag, this command only reports what it would do.",
941
- "name": "apply",
942
- "allowNo": false,
943
- "type": "boolean"
944
- },
945
- "verbose": {
946
- "char": "v",
947
- "description": "Print every candidate row, not just the summary.",
948
- "name": "verbose",
949
- "allowNo": false,
950
- "type": "boolean"
951
- }
952
- },
953
- "hasDynamicHelp": false,
954
- "hiddenAliases": [],
955
- "id": "artifacts:reclassify",
956
- "pluginAlias": "@memberjunction/cli",
957
- "pluginName": "@memberjunction/cli",
958
- "pluginType": "core",
959
- "strict": true,
960
- "enableJsonFlag": false,
961
- "isESM": true,
962
- "relativePath": [
963
- "dist",
964
- "commands",
965
- "artifacts",
966
- "reclassify.js"
967
- ]
968
- },
969
982
  "codegen:5-0-fix-entity-names": {
970
983
  "aliases": [],
971
984
  "args": {},
@@ -1964,106 +1977,90 @@
1964
1977
  "index.js"
1965
1978
  ]
1966
1979
  },
1967
- "install:claude": {
1980
+ "migrate:convert": {
1968
1981
  "aliases": [],
1969
1982
  "args": {},
1970
- "description": "Install or refresh the Claude Code pack in the current directory.",
1983
+ "description": "Convert T-SQL migrations to PostgreSQL",
1971
1984
  "examples": [
1972
- "<%= config.bin %> install:claude",
1973
- "<%= config.bin %> install:claude --dry-run",
1974
- "<%= config.bin %> install:claude --from ./local-pack",
1975
- "<%= config.bin %> install:claude --json"
1985
+ "<%= config.bin %> migrate convert --split",
1986
+ "<%= config.bin %> migrate convert --split --dry-run",
1987
+ "<%= config.bin %> migrate convert --split --file V202604060452__v5.24.x__KnowledgeHub.sql",
1988
+ "<%= config.bin %> migrate convert --source-dir ./migrations/v5 --output-dir ./migrations-pg/v5",
1989
+ "<%= config.bin %> migrate convert --verbose"
1976
1990
  ],
1977
1991
  "flags": {
1978
- "dir": {
1979
- "description": "Target directory for the install",
1980
- "name": "dir",
1981
- "default": ".",
1992
+ "source-dir": {
1993
+ "description": "Source T-SQL migrations directory",
1994
+ "name": "source-dir",
1995
+ "default": "./migrations/v5",
1982
1996
  "hasDynamicHelp": false,
1983
1997
  "multiple": false,
1984
1998
  "type": "option"
1985
1999
  },
1986
- "major": {
1987
- "description": "Force a specific MJ major (default: detected from package.json)",
1988
- "name": "major",
2000
+ "output-dir": {
2001
+ "description": "Output PG migrations directory",
2002
+ "name": "output-dir",
2003
+ "default": "./migrations-pg/v5",
1989
2004
  "hasDynamicHelp": false,
1990
2005
  "multiple": false,
1991
2006
  "type": "option"
1992
2007
  },
1993
- "ref": {
1994
- "description": "Git ref to fetch from (branch or tag). Default: main.",
1995
- "name": "ref",
2008
+ "file": {
2009
+ "description": "Convert a specific file (filename only, looked up in source-dir)",
2010
+ "name": "file",
1996
2011
  "hasDynamicHelp": false,
1997
2012
  "multiple": false,
1998
2013
  "type": "option"
1999
2014
  },
2000
- "from": {
2001
- "description": "Use a local pack source instead of fetching from GitHub",
2002
- "name": "from",
2015
+ "schema": {
2016
+ "description": "Target schema name",
2017
+ "name": "schema",
2018
+ "default": "__mj",
2003
2019
  "hasDynamicHelp": false,
2004
2020
  "multiple": false,
2005
2021
  "type": "option"
2006
2022
  },
2007
- "offline": {
2008
- "description": "Forbid network; requires --from <path>",
2009
- "name": "offline",
2010
- "allowNo": false,
2011
- "type": "boolean"
2012
- },
2013
2023
  "dry-run": {
2014
- "description": "Print what would be written; change nothing",
2024
+ "description": "Show what would be converted without writing files",
2015
2025
  "name": "dry-run",
2016
2026
  "allowNo": false,
2017
2027
  "type": "boolean"
2018
2028
  },
2019
- "yes": {
2020
- "char": "y",
2021
- "description": "Don't prompt (reserved for future interactive paths; currently no-op)",
2022
- "name": "yes",
2023
- "allowNo": false,
2024
- "type": "boolean"
2025
- },
2026
- "force": {
2027
- "description": "Overwrite user-customized commands/skills (saves .bak files)",
2028
- "name": "force",
2029
- "allowNo": false,
2030
- "type": "boolean"
2031
- },
2032
- "skip-commands": {
2033
- "description": "Skip seeding .claude/commands/",
2034
- "name": "skip-commands",
2029
+ "no-header": {
2030
+ "description": "Skip PG header (extensions, schema, implicit cast)",
2031
+ "name": "no-header",
2035
2032
  "allowNo": false,
2036
2033
  "type": "boolean"
2037
2034
  },
2038
- "skip-skills": {
2039
- "description": "Skip seeding .claude/skills/",
2040
- "name": "skip-skills",
2035
+ "verbose": {
2036
+ "char": "v",
2037
+ "description": "Show per-statement progress",
2038
+ "name": "verbose",
2041
2039
  "allowNo": false,
2042
2040
  "type": "boolean"
2043
2041
  },
2044
- "skip-settings": {
2045
- "description": "Skip merging .claude/settings.json",
2046
- "name": "skip-settings",
2042
+ "split": {
2043
+ "description": "Split-and-regenerate (the standard path): transpile only hand-written DDL via the AST dialect; CodeGen objects are regenerated by `mj codegen` and mj-sync metadata re-seeded by `mj sync push`; every conversion gap is surfaced and fails the run unless --allow-gaps.",
2044
+ "name": "split",
2047
2045
  "allowNo": false,
2048
2046
  "type": "boolean"
2049
2047
  },
2050
- "json": {
2051
- "description": "Output as JSON (matches plan §7.5 schema)",
2052
- "name": "json",
2048
+ "allow-gaps": {
2049
+ "description": "With --split: exit 0 even when migrations have conversion gaps (hand-authoring needed or unhandled statements). Gaps are still embedded as comments and listed in the summary.",
2050
+ "name": "allow-gaps",
2053
2051
  "allowNo": false,
2054
2052
  "type": "boolean"
2055
2053
  },
2056
- "verbose": {
2057
- "char": "v",
2058
- "description": "Show progress messages from the fetcher and merger",
2059
- "name": "verbose",
2054
+ "bake-codegen": {
2055
+ "description": "With --split: bake native PG CodeGen objects inline per migration (Path C), so the set deploys with `mj migrate` alone — no `mj codegen` step. Requires a LIVE working PG database (DB_PLATFORM=postgresql + PG_* env, same as `mj codegen`) seeded to the state just BEFORE the migrations being converted (typically the latest baseline); the converter brings it forward in committed order as it bakes. Not compatible with --dry-run.",
2056
+ "name": "bake-codegen",
2060
2057
  "allowNo": false,
2061
2058
  "type": "boolean"
2062
2059
  }
2063
2060
  },
2064
2061
  "hasDynamicHelp": false,
2065
2062
  "hiddenAliases": [],
2066
- "id": "install:claude",
2063
+ "id": "migrate:convert",
2067
2064
  "pluginAlias": "@memberjunction/cli",
2068
2065
  "pluginName": "@memberjunction/cli",
2069
2066
  "pluginType": "core",
@@ -2073,248 +2070,30 @@
2073
2070
  "relativePath": [
2074
2071
  "dist",
2075
2072
  "commands",
2076
- "install",
2077
- "claude.js"
2073
+ "migrate",
2074
+ "convert.js"
2078
2075
  ]
2079
2076
  },
2080
- "install": {
2077
+ "migrate:create": {
2081
2078
  "aliases": [],
2082
- "args": {},
2083
- "description": "Install MemberJunction from a GitHub release",
2079
+ "args": {
2080
+ "description": {
2081
+ "description": "Short description (will be converted to PascalCase with underscores)",
2082
+ "name": "description",
2083
+ "required": true
2084
+ }
2085
+ },
2086
+ "description": "Scaffold a new migration file for the current database platform",
2084
2087
  "examples": [
2085
- "<%= config.bin %> <%= command.id %>",
2086
- "<%= config.bin %> <%= command.id %> -t v4.3.0",
2087
- "<%= config.bin %> <%= command.id %> --dry-run",
2088
- "<%= config.bin %> <%= command.id %> --yes"
2088
+ "<%= config.bin %> <%= command.id %> \"Add FooID to Bar\"",
2089
+ "<%= config.bin %> <%= command.id %> \"Add FooID to Bar\" --version 5.25 --platform postgresql",
2090
+ "<%= config.bin %> <%= command.id %> \"Add FooID to Bar\" --dir ./migrations/v5"
2089
2091
  ],
2090
2092
  "flags": {
2091
- "tag": {
2092
- "char": "t",
2093
- "description": "Release tag to install (e.g. v4.3.0). If omitted, shows a version picker.",
2094
- "name": "tag",
2095
- "hasDynamicHelp": false,
2096
- "multiple": false,
2097
- "type": "option"
2098
- },
2099
- "dir": {
2100
- "description": "Target directory for the installation",
2101
- "name": "dir",
2102
- "default": ".",
2103
- "hasDynamicHelp": false,
2104
- "multiple": false,
2105
- "type": "option"
2106
- },
2107
- "config": {
2108
- "char": "c",
2109
- "description": "Path to JSON config file with install settings (database, auth, ports, etc.)",
2110
- "name": "config",
2111
- "hasDynamicHelp": false,
2112
- "multiple": false,
2113
- "type": "option"
2114
- },
2115
- "legacy": {
2116
- "description": "Use the legacy interactive installer (ZIP-only distribution)",
2117
- "hidden": true,
2118
- "name": "legacy",
2119
- "allowNo": false,
2120
- "type": "boolean"
2121
- },
2122
- "dry-run": {
2123
- "description": "Show the install plan without executing it",
2124
- "name": "dry-run",
2125
- "allowNo": false,
2126
- "type": "boolean"
2127
- },
2128
- "yes": {
2129
- "char": "y",
2130
- "description": "Non-interactive mode: auto-select latest version and accept defaults",
2131
- "name": "yes",
2132
- "allowNo": false,
2133
- "type": "boolean"
2134
- },
2135
- "verbose": {
2136
- "char": "v",
2137
- "description": "Show detailed output",
2138
- "name": "verbose",
2139
- "allowNo": false,
2140
- "type": "boolean"
2141
- },
2142
- "skip-db": {
2143
- "description": "Skip database provisioning phases",
2144
- "name": "skip-db",
2145
- "allowNo": false,
2146
- "type": "boolean"
2147
- },
2148
- "skip-start": {
2149
- "description": "Skip service startup and smoke tests",
2150
- "name": "skip-start",
2151
- "allowNo": false,
2152
- "type": "boolean"
2153
- },
2154
- "no-resume": {
2155
- "description": "Ignore any existing checkpoint and start fresh",
2156
- "name": "no-resume",
2157
- "allowNo": false,
2158
- "type": "boolean"
2159
- },
2160
- "fast": {
2161
- "description": "Fast mode: skip smoke test and optimize post-codegen steps. Re-run without --fast if you encounter issues.",
2162
- "name": "fast",
2163
- "allowNo": false,
2164
- "type": "boolean"
2165
- },
2166
- "overwrite-config": {
2167
- "description": "Overwrite existing config files (.env, mj.config.cjs, environment.ts) instead of preserving them",
2168
- "name": "overwrite-config",
2169
- "allowNo": false,
2170
- "type": "boolean"
2171
- },
2172
- "monorepo": {
2173
- "description": "Install the full MemberJunction source repository instead of the lightweight distribution. Use this for MJ framework development.",
2174
- "name": "monorepo",
2175
- "allowNo": false,
2176
- "type": "boolean"
2177
- },
2178
- "no-claude-pack": {
2179
- "description": "Exclude the Claude Code pack (CLAUDE.md + .claude/ tree) from the scaffold. By default the pack ships with the install so opening Claude Code in your new MJ project gives you the curated MJ-aware experience immediately.",
2180
- "name": "no-claude-pack",
2181
- "allowNo": false,
2182
- "type": "boolean"
2183
- }
2184
- },
2185
- "hasDynamicHelp": false,
2186
- "hiddenAliases": [],
2187
- "id": "install",
2188
- "pluginAlias": "@memberjunction/cli",
2189
- "pluginName": "@memberjunction/cli",
2190
- "pluginType": "core",
2191
- "strict": true,
2192
- "enableJsonFlag": false,
2193
- "isESM": true,
2194
- "relativePath": [
2195
- "dist",
2196
- "commands",
2197
- "install",
2198
- "index.js"
2199
- ]
2200
- },
2201
- "migrate:convert": {
2202
- "aliases": [],
2203
- "args": {},
2204
- "description": "Convert T-SQL migrations to PostgreSQL",
2205
- "examples": [
2206
- "<%= config.bin %> migrate convert --split",
2207
- "<%= config.bin %> migrate convert --split --dry-run",
2208
- "<%= config.bin %> migrate convert --split --file V202604060452__v5.24.x__KnowledgeHub.sql",
2209
- "<%= config.bin %> migrate convert --source-dir ./migrations/v5 --output-dir ./migrations-pg/v5",
2210
- "<%= config.bin %> migrate convert --verbose"
2211
- ],
2212
- "flags": {
2213
- "source-dir": {
2214
- "description": "Source T-SQL migrations directory",
2215
- "name": "source-dir",
2216
- "default": "./migrations/v5",
2217
- "hasDynamicHelp": false,
2218
- "multiple": false,
2219
- "type": "option"
2220
- },
2221
- "output-dir": {
2222
- "description": "Output PG migrations directory",
2223
- "name": "output-dir",
2224
- "default": "./migrations-pg/v5",
2225
- "hasDynamicHelp": false,
2226
- "multiple": false,
2227
- "type": "option"
2228
- },
2229
- "file": {
2230
- "description": "Convert a specific file (filename only, looked up in source-dir)",
2231
- "name": "file",
2232
- "hasDynamicHelp": false,
2233
- "multiple": false,
2234
- "type": "option"
2235
- },
2236
- "schema": {
2237
- "description": "Target schema name",
2238
- "name": "schema",
2239
- "default": "__mj",
2240
- "hasDynamicHelp": false,
2241
- "multiple": false,
2242
- "type": "option"
2243
- },
2244
- "dry-run": {
2245
- "description": "Show what would be converted without writing files",
2246
- "name": "dry-run",
2247
- "allowNo": false,
2248
- "type": "boolean"
2249
- },
2250
- "no-header": {
2251
- "description": "Skip PG header (extensions, schema, implicit cast)",
2252
- "name": "no-header",
2253
- "allowNo": false,
2254
- "type": "boolean"
2255
- },
2256
- "verbose": {
2257
- "char": "v",
2258
- "description": "Show per-statement progress",
2259
- "name": "verbose",
2260
- "allowNo": false,
2261
- "type": "boolean"
2262
- },
2263
- "split": {
2264
- "description": "Split-and-regenerate (the standard path): transpile only hand-written DDL via the AST dialect; CodeGen objects are regenerated by `mj codegen` and mj-sync metadata re-seeded by `mj sync push`; every conversion gap is surfaced and fails the run unless --allow-gaps.",
2265
- "name": "split",
2266
- "allowNo": false,
2267
- "type": "boolean"
2268
- },
2269
- "allow-gaps": {
2270
- "description": "With --split: exit 0 even when migrations have conversion gaps (hand-authoring needed or unhandled statements). Gaps are still embedded as comments and listed in the summary.",
2271
- "name": "allow-gaps",
2272
- "allowNo": false,
2273
- "type": "boolean"
2274
- },
2275
- "bake-codegen": {
2276
- "description": "With --split: bake native PG CodeGen objects inline per migration (Path C), so the set deploys with `mj migrate` alone — no `mj codegen` step. Requires a LIVE working PG database (DB_PLATFORM=postgresql + PG_* env, same as `mj codegen`) seeded to the state just BEFORE the migrations being converted (typically the latest baseline); the converter brings it forward in committed order as it bakes. Not compatible with --dry-run.",
2277
- "name": "bake-codegen",
2278
- "allowNo": false,
2279
- "type": "boolean"
2280
- }
2281
- },
2282
- "hasDynamicHelp": false,
2283
- "hiddenAliases": [],
2284
- "id": "migrate:convert",
2285
- "pluginAlias": "@memberjunction/cli",
2286
- "pluginName": "@memberjunction/cli",
2287
- "pluginType": "core",
2288
- "strict": true,
2289
- "enableJsonFlag": false,
2290
- "isESM": true,
2291
- "relativePath": [
2292
- "dist",
2293
- "commands",
2294
- "migrate",
2295
- "convert.js"
2296
- ]
2297
- },
2298
- "migrate:create": {
2299
- "aliases": [],
2300
- "args": {
2301
- "description": {
2302
- "description": "Short description (will be converted to PascalCase with underscores)",
2303
- "name": "description",
2304
- "required": true
2305
- }
2306
- },
2307
- "description": "Scaffold a new migration file for the current database platform",
2308
- "examples": [
2309
- "<%= config.bin %> <%= command.id %> \"Add FooID to Bar\"",
2310
- "<%= config.bin %> <%= command.id %> \"Add FooID to Bar\" --version 5.25 --platform postgresql",
2311
- "<%= config.bin %> <%= command.id %> \"Add FooID to Bar\" --dir ./migrations/v5"
2312
- ],
2313
- "flags": {
2314
- "version": {
2315
- "char": "v",
2316
- "description": "Migration version tag, e.g. \"5.25\" (default: parsed from repo baseline or \"0.0\")",
2317
- "name": "version",
2093
+ "version": {
2094
+ "char": "v",
2095
+ "description": "Migration version tag, e.g. \"5.25\" (default: parsed from repo baseline or \"0.0\")",
2096
+ "name": "version",
2318
2097
  "hasDynamicHelp": false,
2319
2098
  "multiple": false,
2320
2099
  "type": "option"
@@ -2898,52 +2677,187 @@
2898
2677
  "index.js"
2899
2678
  ]
2900
2679
  },
2901
- "sync:file-reset": {
2680
+ "test:compare": {
2902
2681
  "aliases": [],
2903
- "args": {},
2904
- "description": "Reset file metadata sections",
2682
+ "args": {
2683
+ "runId1": {
2684
+ "description": "First test run ID to compare",
2685
+ "name": "runId1",
2686
+ "required": false
2687
+ },
2688
+ "runId2": {
2689
+ "description": "Second test run ID to compare",
2690
+ "name": "runId2",
2691
+ "required": false
2692
+ }
2693
+ },
2694
+ "description": "Compare test runs for regression detection",
2905
2695
  "examples": [
2906
2696
  "<%= config.bin %> <%= command.id %>",
2907
- "<%= config.bin %> <%= command.id %> --dir=\"ai-prompts\"",
2908
- "<%= config.bin %> <%= command.id %> --sections=\"dependencies,references\"",
2909
- "<%= config.bin %> <%= command.id %> --all"
2697
+ "<%= config.bin %> <%= command.id %> --latest",
2698
+ "<%= config.bin %> <%= command.id %> <run-id-1> <run-id-2>",
2699
+ "<%= config.bin %> <%= command.id %> -v 5.17.0 -v 5.18.0",
2700
+ "<%= config.bin %> <%= command.id %> -c abc1234 -c def5678",
2701
+ "<%= config.bin %> <%= command.id %> --from-json baseline.json latest.json",
2702
+ "<%= config.bin %> <%= command.id %> --latest --format=markdown --output=report.md"
2910
2703
  ],
2911
2704
  "flags": {
2912
- "dir": {
2913
- "description": "Specific entity directory to reset",
2914
- "name": "dir",
2705
+ "version": {
2706
+ "char": "v",
2707
+ "description": "Compare runs by version",
2708
+ "name": "version",
2915
2709
  "hasDynamicHelp": false,
2916
- "multiple": false,
2710
+ "multiple": true,
2917
2711
  "type": "option"
2918
2712
  },
2919
- "sections": {
2920
- "description": "Comma-separated list of sections to reset (dependencies,references,related,lookup)",
2921
- "name": "sections",
2713
+ "commit": {
2714
+ "char": "c",
2715
+ "description": "Compare runs by git commit",
2716
+ "name": "commit",
2922
2717
  "hasDynamicHelp": false,
2923
- "multiple": false,
2718
+ "multiple": true,
2924
2719
  "type": "option"
2925
2720
  },
2926
- "all": {
2927
- "description": "Reset all metadata sections",
2928
- "name": "all",
2721
+ "diff-only": {
2722
+ "description": "Show only differences",
2723
+ "name": "diff-only",
2929
2724
  "allowNo": false,
2930
2725
  "type": "boolean"
2931
2726
  },
2932
- "dry-run": {
2933
- "description": "Show what would be reset without actually resetting",
2934
- "name": "dry-run",
2727
+ "latest": {
2728
+ "char": "l",
2729
+ "description": "Compare the two most recent completed suite runs",
2730
+ "name": "latest",
2935
2731
  "allowNo": false,
2936
2732
  "type": "boolean"
2937
2733
  },
2938
- "force": {
2939
- "description": "Skip confirmation prompts",
2940
- "name": "force",
2734
+ "from-json": {
2735
+ "description": "Compare two results.json files directly (no DB). Pass twice: --from-json PREV --from-json CURR",
2736
+ "name": "from-json",
2737
+ "hasDynamicHelp": false,
2738
+ "multiple": true,
2739
+ "type": "option"
2740
+ },
2741
+ "format": {
2742
+ "char": "f",
2743
+ "description": "Output format",
2744
+ "name": "format",
2745
+ "default": "console",
2746
+ "hasDynamicHelp": false,
2747
+ "multiple": false,
2748
+ "options": [
2749
+ "console",
2750
+ "json",
2751
+ "markdown"
2752
+ ],
2753
+ "type": "option"
2754
+ },
2755
+ "output": {
2756
+ "char": "o",
2757
+ "description": "Output file path",
2758
+ "name": "output",
2759
+ "hasDynamicHelp": false,
2760
+ "multiple": false,
2761
+ "type": "option"
2762
+ },
2763
+ "verbose": {
2764
+ "description": "Show detailed information",
2765
+ "name": "verbose",
2941
2766
  "allowNo": false,
2942
2767
  "type": "boolean"
2943
2768
  },
2769
+ "tag": {
2770
+ "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.",
2771
+ "name": "tag",
2772
+ "hasDynamicHelp": false,
2773
+ "multiple": false,
2774
+ "type": "option"
2775
+ }
2776
+ },
2777
+ "hasDynamicHelp": false,
2778
+ "hiddenAliases": [],
2779
+ "id": "test:compare",
2780
+ "pluginAlias": "@memberjunction/cli",
2781
+ "pluginName": "@memberjunction/cli",
2782
+ "pluginType": "core",
2783
+ "strict": true,
2784
+ "enableJsonFlag": false,
2785
+ "isESM": true,
2786
+ "relativePath": [
2787
+ "dist",
2788
+ "commands",
2789
+ "test",
2790
+ "compare.js"
2791
+ ]
2792
+ },
2793
+ "test:history": {
2794
+ "aliases": [],
2795
+ "args": {},
2796
+ "description": "View test execution history",
2797
+ "examples": [
2798
+ "<%= config.bin %> <%= command.id %>",
2799
+ "<%= config.bin %> <%= command.id %> --test=<test-id>",
2800
+ "<%= config.bin %> <%= command.id %> --suite=<suite-id>",
2801
+ "<%= config.bin %> <%= command.id %> --since=\"2024-01-01\"",
2802
+ "<%= config.bin %> <%= command.id %> --limit=50"
2803
+ ],
2804
+ "flags": {
2805
+ "test": {
2806
+ "char": "t",
2807
+ "description": "Filter by test ID",
2808
+ "name": "test",
2809
+ "hasDynamicHelp": false,
2810
+ "multiple": false,
2811
+ "type": "option"
2812
+ },
2813
+ "recent": {
2814
+ "char": "r",
2815
+ "description": "Number of recent runs to show",
2816
+ "name": "recent",
2817
+ "hasDynamicHelp": false,
2818
+ "multiple": false,
2819
+ "type": "option"
2820
+ },
2821
+ "from": {
2822
+ "description": "Show history from date (YYYY-MM-DD)",
2823
+ "name": "from",
2824
+ "hasDynamicHelp": false,
2825
+ "multiple": false,
2826
+ "type": "option"
2827
+ },
2828
+ "status": {
2829
+ "char": "s",
2830
+ "description": "Filter by status",
2831
+ "name": "status",
2832
+ "hasDynamicHelp": false,
2833
+ "multiple": false,
2834
+ "type": "option"
2835
+ },
2836
+ "format": {
2837
+ "char": "f",
2838
+ "description": "Output format",
2839
+ "name": "format",
2840
+ "default": "console",
2841
+ "hasDynamicHelp": false,
2842
+ "multiple": false,
2843
+ "options": [
2844
+ "console",
2845
+ "json",
2846
+ "markdown"
2847
+ ],
2848
+ "type": "option"
2849
+ },
2850
+ "output": {
2851
+ "char": "o",
2852
+ "description": "Output file path",
2853
+ "name": "output",
2854
+ "hasDynamicHelp": false,
2855
+ "multiple": false,
2856
+ "type": "option"
2857
+ },
2944
2858
  "verbose": {
2945
2859
  "char": "v",
2946
- "description": "Show detailed output",
2860
+ "description": "Show detailed information",
2947
2861
  "name": "verbose",
2948
2862
  "allowNo": false,
2949
2863
  "type": "boolean"
@@ -2951,7 +2865,7 @@
2951
2865
  },
2952
2866
  "hasDynamicHelp": false,
2953
2867
  "hiddenAliases": [],
2954
- "id": "sync:file-reset",
2868
+ "id": "test:history",
2955
2869
  "pluginAlias": "@memberjunction/cli",
2956
2870
  "pluginName": "@memberjunction/cli",
2957
2871
  "pluginType": "core",
@@ -2961,21 +2875,26 @@
2961
2875
  "relativePath": [
2962
2876
  "dist",
2963
2877
  "commands",
2964
- "sync",
2965
- "file-reset.js"
2878
+ "test",
2879
+ "history.js"
2966
2880
  ]
2967
2881
  },
2968
- "sync:init": {
2882
+ "test": {
2969
2883
  "aliases": [],
2970
2884
  "args": {},
2971
- "description": "Initialize a directory for metadata synchronization",
2885
+ "description": "MemberJunction Testing Framework - Execute and manage tests",
2972
2886
  "examples": [
2973
- "<%= config.bin %> <%= command.id %>"
2887
+ "<%= config.bin %> <%= command.id %> run <test-id>",
2888
+ "<%= config.bin %> <%= command.id %> run --name=\"Active Members Count\"",
2889
+ "<%= config.bin %> <%= command.id %> suite <suite-id>",
2890
+ "<%= config.bin %> <%= command.id %> list",
2891
+ "<%= config.bin %> <%= command.id %> list --suites",
2892
+ "<%= config.bin %> <%= command.id %> validate --all"
2974
2893
  ],
2975
2894
  "flags": {},
2976
2895
  "hasDynamicHelp": false,
2977
2896
  "hiddenAliases": [],
2978
- "id": "sync:init",
2897
+ "id": "test",
2979
2898
  "pluginAlias": "@memberjunction/cli",
2980
2899
  "pluginName": "@memberjunction/cli",
2981
2900
  "pluginType": "core",
@@ -2985,148 +2904,176 @@
2985
2904
  "relativePath": [
2986
2905
  "dist",
2987
2906
  "commands",
2988
- "sync",
2989
- "init.js"
2907
+ "test",
2908
+ "index.js"
2990
2909
  ]
2991
2910
  },
2992
- "sync:pull": {
2911
+ "test:list": {
2993
2912
  "aliases": [],
2994
2913
  "args": {},
2995
- "description": "Pull metadata from database to local files",
2914
+ "description": "List available tests, suites, and types",
2996
2915
  "examples": [
2997
- "<%= config.bin %> <%= command.id %> --entity=\"MJ: AI Prompts\"",
2998
- "<%= config.bin %> <%= command.id %> --entity=\"MJ: AI Agents\" --merge-strategy=overwrite",
2999
- "<%= config.bin %> <%= command.id %> --entity=\"Templates\" --dry-run --verbose"
2916
+ "<%= config.bin %> <%= command.id %>",
2917
+ "<%= config.bin %> <%= command.id %> --suites",
2918
+ "<%= config.bin %> <%= command.id %> --types",
2919
+ "<%= config.bin %> <%= command.id %> --type=agent-eval",
2920
+ "<%= config.bin %> <%= command.id %> --tag=smoke",
2921
+ "<%= config.bin %> <%= command.id %> --status=active --verbose"
3000
2922
  ],
3001
2923
  "flags": {
3002
- "format": {
3003
- "description": "Output format: text (human), json (machine-readable), md (Markdown-fenced)",
3004
- "name": "format",
3005
- "default": "text",
3006
- "hasDynamicHelp": false,
3007
- "multiple": false,
3008
- "options": [
3009
- "text",
3010
- "json",
3011
- "md"
3012
- ],
3013
- "type": "option"
3014
- },
3015
- "verbose": {
3016
- "char": "v",
3017
- "description": "Show detailed output",
3018
- "name": "verbose",
2924
+ "suites": {
2925
+ "description": "List test suites instead of tests",
2926
+ "name": "suites",
3019
2927
  "allowNo": false,
3020
2928
  "type": "boolean"
3021
2929
  },
3022
- "no-banner": {
3023
- "description": "Suppress the startup banner and runtime advisory",
3024
- "name": "no-banner",
2930
+ "types": {
2931
+ "description": "List test types",
2932
+ "name": "types",
3025
2933
  "allowNo": false,
3026
2934
  "type": "boolean"
3027
2935
  },
3028
- "entity": {
3029
- "description": "Entity name to pull",
3030
- "name": "entity",
3031
- "required": true,
2936
+ "type": {
2937
+ "char": "t",
2938
+ "description": "Filter by test type",
2939
+ "name": "type",
3032
2940
  "hasDynamicHelp": false,
3033
2941
  "multiple": false,
3034
2942
  "type": "option"
3035
2943
  },
3036
- "filter": {
3037
- "description": "Additional filter for pulling specific records",
3038
- "name": "filter",
2944
+ "tag": {
2945
+ "description": "Filter by tag",
2946
+ "name": "tag",
3039
2947
  "hasDynamicHelp": false,
3040
2948
  "multiple": false,
3041
2949
  "type": "option"
3042
2950
  },
3043
- "dry-run": {
3044
- "description": "Show what would be pulled without actually pulling",
3045
- "name": "dry-run",
3046
- "allowNo": false,
3047
- "type": "boolean"
3048
- },
3049
- "multi-file": {
3050
- "description": "Create a single file with multiple records (provide filename)",
3051
- "name": "multi-file",
2951
+ "status": {
2952
+ "char": "s",
2953
+ "description": "Filter by status",
2954
+ "name": "status",
3052
2955
  "hasDynamicHelp": false,
3053
2956
  "multiple": false,
3054
2957
  "type": "option"
3055
2958
  },
3056
- "no-validate": {
3057
- "description": "Skip validation before pull",
3058
- "name": "no-validate",
3059
- "allowNo": false,
3060
- "type": "boolean"
2959
+ "format": {
2960
+ "char": "f",
2961
+ "description": "Output format",
2962
+ "name": "format",
2963
+ "default": "console",
2964
+ "hasDynamicHelp": false,
2965
+ "multiple": false,
2966
+ "options": [
2967
+ "console",
2968
+ "json",
2969
+ "markdown"
2970
+ ],
2971
+ "type": "option"
3061
2972
  },
3062
- "update-existing": {
3063
- "description": "Update existing records during pull",
3064
- "name": "update-existing",
3065
- "allowNo": false,
3066
- "type": "boolean"
3067
- },
3068
- "create-new": {
3069
- "description": "Create new files for records not found locally",
3070
- "name": "create-new",
3071
- "allowNo": false,
3072
- "type": "boolean"
3073
- },
3074
- "backup-before-update": {
3075
- "description": "Create backups before updating files",
3076
- "name": "backup-before-update",
3077
- "allowNo": false,
3078
- "type": "boolean"
3079
- },
3080
- "merge-strategy": {
3081
- "description": "Merge strategy for updates",
3082
- "name": "merge-strategy",
3083
- "default": "merge",
2973
+ "output": {
2974
+ "char": "o",
2975
+ "description": "Output file path",
2976
+ "name": "output",
3084
2977
  "hasDynamicHelp": false,
3085
2978
  "multiple": false,
3086
- "options": [
3087
- "merge",
3088
- "overwrite",
3089
- "skip"
3090
- ],
3091
2979
  "type": "option"
3092
2980
  },
3093
- "backup-directory": {
3094
- "description": "Custom backup directory (default: .backups)",
3095
- "name": "backup-directory",
2981
+ "verbose": {
2982
+ "char": "v",
2983
+ "description": "Show detailed information",
2984
+ "name": "verbose",
2985
+ "allowNo": false,
2986
+ "type": "boolean"
2987
+ }
2988
+ },
2989
+ "hasDynamicHelp": false,
2990
+ "hiddenAliases": [],
2991
+ "id": "test:list",
2992
+ "pluginAlias": "@memberjunction/cli",
2993
+ "pluginName": "@memberjunction/cli",
2994
+ "pluginType": "core",
2995
+ "strict": true,
2996
+ "enableJsonFlag": false,
2997
+ "isESM": true,
2998
+ "relativePath": [
2999
+ "dist",
3000
+ "commands",
3001
+ "test",
3002
+ "list.js"
3003
+ ]
3004
+ },
3005
+ "test:run": {
3006
+ "aliases": [],
3007
+ "args": {
3008
+ "testId": {
3009
+ "description": "Test ID to execute",
3010
+ "name": "testId",
3011
+ "required": false
3012
+ }
3013
+ },
3014
+ "description": "Execute a single test by ID or name",
3015
+ "examples": [
3016
+ "<%= config.bin %> <%= command.id %> <test-id>",
3017
+ "<%= config.bin %> <%= command.id %> --name=\"Active Members Count\"",
3018
+ "<%= config.bin %> <%= command.id %> <test-id> --environment=staging",
3019
+ "<%= config.bin %> <%= command.id %> <test-id> --format=json --output=results.json",
3020
+ "<%= config.bin %> <%= command.id %> <test-id> --dry-run"
3021
+ ],
3022
+ "flags": {
3023
+ "name": {
3024
+ "char": "n",
3025
+ "description": "Test name to execute",
3026
+ "name": "name",
3096
3027
  "hasDynamicHelp": false,
3097
3028
  "multiple": false,
3098
3029
  "type": "option"
3099
3030
  },
3100
- "preserve-fields": {
3101
- "description": "Comma-separated list of fields to preserve during updates",
3102
- "name": "preserve-fields",
3031
+ "environment": {
3032
+ "char": "e",
3033
+ "description": "Environment context (dev, staging, prod)",
3034
+ "name": "environment",
3103
3035
  "hasDynamicHelp": false,
3104
- "multiple": true,
3036
+ "multiple": false,
3105
3037
  "type": "option"
3106
3038
  },
3107
- "exclude-fields": {
3108
- "description": "Comma-separated list of fields to exclude from pull",
3109
- "name": "exclude-fields",
3039
+ "format": {
3040
+ "char": "f",
3041
+ "description": "Output format",
3042
+ "name": "format",
3043
+ "default": "console",
3110
3044
  "hasDynamicHelp": false,
3111
- "multiple": true,
3045
+ "multiple": false,
3046
+ "options": [
3047
+ "console",
3048
+ "json",
3049
+ "markdown"
3050
+ ],
3112
3051
  "type": "option"
3113
3052
  },
3114
- "target-dir": {
3115
- "description": "Specific target directory (overrides auto-discovery)",
3116
- "name": "target-dir",
3053
+ "output": {
3054
+ "char": "o",
3055
+ "description": "Output file path",
3056
+ "name": "output",
3117
3057
  "hasDynamicHelp": false,
3118
3058
  "multiple": false,
3119
3059
  "type": "option"
3120
3060
  },
3121
- "incremental": {
3122
- "description": "Only pull records updated since last successful pull",
3123
- "name": "incremental",
3061
+ "dry-run": {
3062
+ "description": "Validate without executing",
3063
+ "name": "dry-run",
3124
3064
  "allowNo": false,
3125
3065
  "type": "boolean"
3126
3066
  },
3127
- "since": {
3128
- "description": "Only pull records updated after this ISO 8601 timestamp",
3129
- "name": "since",
3067
+ "verbose": {
3068
+ "char": "v",
3069
+ "description": "Show detailed execution information",
3070
+ "name": "verbose",
3071
+ "allowNo": false,
3072
+ "type": "boolean"
3073
+ },
3074
+ "oracles-module": {
3075
+ "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.",
3076
+ "name": "oracles-module",
3130
3077
  "hasDynamicHelp": false,
3131
3078
  "multiple": false,
3132
3079
  "type": "option"
@@ -3134,305 +3081,201 @@
3134
3081
  },
3135
3082
  "hasDynamicHelp": false,
3136
3083
  "hiddenAliases": [],
3137
- "id": "sync:pull",
3084
+ "id": "test:run",
3138
3085
  "pluginAlias": "@memberjunction/cli",
3139
3086
  "pluginName": "@memberjunction/cli",
3140
3087
  "pluginType": "core",
3141
3088
  "strict": true,
3142
3089
  "enableJsonFlag": false,
3143
- "Usage": {
3144
- "domain": "sync",
3145
- "command": "sync:pull",
3146
- "summary": "Pull database records into local metadata files.",
3147
- "description": "Writes records of --entity into the matching entity directory, creating or updating files per the merge strategy.",
3148
- "flags": [
3149
- {
3150
- "name": "--entity",
3151
- "type": "string",
3152
- "description": "Entity name to pull (required)"
3153
- },
3154
- {
3155
- "name": "--filter",
3156
- "type": "string",
3157
- "description": "Extra SQL filter for which records to pull"
3158
- },
3159
- {
3160
- "name": "--merge-strategy",
3161
- "type": "merge|overwrite|skip",
3162
- "description": "How to reconcile existing files"
3163
- },
3164
- {
3165
- "name": "--dry-run",
3166
- "type": "boolean",
3167
- "description": "Report what would be pulled without writing"
3168
- },
3169
- {
3170
- "name": "--format",
3171
- "type": "text|json|md",
3172
- "description": "Output format (json for machine-readable result)"
3173
- }
3174
- ],
3175
- "examples": [
3176
- "mj sync pull --entity=\"MJ: AI Prompts\"",
3177
- "mj sync pull --entity=\"Actions\" --format=json"
3178
- ],
3179
- "runtime": {
3180
- "class": "variable",
3181
- "typicalSeconds": 15,
3182
- "note": "scales with number of records matched for --entity"
3183
- }
3184
- },
3185
3090
  "isESM": true,
3186
3091
  "relativePath": [
3187
3092
  "dist",
3188
3093
  "commands",
3189
- "sync",
3190
- "pull.js"
3094
+ "test",
3095
+ "run.js"
3191
3096
  ]
3192
3097
  },
3193
- "sync:push": {
3098
+ "test:suite": {
3194
3099
  "aliases": [],
3195
- "args": {},
3196
- "description": "Push local file changes to the database",
3100
+ "args": {
3101
+ "suiteId": {
3102
+ "description": "Test suite ID to execute",
3103
+ "name": "suiteId",
3104
+ "required": false
3105
+ }
3106
+ },
3107
+ "description": "Execute a test suite",
3197
3108
  "examples": [
3198
- "<%= config.bin %> <%= command.id %>",
3199
- "<%= config.bin %> <%= command.id %> --dry-run",
3200
- "<%= config.bin %> <%= command.id %> --dir=\"ai-prompts\"",
3201
- "<%= config.bin %> <%= command.id %> --ci --format=json"
3109
+ "<%= config.bin %> <%= command.id %> <suite-id>",
3110
+ "<%= config.bin %> <%= command.id %> --name=\"Agent Quality Suite\"",
3111
+ "<%= config.bin %> <%= command.id %> <suite-id> --format=json",
3112
+ "<%= config.bin %> <%= command.id %> <suite-id> --output=suite-results.json"
3202
3113
  ],
3203
3114
  "flags": {
3115
+ "name": {
3116
+ "char": "n",
3117
+ "description": "Test suite name to execute",
3118
+ "name": "name",
3119
+ "hasDynamicHelp": false,
3120
+ "multiple": false,
3121
+ "type": "option"
3122
+ },
3204
3123
  "format": {
3205
- "description": "Output format: text (human), json (machine-readable), md (Markdown-fenced)",
3124
+ "char": "f",
3125
+ "description": "Output format",
3206
3126
  "name": "format",
3207
- "default": "text",
3127
+ "default": "console",
3208
3128
  "hasDynamicHelp": false,
3209
3129
  "multiple": false,
3210
3130
  "options": [
3211
- "text",
3131
+ "console",
3212
3132
  "json",
3213
- "md"
3133
+ "markdown"
3214
3134
  ],
3215
3135
  "type": "option"
3216
3136
  },
3137
+ "output": {
3138
+ "char": "o",
3139
+ "description": "Output file path",
3140
+ "name": "output",
3141
+ "hasDynamicHelp": false,
3142
+ "multiple": false,
3143
+ "type": "option"
3144
+ },
3217
3145
  "verbose": {
3218
3146
  "char": "v",
3219
- "description": "Show detailed output",
3147
+ "description": "Show detailed execution information",
3220
3148
  "name": "verbose",
3221
3149
  "allowNo": false,
3222
3150
  "type": "boolean"
3223
3151
  },
3224
- "no-banner": {
3225
- "description": "Suppress the startup banner and runtime advisory",
3226
- "name": "no-banner",
3227
- "allowNo": false,
3228
- "type": "boolean"
3229
- },
3230
- "dir": {
3231
- "description": "Specific entity directory to push",
3232
- "name": "dir",
3152
+ "delay": {
3153
+ "char": "d",
3154
+ "description": "Delay in milliseconds between test executions (avoids Auth0 rate limits)",
3155
+ "name": "delay",
3156
+ "default": 0,
3233
3157
  "hasDynamicHelp": false,
3234
3158
  "multiple": false,
3235
3159
  "type": "option"
3236
3160
  },
3237
- "dry-run": {
3238
- "description": "Show what would be pushed without actually pushing",
3239
- "name": "dry-run",
3240
- "allowNo": false,
3241
- "type": "boolean"
3242
- },
3243
- "ci": {
3244
- "description": "CI mode - no prompts, fail on issues",
3245
- "name": "ci",
3161
+ "parallel": {
3162
+ "char": "p",
3163
+ "description": "Run tests in parallel with shared browser sessions",
3164
+ "name": "parallel",
3246
3165
  "allowNo": false,
3247
3166
  "type": "boolean"
3248
3167
  },
3249
- "no-validate": {
3250
- "description": "Skip validation before push",
3251
- "name": "no-validate",
3252
- "allowNo": false,
3253
- "type": "boolean"
3254
- },
3255
- "delete-db-only": {
3256
- "description": "Delete database-only records that reference records being deleted (prevents FK errors)",
3257
- "name": "delete-db-only",
3258
- "allowNo": false,
3259
- "type": "boolean"
3260
- },
3261
- "parallel-batch-size": {
3262
- "description": "Number of records to process in parallel (default: 10)",
3263
- "name": "parallel-batch-size",
3264
- "default": 10,
3168
+ "max-parallel": {
3169
+ "description": "Maximum number of parallel workers (default 4)",
3170
+ "name": "max-parallel",
3171
+ "default": 4,
3265
3172
  "hasDynamicHelp": false,
3266
3173
  "multiple": false,
3267
3174
  "type": "option"
3268
3175
  },
3269
- "include": {
3270
- "description": "Only process these directories (comma-separated, supports patterns)",
3271
- "name": "include",
3176
+ "flaky-check": {
3177
+ "description": "Run each test N times to detect flakiness (variance > 0.3 or mixed pass/fail = flaky). Recommended: 3 or 5",
3178
+ "name": "flaky-check",
3272
3179
  "hasDynamicHelp": false,
3273
3180
  "multiple": false,
3274
3181
  "type": "option"
3275
3182
  },
3276
- "exclude": {
3277
- "description": "Skip these directories (comma-separated, supports patterns)",
3278
- "name": "exclude",
3183
+ "oracles-module": {
3184
+ "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.",
3185
+ "name": "oracles-module",
3279
3186
  "hasDynamicHelp": false,
3280
3187
  "multiple": false,
3281
3188
  "type": "option"
3282
- },
3283
- "incremental": {
3284
- "description": "Skip unchanged files using stored checksums from last push",
3285
- "name": "incremental",
3286
- "allowNo": false,
3287
- "type": "boolean"
3288
- },
3289
- "change-detail": {
3290
- "description": "Write a detailed per-record change report (primary keys + field diffs) to a file",
3291
- "name": "change-detail",
3292
- "allowNo": false,
3293
- "type": "boolean"
3294
3189
  }
3295
3190
  },
3296
3191
  "hasDynamicHelp": false,
3297
3192
  "hiddenAliases": [],
3298
- "id": "sync:push",
3193
+ "id": "test:suite",
3299
3194
  "pluginAlias": "@memberjunction/cli",
3300
3195
  "pluginName": "@memberjunction/cli",
3301
3196
  "pluginType": "core",
3302
3197
  "strict": true,
3303
3198
  "enableJsonFlag": false,
3304
- "Usage": {
3305
- "domain": "sync",
3306
- "command": "sync:push",
3307
- "summary": "Push local metadata files to the database (upsert).",
3308
- "description": "Reads entity directories under --dir and creates/updates matching records. Runs validation first unless --no-validate.",
3309
- "flags": [
3310
- {
3311
- "name": "--dir",
3312
- "type": "string",
3313
- "description": "Entity directory to push"
3314
- },
3315
- {
3316
- "name": "--dry-run",
3317
- "type": "boolean",
3318
- "description": "Report what would change without writing"
3319
- },
3320
- {
3321
- "name": "--ci",
3322
- "type": "boolean",
3323
- "description": "No prompts; non-zero exit on error"
3324
- },
3325
- {
3326
- "name": "--no-validate",
3327
- "type": "boolean",
3328
- "description": "Skip pre-push validation"
3329
- },
3330
- {
3331
- "name": "--incremental",
3332
- "type": "boolean",
3333
- "description": "Skip unchanged files using stored checksums"
3334
- },
3335
- {
3336
- "name": "--format",
3337
- "type": "text|json|md",
3338
- "description": "Output format (json for machine-readable result)"
3339
- }
3340
- ],
3341
- "examples": [
3342
- "mj sync push --dir=ai-agents",
3343
- "mj sync push --ci --format=json"
3344
- ],
3345
- "runtime": {
3346
- "class": "variable",
3347
- "typicalSeconds": 20,
3348
- "note": "scales with number of records in --dir"
3349
- }
3350
- },
3351
3199
  "isESM": true,
3352
3200
  "relativePath": [
3353
3201
  "dist",
3354
3202
  "commands",
3355
- "sync",
3356
- "push.js"
3203
+ "test",
3204
+ "suite.js"
3357
3205
  ]
3358
3206
  },
3359
- "sync:status": {
3207
+ "test:validate": {
3360
3208
  "aliases": [],
3361
- "args": {},
3362
- "description": "Show status of local files vs database",
3209
+ "args": {
3210
+ "testId": {
3211
+ "description": "Test ID to validate",
3212
+ "name": "testId",
3213
+ "required": false
3214
+ }
3215
+ },
3216
+ "description": "Validate test definitions without executing",
3363
3217
  "examples": [
3364
- "<%= config.bin %> <%= command.id %>",
3365
- "<%= config.bin %> <%= command.id %> --dir=\"ai-prompts\"",
3366
- "<%= config.bin %> <%= command.id %> --verbose"
3218
+ "<%= config.bin %> <%= command.id %> <test-id>",
3219
+ "<%= config.bin %> <%= command.id %> --all",
3220
+ "<%= config.bin %> <%= command.id %> --type=agent-eval",
3221
+ "<%= config.bin %> <%= command.id %> --all --save-report",
3222
+ "<%= config.bin %> <%= command.id %> --all --output=validation-report.md"
3367
3223
  ],
3368
3224
  "flags": {
3369
- "dir": {
3370
- "description": "Specific entity directory to check status",
3371
- "name": "dir",
3372
- "hasDynamicHelp": false,
3373
- "multiple": false,
3374
- "type": "option"
3375
- },
3376
- "verbose": {
3377
- "char": "v",
3378
- "description": "Show detailed field-level differences",
3379
- "name": "verbose",
3225
+ "all": {
3226
+ "char": "a",
3227
+ "description": "Validate all tests",
3228
+ "name": "all",
3380
3229
  "allowNo": false,
3381
3230
  "type": "boolean"
3382
3231
  },
3383
- "include": {
3384
- "description": "Only process these directories (comma-separated, supports patterns)",
3385
- "name": "include",
3232
+ "type": {
3233
+ "char": "t",
3234
+ "description": "Validate tests by type",
3235
+ "name": "type",
3386
3236
  "hasDynamicHelp": false,
3387
3237
  "multiple": false,
3388
3238
  "type": "option"
3389
3239
  },
3390
- "exclude": {
3391
- "description": "Skip these directories (comma-separated, supports patterns)",
3392
- "name": "exclude",
3393
- "hasDynamicHelp": false,
3394
- "multiple": false,
3395
- "type": "option"
3396
- }
3397
- },
3398
- "hasDynamicHelp": false,
3399
- "hiddenAliases": [],
3400
- "id": "sync:status",
3401
- "pluginAlias": "@memberjunction/cli",
3402
- "pluginName": "@memberjunction/cli",
3403
- "pluginType": "core",
3404
- "strict": true,
3405
- "enableJsonFlag": false,
3406
- "isESM": true,
3407
- "relativePath": [
3408
- "dist",
3409
- "commands",
3410
- "sync",
3411
- "status.js"
3412
- ]
3413
- },
3414
- "sync:usage": {
3415
- "aliases": [],
3416
- "args": {},
3417
- "description": "Show usage, flags, examples, and runtime hints for every `mj sync` command.",
3418
- "flags": {
3240
+ "save-report": {
3241
+ "description": "Save validation report to file",
3242
+ "name": "save-report",
3243
+ "allowNo": false,
3244
+ "type": "boolean"
3245
+ },
3419
3246
  "format": {
3247
+ "char": "f",
3420
3248
  "description": "Output format",
3421
3249
  "name": "format",
3422
- "default": "text",
3250
+ "default": "console",
3423
3251
  "hasDynamicHelp": false,
3424
3252
  "multiple": false,
3425
3253
  "options": [
3426
- "text",
3254
+ "console",
3427
3255
  "json",
3428
- "md"
3256
+ "markdown"
3429
3257
  ],
3430
3258
  "type": "option"
3259
+ },
3260
+ "output": {
3261
+ "char": "o",
3262
+ "description": "Output file path",
3263
+ "name": "output",
3264
+ "hasDynamicHelp": false,
3265
+ "multiple": false,
3266
+ "type": "option"
3267
+ },
3268
+ "verbose": {
3269
+ "char": "v",
3270
+ "description": "Show detailed information",
3271
+ "name": "verbose",
3272
+ "allowNo": false,
3273
+ "type": "boolean"
3431
3274
  }
3432
3275
  },
3433
3276
  "hasDynamicHelp": false,
3434
3277
  "hiddenAliases": [],
3435
- "id": "sync:usage",
3278
+ "id": "test:validate",
3436
3279
  "pluginAlias": "@memberjunction/cli",
3437
3280
  "pluginName": "@memberjunction/cli",
3438
3281
  "pluginType": "core",
@@ -3442,52 +3285,64 @@
3442
3285
  "relativePath": [
3443
3286
  "dist",
3444
3287
  "commands",
3445
- "sync",
3446
- "usage.js"
3288
+ "test",
3289
+ "validate.js"
3447
3290
  ]
3448
3291
  },
3449
- "sync:validate": {
3292
+ "sync:file-reset": {
3450
3293
  "aliases": [],
3451
3294
  "args": {},
3452
- "description": "Validate metadata files",
3295
+ "description": "Reset file metadata sections",
3453
3296
  "examples": [
3454
3297
  "<%= config.bin %> <%= command.id %>",
3455
3298
  "<%= config.bin %> <%= command.id %> --dir=\"ai-prompts\"",
3456
- "<%= config.bin %> <%= command.id %> --save-report",
3457
- "<%= config.bin %> <%= command.id %> --verbose"
3299
+ "<%= config.bin %> <%= command.id %> --sections=\"dependencies,references\"",
3300
+ "<%= config.bin %> <%= command.id %> --all"
3458
3301
  ],
3459
3302
  "flags": {
3460
3303
  "dir": {
3461
- "description": "Specific entity directory to validate",
3304
+ "description": "Specific entity directory to reset",
3462
3305
  "name": "dir",
3463
3306
  "hasDynamicHelp": false,
3464
3307
  "multiple": false,
3465
3308
  "type": "option"
3466
3309
  },
3467
- "verbose": {
3468
- "char": "v",
3469
- "description": "Show detailed validation output",
3470
- "name": "verbose",
3310
+ "sections": {
3311
+ "description": "Comma-separated list of sections to reset (dependencies,references,related,lookup)",
3312
+ "name": "sections",
3313
+ "hasDynamicHelp": false,
3314
+ "multiple": false,
3315
+ "type": "option"
3316
+ },
3317
+ "all": {
3318
+ "description": "Reset all metadata sections",
3319
+ "name": "all",
3471
3320
  "allowNo": false,
3472
3321
  "type": "boolean"
3473
3322
  },
3474
- "save-report": {
3475
- "description": "Save validation report as markdown file",
3476
- "name": "save-report",
3323
+ "dry-run": {
3324
+ "description": "Show what would be reset without actually resetting",
3325
+ "name": "dry-run",
3477
3326
  "allowNo": false,
3478
3327
  "type": "boolean"
3479
3328
  },
3480
- "output": {
3481
- "description": "Output file path for validation report (default: validation-report.md)",
3482
- "name": "output",
3483
- "hasDynamicHelp": false,
3484
- "multiple": false,
3485
- "type": "option"
3329
+ "force": {
3330
+ "description": "Skip confirmation prompts",
3331
+ "name": "force",
3332
+ "allowNo": false,
3333
+ "type": "boolean"
3334
+ },
3335
+ "verbose": {
3336
+ "char": "v",
3337
+ "description": "Show detailed output",
3338
+ "name": "verbose",
3339
+ "allowNo": false,
3340
+ "type": "boolean"
3486
3341
  }
3487
3342
  },
3488
3343
  "hasDynamicHelp": false,
3489
3344
  "hiddenAliases": [],
3490
- "id": "sync:validate",
3345
+ "id": "sync:file-reset",
3491
3346
  "pluginAlias": "@memberjunction/cli",
3492
3347
  "pluginName": "@memberjunction/cli",
3493
3348
  "pluginType": "core",
@@ -3498,51 +3353,20 @@
3498
3353
  "dist",
3499
3354
  "commands",
3500
3355
  "sync",
3501
- "validate.js"
3356
+ "file-reset.js"
3502
3357
  ]
3503
3358
  },
3504
- "sync:watch": {
3359
+ "sync:init": {
3505
3360
  "aliases": [],
3506
3361
  "args": {},
3507
- "description": "Watch for file changes and sync automatically",
3362
+ "description": "Initialize a directory for metadata synchronization",
3508
3363
  "examples": [
3509
- "<%= config.bin %> <%= command.id %>",
3510
- "<%= config.bin %> <%= command.id %> --dir=\"ai-prompts\"",
3511
- "<%= config.bin %> <%= command.id %> --debounce=1000",
3512
- "<%= config.bin %> <%= command.id %> --no-validate"
3364
+ "<%= config.bin %> <%= command.id %>"
3513
3365
  ],
3514
- "flags": {
3515
- "dir": {
3516
- "description": "Specific entity directory to watch",
3517
- "name": "dir",
3518
- "hasDynamicHelp": false,
3519
- "multiple": false,
3520
- "type": "option"
3521
- },
3522
- "debounce": {
3523
- "description": "Debounce delay in milliseconds (default: 500)",
3524
- "name": "debounce",
3525
- "hasDynamicHelp": false,
3526
- "multiple": false,
3527
- "type": "option"
3528
- },
3529
- "no-validate": {
3530
- "description": "Skip validation before sync",
3531
- "name": "no-validate",
3532
- "allowNo": false,
3533
- "type": "boolean"
3534
- },
3535
- "verbose": {
3536
- "char": "v",
3537
- "description": "Show detailed output",
3538
- "name": "verbose",
3539
- "allowNo": false,
3540
- "type": "boolean"
3541
- }
3542
- },
3366
+ "flags": {},
3543
3367
  "hasDynamicHelp": false,
3544
3368
  "hiddenAliases": [],
3545
- "id": "sync:watch",
3369
+ "id": "sync:init",
3546
3370
  "pluginAlias": "@memberjunction/cli",
3547
3371
  "pluginName": "@memberjunction/cli",
3548
3372
  "pluginType": "core",
@@ -3553,101 +3377,147 @@
3553
3377
  "dist",
3554
3378
  "commands",
3555
3379
  "sync",
3556
- "watch.js"
3380
+ "init.js"
3557
3381
  ]
3558
3382
  },
3559
- "test:compare": {
3383
+ "sync:pull": {
3560
3384
  "aliases": [],
3561
- "args": {
3562
- "runId1": {
3563
- "description": "First test run ID to compare",
3564
- "name": "runId1",
3565
- "required": false
3566
- },
3567
- "runId2": {
3568
- "description": "Second test run ID to compare",
3569
- "name": "runId2",
3570
- "required": false
3571
- }
3572
- },
3573
- "description": "Compare test runs for regression detection",
3385
+ "args": {},
3386
+ "description": "Pull metadata from database to local files",
3574
3387
  "examples": [
3575
- "<%= config.bin %> <%= command.id %>",
3576
- "<%= config.bin %> <%= command.id %> --latest",
3577
- "<%= config.bin %> <%= command.id %> <run-id-1> <run-id-2>",
3578
- "<%= config.bin %> <%= command.id %> -v 5.17.0 -v 5.18.0",
3579
- "<%= config.bin %> <%= command.id %> -c abc1234 -c def5678",
3580
- "<%= config.bin %> <%= command.id %> --from-json baseline.json latest.json",
3581
- "<%= config.bin %> <%= command.id %> --latest --format=markdown --output=report.md"
3388
+ "<%= config.bin %> <%= command.id %> --entity=\"MJ: AI Prompts\"",
3389
+ "<%= config.bin %> <%= command.id %> --entity=\"MJ: AI Agents\" --merge-strategy=overwrite",
3390
+ "<%= config.bin %> <%= command.id %> --entity=\"Templates\" --dry-run --verbose"
3582
3391
  ],
3583
3392
  "flags": {
3584
- "version": {
3393
+ "format": {
3394
+ "description": "Output format: text (human), json (machine-readable), md (Markdown-fenced)",
3395
+ "name": "format",
3396
+ "default": "text",
3397
+ "hasDynamicHelp": false,
3398
+ "multiple": false,
3399
+ "options": [
3400
+ "text",
3401
+ "json",
3402
+ "md"
3403
+ ],
3404
+ "type": "option"
3405
+ },
3406
+ "verbose": {
3585
3407
  "char": "v",
3586
- "description": "Compare runs by version",
3587
- "name": "version",
3408
+ "description": "Show detailed output",
3409
+ "name": "verbose",
3410
+ "allowNo": false,
3411
+ "type": "boolean"
3412
+ },
3413
+ "no-banner": {
3414
+ "description": "Suppress the startup banner and runtime advisory",
3415
+ "name": "no-banner",
3416
+ "allowNo": false,
3417
+ "type": "boolean"
3418
+ },
3419
+ "entity": {
3420
+ "description": "Entity name to pull",
3421
+ "name": "entity",
3422
+ "required": true,
3588
3423
  "hasDynamicHelp": false,
3589
- "multiple": true,
3424
+ "multiple": false,
3590
3425
  "type": "option"
3591
3426
  },
3592
- "commit": {
3593
- "char": "c",
3594
- "description": "Compare runs by git commit",
3595
- "name": "commit",
3427
+ "filter": {
3428
+ "description": "Additional filter for pulling specific records",
3429
+ "name": "filter",
3596
3430
  "hasDynamicHelp": false,
3597
- "multiple": true,
3431
+ "multiple": false,
3598
3432
  "type": "option"
3599
3433
  },
3600
- "diff-only": {
3601
- "description": "Show only differences",
3602
- "name": "diff-only",
3434
+ "dry-run": {
3435
+ "description": "Show what would be pulled without actually pulling",
3436
+ "name": "dry-run",
3603
3437
  "allowNo": false,
3604
3438
  "type": "boolean"
3605
3439
  },
3606
- "latest": {
3607
- "char": "l",
3608
- "description": "Compare the two most recent completed suite runs",
3609
- "name": "latest",
3440
+ "multi-file": {
3441
+ "description": "Create a single file with multiple records (provide filename)",
3442
+ "name": "multi-file",
3443
+ "hasDynamicHelp": false,
3444
+ "multiple": false,
3445
+ "type": "option"
3446
+ },
3447
+ "no-validate": {
3448
+ "description": "Skip validation before pull",
3449
+ "name": "no-validate",
3610
3450
  "allowNo": false,
3611
3451
  "type": "boolean"
3612
3452
  },
3613
- "from-json": {
3614
- "description": "Compare two results.json files directly (no DB). Pass twice: --from-json PREV --from-json CURR",
3615
- "name": "from-json",
3616
- "hasDynamicHelp": false,
3617
- "multiple": true,
3618
- "type": "option"
3453
+ "update-existing": {
3454
+ "description": "Update existing records during pull",
3455
+ "name": "update-existing",
3456
+ "allowNo": false,
3457
+ "type": "boolean"
3619
3458
  },
3620
- "format": {
3621
- "char": "f",
3622
- "description": "Output format",
3623
- "name": "format",
3624
- "default": "console",
3459
+ "create-new": {
3460
+ "description": "Create new files for records not found locally",
3461
+ "name": "create-new",
3462
+ "allowNo": false,
3463
+ "type": "boolean"
3464
+ },
3465
+ "backup-before-update": {
3466
+ "description": "Create backups before updating files",
3467
+ "name": "backup-before-update",
3468
+ "allowNo": false,
3469
+ "type": "boolean"
3470
+ },
3471
+ "merge-strategy": {
3472
+ "description": "Merge strategy for updates",
3473
+ "name": "merge-strategy",
3474
+ "default": "merge",
3625
3475
  "hasDynamicHelp": false,
3626
3476
  "multiple": false,
3627
3477
  "options": [
3628
- "console",
3629
- "json",
3630
- "markdown"
3478
+ "merge",
3479
+ "overwrite",
3480
+ "skip"
3631
3481
  ],
3632
3482
  "type": "option"
3633
3483
  },
3634
- "output": {
3635
- "char": "o",
3636
- "description": "Output file path",
3637
- "name": "output",
3484
+ "backup-directory": {
3485
+ "description": "Custom backup directory (default: .backups)",
3486
+ "name": "backup-directory",
3638
3487
  "hasDynamicHelp": false,
3639
3488
  "multiple": false,
3640
3489
  "type": "option"
3641
3490
  },
3642
- "verbose": {
3643
- "description": "Show detailed information",
3644
- "name": "verbose",
3491
+ "preserve-fields": {
3492
+ "description": "Comma-separated list of fields to preserve during updates",
3493
+ "name": "preserve-fields",
3494
+ "hasDynamicHelp": false,
3495
+ "multiple": true,
3496
+ "type": "option"
3497
+ },
3498
+ "exclude-fields": {
3499
+ "description": "Comma-separated list of fields to exclude from pull",
3500
+ "name": "exclude-fields",
3501
+ "hasDynamicHelp": false,
3502
+ "multiple": true,
3503
+ "type": "option"
3504
+ },
3505
+ "target-dir": {
3506
+ "description": "Specific target directory (overrides auto-discovery)",
3507
+ "name": "target-dir",
3508
+ "hasDynamicHelp": false,
3509
+ "multiple": false,
3510
+ "type": "option"
3511
+ },
3512
+ "incremental": {
3513
+ "description": "Only pull records updated since last successful pull",
3514
+ "name": "incremental",
3645
3515
  "allowNo": false,
3646
3516
  "type": "boolean"
3647
3517
  },
3648
- "tag": {
3649
- "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.",
3650
- "name": "tag",
3518
+ "since": {
3519
+ "description": "Only pull records updated after this ISO 8601 timestamp",
3520
+ "name": "since",
3651
3521
  "hasDynamicHelp": false,
3652
3522
  "multiple": false,
3653
3523
  "type": "option"
@@ -3655,219 +3525,270 @@
3655
3525
  },
3656
3526
  "hasDynamicHelp": false,
3657
3527
  "hiddenAliases": [],
3658
- "id": "test:compare",
3528
+ "id": "sync:pull",
3659
3529
  "pluginAlias": "@memberjunction/cli",
3660
3530
  "pluginName": "@memberjunction/cli",
3661
3531
  "pluginType": "core",
3662
3532
  "strict": true,
3663
3533
  "enableJsonFlag": false,
3534
+ "Usage": {
3535
+ "domain": "sync",
3536
+ "command": "sync:pull",
3537
+ "summary": "Pull database records into local metadata files.",
3538
+ "description": "Writes records of --entity into the matching entity directory, creating or updating files per the merge strategy.",
3539
+ "flags": [
3540
+ {
3541
+ "name": "--entity",
3542
+ "type": "string",
3543
+ "description": "Entity name to pull (required)"
3544
+ },
3545
+ {
3546
+ "name": "--filter",
3547
+ "type": "string",
3548
+ "description": "Extra SQL filter for which records to pull"
3549
+ },
3550
+ {
3551
+ "name": "--merge-strategy",
3552
+ "type": "merge|overwrite|skip",
3553
+ "description": "How to reconcile existing files"
3554
+ },
3555
+ {
3556
+ "name": "--dry-run",
3557
+ "type": "boolean",
3558
+ "description": "Report what would be pulled without writing"
3559
+ },
3560
+ {
3561
+ "name": "--format",
3562
+ "type": "text|json|md",
3563
+ "description": "Output format (json for machine-readable result)"
3564
+ }
3565
+ ],
3566
+ "examples": [
3567
+ "mj sync pull --entity=\"MJ: AI Prompts\"",
3568
+ "mj sync pull --entity=\"Actions\" --format=json"
3569
+ ],
3570
+ "runtime": {
3571
+ "class": "variable",
3572
+ "typicalSeconds": 15,
3573
+ "note": "scales with number of records matched for --entity"
3574
+ }
3575
+ },
3664
3576
  "isESM": true,
3665
3577
  "relativePath": [
3666
3578
  "dist",
3667
3579
  "commands",
3668
- "test",
3669
- "compare.js"
3580
+ "sync",
3581
+ "pull.js"
3670
3582
  ]
3671
3583
  },
3672
- "test:history": {
3584
+ "sync:push": {
3673
3585
  "aliases": [],
3674
3586
  "args": {},
3675
- "description": "View test execution history",
3587
+ "description": "Push local file changes to the database",
3676
3588
  "examples": [
3677
3589
  "<%= config.bin %> <%= command.id %>",
3678
- "<%= config.bin %> <%= command.id %> --test=<test-id>",
3679
- "<%= config.bin %> <%= command.id %> --suite=<suite-id>",
3680
- "<%= config.bin %> <%= command.id %> --since=\"2024-01-01\"",
3681
- "<%= config.bin %> <%= command.id %> --limit=50"
3590
+ "<%= config.bin %> <%= command.id %> --dry-run",
3591
+ "<%= config.bin %> <%= command.id %> --dir=\"ai-prompts\"",
3592
+ "<%= config.bin %> <%= command.id %> --ci --format=json"
3682
3593
  ],
3683
3594
  "flags": {
3684
- "test": {
3685
- "char": "t",
3686
- "description": "Filter by test ID",
3687
- "name": "test",
3595
+ "format": {
3596
+ "description": "Output format: text (human), json (machine-readable), md (Markdown-fenced)",
3597
+ "name": "format",
3598
+ "default": "text",
3688
3599
  "hasDynamicHelp": false,
3689
3600
  "multiple": false,
3601
+ "options": [
3602
+ "text",
3603
+ "json",
3604
+ "md"
3605
+ ],
3690
3606
  "type": "option"
3691
3607
  },
3692
- "recent": {
3693
- "char": "r",
3694
- "description": "Number of recent runs to show",
3695
- "name": "recent",
3696
- "hasDynamicHelp": false,
3697
- "multiple": false,
3698
- "type": "option"
3608
+ "verbose": {
3609
+ "char": "v",
3610
+ "description": "Show detailed output",
3611
+ "name": "verbose",
3612
+ "allowNo": false,
3613
+ "type": "boolean"
3699
3614
  },
3700
- "from": {
3701
- "description": "Show history from date (YYYY-MM-DD)",
3702
- "name": "from",
3615
+ "no-banner": {
3616
+ "description": "Suppress the startup banner and runtime advisory",
3617
+ "name": "no-banner",
3618
+ "allowNo": false,
3619
+ "type": "boolean"
3620
+ },
3621
+ "dir": {
3622
+ "description": "Specific entity directory to push",
3623
+ "name": "dir",
3703
3624
  "hasDynamicHelp": false,
3704
3625
  "multiple": false,
3705
3626
  "type": "option"
3706
3627
  },
3707
- "status": {
3708
- "char": "s",
3709
- "description": "Filter by status",
3710
- "name": "status",
3628
+ "dry-run": {
3629
+ "description": "Show what would be pushed without actually pushing",
3630
+ "name": "dry-run",
3631
+ "allowNo": false,
3632
+ "type": "boolean"
3633
+ },
3634
+ "ci": {
3635
+ "description": "CI mode - no prompts, fail on issues",
3636
+ "name": "ci",
3637
+ "allowNo": false,
3638
+ "type": "boolean"
3639
+ },
3640
+ "no-validate": {
3641
+ "description": "Skip validation before push",
3642
+ "name": "no-validate",
3643
+ "allowNo": false,
3644
+ "type": "boolean"
3645
+ },
3646
+ "delete-db-only": {
3647
+ "description": "Delete database-only records that reference records being deleted (prevents FK errors)",
3648
+ "name": "delete-db-only",
3649
+ "allowNo": false,
3650
+ "type": "boolean"
3651
+ },
3652
+ "parallel-batch-size": {
3653
+ "description": "Number of records to process in parallel (default: 10)",
3654
+ "name": "parallel-batch-size",
3655
+ "default": 10,
3711
3656
  "hasDynamicHelp": false,
3712
3657
  "multiple": false,
3713
3658
  "type": "option"
3714
3659
  },
3715
- "format": {
3716
- "char": "f",
3717
- "description": "Output format",
3718
- "name": "format",
3719
- "default": "console",
3660
+ "include": {
3661
+ "description": "Only process these directories (comma-separated, supports patterns)",
3662
+ "name": "include",
3720
3663
  "hasDynamicHelp": false,
3721
3664
  "multiple": false,
3722
- "options": [
3723
- "console",
3724
- "json",
3725
- "markdown"
3726
- ],
3727
3665
  "type": "option"
3728
3666
  },
3729
- "output": {
3730
- "char": "o",
3731
- "description": "Output file path",
3732
- "name": "output",
3667
+ "exclude": {
3668
+ "description": "Skip these directories (comma-separated, supports patterns)",
3669
+ "name": "exclude",
3733
3670
  "hasDynamicHelp": false,
3734
3671
  "multiple": false,
3735
3672
  "type": "option"
3736
3673
  },
3737
- "verbose": {
3738
- "char": "v",
3739
- "description": "Show detailed information",
3740
- "name": "verbose",
3674
+ "incremental": {
3675
+ "description": "Skip unchanged files using stored checksums from last push",
3676
+ "name": "incremental",
3677
+ "allowNo": false,
3678
+ "type": "boolean"
3679
+ },
3680
+ "change-detail": {
3681
+ "description": "Write a detailed per-record change report (primary keys + field diffs) to a file",
3682
+ "name": "change-detail",
3741
3683
  "allowNo": false,
3742
3684
  "type": "boolean"
3743
3685
  }
3744
3686
  },
3745
3687
  "hasDynamicHelp": false,
3746
3688
  "hiddenAliases": [],
3747
- "id": "test:history",
3748
- "pluginAlias": "@memberjunction/cli",
3749
- "pluginName": "@memberjunction/cli",
3750
- "pluginType": "core",
3751
- "strict": true,
3752
- "enableJsonFlag": false,
3753
- "isESM": true,
3754
- "relativePath": [
3755
- "dist",
3756
- "commands",
3757
- "test",
3758
- "history.js"
3759
- ]
3760
- },
3761
- "test": {
3762
- "aliases": [],
3763
- "args": {},
3764
- "description": "MemberJunction Testing Framework - Execute and manage tests",
3765
- "examples": [
3766
- "<%= config.bin %> <%= command.id %> run <test-id>",
3767
- "<%= config.bin %> <%= command.id %> run --name=\"Active Members Count\"",
3768
- "<%= config.bin %> <%= command.id %> suite <suite-id>",
3769
- "<%= config.bin %> <%= command.id %> list",
3770
- "<%= config.bin %> <%= command.id %> list --suites",
3771
- "<%= config.bin %> <%= command.id %> validate --all"
3772
- ],
3773
- "flags": {},
3774
- "hasDynamicHelp": false,
3775
- "hiddenAliases": [],
3776
- "id": "test",
3689
+ "id": "sync:push",
3777
3690
  "pluginAlias": "@memberjunction/cli",
3778
3691
  "pluginName": "@memberjunction/cli",
3779
3692
  "pluginType": "core",
3780
3693
  "strict": true,
3781
3694
  "enableJsonFlag": false,
3695
+ "Usage": {
3696
+ "domain": "sync",
3697
+ "command": "sync:push",
3698
+ "summary": "Push local metadata files to the database (upsert).",
3699
+ "description": "Reads entity directories under --dir and creates/updates matching records. Runs validation first unless --no-validate.",
3700
+ "flags": [
3701
+ {
3702
+ "name": "--dir",
3703
+ "type": "string",
3704
+ "description": "Entity directory to push"
3705
+ },
3706
+ {
3707
+ "name": "--dry-run",
3708
+ "type": "boolean",
3709
+ "description": "Report what would change without writing"
3710
+ },
3711
+ {
3712
+ "name": "--ci",
3713
+ "type": "boolean",
3714
+ "description": "No prompts; non-zero exit on error"
3715
+ },
3716
+ {
3717
+ "name": "--no-validate",
3718
+ "type": "boolean",
3719
+ "description": "Skip pre-push validation"
3720
+ },
3721
+ {
3722
+ "name": "--incremental",
3723
+ "type": "boolean",
3724
+ "description": "Skip unchanged files using stored checksums"
3725
+ },
3726
+ {
3727
+ "name": "--format",
3728
+ "type": "text|json|md",
3729
+ "description": "Output format (json for machine-readable result)"
3730
+ }
3731
+ ],
3732
+ "examples": [
3733
+ "mj sync push --dir=ai-agents",
3734
+ "mj sync push --ci --format=json"
3735
+ ],
3736
+ "runtime": {
3737
+ "class": "variable",
3738
+ "typicalSeconds": 20,
3739
+ "note": "scales with number of records in --dir"
3740
+ }
3741
+ },
3782
3742
  "isESM": true,
3783
3743
  "relativePath": [
3784
3744
  "dist",
3785
3745
  "commands",
3786
- "test",
3787
- "index.js"
3746
+ "sync",
3747
+ "push.js"
3788
3748
  ]
3789
3749
  },
3790
- "test:list": {
3750
+ "sync:status": {
3791
3751
  "aliases": [],
3792
3752
  "args": {},
3793
- "description": "List available tests, suites, and types",
3753
+ "description": "Show status of local files vs database",
3794
3754
  "examples": [
3795
- "<%= config.bin %> <%= command.id %>",
3796
- "<%= config.bin %> <%= command.id %> --suites",
3797
- "<%= config.bin %> <%= command.id %> --types",
3798
- "<%= config.bin %> <%= command.id %> --type=agent-eval",
3799
- "<%= config.bin %> <%= command.id %> --tag=smoke",
3800
- "<%= config.bin %> <%= command.id %> --status=active --verbose"
3801
- ],
3802
- "flags": {
3803
- "suites": {
3804
- "description": "List test suites instead of tests",
3805
- "name": "suites",
3806
- "allowNo": false,
3807
- "type": "boolean"
3808
- },
3809
- "types": {
3810
- "description": "List test types",
3811
- "name": "types",
3812
- "allowNo": false,
3813
- "type": "boolean"
3814
- },
3815
- "type": {
3816
- "char": "t",
3817
- "description": "Filter by test type",
3818
- "name": "type",
3819
- "hasDynamicHelp": false,
3820
- "multiple": false,
3821
- "type": "option"
3822
- },
3823
- "tag": {
3824
- "description": "Filter by tag",
3825
- "name": "tag",
3826
- "hasDynamicHelp": false,
3827
- "multiple": false,
3828
- "type": "option"
3829
- },
3830
- "status": {
3831
- "char": "s",
3832
- "description": "Filter by status",
3833
- "name": "status",
3834
- "hasDynamicHelp": false,
3835
- "multiple": false,
3836
- "type": "option"
3837
- },
3838
- "format": {
3839
- "char": "f",
3840
- "description": "Output format",
3841
- "name": "format",
3842
- "default": "console",
3843
- "hasDynamicHelp": false,
3844
- "multiple": false,
3845
- "options": [
3846
- "console",
3847
- "json",
3848
- "markdown"
3849
- ],
3850
- "type": "option"
3851
- },
3852
- "output": {
3853
- "char": "o",
3854
- "description": "Output file path",
3855
- "name": "output",
3755
+ "<%= config.bin %> <%= command.id %>",
3756
+ "<%= config.bin %> <%= command.id %> --dir=\"ai-prompts\"",
3757
+ "<%= config.bin %> <%= command.id %> --verbose"
3758
+ ],
3759
+ "flags": {
3760
+ "dir": {
3761
+ "description": "Specific entity directory to check status",
3762
+ "name": "dir",
3856
3763
  "hasDynamicHelp": false,
3857
3764
  "multiple": false,
3858
3765
  "type": "option"
3859
3766
  },
3860
3767
  "verbose": {
3861
3768
  "char": "v",
3862
- "description": "Show detailed information",
3769
+ "description": "Show detailed field-level differences",
3863
3770
  "name": "verbose",
3864
3771
  "allowNo": false,
3865
3772
  "type": "boolean"
3773
+ },
3774
+ "include": {
3775
+ "description": "Only process these directories (comma-separated, supports patterns)",
3776
+ "name": "include",
3777
+ "hasDynamicHelp": false,
3778
+ "multiple": false,
3779
+ "type": "option"
3780
+ },
3781
+ "exclude": {
3782
+ "description": "Skip these directories (comma-separated, supports patterns)",
3783
+ "name": "exclude",
3784
+ "hasDynamicHelp": false,
3785
+ "multiple": false,
3786
+ "type": "option"
3866
3787
  }
3867
3788
  },
3868
3789
  "hasDynamicHelp": false,
3869
3790
  "hiddenAliases": [],
3870
- "id": "test:list",
3791
+ "id": "sync:status",
3871
3792
  "pluginAlias": "@memberjunction/cli",
3872
3793
  "pluginName": "@memberjunction/cli",
3873
3794
  "pluginType": "core",
@@ -3877,90 +3798,32 @@
3877
3798
  "relativePath": [
3878
3799
  "dist",
3879
3800
  "commands",
3880
- "test",
3881
- "list.js"
3801
+ "sync",
3802
+ "status.js"
3882
3803
  ]
3883
3804
  },
3884
- "test:run": {
3805
+ "sync:usage": {
3885
3806
  "aliases": [],
3886
- "args": {
3887
- "testId": {
3888
- "description": "Test ID to execute",
3889
- "name": "testId",
3890
- "required": false
3891
- }
3892
- },
3893
- "description": "Execute a single test by ID or name",
3894
- "examples": [
3895
- "<%= config.bin %> <%= command.id %> <test-id>",
3896
- "<%= config.bin %> <%= command.id %> --name=\"Active Members Count\"",
3897
- "<%= config.bin %> <%= command.id %> <test-id> --environment=staging",
3898
- "<%= config.bin %> <%= command.id %> <test-id> --format=json --output=results.json",
3899
- "<%= config.bin %> <%= command.id %> <test-id> --dry-run"
3900
- ],
3807
+ "args": {},
3808
+ "description": "Show usage, flags, examples, and runtime hints for every `mj sync` command.",
3901
3809
  "flags": {
3902
- "name": {
3903
- "char": "n",
3904
- "description": "Test name to execute",
3905
- "name": "name",
3906
- "hasDynamicHelp": false,
3907
- "multiple": false,
3908
- "type": "option"
3909
- },
3910
- "environment": {
3911
- "char": "e",
3912
- "description": "Environment context (dev, staging, prod)",
3913
- "name": "environment",
3914
- "hasDynamicHelp": false,
3915
- "multiple": false,
3916
- "type": "option"
3917
- },
3918
3810
  "format": {
3919
- "char": "f",
3920
3811
  "description": "Output format",
3921
3812
  "name": "format",
3922
- "default": "console",
3813
+ "default": "text",
3923
3814
  "hasDynamicHelp": false,
3924
3815
  "multiple": false,
3925
3816
  "options": [
3926
- "console",
3817
+ "text",
3927
3818
  "json",
3928
- "markdown"
3819
+ "md"
3929
3820
  ],
3930
3821
  "type": "option"
3931
- },
3932
- "output": {
3933
- "char": "o",
3934
- "description": "Output file path",
3935
- "name": "output",
3936
- "hasDynamicHelp": false,
3937
- "multiple": false,
3938
- "type": "option"
3939
- },
3940
- "dry-run": {
3941
- "description": "Validate without executing",
3942
- "name": "dry-run",
3943
- "allowNo": false,
3944
- "type": "boolean"
3945
- },
3946
- "verbose": {
3947
- "char": "v",
3948
- "description": "Show detailed execution information",
3949
- "name": "verbose",
3950
- "allowNo": false,
3951
- "type": "boolean"
3952
- },
3953
- "oracles-module": {
3954
- "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.",
3955
- "name": "oracles-module",
3956
- "hasDynamicHelp": false,
3957
- "multiple": false,
3958
- "type": "option"
3959
3822
  }
3960
3823
  },
3961
3824
  "hasDynamicHelp": false,
3962
3825
  "hiddenAliases": [],
3963
- "id": "test:run",
3826
+ "id": "sync:usage",
3964
3827
  "pluginAlias": "@memberjunction/cli",
3965
3828
  "pluginName": "@memberjunction/cli",
3966
3829
  "pluginType": "core",
@@ -3970,98 +3833,44 @@
3970
3833
  "relativePath": [
3971
3834
  "dist",
3972
3835
  "commands",
3973
- "test",
3974
- "run.js"
3836
+ "sync",
3837
+ "usage.js"
3975
3838
  ]
3976
3839
  },
3977
- "test:suite": {
3840
+ "sync:validate": {
3978
3841
  "aliases": [],
3979
- "args": {
3980
- "suiteId": {
3981
- "description": "Test suite ID to execute",
3982
- "name": "suiteId",
3983
- "required": false
3984
- }
3985
- },
3986
- "description": "Execute a test suite",
3842
+ "args": {},
3843
+ "description": "Validate metadata files",
3987
3844
  "examples": [
3988
- "<%= config.bin %> <%= command.id %> <suite-id>",
3989
- "<%= config.bin %> <%= command.id %> --name=\"Agent Quality Suite\"",
3990
- "<%= config.bin %> <%= command.id %> <suite-id> --format=json",
3991
- "<%= config.bin %> <%= command.id %> <suite-id> --output=suite-results.json"
3845
+ "<%= config.bin %> <%= command.id %>",
3846
+ "<%= config.bin %> <%= command.id %> --dir=\"ai-prompts\"",
3847
+ "<%= config.bin %> <%= command.id %> --save-report",
3848
+ "<%= config.bin %> <%= command.id %> --verbose"
3992
3849
  ],
3993
3850
  "flags": {
3994
- "name": {
3995
- "char": "n",
3996
- "description": "Test suite name to execute",
3997
- "name": "name",
3998
- "hasDynamicHelp": false,
3999
- "multiple": false,
4000
- "type": "option"
4001
- },
4002
- "format": {
4003
- "char": "f",
4004
- "description": "Output format",
4005
- "name": "format",
4006
- "default": "console",
4007
- "hasDynamicHelp": false,
4008
- "multiple": false,
4009
- "options": [
4010
- "console",
4011
- "json",
4012
- "markdown"
4013
- ],
4014
- "type": "option"
4015
- },
4016
- "output": {
4017
- "char": "o",
4018
- "description": "Output file path",
4019
- "name": "output",
3851
+ "dir": {
3852
+ "description": "Specific entity directory to validate",
3853
+ "name": "dir",
4020
3854
  "hasDynamicHelp": false,
4021
3855
  "multiple": false,
4022
3856
  "type": "option"
4023
3857
  },
4024
3858
  "verbose": {
4025
3859
  "char": "v",
4026
- "description": "Show detailed execution information",
3860
+ "description": "Show detailed validation output",
4027
3861
  "name": "verbose",
4028
3862
  "allowNo": false,
4029
3863
  "type": "boolean"
4030
3864
  },
4031
- "delay": {
4032
- "char": "d",
4033
- "description": "Delay in milliseconds between test executions (avoids Auth0 rate limits)",
4034
- "name": "delay",
4035
- "default": 0,
4036
- "hasDynamicHelp": false,
4037
- "multiple": false,
4038
- "type": "option"
4039
- },
4040
- "parallel": {
4041
- "char": "p",
4042
- "description": "Run tests in parallel with shared browser sessions",
4043
- "name": "parallel",
3865
+ "save-report": {
3866
+ "description": "Save validation report as markdown file",
3867
+ "name": "save-report",
4044
3868
  "allowNo": false,
4045
3869
  "type": "boolean"
4046
3870
  },
4047
- "max-parallel": {
4048
- "description": "Maximum number of parallel workers (default 4)",
4049
- "name": "max-parallel",
4050
- "default": 4,
4051
- "hasDynamicHelp": false,
4052
- "multiple": false,
4053
- "type": "option"
4054
- },
4055
- "flaky-check": {
4056
- "description": "Run each test N times to detect flakiness (variance > 0.3 or mixed pass/fail = flaky). Recommended: 3 or 5",
4057
- "name": "flaky-check",
4058
- "hasDynamicHelp": false,
4059
- "multiple": false,
4060
- "type": "option"
4061
- },
4062
- "oracles-module": {
4063
- "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.",
4064
- "name": "oracles-module",
3871
+ "output": {
3872
+ "description": "Output file path for validation report (default: validation-report.md)",
3873
+ "name": "output",
4065
3874
  "hasDynamicHelp": false,
4066
3875
  "multiple": false,
4067
3876
  "type": "option"
@@ -4069,7 +3878,7 @@
4069
3878
  },
4070
3879
  "hasDynamicHelp": false,
4071
3880
  "hiddenAliases": [],
4072
- "id": "test:suite",
3881
+ "id": "sync:validate",
4073
3882
  "pluginAlias": "@memberjunction/cli",
4074
3883
  "pluginName": "@memberjunction/cli",
4075
3884
  "pluginType": "core",
@@ -4079,74 +3888,44 @@
4079
3888
  "relativePath": [
4080
3889
  "dist",
4081
3890
  "commands",
4082
- "test",
4083
- "suite.js"
3891
+ "sync",
3892
+ "validate.js"
4084
3893
  ]
4085
3894
  },
4086
- "test:validate": {
3895
+ "sync:watch": {
4087
3896
  "aliases": [],
4088
- "args": {
4089
- "testId": {
4090
- "description": "Test ID to validate",
4091
- "name": "testId",
4092
- "required": false
4093
- }
4094
- },
4095
- "description": "Validate test definitions without executing",
3897
+ "args": {},
3898
+ "description": "Watch for file changes and sync automatically",
4096
3899
  "examples": [
4097
- "<%= config.bin %> <%= command.id %> <test-id>",
4098
- "<%= config.bin %> <%= command.id %> --all",
4099
- "<%= config.bin %> <%= command.id %> --type=agent-eval",
4100
- "<%= config.bin %> <%= command.id %> --all --save-report",
4101
- "<%= config.bin %> <%= command.id %> --all --output=validation-report.md"
3900
+ "<%= config.bin %> <%= command.id %>",
3901
+ "<%= config.bin %> <%= command.id %> --dir=\"ai-prompts\"",
3902
+ "<%= config.bin %> <%= command.id %> --debounce=1000",
3903
+ "<%= config.bin %> <%= command.id %> --no-validate"
4102
3904
  ],
4103
3905
  "flags": {
4104
- "all": {
4105
- "char": "a",
4106
- "description": "Validate all tests",
4107
- "name": "all",
4108
- "allowNo": false,
4109
- "type": "boolean"
4110
- },
4111
- "type": {
4112
- "char": "t",
4113
- "description": "Validate tests by type",
4114
- "name": "type",
4115
- "hasDynamicHelp": false,
4116
- "multiple": false,
4117
- "type": "option"
4118
- },
4119
- "save-report": {
4120
- "description": "Save validation report to file",
4121
- "name": "save-report",
4122
- "allowNo": false,
4123
- "type": "boolean"
4124
- },
4125
- "format": {
4126
- "char": "f",
4127
- "description": "Output format",
4128
- "name": "format",
4129
- "default": "console",
3906
+ "dir": {
3907
+ "description": "Specific entity directory to watch",
3908
+ "name": "dir",
4130
3909
  "hasDynamicHelp": false,
4131
- "multiple": false,
4132
- "options": [
4133
- "console",
4134
- "json",
4135
- "markdown"
4136
- ],
3910
+ "multiple": false,
4137
3911
  "type": "option"
4138
3912
  },
4139
- "output": {
4140
- "char": "o",
4141
- "description": "Output file path",
4142
- "name": "output",
3913
+ "debounce": {
3914
+ "description": "Debounce delay in milliseconds (default: 500)",
3915
+ "name": "debounce",
4143
3916
  "hasDynamicHelp": false,
4144
3917
  "multiple": false,
4145
3918
  "type": "option"
4146
3919
  },
3920
+ "no-validate": {
3921
+ "description": "Skip validation before sync",
3922
+ "name": "no-validate",
3923
+ "allowNo": false,
3924
+ "type": "boolean"
3925
+ },
4147
3926
  "verbose": {
4148
3927
  "char": "v",
4149
- "description": "Show detailed information",
3928
+ "description": "Show detailed output",
4150
3929
  "name": "verbose",
4151
3930
  "allowNo": false,
4152
3931
  "type": "boolean"
@@ -4154,7 +3933,7 @@
4154
3933
  },
4155
3934
  "hasDynamicHelp": false,
4156
3935
  "hiddenAliases": [],
4157
- "id": "test:validate",
3936
+ "id": "sync:watch",
4158
3937
  "pluginAlias": "@memberjunction/cli",
4159
3938
  "pluginName": "@memberjunction/cli",
4160
3939
  "pluginType": "core",
@@ -4164,8 +3943,8 @@
4164
3943
  "relativePath": [
4165
3944
  "dist",
4166
3945
  "commands",
4167
- "test",
4168
- "validate.js"
3946
+ "sync",
3947
+ "watch.js"
4169
3948
  ]
4170
3949
  },
4171
3950
  "translate-sql": {
@@ -4405,6 +4184,240 @@
4405
4184
  "claude.js"
4406
4185
  ]
4407
4186
  },
4187
+ "install:claude": {
4188
+ "aliases": [],
4189
+ "args": {},
4190
+ "description": "Install or refresh the Claude Code pack in the current directory.",
4191
+ "examples": [
4192
+ "<%= config.bin %> install:claude",
4193
+ "<%= config.bin %> install:claude --dry-run",
4194
+ "<%= config.bin %> install:claude --from ./local-pack",
4195
+ "<%= config.bin %> install:claude --json"
4196
+ ],
4197
+ "flags": {
4198
+ "dir": {
4199
+ "description": "Target directory for the install",
4200
+ "name": "dir",
4201
+ "default": ".",
4202
+ "hasDynamicHelp": false,
4203
+ "multiple": false,
4204
+ "type": "option"
4205
+ },
4206
+ "major": {
4207
+ "description": "Force a specific MJ major (default: detected from package.json)",
4208
+ "name": "major",
4209
+ "hasDynamicHelp": false,
4210
+ "multiple": false,
4211
+ "type": "option"
4212
+ },
4213
+ "ref": {
4214
+ "description": "Git ref to fetch from (branch or tag). Default: main.",
4215
+ "name": "ref",
4216
+ "hasDynamicHelp": false,
4217
+ "multiple": false,
4218
+ "type": "option"
4219
+ },
4220
+ "from": {
4221
+ "description": "Use a local pack source instead of fetching from GitHub",
4222
+ "name": "from",
4223
+ "hasDynamicHelp": false,
4224
+ "multiple": false,
4225
+ "type": "option"
4226
+ },
4227
+ "offline": {
4228
+ "description": "Forbid network; requires --from <path>",
4229
+ "name": "offline",
4230
+ "allowNo": false,
4231
+ "type": "boolean"
4232
+ },
4233
+ "dry-run": {
4234
+ "description": "Print what would be written; change nothing",
4235
+ "name": "dry-run",
4236
+ "allowNo": false,
4237
+ "type": "boolean"
4238
+ },
4239
+ "yes": {
4240
+ "char": "y",
4241
+ "description": "Don't prompt (reserved for future interactive paths; currently no-op)",
4242
+ "name": "yes",
4243
+ "allowNo": false,
4244
+ "type": "boolean"
4245
+ },
4246
+ "force": {
4247
+ "description": "Overwrite user-customized commands/skills (saves .bak files)",
4248
+ "name": "force",
4249
+ "allowNo": false,
4250
+ "type": "boolean"
4251
+ },
4252
+ "skip-commands": {
4253
+ "description": "Skip seeding .claude/commands/",
4254
+ "name": "skip-commands",
4255
+ "allowNo": false,
4256
+ "type": "boolean"
4257
+ },
4258
+ "skip-skills": {
4259
+ "description": "Skip seeding .claude/skills/",
4260
+ "name": "skip-skills",
4261
+ "allowNo": false,
4262
+ "type": "boolean"
4263
+ },
4264
+ "skip-settings": {
4265
+ "description": "Skip merging .claude/settings.json",
4266
+ "name": "skip-settings",
4267
+ "allowNo": false,
4268
+ "type": "boolean"
4269
+ },
4270
+ "json": {
4271
+ "description": "Output as JSON (matches plan §7.5 schema)",
4272
+ "name": "json",
4273
+ "allowNo": false,
4274
+ "type": "boolean"
4275
+ },
4276
+ "verbose": {
4277
+ "char": "v",
4278
+ "description": "Show progress messages from the fetcher and merger",
4279
+ "name": "verbose",
4280
+ "allowNo": false,
4281
+ "type": "boolean"
4282
+ }
4283
+ },
4284
+ "hasDynamicHelp": false,
4285
+ "hiddenAliases": [],
4286
+ "id": "install:claude",
4287
+ "pluginAlias": "@memberjunction/cli",
4288
+ "pluginName": "@memberjunction/cli",
4289
+ "pluginType": "core",
4290
+ "strict": true,
4291
+ "enableJsonFlag": false,
4292
+ "isESM": true,
4293
+ "relativePath": [
4294
+ "dist",
4295
+ "commands",
4296
+ "install",
4297
+ "claude.js"
4298
+ ]
4299
+ },
4300
+ "install": {
4301
+ "aliases": [],
4302
+ "args": {},
4303
+ "description": "Install MemberJunction from a GitHub release",
4304
+ "examples": [
4305
+ "<%= config.bin %> <%= command.id %>",
4306
+ "<%= config.bin %> <%= command.id %> -t v4.3.0",
4307
+ "<%= config.bin %> <%= command.id %> --dry-run",
4308
+ "<%= config.bin %> <%= command.id %> --yes"
4309
+ ],
4310
+ "flags": {
4311
+ "tag": {
4312
+ "char": "t",
4313
+ "description": "Release tag to install (e.g. v4.3.0). If omitted, shows a version picker.",
4314
+ "name": "tag",
4315
+ "hasDynamicHelp": false,
4316
+ "multiple": false,
4317
+ "type": "option"
4318
+ },
4319
+ "dir": {
4320
+ "description": "Target directory for the installation",
4321
+ "name": "dir",
4322
+ "default": ".",
4323
+ "hasDynamicHelp": false,
4324
+ "multiple": false,
4325
+ "type": "option"
4326
+ },
4327
+ "config": {
4328
+ "char": "c",
4329
+ "description": "Path to JSON config file with install settings (database, auth, ports, etc.)",
4330
+ "name": "config",
4331
+ "hasDynamicHelp": false,
4332
+ "multiple": false,
4333
+ "type": "option"
4334
+ },
4335
+ "legacy": {
4336
+ "description": "Use the legacy interactive installer (ZIP-only distribution)",
4337
+ "hidden": true,
4338
+ "name": "legacy",
4339
+ "allowNo": false,
4340
+ "type": "boolean"
4341
+ },
4342
+ "dry-run": {
4343
+ "description": "Show the install plan without executing it",
4344
+ "name": "dry-run",
4345
+ "allowNo": false,
4346
+ "type": "boolean"
4347
+ },
4348
+ "yes": {
4349
+ "char": "y",
4350
+ "description": "Non-interactive mode: auto-select latest version and accept defaults",
4351
+ "name": "yes",
4352
+ "allowNo": false,
4353
+ "type": "boolean"
4354
+ },
4355
+ "verbose": {
4356
+ "char": "v",
4357
+ "description": "Show detailed output",
4358
+ "name": "verbose",
4359
+ "allowNo": false,
4360
+ "type": "boolean"
4361
+ },
4362
+ "skip-db": {
4363
+ "description": "Skip database provisioning phases",
4364
+ "name": "skip-db",
4365
+ "allowNo": false,
4366
+ "type": "boolean"
4367
+ },
4368
+ "skip-start": {
4369
+ "description": "Skip service startup and smoke tests",
4370
+ "name": "skip-start",
4371
+ "allowNo": false,
4372
+ "type": "boolean"
4373
+ },
4374
+ "no-resume": {
4375
+ "description": "Ignore any existing checkpoint and start fresh",
4376
+ "name": "no-resume",
4377
+ "allowNo": false,
4378
+ "type": "boolean"
4379
+ },
4380
+ "fast": {
4381
+ "description": "Fast mode: skip smoke test and optimize post-codegen steps. Re-run without --fast if you encounter issues.",
4382
+ "name": "fast",
4383
+ "allowNo": false,
4384
+ "type": "boolean"
4385
+ },
4386
+ "overwrite-config": {
4387
+ "description": "Overwrite existing config files (.env, mj.config.cjs, environment.ts) instead of preserving them",
4388
+ "name": "overwrite-config",
4389
+ "allowNo": false,
4390
+ "type": "boolean"
4391
+ },
4392
+ "monorepo": {
4393
+ "description": "Install the full MemberJunction source repository instead of the lightweight distribution. Use this for MJ framework development.",
4394
+ "name": "monorepo",
4395
+ "allowNo": false,
4396
+ "type": "boolean"
4397
+ },
4398
+ "no-claude-pack": {
4399
+ "description": "Exclude the Claude Code pack (CLAUDE.md + .claude/ tree) from the scaffold. By default the pack ships with the install so opening Claude Code in your new MJ project gives you the curated MJ-aware experience immediately.",
4400
+ "name": "no-claude-pack",
4401
+ "allowNo": false,
4402
+ "type": "boolean"
4403
+ }
4404
+ },
4405
+ "hasDynamicHelp": false,
4406
+ "hiddenAliases": [],
4407
+ "id": "install",
4408
+ "pluginAlias": "@memberjunction/cli",
4409
+ "pluginName": "@memberjunction/cli",
4410
+ "pluginType": "core",
4411
+ "strict": true,
4412
+ "enableJsonFlag": false,
4413
+ "isESM": true,
4414
+ "relativePath": [
4415
+ "dist",
4416
+ "commands",
4417
+ "install",
4418
+ "index.js"
4419
+ ]
4420
+ },
4408
4421
  "ai:actions:list": {
4409
4422
  "aliases": [],
4410
4423
  "args": {},
@@ -5453,5 +5466,5 @@
5453
5466
  ]
5454
5467
  }
5455
5468
  },
5456
- "version": "5.44.0"
5469
+ "version": "5.45.1"
5457
5470
  }