qfai 0.4.2 → 0.4.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (171) hide show
  1. package/README.md +14 -0
  2. package/assets/init/.qfai/README.md +1 -0
  3. package/assets/init/.qfai/contracts/README.md +17 -8
  4. package/assets/init/.qfai/contracts/api/api-0001-sample.yaml +3 -2
  5. package/assets/init/.qfai/contracts/db/db-0001-sample.sql +2 -1
  6. package/assets/init/.qfai/contracts/ui/ui-0001-sample.yaml +3 -1
  7. package/assets/init/.qfai/promptpack/modes/change.md +3 -2
  8. package/assets/init/.qfai/promptpack/modes/compatibility.md +2 -0
  9. package/assets/init/.qfai/prompts/require-to-spec.md +4 -2
  10. package/assets/init/.qfai/specs/README.md +9 -2
  11. package/assets/init/.qfai/specs/spec-0001/spec.md +2 -0
  12. package/assets/init/root/qfai.config.yaml +0 -1
  13. package/dist/cli/commands/init.d.ts +8 -0
  14. package/dist/cli/commands/init.d.ts.map +1 -0
  15. package/dist/cli/commands/init.js +30 -0
  16. package/dist/cli/commands/init.js.map +1 -0
  17. package/dist/cli/commands/report.d.ts +7 -0
  18. package/dist/cli/commands/report.d.ts.map +1 -0
  19. package/dist/cli/commands/report.js +80 -0
  20. package/dist/cli/commands/report.js.map +1 -0
  21. package/dist/cli/commands/validate.d.ts +9 -0
  22. package/dist/cli/commands/validate.d.ts.map +1 -0
  23. package/dist/cli/commands/validate.js +57 -0
  24. package/dist/cli/commands/validate.js.map +1 -0
  25. package/dist/cli/index.cjs +504 -328
  26. package/dist/cli/index.cjs.map +1 -1
  27. package/dist/cli/index.d.ts +2 -0
  28. package/dist/cli/index.d.ts.map +1 -0
  29. package/dist/cli/index.js +7 -0
  30. package/dist/cli/index.js.map +1 -0
  31. package/dist/cli/index.mjs +504 -328
  32. package/dist/cli/index.mjs.map +1 -1
  33. package/dist/cli/lib/args.d.ts +18 -0
  34. package/dist/cli/lib/args.d.ts.map +1 -0
  35. package/dist/cli/lib/args.js +98 -0
  36. package/dist/cli/lib/args.js.map +1 -0
  37. package/dist/cli/lib/assets.d.ts +2 -0
  38. package/dist/cli/lib/assets.d.ts.map +1 -0
  39. package/dist/cli/lib/assets.js +24 -0
  40. package/dist/cli/lib/assets.js.map +1 -0
  41. package/dist/cli/lib/failOn.d.ts +5 -0
  42. package/dist/cli/lib/failOn.d.ts.map +1 -0
  43. package/dist/cli/lib/failOn.js +10 -0
  44. package/dist/cli/lib/failOn.js.map +1 -0
  45. package/dist/cli/lib/fs.d.ts +11 -0
  46. package/dist/cli/lib/fs.d.ts.map +1 -0
  47. package/dist/cli/lib/fs.js +91 -0
  48. package/dist/cli/lib/fs.js.map +1 -0
  49. package/dist/cli/lib/logger.d.ts +4 -0
  50. package/dist/cli/lib/logger.d.ts.map +1 -0
  51. package/dist/cli/lib/logger.js +10 -0
  52. package/dist/cli/lib/logger.js.map +1 -0
  53. package/dist/cli/main.d.ts +2 -0
  54. package/dist/cli/main.d.ts.map +1 -0
  55. package/dist/cli/main.js +66 -0
  56. package/dist/cli/main.js.map +1 -0
  57. package/dist/core/config.d.ts +47 -0
  58. package/dist/core/config.d.ts.map +1 -0
  59. package/dist/core/config.js +224 -0
  60. package/dist/core/config.js.map +1 -0
  61. package/dist/core/contractIndex.d.ts +12 -0
  62. package/dist/core/contractIndex.d.ts.map +1 -0
  63. package/dist/core/contractIndex.js +38 -0
  64. package/dist/core/contractIndex.js.map +1 -0
  65. package/dist/core/contracts.d.ts +5 -0
  66. package/dist/core/contracts.d.ts.map +1 -0
  67. package/dist/core/contracts.js +42 -0
  68. package/dist/core/contracts.js.map +1 -0
  69. package/dist/core/contractsDecl.d.ts +3 -0
  70. package/dist/core/contractsDecl.d.ts.map +1 -0
  71. package/dist/core/contractsDecl.js +19 -0
  72. package/dist/core/contractsDecl.js.map +1 -0
  73. package/dist/core/discovery.d.ts +14 -0
  74. package/dist/core/discovery.d.ts.map +1 -0
  75. package/dist/core/discovery.js +55 -0
  76. package/dist/core/discovery.js.map +1 -0
  77. package/dist/core/fs.d.ts +11 -0
  78. package/dist/core/fs.d.ts.map +1 -0
  79. package/dist/core/fs.js +68 -0
  80. package/dist/core/fs.js.map +1 -0
  81. package/dist/core/gherkin/parse.d.ts +7 -0
  82. package/dist/core/gherkin/parse.d.ts.map +1 -0
  83. package/dist/core/gherkin/parse.js +25 -0
  84. package/dist/core/gherkin/parse.js.map +1 -0
  85. package/dist/core/ids.d.ts +6 -0
  86. package/dist/core/ids.d.ts.map +1 -0
  87. package/dist/core/ids.js +52 -0
  88. package/dist/core/ids.js.map +1 -0
  89. package/dist/core/index.d.ts +13 -0
  90. package/dist/core/index.d.ts.map +1 -0
  91. package/dist/core/index.js +13 -0
  92. package/dist/core/index.js.map +1 -0
  93. package/dist/core/parse/adr.d.ts +13 -0
  94. package/dist/core/parse/adr.d.ts.map +1 -0
  95. package/dist/core/parse/adr.js +33 -0
  96. package/dist/core/parse/adr.js.map +1 -0
  97. package/dist/core/parse/gherkin.d.ts +12 -0
  98. package/dist/core/parse/gherkin.d.ts.map +1 -0
  99. package/dist/core/parse/gherkin.js +22 -0
  100. package/dist/core/parse/gherkin.js.map +1 -0
  101. package/dist/core/parse/markdown.d.ts +14 -0
  102. package/dist/core/parse/markdown.d.ts.map +1 -0
  103. package/dist/core/parse/markdown.js +45 -0
  104. package/dist/core/parse/markdown.js.map +1 -0
  105. package/dist/core/parse/spec.d.ts +36 -0
  106. package/dist/core/parse/spec.d.ts.map +1 -0
  107. package/dist/core/parse/spec.js +123 -0
  108. package/dist/core/parse/spec.js.map +1 -0
  109. package/dist/core/report.d.ts +55 -0
  110. package/dist/core/report.d.ts.map +1 -0
  111. package/dist/core/report.js +393 -0
  112. package/dist/core/report.js.map +1 -0
  113. package/dist/core/scenarioModel.d.ts +33 -0
  114. package/dist/core/scenarioModel.d.ts.map +1 -0
  115. package/dist/core/scenarioModel.js +128 -0
  116. package/dist/core/scenarioModel.js.map +1 -0
  117. package/dist/core/specLayout.d.ts +8 -0
  118. package/dist/core/specLayout.d.ts.map +1 -0
  119. package/dist/core/specLayout.js +36 -0
  120. package/dist/core/specLayout.js.map +1 -0
  121. package/dist/core/traceability.d.ts +26 -0
  122. package/dist/core/traceability.d.ts.map +1 -0
  123. package/dist/core/traceability.js +157 -0
  124. package/dist/core/traceability.js.map +1 -0
  125. package/dist/core/types.d.ts +31 -0
  126. package/dist/core/types.d.ts.map +1 -0
  127. package/dist/core/types.js +2 -0
  128. package/dist/core/types.js.map +1 -0
  129. package/dist/core/validate.d.ts +4 -0
  130. package/dist/core/validate.d.ts.map +1 -0
  131. package/dist/core/validate.js +45 -0
  132. package/dist/core/validate.js.map +1 -0
  133. package/dist/core/validators/contracts.d.ts +5 -0
  134. package/dist/core/validators/contracts.d.ts.map +1 -0
  135. package/dist/core/validators/contracts.js +189 -0
  136. package/dist/core/validators/contracts.js.map +1 -0
  137. package/dist/core/validators/delta.d.ts +4 -0
  138. package/dist/core/validators/delta.d.ts.map +1 -0
  139. package/dist/core/validators/delta.js +68 -0
  140. package/dist/core/validators/delta.js.map +1 -0
  141. package/dist/core/validators/ids.d.ts +4 -0
  142. package/dist/core/validators/ids.d.ts.map +1 -0
  143. package/dist/core/validators/ids.js +88 -0
  144. package/dist/core/validators/ids.js.map +1 -0
  145. package/dist/core/validators/scenario.d.ts +5 -0
  146. package/dist/core/validators/scenario.d.ts.map +1 -0
  147. package/dist/core/validators/scenario.js +127 -0
  148. package/dist/core/validators/scenario.js.map +1 -0
  149. package/dist/core/validators/spec.d.ts +5 -0
  150. package/dist/core/validators/spec.d.ts.map +1 -0
  151. package/dist/core/validators/spec.js +94 -0
  152. package/dist/core/validators/spec.js.map +1 -0
  153. package/dist/core/validators/traceability.d.ts +4 -0
  154. package/dist/core/validators/traceability.d.ts.map +1 -0
  155. package/dist/core/validators/traceability.js +222 -0
  156. package/dist/core/validators/traceability.js.map +1 -0
  157. package/dist/core/version.d.ts +2 -0
  158. package/dist/core/version.d.ts.map +1 -0
  159. package/dist/core/version.js +25 -0
  160. package/dist/core/version.js.map +1 -0
  161. package/dist/index.cjs +504 -328
  162. package/dist/index.cjs.map +1 -1
  163. package/dist/index.d.cts +15 -4
  164. package/dist/index.d.ts +2 -156
  165. package/dist/index.d.ts.map +1 -0
  166. package/dist/index.js +2 -0
  167. package/dist/index.js.map +1 -0
  168. package/dist/index.mjs +504 -328
  169. package/dist/index.mjs.map +1 -1
  170. package/dist/tsconfig.tsbuildinfo +1 -0
  171. package/package.json +1 -1
