qfai 0.9.2 → 1.0.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.
package/README.md CHANGED
@@ -39,7 +39,7 @@ pnpm の場合(推奨):
39
39
  pnpm add -D qfai
40
40
  ```
41
41
 
42
- **必要環境**: Node.js >= 18
42
+ **必要環境**: Node.js >= 18.0.0(Supported) / Tested: Node.js 18, 20 / Recommended: Node.js 20 LTS 以上
43
43
 
44
44
  ## パッケージ
45
45
 
@@ -62,12 +62,12 @@ npx qfai report
62
62
  - `npx qfai doctor` による設定/探索/パス/glob/validate.json の事前診断
63
63
  - `npx qfai report` によるレポート出力
64
64
 
65
- 補足: v0.x は日本語テンプレ中心で提供します。将来は英語を正本、日本語を別ドキュメントに切り替える方針です。
65
+ 補足: v1.x は日本語テンプレ中心で提供します。将来は英語を正本、日本語を別ドキュメントに切り替える方針です。
66
66
 
67
67
  ## 使い方(CLI)
68
68
 
69
69
  `validate` は `--fail-on` / `--strict` によって CI ゲート化できます。`validate` は常に `.qfai/out/validate.json`(`output.validateJsonPath`)へ JSON を出力します。`--format` は画面表示(text/github)のみを制御します。`--format github` はアノテーションの上限と重複排除を行い、先頭にサマリを出します(全量は `validate.json` か `--format text` を参照)。
70
- `report` は `.qfai/out/validate.json` を既定入力とし、`--in` で上書きできます(優先順位: CLI > config)。`--run-validate` を指定すると validate を実行してから report を生成します。出力先は `--out` で変更できます(`--format json` の場合は `.qfai/out/report.json`)。
70
+ `report` は `.qfai/out/validate.json` を既定入力とし、`--in` で上書きできます(優先順位: CLI > config)。`--run-validate` を指定すると validate を実行してから report を生成します。出力先は `--out` で変更できます(`--format json` の場合は `.qfai/out/report.json`)。`--base-url <url>` を指定すると、report.md 内の相対パスをリンク化します(例: `npx qfai report --base-url https://example.com/repo`)。
71
71
  `doctor` は validate/report の前段で設定/探索/パス/glob/validate.json を診断します。`--format text|json`、`--out` をサポートし、診断のみ(修復はしません)。`--fail-on warning|error` を指定すると該当 severity 以上で exit 1(未指定は常に exit 0)になります。
72
72
 
73
73
  ### Prompts Overlay(v0.7 以降の方針)
@@ -78,7 +78,8 @@ QFAI が提供するプロンプト資産は次の 2 つに分離します。
78
78
  - `.qfai/prompts.local/**`: 利用者カスタム資産(QFAI はここを上書きしない)
79
79
 
80
80
  同じ相対パスのファイルがある場合は `.qfai/prompts.local` を優先して参照する運用とします。
81
- `report.json` は非契約(experimental / internal)として扱います。外部 consumer は依存しないでください。フィールドは例であり固定ではありません。短い例:
81
+
82
+ `report.json` / `doctor.json` は内部表現で互換非保証です。外部連携は `report.md` など Markdown 出力を推奨します。破壊的変更は SemVer で管理しますが、JSON schema を固定する約束はしません。短い例:
82
83
 
83
84
  ```json
84
85
  {
@@ -100,7 +101,7 @@ qfai doctor: root=. config=qfai.config.yaml (found)
100
101
  summary: ok=10 info=1 warning=2 error=0
101
102
  ```
102
103
 
103
- doctor の JSON も非契約(内部形式。将来予告なく変更あり)です。フィールドは例であり固定ではありません。短い例:
104
+ doctor の JSON 例:
104
105
 
