@bryan-thompson/inspector-assessment-cli 1.39.0 → 1.40.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.
@@ -388,7 +388,10 @@ describe("Module Name Validation", () => {
388
388
  const VALID_MODULE_NAMES = [
389
389
  "functionality",
390
390
  "security",
391
+ "documentation",
391
392
  "errorHandling",
393
+ "usability",
394
+ "mcpSpecCompliance", // deprecated, use protocolCompliance
392
395
  "protocolCompliance",
393
396
  "aupCompliance",
394
397
  "toolAnnotations",
@@ -399,9 +402,12 @@ describe("Module Name Validation", () => {
399
402
  "resources",
400
403
  "prompts",
401
404
  "crossCapability",
405
+ "protocolConformance", // deprecated, use protocolCompliance
402
406
  "developerExperience",
403
407
  "portability",
404
408
  "externalAPIScanner",
409
+ "fileModularization",
410
+ "conformance",
405
411
  ];
406
412
  function validateModuleNames(input) {
407
413
  const names = input
@@ -840,3 +846,610 @@ describe("parseArgs Zod Schema Integration", () => {
840
846
  });
841
847
  });
842
848
  });
849
+ /**
850
+ * Transport Flag Tests (--http, --sse)
851
+ *
852
+ * Tests for the convenience transport flags that allow quick testing
853
+ * without creating a config file.
854
+ */
855
+ describe("Transport Flags (--http, --sse)", () => {
856
+ let processExitSpy;
857
+ let consoleErrorSpy;
858
+ beforeEach(() => {
859
+ jest.useFakeTimers();
860
+ processExitSpy = jest
861
+ .spyOn(process, "exit")
862
+ .mockImplementation((() => { }));
863
+ consoleErrorSpy = jest.spyOn(console, "error").mockImplementation(() => { });
864
+ });
865
+ afterEach(() => {
866
+ jest.runAllTimers();
867
+ jest.useRealTimers();
868
+ processExitSpy?.mockRestore();
869
+ consoleErrorSpy?.mockRestore();
870
+ });
871
+ describe("--http flag", () => {
872
+ it("should accept valid HTTP URL", () => {
873
+ const result = parseArgs([
874
+ "test-server",
875
+ "--http",
876
+ "http://localhost:10900/mcp",
877
+ ]);
878
+ expect(result.httpUrl).toBe("http://localhost:10900/mcp");
879
+ expect(result.helpRequested).toBeFalsy();
880
+ });
881
+ it("should accept valid HTTPS URL", () => {
882
+ const result = parseArgs([
883
+ "test-server",
884
+ "--http",
885
+ "https://api.example.com/mcp",
886
+ ]);
887
+ expect(result.httpUrl).toBe("https://api.example.com/mcp");
888
+ expect(result.helpRequested).toBeFalsy();
889
+ });
890
+ it("should reject invalid URL", () => {
891
+ const result = parseArgs(["test-server", "--http", "not-a-valid-url"]);
892
+ expect(result.helpRequested).toBe(true);
893
+ expect(consoleErrorSpy).toHaveBeenCalledWith(expect.stringContaining("Invalid URL for --http"));
894
+ });
895
+ it("should reject missing URL argument", () => {
896
+ const result = parseArgs(["test-server", "--http"]);
897
+ expect(result.helpRequested).toBe(true);
898
+ expect(consoleErrorSpy).toHaveBeenCalledWith(expect.stringContaining("--http requires a URL argument"));
899
+ });
900
+ it("should reject when next argument is another flag", () => {
901
+ const result = parseArgs(["test-server", "--http", "--verbose"]);
902
+ expect(result.helpRequested).toBe(true);
903
+ expect(consoleErrorSpy).toHaveBeenCalledWith(expect.stringContaining("--http requires a URL argument"));
904
+ });
905
+ it("should reject non-HTTP protocol (file://)", () => {
906
+ const result = parseArgs(["test-server", "--http", "file:///etc/passwd"]);
907
+ expect(result.helpRequested).toBe(true);
908
+ expect(consoleErrorSpy).toHaveBeenCalledWith(expect.stringContaining("--http requires HTTP or HTTPS URL, got: file:"));
909
+ });
910
+ it("should reject non-HTTP protocol (ftp://)", () => {
911
+ const result = parseArgs([
912
+ "test-server",
913
+ "--http",
914
+ "ftp://example.com/file",
915
+ ]);
916
+ expect(result.helpRequested).toBe(true);
917
+ expect(consoleErrorSpy).toHaveBeenCalledWith(expect.stringContaining("--http requires HTTP or HTTPS URL, got: ftp:"));
918
+ });
919
+ });
920
+ describe("--sse flag", () => {
921
+ it("should accept valid SSE URL", () => {
922
+ const result = parseArgs([
923
+ "test-server",
924
+ "--sse",
925
+ "http://localhost:9002/sse",
926
+ ]);
927
+ expect(result.sseUrl).toBe("http://localhost:9002/sse");
928
+ expect(result.helpRequested).toBeFalsy();
929
+ });
930
+ it("should accept valid HTTPS SSE URL", () => {
931
+ const result = parseArgs([
932
+ "test-server",
933
+ "--sse",
934
+ "https://api.example.com/sse",
935
+ ]);
936
+ expect(result.sseUrl).toBe("https://api.example.com/sse");
937
+ expect(result.helpRequested).toBeFalsy();
938
+ });
939
+ it("should reject invalid URL", () => {
940
+ const result = parseArgs(["test-server", "--sse", "invalid-url"]);
941
+ expect(result.helpRequested).toBe(true);
942
+ expect(consoleErrorSpy).toHaveBeenCalledWith(expect.stringContaining("Invalid URL for --sse"));
943
+ });
944
+ it("should reject missing URL argument", () => {
945
+ const result = parseArgs(["test-server", "--sse"]);
946
+ expect(result.helpRequested).toBe(true);
947
+ expect(consoleErrorSpy).toHaveBeenCalledWith(expect.stringContaining("--sse requires a URL argument"));
948
+ });
949
+ it("should reject non-HTTP protocol (file://)", () => {
950
+ const result = parseArgs(["test-server", "--sse", "file:///etc/passwd"]);
951
+ expect(result.helpRequested).toBe(true);
952
+ expect(consoleErrorSpy).toHaveBeenCalledWith(expect.stringContaining("--sse requires HTTP or HTTPS URL, got: file:"));
953
+ });
954
+ });
955
+ describe("mutual exclusivity", () => {
956
+ it("should reject --http with --config", () => {
957
+ const result = parseArgs([
958
+ "test-server",
959
+ "--http",
960
+ "http://localhost:10900/mcp",
961
+ "--config",
962
+ "config.json",
963
+ ]);
964
+ expect(result.helpRequested).toBe(true);
965
+ expect(consoleErrorSpy).toHaveBeenCalledWith(expect.stringContaining("--http/--sse cannot be used with --config"));
966
+ });
967
+ it("should reject --sse with --config", () => {
968
+ const result = parseArgs([
969
+ "test-server",
970
+ "--sse",
971
+ "http://localhost:9002/sse",
972
+ "--config",
973
+ "config.json",
974
+ ]);
975
+ expect(result.helpRequested).toBe(true);
976
+ expect(consoleErrorSpy).toHaveBeenCalledWith(expect.stringContaining("--http/--sse cannot be used with --config"));
977
+ });
978
+ it("should reject --http with --sse", () => {
979
+ const result = parseArgs([
980
+ "test-server",
981
+ "--http",
982
+ "http://localhost:10900/mcp",
983
+ "--sse",
984
+ "http://localhost:9002/sse",
985
+ ]);
986
+ expect(result.helpRequested).toBe(true);
987
+ expect(consoleErrorSpy).toHaveBeenCalledWith(expect.stringContaining("--http and --sse are mutually exclusive"));
988
+ });
989
+ it("should allow --http without --config or --sse", () => {
990
+ const result = parseArgs([
991
+ "test-server",
992
+ "--http",
993
+ "http://localhost:10900/mcp",
994
+ ]);
995
+ expect(result.httpUrl).toBe("http://localhost:10900/mcp");
996
+ expect(result.sseUrl).toBeUndefined();
997
+ expect(result.serverConfigPath).toBeUndefined();
998
+ expect(result.helpRequested).toBeFalsy();
999
+ });
1000
+ it("should allow --sse without --config or --http", () => {
1001
+ const result = parseArgs([
1002
+ "test-server",
1003
+ "--sse",
1004
+ "http://localhost:9002/sse",
1005
+ ]);
1006
+ expect(result.sseUrl).toBe("http://localhost:9002/sse");
1007
+ expect(result.httpUrl).toBeUndefined();
1008
+ expect(result.serverConfigPath).toBeUndefined();
1009
+ expect(result.helpRequested).toBeFalsy();
1010
+ });
1011
+ });
1012
+ describe("combined with other options", () => {
1013
+ it("should work with --http and --temporal-invocations", () => {
1014
+ const result = parseArgs([
1015
+ "test-server",
1016
+ "--http",
1017
+ "http://localhost:10900/mcp",
1018
+ "--temporal-invocations",
1019
+ "5",
1020
+ ]);
1021
+ expect(result.httpUrl).toBe("http://localhost:10900/mcp");
1022
+ expect(result.temporalInvocations).toBe(5);
1023
+ expect(result.helpRequested).toBeFalsy();
1024
+ });
1025
+ it("should work with --sse and --profile", () => {
1026
+ const result = parseArgs([
1027
+ "test-server",
1028
+ "--sse",
1029
+ "http://localhost:9002/sse",
1030
+ "--profile",
1031
+ "quick",
1032
+ ]);
1033
+ expect(result.sseUrl).toBe("http://localhost:9002/sse");
1034
+ expect(result.profile).toBe("quick");
1035
+ expect(result.helpRequested).toBeFalsy();
1036
+ });
1037
+ it("should work with --http and --output", () => {
1038
+ const result = parseArgs([
1039
+ "test-server",
1040
+ "--http",
1041
+ "http://localhost:10900/mcp",
1042
+ "--output",
1043
+ "/tmp/results.json",
1044
+ ]);
1045
+ expect(result.httpUrl).toBe("http://localhost:10900/mcp");
1046
+ expect(result.outputPath).toBe("/tmp/results.json");
1047
+ expect(result.helpRequested).toBeFalsy();
1048
+ });
1049
+ it("should work with --http and --conformance", () => {
1050
+ const result = parseArgs([
1051
+ "test-server",
1052
+ "--http",
1053
+ "http://localhost:10900/mcp",
1054
+ "--conformance",
1055
+ ]);
1056
+ expect(result.httpUrl).toBe("http://localhost:10900/mcp");
1057
+ expect(result.conformanceEnabled).toBe(true);
1058
+ expect(result.helpRequested).toBeFalsy();
1059
+ });
1060
+ it("should work with --sse and --conformance", () => {
1061
+ const result = parseArgs([
1062
+ "test-server",
1063
+ "--sse",
1064
+ "http://localhost:9002/sse",
1065
+ "--conformance",
1066
+ ]);
1067
+ expect(result.sseUrl).toBe("http://localhost:9002/sse");
1068
+ expect(result.conformanceEnabled).toBe(true);
1069
+ expect(result.helpRequested).toBeFalsy();
1070
+ });
1071
+ });
1072
+ });
1073
+ /**
1074
+ * Module Flag Tests (--module, -m)
1075
+ *
1076
+ * Tests for the single module execution flag that bypasses orchestrator.
1077
+ * Issue #184: Single module runner for focused testing without orchestration overhead.
1078
+ */
1079
+ describe("Module Flag (--module, -m)", () => {
1080
+ let processExitSpy;
1081
+ let consoleErrorSpy;
1082
+ beforeEach(() => {
1083
+ jest.useFakeTimers();
1084
+ processExitSpy = jest
1085
+ .spyOn(process, "exit")
1086
+ .mockImplementation((() => { }));
1087
+ consoleErrorSpy = jest.spyOn(console, "error").mockImplementation(() => { });
1088
+ });
1089
+ afterEach(() => {
1090
+ jest.runAllTimers();
1091
+ jest.useRealTimers();
1092
+ processExitSpy?.mockRestore();
1093
+ consoleErrorSpy?.mockRestore();
1094
+ });
1095
+ describe("valid module names", () => {
1096
+ it("should accept valid module name with long flag", () => {
1097
+ const result = parseArgs([
1098
+ "test-server",
1099
+ "--config",
1100
+ "config.json",
1101
+ "--module",
1102
+ "toolAnnotations",
1103
+ ]);
1104
+ expect(result.singleModule).toBe("toolAnnotations");
1105
+ expect(result.helpRequested).toBeFalsy();
1106
+ });
1107
+ it("should accept valid module name with short flag", () => {
1108
+ const result = parseArgs([
1109
+ "test-server",
1110
+ "--config",
1111
+ "config.json",
1112
+ "-m",
1113
+ "security",
1114
+ ]);
1115
+ expect(result.singleModule).toBe("security");
1116
+ expect(result.helpRequested).toBeFalsy();
1117
+ });
1118
+ it("should accept all valid core module names", () => {
1119
+ const coreModules = [
1120
+ "functionality",
1121
+ "security",
1122
+ "documentation",
1123
+ "errorHandling",
1124
+ "usability",
1125
+ "mcpSpecCompliance",
1126
+ "aupCompliance",
1127
+ "toolAnnotations",
1128
+ "prohibitedLibraries",
1129
+ "externalAPIScanner",
1130
+ "authentication",
1131
+ "temporal",
1132
+ "resources",
1133
+ "prompts",
1134
+ "crossCapability",
1135
+ "protocolConformance",
1136
+ ];
1137
+ for (const moduleName of coreModules) {
1138
+ consoleErrorSpy.mockClear();
1139
+ const result = parseArgs([
1140
+ "test-server",
1141
+ "--config",
1142
+ "config.json",
1143
+ "--module",
1144
+ moduleName,
1145
+ ]);
1146
+ expect(result.singleModule).toBe(moduleName);
1147
+ expect(result.helpRequested).toBeFalsy();
1148
+ }
1149
+ });
1150
+ it("should accept optional module names", () => {
1151
+ const optionalModules = ["manifestValidation", "portability"];
1152
+ for (const moduleName of optionalModules) {
1153
+ consoleErrorSpy.mockClear();
1154
+ const result = parseArgs([
1155
+ "test-server",
1156
+ "--config",
1157
+ "config.json",
1158
+ "--module",
1159
+ moduleName,
1160
+ ]);
1161
+ expect(result.singleModule).toBe(moduleName);
1162
+ expect(result.helpRequested).toBeFalsy();
1163
+ }
1164
+ });
1165
+ });
1166
+ describe("invalid module names", () => {
1167
+ it("should reject invalid module name", () => {
1168
+ const result = parseArgs([
1169
+ "test-server",
1170
+ "--config",
1171
+ "config.json",
1172
+ "--module",
1173
+ "invalidModule",
1174
+ ]);
1175
+ expect(result.helpRequested).toBe(true);
1176
+ expect(consoleErrorSpy).toHaveBeenCalledWith(expect.stringContaining("Invalid module name"));
1177
+ });
1178
+ it("should reject missing module argument", () => {
1179
+ const result = parseArgs([
1180
+ "test-server",
1181
+ "--config",
1182
+ "config.json",
1183
+ "--module",
1184
+ ]);
1185
+ expect(result.helpRequested).toBe(true);
1186
+ expect(consoleErrorSpy).toHaveBeenCalledWith(expect.stringContaining("--module requires a module name"));
1187
+ });
1188
+ it("should reject when next argument is another flag", () => {
1189
+ const result = parseArgs([
1190
+ "test-server",
1191
+ "--config",
1192
+ "config.json",
1193
+ "--module",
1194
+ "--verbose",
1195
+ ]);
1196
+ expect(result.helpRequested).toBe(true);
1197
+ expect(consoleErrorSpy).toHaveBeenCalledWith(expect.stringContaining("--module requires a module name"));
1198
+ });
1199
+ it("should reject case-sensitive mismatch", () => {
1200
+ const result = parseArgs([
1201
+ "test-server",
1202
+ "--config",
1203
+ "config.json",
1204
+ "--module",
1205
+ "SECURITY",
1206
+ ]);
1207
+ expect(result.helpRequested).toBe(true);
1208
+ expect(consoleErrorSpy).toHaveBeenCalledWith(expect.stringContaining("Invalid module name"));
1209
+ });
1210
+ it("should reject module name with typo", () => {
1211
+ const result = parseArgs([
1212
+ "test-server",
1213
+ "--config",
1214
+ "config.json",
1215
+ "--module",
1216
+ "functionalaty",
1217
+ ]);
1218
+ expect(result.helpRequested).toBe(true);
1219
+ expect(consoleErrorSpy).toHaveBeenCalledWith(expect.stringContaining("Invalid module name"));
1220
+ });
1221
+ });
1222
+ describe("mutual exclusivity with orchestrator flags", () => {
1223
+ it("should reject --module with --profile", () => {
1224
+ const result = parseArgs([
1225
+ "test-server",
1226
+ "--config",
1227
+ "config.json",
1228
+ "--module",
1229
+ "security",
1230
+ "--profile",
1231
+ "quick",
1232
+ ]);
1233
+ expect(result.helpRequested).toBe(true);
1234
+ expect(consoleErrorSpy).toHaveBeenCalledWith(expect.stringContaining("--module cannot be used with --skip-modules, --only-modules, or --profile"));
1235
+ });
1236
+ it("should reject --module with --skip-modules", () => {
1237
+ const result = parseArgs([
1238
+ "test-server",
1239
+ "--config",
1240
+ "config.json",
1241
+ "--module",
1242
+ "security",
1243
+ "--skip-modules",
1244
+ "temporal",
1245
+ ]);
1246
+ expect(result.helpRequested).toBe(true);
1247
+ expect(consoleErrorSpy).toHaveBeenCalledWith(expect.stringContaining("--module cannot be used with"));
1248
+ });
1249
+ it("should reject --module with --only-modules", () => {
1250
+ const result = parseArgs([
1251
+ "test-server",
1252
+ "--config",
1253
+ "config.json",
1254
+ "--module",
1255
+ "security",
1256
+ "--only-modules",
1257
+ "functionality",
1258
+ ]);
1259
+ expect(result.helpRequested).toBe(true);
1260
+ expect(consoleErrorSpy).toHaveBeenCalledWith(expect.stringContaining("--module cannot be used with"));
1261
+ });
1262
+ it("should reject --profile with --module (order reversed)", () => {
1263
+ const result = parseArgs([
1264
+ "test-server",
1265
+ "--config",
1266
+ "config.json",
1267
+ "--profile",
1268
+ "quick",
1269
+ "--module",
1270
+ "security",
1271
+ ]);
1272
+ expect(result.helpRequested).toBe(true);
1273
+ expect(consoleErrorSpy).toHaveBeenCalledWith(expect.stringContaining("--module cannot be used with"));
1274
+ });
1275
+ });
1276
+ describe("combined with transport flags", () => {
1277
+ it("should work with --http", () => {
1278
+ const result = parseArgs([
1279
+ "test-server",
1280
+ "--http",
1281
+ "http://localhost:10900/mcp",
1282
+ "--module",
1283
+ "security",
1284
+ ]);
1285
+ expect(result.httpUrl).toBe("http://localhost:10900/mcp");
1286
+ expect(result.singleModule).toBe("security");
1287
+ expect(result.helpRequested).toBeFalsy();
1288
+ });
1289
+ it("should work with --sse", () => {
1290
+ const result = parseArgs([
1291
+ "test-server",
1292
+ "--sse",
1293
+ "http://localhost:9002/sse",
1294
+ "--module",
1295
+ "functionality",
1296
+ ]);
1297
+ expect(result.sseUrl).toBe("http://localhost:9002/sse");
1298
+ expect(result.singleModule).toBe("functionality");
1299
+ expect(result.helpRequested).toBeFalsy();
1300
+ });
1301
+ it("should work with --config", () => {
1302
+ const result = parseArgs([
1303
+ "test-server",
1304
+ "--config",
1305
+ "config.json",
1306
+ "--module",
1307
+ "temporal",
1308
+ ]);
1309
+ expect(result.serverConfigPath).toBe("config.json");
1310
+ expect(result.singleModule).toBe("temporal");
1311
+ expect(result.helpRequested).toBeFalsy();
1312
+ });
1313
+ });
1314
+ describe("combined with other compatible flags", () => {
1315
+ it("should work with --output", () => {
1316
+ const result = parseArgs([
1317
+ "test-server",
1318
+ "--config",
1319
+ "config.json",
1320
+ "--module",
1321
+ "security",
1322
+ "--output",
1323
+ "/tmp/results.json",
1324
+ ]);
1325
+ expect(result.singleModule).toBe("security");
1326
+ expect(result.outputPath).toBe("/tmp/results.json");
1327
+ expect(result.helpRequested).toBeFalsy();
1328
+ });
1329
+ it("should work with --verbose", () => {
1330
+ const result = parseArgs([
1331
+ "test-server",
1332
+ "--config",
1333
+ "config.json",
1334
+ "--module",
1335
+ "toolAnnotations",
1336
+ "--verbose",
1337
+ ]);
1338
+ expect(result.singleModule).toBe("toolAnnotations");
1339
+ expect(result.verbose).toBe(true);
1340
+ expect(result.helpRequested).toBeFalsy();
1341
+ });
1342
+ it("should work with --log-level", () => {
1343
+ const result = parseArgs([
1344
+ "test-server",
1345
+ "--config",
1346
+ "config.json",
1347
+ "--module",
1348
+ "errorHandling",
1349
+ "--log-level",
1350
+ "debug",
1351
+ ]);
1352
+ expect(result.singleModule).toBe("errorHandling");
1353
+ expect(result.logLevel).toBe("debug");
1354
+ expect(result.helpRequested).toBeFalsy();
1355
+ });
1356
+ it("should work with --temporal-invocations", () => {
1357
+ const result = parseArgs([
1358
+ "test-server",
1359
+ "--config",
1360
+ "config.json",
1361
+ "--module",
1362
+ "temporal",
1363
+ "--temporal-invocations",
1364
+ "10",
1365
+ ]);
1366
+ expect(result.singleModule).toBe("temporal");
1367
+ expect(result.temporalInvocations).toBe(10);
1368
+ expect(result.helpRequested).toBeFalsy();
1369
+ });
1370
+ it("should work with --conformance", () => {
1371
+ const result = parseArgs([
1372
+ "test-server",
1373
+ "--http",
1374
+ "http://localhost:10900/mcp",
1375
+ "--module",
1376
+ "protocolConformance",
1377
+ "--conformance",
1378
+ ]);
1379
+ expect(result.singleModule).toBe("protocolConformance");
1380
+ expect(result.conformanceEnabled).toBe(true);
1381
+ expect(result.helpRequested).toBeFalsy();
1382
+ });
1383
+ it("should work with --format", () => {
1384
+ const result = parseArgs([
1385
+ "test-server",
1386
+ "--config",
1387
+ "config.json",
1388
+ "--module",
1389
+ "security",
1390
+ "--format",
1391
+ "markdown",
1392
+ ]);
1393
+ expect(result.singleModule).toBe("security");
1394
+ expect(result.format).toBe("markdown");
1395
+ expect(result.helpRequested).toBeFalsy();
1396
+ });
1397
+ });
1398
+ describe("short flag behavior", () => {
1399
+ it("should accept -m with all transport types", () => {
1400
+ // Test with --http
1401
+ let result = parseArgs([
1402
+ "test-server",
1403
+ "--http",
1404
+ "http://localhost:10900/mcp",
1405
+ "-m",
1406
+ "security",
1407
+ ]);
1408
+ expect(result.singleModule).toBe("security");
1409
+ expect(result.helpRequested).toBeFalsy();
1410
+ // Test with --sse
1411
+ consoleErrorSpy.mockClear();
1412
+ result = parseArgs([
1413
+ "test-server",
1414
+ "--sse",
1415
+ "http://localhost:9002/sse",
1416
+ "-m",
1417
+ "functionality",
1418
+ ]);
1419
+ expect(result.singleModule).toBe("functionality");
1420
+ expect(result.helpRequested).toBeFalsy();
1421
+ // Test with --config
1422
+ consoleErrorSpy.mockClear();
1423
+ result = parseArgs([
1424
+ "test-server",
1425
+ "--config",
1426
+ "config.json",
1427
+ "-m",
1428
+ "temporal",
1429
+ ]);
1430
+ expect(result.singleModule).toBe("temporal");
1431
+ expect(result.helpRequested).toBeFalsy();
1432
+ });
1433
+ it("should reject -m with missing argument", () => {
1434
+ const result = parseArgs([
1435
+ "test-server",
1436
+ "--config",
1437
+ "config.json",
1438
+ "-m",
1439
+ ]);
1440
+ expect(result.helpRequested).toBe(true);
1441
+ expect(consoleErrorSpy).toHaveBeenCalledWith(expect.stringContaining("--module requires a module name"));
1442
+ });
1443
+ it("should reject -m with invalid module", () => {
1444
+ const result = parseArgs([
1445
+ "test-server",
1446
+ "--config",
1447
+ "config.json",
1448
+ "-m",
1449
+ "notAModule",
1450
+ ]);
1451
+ expect(result.helpRequested).toBe(true);
1452
+ expect(consoleErrorSpy).toHaveBeenCalledWith(expect.stringContaining("Invalid module name"));
1453
+ });
1454
+ });
1455
+ });
@@ -12,8 +12,8 @@
12
12
  import { ScopedListenerConfig } from "./lib/event-config.js";
13
13
  // Import from extracted modules
14
14
  import { parseArgs } from "./lib/cli-parser.js";
15
- import { runFullAssessment } from "./lib/assessment-runner.js";
16
- import { saveResults, saveTieredResults, saveSummaryOnly, displaySummary, } from "./lib/result-output.js";
15
+ import { runFullAssessment, runSingleModule } from "./lib/assessment-runner.js";
16
+ import { saveResults, saveTieredResults, saveSummaryOnly, displaySummary, saveSingleModuleResults, displaySingleModuleSummary, } from "./lib/result-output.js";
17
17
  import { handleComparison, displayComparisonSummary, } from "./lib/comparison-handler.js";
18
18
  import { shouldAutoTier, formatTokenEstimate, } from "../../client/lib/lib/assessment/summarizer/index.js";
19
19
  // ============================================================================
@@ -35,6 +35,23 @@ async function main() {
35
35
  }
36
36
  // Apply scoped listener configuration for assessment
37
37
  listenerConfig.apply();
38
+ // Single module mode - bypass orchestrator for lightweight execution (Issue #184)
39
+ if (options.singleModule) {
40
+ const result = await runSingleModule(options.singleModule, options);
41
+ if (!options.jsonOnly) {
42
+ displaySingleModuleSummary(result);
43
+ }
44
+ const outputPath = saveSingleModuleResults(options.serverName, options.singleModule, result, options);
45
+ if (options.jsonOnly) {
46
+ console.log(outputPath);
47
+ }
48
+ else {
49
+ console.log(`\nšŸ“„ Results saved to: ${outputPath}\n`);
50
+ }
51
+ const exitCode = result.status === "FAIL" ? 1 : 0;
52
+ setTimeout(() => process.exit(exitCode), 10);
53
+ return;
54
+ }
38
55
  const results = await runFullAssessment(options);
39
56
  // Pre-flight mode handles its own output and exit
40
57
  if (options.preflightOnly) {