package/README.md CHANGED
@@ -32,6 +32,20 @@ npx qfai report
32
32
  設定はリポジトリ直下の `qfai.config.yaml` で行います。
33
33
  命名規約は `docs/rules/naming.md` を参照してください。
34
34
 
35
+ ## Contracts
36
+
37
+ Spec では `QFAI-CONTRACT-REF:` 行で参照する契約IDを宣言します(`none` 可、宣言行は必須)。
38
+ 契約ファイルは `QFAI-CONTRACT-ID: <ID>` を **1ファイル1ID** で宣言します。
39
+ Contract ID prefix は `UI-0001` / `API-0001` / `DB-0001` です。
40
+ 宣言では大文字(`UI-0001`)、ファイル名は小文字(`ui-0001-...`)を使用します。
41
+
42
+ 契約関連の検証は `validation.traceability` で制御します。
43
+
44
+ - `validation.traceability.allowOrphanContracts`: Spec から参照されない契約の許可(default: `false`)
45
+ - `validation.traceability.unknownContractIdSeverity`: Spec が参照した契約 ID が存在しない場合の severity(default: `error`、`error` / `warning` のみ)
46
+
47
+ `npx qfai init` は `.qfai/contracts/` 配下に UI/API/DB のサンプルを生成します。
48
+
35
49
  SC→Test の参照はテストコード内の `QFAI:SC-xxxx` アノテーションで宣言します。