105
106
  ```json
106
107
  {
@@ -123,7 +124,7 @@ doctor の JSON も非契約(内部形式。将来予告なく変更あり)
123
124
 
124
125
  ## analyze(意味矛盾のレビュー補助)
125
126
 
126
- `validate` は deterministic な構造矛盾(参照/フォーマット/トレーサビリティ)を検査し、CI Hard Gate にできます。一方で、**意味矛盾(解釈/前提/用語/例外/受入条件の齟齬)**は deterministic に検出できないため、v0.9 では **手動プロンプト**として導線を提供します。
127
+ `validate` は deterministic な構造矛盾(参照/フォーマット/トレーサビリティ)を検査し、CI Hard Gate にできます。一方で、**意味矛盾(解釈/前提/用語/例外/受入条件の齟齬)**は deterministic に検出できないため、v1.0 では **手動プロンプト**として導線を提供します。
127
128
 
128
129
  重要:
129
130
 
@@ -301,4 +302,4 @@ pnpm test:assets
301
302
 
302
303
  ## ライセンス
303
304
 
304
- [MIT](https://github.com/aganesy/QFAI/blob/main/packages/qfai/LICENSE)
305
+ [MIT](./LICENSE)
@@ -39,6 +39,7 @@ var DEFAULT_IGNORE_DIRS = /* @__PURE__ */ new Set([
39
39
  "tmp",
40
40
  ".mcp-tools"
41
41
  ]);
42
+ var DEFAULT_GLOB_FILE_LIMIT = 2e4;
42
43
  async function collectFiles(root, options = {}) {
43
44
  const entries = [];
44
45
  if (!await exists(root)) {
@@ -53,16 +54,29 @@ async function collectFiles(root, options = {}) {
53
54
  return entries;
54
55
  }
55
56
  async function collectFilesByGlobs(root, options) {
57
+ const limit = normalizeLimit(options.limit);
56
58
  if (options.globs.length === 0) {
57
- return [];
59
+ return { files: [], truncated: false, matchedFileCount: 0, limit };
58
60
  }
59
- return (0, import_fast_glob.default)(options.globs, {
61
+ const stream = import_fast_glob.default.stream(options.globs, {
60
62
  cwd: root,
61
63
  ignore: options.ignore ?? [],
62
64
  onlyFiles: true,
63
65
  absolute: true,
64
66
  unique: true
65
67
  });
68
+ const files = [];
69
+ let truncated = false;
70
+ for await (const entry of stream) {
71
+ if (files.length >= limit) {
72
+ truncated = true;
73
+ destroyStream(stream);
74
+ break;
75
+ }
76
+ files.push(String(entry));
77
+ }
78
+ const matchedFileCount = files.length;
79
+ return { files, truncated, matchedFileCount, limit };
66
80
  }
67
81
  async function walk(base, current, ignoreDirs, extensions, out) {
68
82
  const items = await (0, import_promises.readdir)(current, { withFileTypes: true });
@@ -94,6 +108,25 @@ async function exists(target) {
94
108
  return false;
95
109
  }
96
110
  }
111
+ function normalizeLimit(value) {
112
+ if (typeof value !== "number" || Number.isNaN(value)) {
113
+ return DEFAULT_GLOB_FILE_LIMIT;
114
+ }
115
+ const flooredValue = Math.floor(value);
116
+ if (flooredValue <= 0) {
117
+ return DEFAULT_GLOB_FILE_LIMIT;
118
+ }
119
+ return flooredValue;
120
+ }
121
+ function destroyStream(stream) {
122
+ if (!stream || typeof stream !== "object") {
123
+ return;
124
+ }
125
+ const record2 = stream;
126
+ if (typeof record2.destroy === "function") {
127
+ record2.destroy();
128
+ }
129
+ }
97
130
 
98
131
  // src/cli/commands/analyze.ts
99
132
  async function runAnalyze(options) {
@@ -909,15 +942,18 @@ async function collectScTestReferences(root, globs, excludeGlobs) {
909
942
  scan: {
910
943
  globs: normalizedGlobs,
911
944
  excludeGlobs: mergedExcludeGlobs,
912
- matchedFileCount: 0
945
+ matchedFileCount: 0,
946
+ truncated: false,
947
+ limit: DEFAULT_GLOB_FILE_LIMIT
913
948
  }
914
949
  };
915
950
  }
916
- let files = [];
951
+ let scanResult;
917
952
  try {
918
- files = await collectFilesByGlobs(root, {
953
+ scanResult = await collectFilesByGlobs(root, {
919
954
  globs: normalizedGlobs,
920
- ignore: mergedExcludeGlobs
955
+ ignore: mergedExcludeGlobs,
956
+ limit: DEFAULT_GLOB_FILE_LIMIT
921
957
  });
922
958
  } catch (error2) {
923
959
  return {
@@ -925,13 +961,15 @@ async function collectScTestReferences(root, globs, excludeGlobs) {
925
961
  scan: {
926
962
  globs: normalizedGlobs,
927
963
  excludeGlobs: mergedExcludeGlobs,
928
- matchedFileCount: 0
964
+ matchedFileCount: 0,
965
+ truncated: false,
966
+ limit: DEFAULT_GLOB_FILE_LIMIT
929
967
  },
930
968
  error: formatError3(error2)
931
969
  };
932
970
  }
933
971
  const normalizedFiles = Array.from(
934
- new Set(files.map((file) => import_node_path6.default.normalize(file)))
972
+ new Set(scanResult.files.map((file) => import_node_path6.default.normalize(file)))
935
973
  );
936
974
  for (const file of normalizedFiles) {
937
975
  const text = await (0, import_promises6.readFile)(file, "utf-8");
@@ -950,7 +988,9 @@ async function collectScTestReferences(root, globs, excludeGlobs) {
950
988
  scan: {
951
989
  globs: normalizedGlobs,
952
990
  excludeGlobs: mergedExcludeGlobs,
953
- matchedFileCount: normalizedFiles.length
991
+ matchedFileCount: scanResult.matchedFileCount,
992
+ truncated: scanResult.truncated,
993
+ limit: scanResult.limit
954
994
  }
955
995
  };
956
996
  }
@@ -1120,8 +1160,8 @@ var import_promises8 = require("fs/promises");
1120
1160
  var import_node_path9 = __toESM(require("path"), 1);
1121
1161
  var import_node_url2 = require("url");
1122
1162
  async function resolveToolVersion() {
1123
- if ("0.9.2".length > 0) {
1124
- return "0.9.2";
1163
+ if ("1.0.1".length > 0) {
1164
+ return "1.0.1";
1125
1165
  }
1126
1166
  try {
1127
1167
  const packagePath = resolvePackageJsonPath();
@@ -1332,19 +1372,27 @@ async function createDoctorData(options) {
1332
1372
  ...config.validation.traceability.testFileExcludeGlobs
1333
1373
  ]);
1334
1374
  try {
1335
- const matched = globs.length === 0 ? [] : await collectFilesByGlobs(root, { globs, ignore: exclude });
1336
- const matchedCount = matched.length;
1337
- const severity = globs.length === 0 ? "warning" : scenarioFiles.length > 0 && config.validation.traceability.scMustHaveTest && matchedCount === 0 ? "warning" : "ok";
1375
+ const scanResult = globs.length === 0 ? {
1376
+ files: [],
1377
+ truncated: false,
1378
+ matchedFileCount: 0,
1379
+ limit: DEFAULT_GLOB_FILE_LIMIT
1380
+ } : await collectFilesByGlobs(root, { globs, ignore: exclude });
1381
+ const matchedCount = scanResult.matchedFileCount;
1382
+ const truncated = scanResult.truncated;
1383
+ const severity = globs.length === 0 ? "warning" : truncated ? "warning" : scenarioFiles.length > 0 && config.validation.traceability.scMustHaveTest && matchedCount === 0 ? "warning" : "ok";
1338
1384
  addCheck(checks, {
1339
1385
  id: "traceability.testGlobs",
1340
1386
  severity,
1341
1387
  title: "Test file globs",
1342
- message: globs.length === 0 ? "testFileGlobs is empty (SC\u2192Test cannot be verified)" : `matchedFileCount=${matchedCount}`,
1388
+ message: globs.length === 0 ? "testFileGlobs is empty (SC\u2192Test cannot be verified)" : truncated ? `fileCount=${matchedCount} (truncated, limit=${scanResult.limit})` : `fileCount=${matchedCount}`,
1343
1389
  details: {
1344
1390
  globs,
1345
1391
  excludeGlobs: exclude,
1346
1392
  scenarioFiles: scenarioFiles.length,
1347
- scMustHaveTest: config.validation.traceability.scMustHaveTest
1393
+ scMustHaveTest: config.validation.traceability.scMustHaveTest,
1394
+ truncated,
1395
+ limit: scanResult.limit
1348
1396
  }
1349
1397
  });
1350
1398
  } catch (error2) {
@@ -1353,7 +1401,12 @@ async function createDoctorData(options) {
1353
1401
  severity: "error",
1354
1402
  title: "Test file globs",
1355
1403
  message: "Glob scan failed (invalid pattern or filesystem error)",
1356
- details: { globs, excludeGlobs: exclude, error: String(error2) }
1404
+ details: {
1405
+ globs,
1406
+ excludeGlobs: exclude,
1407
+ limit: DEFAULT_GLOB_FILE_LIMIT,
1408
+ error: String(error2)
1409
+ }
1357
1410
  });
1358
1411
  }
1359
1412
  return {
@@ -1387,8 +1440,10 @@ async function buildOutDirCollisionCheck(root) {
1387
1440
  (collisionRoot) => toRelativePath(result.monorepoRoot, collisionRoot)
1388
1441
  ).sort((a, b) => a.localeCompare(b))
1389
1442
  })).sort((a, b) => a.outDir.localeCompare(b.outDir));
1390
- const severity = collisions.length > 0 ? "warning" : "ok";
1391
- const message = collisions.length > 0 ? `outDir collision detected (count=${collisions.length})` : `outDir collision not detected (configs=${configRoots.length})`;
1443
+ const truncated = result.scan.truncated;
1444
+ const severity = collisions.length > 0 || truncated ? "warning" : "ok";
1445
+ const messageBase = collisions.length > 0 ? `outDir collision detected (count=${collisions.length})` : `outDir collision not detected (configs=${configRoots.length})`;
1446
+ const message = truncated ? `${messageBase}; scan truncated (collected=${result.scan.matchedFileCount}, limit=${result.scan.limit})` : messageBase;
1392
1447
  return {
1393
1448
  id: "output.outDirCollision",
1394
1449
  severity,
@@ -1397,7 +1452,8 @@ async function buildOutDirCollisionCheck(root) {
1397
1452
  details: {
1398
1453
  monorepoRoot: relativeRoot,
1399
1454
  configRoots,
1400
- collisions
1455
+ collisions,
1456
+ scan: result.scan
1401
1457
  }
1402
1458
  };
1403
1459
  } catch (error2) {
@@ -1412,10 +1468,11 @@ async function buildOutDirCollisionCheck(root) {
1412
1468
  }
1413
1469
  async function detectOutDirCollisions(root) {
1414
1470
  const monorepoRoot = await findMonorepoRoot(root);
1415
- const configPaths = await collectFilesByGlobs(monorepoRoot, {
1471
+ const configScan = await collectFilesByGlobs(monorepoRoot, {
1416
1472
  globs: ["**/qfai.config.yaml"],
1417
1473
  ignore: DEFAULT_CONFIG_SEARCH_IGNORE_GLOBS
1418
1474
  });
1475
+ const configPaths = configScan.files;
1419
1476
  const configRoots = Array.from(
1420
1477
  new Set(configPaths.map((configPath) => import_node_path10.default.dirname(configPath)))
1421
1478
  ).sort((a, b) => a.localeCompare(b));
@@ -1436,7 +1493,16 @@ async function detectOutDirCollisions(root) {
1436
1493
  });
1437
1494
  }
1438
1495
  }
1439
- return { monorepoRoot, configRoots, collisions };
1496
+ return {
1497
+ monorepoRoot,
1498
+ configRoots,
1499
+ collisions,
1500
+ scan: {
1501
+ truncated: configScan.truncated,
1502
+ matchedFileCount: configScan.matchedFileCount,
1503
+ limit: configScan.limit
1504
+ }
1505
+ };
1440
1506
  }
1441
1507
  async function findMonorepoRoot(startDir) {
1442
1508
  let current = import_node_path10.default.resolve(startDir);
@@ -3543,13 +3609,14 @@ async function createReportData(root, validation, configResult) {
3543
3609
  issues: normalizedValidation.issues
3544
3610
  };
3545
3611
  }
3546
- function formatReportMarkdown(data) {
3612
+ function formatReportMarkdown(data, options = {}) {
3547
3613
  const lines = [];
3614
+ const baseUrl = normalizeBaseUrl(options.baseUrl);
3548
3615
  lines.push("# QFAI Report");
3549
3616
  lines.push("");
3550
3617
  lines.push(`- \u751F\u6210\u65E5\u6642: ${data.generatedAt}`);
3551
- lines.push(`- \u30EB\u30FC\u30C8: ${data.root}`);
3552
- lines.push(`- \u8A2D\u5B9A: ${data.configPath}`);
3618
+ lines.push(`- \u30EB\u30FC\u30C8: ${formatPathLink(data.root, baseUrl)}`);
3619
+ lines.push(`- \u8A2D\u5B9A: ${formatPathLink(data.configPath, baseUrl)}`);
3553
3620
  lines.push(`- \u7248: ${data.version}`);
3554
3621
  lines.push("");
3555
3622
  const severityOrder = {
@@ -3688,8 +3755,7 @@ function formatReportMarkdown(data) {
3688
3755
  `#### ${item.severity.toUpperCase()} [${item.code}] ${item.message}`