36
50
  SC→Test の対象ファイルは `validation.traceability.testFileGlobs` で指定します。
37
51
  除外は `validation.traceability.testFileExcludeGlobs` で指定できます。
@@ -12,6 +12,7 @@ npx qfai report
12
12
  ## トレーサビリティ(SC→Test)
13
13
 
14
14
  - `validation.traceability.testFileGlobs` に一致するテストコードで `QFAI:SC-xxxx` を参照する(コメント可)
15
+ - Spec→Contract は `spec.md` の `QFAI-CONTRACT-REF` 行で宣言する
15
16
 
16
17
  ## ディレクトリ概要
17
18
 
@@ -6,11 +6,18 @@
6
6
 
7
7
  - UI: `ui/ui-0001-<slug>.yaml` または `.yml`
8
8
  - API: `api/api-0001-<slug>.yaml` / `.yml` / `.json`(OpenAPI)
9
- - DB: `db/db-0001-<slug>.sql`(ID は `DATA-xxxx`)
9
+ - DB: `db/db-0001-<slug>.sql`(ID は `DB-xxxx`)
10
+
11
+ ## 契約ID宣言(必須)
12
+
13
+ - 1ファイル = 1ID
14
+ - ファイル内に `QFAI-CONTRACT-ID: <ID>` をコメント行で宣言する
15
+ - 例: `# QFAI-CONTRACT-ID: API-0001` / `// QFAI-CONTRACT-ID: UI-0001` / `-- QFAI-CONTRACT-ID: DB-0001`
10
16
 