3689
3756
  );
3690
3757
  if (item.file) {
3691
- const loc = item.loc?.line ? `:${item.loc.line}` : "";
3692
- out.push(`- file: ${item.file}${loc}`);
3758
+ out.push(`- file: ${formatPathWithLine(item.file, item.loc, baseUrl)}`);
3693
3759
  }
3694
3760
  if (item.rule) {
3695
3761
  out.push(`- rule: ${item.rule}`);
@@ -3815,6 +3881,11 @@ function formatReportMarkdown(data) {
3815
3881
  lines.push(
3816
3882
  `- testFileCount: ${data.traceability.testFiles.matchedFileCount}`
3817
3883
  );
3884
+ if (data.traceability.testFiles.truncated) {
3885
+ lines.push(
3886
+ `- testFileTruncated: true (limit=${data.traceability.testFiles.limit})`
3887
+ );
3888
+ }
3818
3889
  if (data.traceability.sc.missingIds.length === 0) {
3819
3890
  lines.push("- missingIds: (none)");
3820
3891
  } else {
@@ -3824,7 +3895,8 @@ function formatReportMarkdown(data) {
3824
3895
  if (files.length === 0) {
3825
3896
  return id;
3826
3897
  }
3827
- return `${id} (${files.join(", ")})`;
3898
+ const formattedFiles = files.map((file) => formatPathLink(file, baseUrl));
3899
+ return `${id} (${formattedFiles.join(", ")})`;
3828
3900
  });
3829
3901
  lines.push(`- missingIds: ${missingWithSources.join(", ")}`);
3830
3902
  }
@@ -3841,7 +3913,8 @@ function formatReportMarkdown(data) {
3841
3913
  if (refs.length === 0) {
3842
3914
  lines.push(`- ${scId}: (none)`);
3843
3915
  } else {
3844
- lines.push(`- ${scId}: ${refs.join(", ")}`);
3916
+ const formattedRefs = refs.map((ref) => formatPathLink(ref, baseUrl));
3917
+ lines.push(`- ${scId}: ${formattedRefs.join(", ")}`);
3845
3918
  }
3846
3919
  }
3847
3920
  }