11
17
  ## 最小例(UI)
12
18
 
13
19
  ```yaml
20
+ # QFAI-CONTRACT-ID: UI-0001
14
21
  id: UI-0001
15
22
  name: 受注登録画面
16
23
  refs:
@@ -20,6 +27,7 @@ refs:
20
27
  ## 最小例(API)
21
28
 
22
29
  ```yaml
30
+ # QFAI-CONTRACT-ID: API-0001
23
31
  openapi: 3.0.0
24
32
  info:
25
33
  title: Sample API
@@ -36,7 +44,7 @@ paths:
36
44
  ## 最小例(DB)
37
45
 
38
46
  ```sql
39
- -- DATA-0001
47
+ -- QFAI-CONTRACT-ID: DB-0001
40
48
  CREATE TABLE sample_table (
41
49
  id INTEGER PRIMARY KEY
42
50
  );
@@ -44,16 +52,17 @@ CREATE TABLE sample_table (
44
52
 
45
53
  ## CI でチェックされること(抜粋)
46
54
 
47
- - UI/API: パース失敗は error、ID 未定義は error
48
- - UI: `UI-xxxx` の ID が必要
49
- - API: OpenAPI 定義があること、`API-xxxx` の operationId が必要
55
+ - 契約宣言: `QFAI-CONTRACT-ID` の未記載/複数宣言/重複ID error
56
+ - 契約ID: 配置ディレクトリ(ui/api/db)と prefix(UI/API/DB)の不整合は error
57
+ - UI/API: パース失敗は error
58
+ - API: OpenAPI 定義があること(`openapi`)
50
59
  - DB: 危険 SQL(DROP/TRUNCATE 等)の警告
51
- - 共通: ID 形式(`PREFIX-0001`)、定義 ID の重複検知
60
+ - 共通: ID 形式(`PREFIX-0001`)、ID の重複検知
52
61
 
53
62
  ## 依存関係
54
63
 
55
- - Scenario → Contracts(UI/API/DATA のいずれかへ接続)
56
- - Spec → Contracts(参照は許容)
64
+ - Spec → Contracts(`QFAI-CONTRACT-REF` で宣言、`none` 可)
65
+ - Scenario → Contracts(UI/API/DB の参照は任意)
57
66
 
58
67
  ## 良い例 / 悪い例
59
68
 
@@ -1,6 +1,7 @@
1
+ # QFAI-CONTRACT-ID: API-0001
1
2
  # OpenAPI contract sample (API-0001)
3
+ # - 必須: QFAI-CONTRACT-ID (1ファイル1ID)
2
4
  # - 必須: openapi, info, paths
3
- # - 重要: operationId に API-0001 のような ID を含める(validate が参照整合に利用)
4
5
  openapi: 3.0.0
5
6
  info:
6
7
  title: QFAI Sample API
@@ -8,7 +9,7 @@ info:
8
9
  paths:
9
10
  /health:
10
11
  get:
11
- operationId: API-0001
12
+ operationId: healthCheck
12
13
  responses:
13
14
  "200":
14
15
  description: OK
@@ -1,4 +1,5 @@
1
- -- DATA-0001 (DB contract sample)
1
+ -- QFAI-CONTRACT-ID: DB-0001
2
+ -- DB-0001 (DB contract sample)
2
3
  -- 破壊的 SQL (削除/破棄系) は警告対象
3
4
  CREATE TABLE sample_table (
4
5
  id INTEGER PRIMARY KEY,
@@ -1,5 +1,7 @@
1
+ # QFAI-CONTRACT-ID: UI-0001
1
2
  # UI contract sample (UI-0001)
2
- # - 必須: id (例: UI-0001), name, refs
3
+ # - 必須: QFAI-CONTRACT-ID (1ファイル1ID)
4
+ # - 任意: id, name, refs
3
5
  id: UI-0001
4
6
  name: Order Registration
5
7
  refs:
@@ -1,4 +1,5 @@
1
1
  # Mode: Change
2
2
 
3
- - 仕様変更の根拠を delta.md に必ず記録する
4
- - 影響範囲を整理し、テストを増分で設計する
3
+ - 期待値/挙動/互換性が変わる場合は Change を選ぶ
4
+ - 仕様変更の根拠(Why)を delta.md に必ず記録する
5
+ - 影響範囲、移行・運用への影響、受入テスト更新方針を明記する
@@ -1,4 +1,6 @@
1
1
  # Mode: Compatibility
2
2
 
3
3
  - 既存仕様との整合を最優先にする
4
+ - 期待値/外部I/Fの変更は行わない(変更がある場合は Change へ)
4
5
  - 影響範囲を最小化し、回帰テストを重視する
6
+ - 分類と根拠(Why)、影響範囲、受入テスト更新方針を明記する
@@ -19,12 +19,14 @@
19
19
  ## Rules
20
20
 
21
21
  - **推測しない**。要件に書かれていないことは `TBD` と明記する。
22
- - ID は `PREFIX-0001` 形式(SPEC/BR/SC/UI/API/DATA)。
22
+ - ID は `PREFIX-0001` 形式(SPEC/BR/SC/UI/API/DB)。
23
23
  - `spec.md` の必須セクションは `qfai.config.yaml` の設定に従う。
24
24
  - BR は `## 業務ルール` にのみ定義し、`- [BR-0001][P1] ...` 形式で書く。