@@ -3856,8 +3929,9 @@ function formatReportMarkdown(data) {
3856
3929
  } else {
3857
3930
  for (const item of specScIssues) {
3858
3931
  const location = item.file ?? "(unknown)";
3932
+ const formattedLocation = location === "(unknown)" ? location : formatPathLink(location, baseUrl);
3859
3933
  const refs = item.refs && item.refs.length > 0 ? item.refs.join(", ") : item.message;
3860
- lines.push(`- ${location}: ${refs}`);
3934
+ lines.push(`- ${formattedLocation}: ${refs}`);
3861
3935
  }
3862
3936
  }
3863
3937
  lines.push("");
@@ -3869,7 +3943,7 @@ function formatReportMarkdown(data) {
3869
3943
  } else {
3870
3944
  for (const spot of hotspots) {
3871
3945
  lines.push(
3872
- `- ${spot.file}: total ${spot.total} (error ${spot.error} / warning ${spot.warning} / info ${spot.info})`
3946
+ `- ${formatPathLink(spot.file, baseUrl)}: total ${spot.total} (error ${spot.error} / warning ${spot.warning} / info ${spot.info})`
3873
3947
  );
3874
3948
  }
3875
3949
  }
@@ -4026,6 +4100,41 @@ function formatMarkdownTable(headers, rows) {
4026
4100
  const separator = `| ${widths.map((width) => "-".repeat(width)).join(" | ")} |`;
4027
4101
  return [formatRow(headers), separator, ...rows.map(formatRow)];
4028
4102
  }