25
+ - `spec.md` に `QFAI-CONTRACT-REF:` を必ず記載する(不要なら `none`)。
25
26
  - `scenario.md` は Gherkin で書き、Feature に `@SPEC-xxxx` を付与する。
26
27
  - 各 Scenario は `@SC-xxxx` を **ちょうど1つ**、`@BR-xxxx` を **1つ以上**持つこと。
27
- - 契約 ID(UI/API/DATA)が必要なら、タグまたは本文に明示する。
28
+ - 契約ファイルには `QFAI-CONTRACT-ID: <ID>` を宣言する。
29
+ - 契約 ID(UI/API/DB)を Scenario で参照する場合はタグまたは本文に明示する。
28
30
  - `delta.md` の「変更区分」は **Compatibility / Change/Improvement のいずれか1つにチェック**する。
29
31
  - 判断できない場合は `Compatibility` を選び、`TBD` を理由欄に記載する。
30
32
 
@@ -15,6 +15,8 @@
15
15
  ```md
16
16
  # SPEC-0001: 注文登録の最小要件
17
17
 
18
+ QFAI-CONTRACT-REF: UI-0001, API-0001, DB-0001
19
+
18
20
  ## 背景
19
21
 
20
22
  - 例: 受注の登録ルールを明文化し、手戻りを減らすため
@@ -30,6 +32,11 @@
30
32
  - Priority は **P0/P1/P2/P3** のいずれかを必ず付与
31
33
  - BR 定義は **`## 業務ルール` セクション内のみ**(他セクションは参照扱い)
32
34
 