4103
+ function normalizeBaseUrl(value) {
4104
+ if (!value) {
4105
+ return void 0;
4106
+ }
4107
+ const trimmed = value.trim();
4108
+ if (!trimmed) {
4109
+ return void 0;
4110
+ }
4111
+ return trimmed.replace(/\/+$/, "");
4112
+ }
4113
+ function formatPathLink(value, baseUrl) {
4114
+ if (!baseUrl) {
4115
+ return value;
4116
+ }
4117
+ if (value === ".") {
4118
+ return `[${value}](${baseUrl})`;
4119
+ }
4120
+ const encoded = encodePathForUrl(value);
4121
+ if (!encoded) {
4122
+ return value;
4123
+ }
4124
+ return `[${value}](${baseUrl}/${encoded})`;
4125
+ }
4126
+ function formatPathWithLine(value, loc, baseUrl) {
4127
+ const link = formatPathLink(value, baseUrl);
4128
+ const line = loc?.line ? `:${loc.line}` : "";
4129
+ return `${link}${line}`;
4130
+ }
4131
+ function encodePathForUrl(value) {
4132
+ const normalized = value.replace(/\\/g, "/");
4133
+ if (normalized === ".") {
4134
+ return "";
4135
+ }
4136
+ return normalized.split("/").map((segment) => encodeURIComponent(segment)).join("/");
4137
+ }
4029
4138
  function toSortedArray2(values) {
4030
4139
  return Array.from(values).sort((a, b) => a.localeCompare(b));
4031
4140
  }