35
+ ### Contract 参照の書き方
36
+
37
+ - `QFAI-CONTRACT-REF:` 行で契約IDを宣言する(複数行可)
38
+ - 参照不要な場合は `QFAI-CONTRACT-REF: none`
39
+
33
40
  ## Delta(delta.md)
34
41
 
35
42
  - 互換維持 / 仕様変更の **どちらか1つ**に必ずチェックする
@@ -44,8 +51,8 @@
44
51
 
45
52
  ## CI でチェックされること(抜粋)
46
53
 
47
- - Spec: 必須セクション、SPEC/BR ID、BR Priority、ID 形式、Contract 参照の実在性
54
+ - Spec: 必須セクション、SPEC/BR ID、BR Priority、ID 形式、Contract 参照の実在性、Contract 参照の必須宣言
48
55
  - Delta: 変更区分(互換/変更)のチェック状態
49
56
  - Scenario: Feature/Scenario の存在、タグ要件、Given/When/Then
50
- - Traceability: BR→SC、SC→契約(UI/API/DATA)、SC→Test の接続、BR の所属 SPEC 整合
57
+ - Traceability: BR→SC、Spec→Contract、SC→Test の接続、BR の所属 SPEC 整合
51
58
  - IDs: 定義 ID の重複検知(Spec/Scenario/Contracts)
@@ -1,5 +1,7 @@
1
1
  # SPEC-0001: 注文登録の最小仕様(サンプル)
2
2
 
3
+ QFAI-CONTRACT-REF: API-0001, UI-0001, DB-0001
4
+
3
5
  > このテンプレは **最小例** です。実際の仕様に合わせて書き換えてください。
4
6
 
5
7
  ## 背景
@@ -19,7 +19,6 @@ validation:
19
19
  - 業務ルール
20
20
  traceability:
21
21
  brMustHaveSc: true
22
- scMustTouchContracts: true
23
22
  scMustHaveTest: true
24
23
  testFileGlobs:
25
24
  - tests/**/*.test.ts