@@ -4079,6 +4188,16 @@ function buildHotspots(issues) {
4079
4188
  );
4080
4189
  }
4081
4190
 
4191
+ // src/cli/lib/warnings.ts
4192
+ function warnIfTruncated(scan, context) {
4193
+ if (!scan.truncated) {
4194
+ return;
4195
+ }
4196
+ warn(
4197
+ `[warn] ${context}: file scan truncated: collected ${scan.matchedFileCount} files (limit ${scan.limit})`
4198
+ );
4199
+ }
4200
+
4082
4201
  // src/cli/commands/report.ts
4083
4202
  async function runReport(options) {
4084
4203
  const root = import_node_path20.default.resolve(options.root);
@@ -4122,7 +4241,8 @@ async function runReport(options) {
4122
4241
  }
4123
4242
  }
4124
4243
  const data = await createReportData(root, validation, configResult);
4125
- const output = options.format === "json" ? formatReportJson(data) : formatReportMarkdown(data);
4244
+ warnIfTruncated(data.traceability.testFiles, "report");
4245
+ const output = options.format === "json" ? formatReportJson(data) : options.baseUrl ? formatReportMarkdown(data, { baseUrl: options.baseUrl }) : formatReportMarkdown(data);
4126
4246
  const outRoot = resolvePath(root, configResult.config, "outDir");