@@ -0,0 +1,8 @@
1
+ export type InitOptions = {
2
+ dir: string;
3
+ force: boolean;
4
+ dryRun: boolean;
5
+ yes: boolean;
6
+ };
7
+ export declare function runInit(options: InitOptions): Promise<void>;
8
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,WAAW,GAAG;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;IAChB,GAAG,EAAE,OAAO,CAAC;CACd,CAAC;AAEF,wBAAsB,OAAO,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAuBjE"}
@@ -0,0 +1,30 @@
1
+ import path from "node:path";
2
+ import { copyTemplateTree } from "../lib/fs.js";
3
+ import { getInitAssetsDir } from "../lib/assets.js";
4
+ import { info } from "../lib/logger.js";
5
+ export async function runInit(options) {
6
+ const assetsRoot = getInitAssetsDir();
7
+ const rootAssets = path.join(assetsRoot, "root");
8
+ const qfaiAssets = path.join(assetsRoot, ".qfai");
9
+ const destRoot = path.resolve(options.dir);
10
+ const destQfai = path.join(destRoot, ".qfai");
11
+ const rootResult = await copyTemplateTree(rootAssets, destRoot, {
12
+ force: options.force,
13
+ dryRun: options.dryRun,
14
+ });
15
+ const qfaiResult = await copyTemplateTree(qfaiAssets, destQfai, {
16
+ force: options.force,
17
+ dryRun: options.dryRun,
18
+ });
19
+ report([...rootResult.copied, ...qfaiResult.copied], [...rootResult.skipped, ...qfaiResult.skipped], options.dryRun, "init");
20
+ }
21
+ function report(copied, skipped, dryRun, label) {
22
+ info(`qfai ${label}: ${dryRun ? "dry-run" : "done"}`);
23
+ if (copied.length > 0) {
24
+ info(` created: ${copied.length}`);
25
+ }
26
+ if (skipped.length > 0) {
27
+ info(` skipped: ${skipped.length}`);
28
+ }
29
+ }
30
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AASxC,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,OAAoB;IAChD,MAAM,UAAU,GAAG,gBAAgB,EAAE,CAAC;IACtC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IACjD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IAElD,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC3C,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAE9C,MAAM,UAAU,GAAG,MAAM,gBAAgB,CAAC,UAAU,EAAE,QAAQ,EAAE;QAC9D,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,MAAM,EAAE,OAAO,CAAC,MAAM;KACvB,CAAC,CAAC;IACH,MAAM,UAAU,GAAG,MAAM,gBAAgB,CAAC,UAAU,EAAE,QAAQ,EAAE;QAC9D,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,MAAM,EAAE,OAAO,CAAC,MAAM;KACvB,CAAC,CAAC;IAEH,MAAM,CACJ,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,GAAG,UAAU,CAAC,MAAM,CAAC,EAC5C,CAAC,GAAG,UAAU,CAAC,OAAO,EAAE,GAAG,UAAU,CAAC,OAAO,CAAC,EAC9C,OAAO,CAAC,MAAM,EACd,MAAM,CACP,CAAC;AACJ,CAAC;AAED,SAAS,MAAM,CACb,MAAgB,EAChB,OAAiB,EACjB,MAAe,EACf,KAAa;IAEb,IAAI,CAAC,QAAQ,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;IACtD,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,IAAI,CAAC,cAAc,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;IACtC,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,IAAI,CAAC,cAAc,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACvC,CAAC;AACH,CAAC"}
@@ -0,0 +1,7 @@
1
+ export type ReportOptions = {
2
+ root: string;
3
+ format: "md" | "json";
4
+ outPath?: string;
5
+ };
6
+ export declare function runReport(options: ReportOptions): Promise<void>;
7
+ //# sourceMappingURL=report.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/report.ts"],"names":[],"mappings":"AAYA,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,IAAI,GAAG,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,wBAAsB,SAAS,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAgDrE"}
@@ -0,0 +1,80 @@
1
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { loadConfig, resolvePath } from "../../core/config.js";
4
+ import { createReportData, formatReportJson, formatReportMarkdown, } from "../../core/report.js";
5
+ import { error, info } from "../lib/logger.js";
6
+ export async function runReport(options) {
7
+ const root = path.resolve(options.root);
8
+ const configResult = await loadConfig(root);
9
+ const input = configResult.config.output.validateJsonPath;
10
+ const inputPath = path.isAbsolute(input) ? input : path.resolve(root, input);
11
+ let validation;
12
+ try {
13
+ validation = await readValidationResult(inputPath);
14
+ }
15
+ catch (err) {
16
+ if (isMissingFileError(err)) {
17
+ error([
18
+ `qfai report: 入力ファイルが見つかりません: ${inputPath}`,
19
+ "",
20
+ "まず qfai validate を実行してください。例:",
21
+ " qfai validate",
22
+ "(デフォルトの出力先: .qfai/out/validate.json)",
23
+ "",
24
+ "GitHub Actions テンプレを使っている場合は、workflow の validate ジョブを先に実行してください。",
25
+ ].join("\n"));
26
+ process.exitCode = 2;
27
+ return;
28
+ }
29
+ throw err;
30
+ }
31
+ const data = await createReportData(root, validation, configResult);
32
+ const output = options.format === "json"
33
+ ? formatReportJson(data)
34
+ : formatReportMarkdown(data);
35
+ const outRoot = resolvePath(root, configResult.config, "outDir");
36
+ const defaultOut = options.format === "json"
37
+ ? path.join(outRoot, "report.json")
38
+ : path.join(outRoot, "report.md");
39
+ const out = options.outPath ?? defaultOut;
40
+ const outPath = path.isAbsolute(out) ? out : path.resolve(root, out);
41
+ await mkdir(path.dirname(outPath), { recursive: true });
42
+ await writeFile(outPath, `${output}\n`, "utf-8");
43
+ info(`report: info=${validation.counts.info} warning=${validation.counts.warning} error=${validation.counts.error}`);
44
+ info(`wrote report: ${outPath}`);
45
+ }
46
+ async function readValidationResult(inputPath) {
47
+ const raw = await readFile(inputPath, "utf-8");
48
+ const parsed = JSON.parse(raw);
49
+ if (!isValidationResult(parsed)) {
50
+ throw new Error(`validate.json の形式が不正です: ${inputPath}`);
51
+ }
52
+ return parsed;
53
+ }
54
+ function isValidationResult(value) {
55
+ if (!value || typeof value !== "object") {
56
+ return false;
57
+ }
58
+ const record = value;
59
+ if (typeof record.toolVersion !== "string") {
60
+ return false;
61
+ }
62
+ if (!Array.isArray(record.issues)) {
63
+ return false;
64
+ }
65
+ const counts = record.counts;
66
+ if (!counts) {
67
+ return false;
68
+ }
69
+ return (typeof counts.info === "number" &&
70
+ typeof counts.warning === "number" &&
71
+ typeof counts.error === "number");
72
+ }
73
+ function isMissingFileError(error) {
74
+ if (!error || typeof error !== "object") {
75
+ return false;
76
+ }
77
+ const record = error;
78
+ return record.code === "ENOENT";
79
+ }
80
+ //# sourceMappingURL=report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.js","sourceRoot":"","sources":["../../../src/cli/commands/report.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { FailOn, OutputFormat } from "../../core/config.js";
2
+ export type ValidateOptions = {
3
+ root: string;
4
+ strict: boolean;
5
+ failOn?: FailOn;
6
+ format?: OutputFormat;
7
+ };
8
+ export declare function runValidate(options: ValidateOptions): Promise<number>;
9
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/validate.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAMjE,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,YAAY,CAAC;CACvB,CAAC;AAEF,wBAAsB,WAAW,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAgB3E"}
@@ -0,0 +1,57 @@
1
+ import { mkdir, writeFile } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { loadConfig } from "../../core/config.js";
4
+ import { validateProject } from "../../core/validate.js";
5
+ import { shouldFail } from "../lib/failOn.js";
6
+ export async function runValidate(options) {
7
+ const root = path.resolve(options.root);
8
+ const configResult = await loadConfig(root);
9
+ const result = await validateProject(root, configResult);
10
+ const format = options.format ?? "text";
11
+ if (format === "text") {
12
+ emitText(result);
13
+ }
14
+ if (format === "github") {
15
+ result.issues.forEach(emitGitHub);
16
+ }
17
+ await emitJson(result, root, configResult.config.output.validateJsonPath);
18
+ const failOn = resolveFailOn(options, configResult.config.validation.failOn);
19
+ return shouldFail(result, failOn) ? 1 : 0;
20
+ }
21
+ function resolveFailOn(options, fallback) {
22
+ if (options.failOn) {
23
+ return options.failOn;
24
+ }
25
+ if (options.strict) {
26
+ return "warning";
27
+ }
28
+ return fallback;
29
+ }
30
+ function emitText(result) {
31
+ for (const item of result.issues) {
32
+ const location = item.file ? ` (${item.file})` : "";
33
+ const refs = item.refs && item.refs.length > 0 ? ` refs=${item.refs.join(",")}` : "";
34
+ process.stdout.write(`[${item.severity}] ${item.code} ${item.message}${location}${refs}\n`);
35
+ }
36
+ process.stdout.write(`counts: info=${result.counts.info} warning=${result.counts.warning} error=${result.counts.error}\n`);
37
+ }
38
+ function emitGitHub(issue) {
39
+ const level = issue.severity === "error"
40
+ ? "error"
41
+ : issue.severity === "warning"
42
+ ? "warning"
43
+ : "notice";
44
+ const file = issue.file ? `file=${issue.file}` : "";
45
+ const line = issue.loc?.line ? `,line=${issue.loc.line}` : "";
46
+ const column = issue.loc?.column ? `,col=${issue.loc.column}` : "";
47
+ const location = file ? ` ${file}${line}${column}` : "";
48
+ process.stdout.write(`::${level}${location}::${issue.code}: ${issue.message}\n`);
49
+ }
50
+ async function emitJson(result, root, jsonPath) {
51
+ const abs = path.isAbsolute(jsonPath)
52
+ ? jsonPath
53
+ : path.resolve(root, jsonPath);
54
+ await mkdir(path.dirname(abs), { recursive: true });
55
+ await writeFile(abs, `${JSON.stringify(result, null, 2)}\n`, "utf-8");
56
+ }
57
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../../src/cli/commands/validate.ts"],"names":[],"mappings":"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"}