4127
4247
  const defaultOut = options.format === "json" ? import_node_path20.default.join(outRoot, "report.json") : import_node_path20.default.join(outRoot, "report.md");
4128
4248
  const out = options.outPath ?? defaultOut;
@@ -4219,6 +4339,7 @@ async function runValidate(options) {
4219
4339
  const configResult = await loadConfig(root);
4220
4340
  const result = await validateProject(root, configResult);
4221
4341
  const normalized = normalizeValidationResult(root, result);
4342
+ warnIfTruncated(normalized.traceability.testFiles, "validate");
4222
4343
  const failOn = resolveFailOn(options, configResult.config.validation.failOn);
4223
4344
  const willFail = shouldFail(normalized, failOn);
4224
4345
  const format = options.format ?? "text";
@@ -4477,6 +4598,17 @@ function parseArgs(argv, cwd) {
4477
4598
  case "--run-validate":
4478
4599
  options.reportRunValidate = true;
4479
4600
  break;
4601
+ case "--base-url": {
4602
+ const next = readOptionValue(args, i);
4603
+ if (next === null) {
4604
+ invalid = true;
4605
+ options.help = true;
4606
+ break;
4607
+ }
4608
+ options.reportBaseUrl = next;
4609
+ i += 1;
4610
+ break;
4611
+ }
4480
4612
  case "--help":
4481
4613
  case "-h":
4482
4614
  options.help = true;
@@ -4573,6 +4705,7 @@ async function run(argv, cwd) {
4573
4705
  format: options.reportFormat,
4574
4706
  ...options.reportOut !== void 0 ? { outPath: options.reportOut } : {},
4575
4707
  ...options.reportIn !== void 0 ? { inputPath: options.reportIn } : {},
4708
+ ...options.reportBaseUrl !== void 0 ? { baseUrl: options.reportBaseUrl } : {},
4576
4709
  ...options.reportRunValidate ? { runValidate: true } : {}
4577
4710
  });
4578
4711
  }
@@ -4622,6 +4755,7 @@ Options:
4622
4755
  --out <path> report/doctor: \u51FA\u529B\u5148
4623
4756
  --in <path> report: validate.json \u306E\u5165\u529B\u5148\uFF08config\u3088\u308A\u512A\u5148\uFF09
4624
4757
  --run-validate report: validate \u3092\u5B9F\u884C\u3057\u3066\u304B\u3089 report \u3092\u751F\u6210
4758
+ --base-url <url> report: \u30D1\u30B9\u3092\u30EA\u30F3\u30AF\u5316\u3059\u308B\u57FA\u6E96URL
4625
4759
  -h, --help \u30D8\u30EB\u30D7\u8868\u793A
4626
4760
  `;
4627
4761
  }