qfai 1.0.3 → 1.0.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.
package/README.md CHANGED
@@ -56,7 +56,7 @@ npx qfai report
56
56
 
57
57
  ## できること
58
58
 
59
- - `npx qfai init` によるテンプレート生成(specs/contracts に加え、`.qfai/require/README.md`、`.qfai/rules/pnpm.md`、`.qfai/prompts/**`、`.qfai/prompts.local/README.md`、`.qfai/prompts/analyze/**`、`.qfai/samples/**`、`.qfai/promptpack/` を含む)
59
+ - `npx qfai init` によるテンプレート生成(specs/contracts に加え、`.qfai/require/README.md`、`.qfai/prompts/**`、`.qfai/prompts.local/README.md`、`.qfai/prompts/analyze/**`、`.qfai/promptpack/` を含む)
60
60
  - `npx qfai validate` による `.qfai/` 内ドキュメントの整合性・トレーサビリティ検査
61
61
  - `npx qfai validate` による SC→Test 参照の検証(`validation.traceability.testFileGlobs` に一致するテストファイルから `QFAI:SC-xxxx` を抽出)
62
62
  - `npx qfai doctor` による設定/探索/パス/glob/validate.json の事前診断
@@ -137,8 +137,7 @@ doctor の JSON 例:
137
137
  2. `npx qfai analyze --prompt spec_to_scenario` のようにプロンプトを出力し、AI に貼り付ける
138
138
  3. 推奨入力(Spec/Scenario/Test/Contract の抜粋 + validate/report 要約 + 差分)を揃えて検討する
139
139
 
140
- 入力の用意に迷う場合は、`npx qfai init` が同梱する `.qfai/samples/analyze/input_bundle.md`(完成例)をコピーして編集してください。
141
- 成果物を残す場合は `.qfai/samples/analyze/analysis.md`(テンプレ)を使う運用を推奨します。
140
+ 入力の用意に迷う場合は、PR テンプレの「検証/証跡」に validate/report の結果を貼る運用を推奨します。
142
141
 
143
142
  ### カスタマイズ(Overlay)
144
143
 
@@ -242,13 +241,9 @@ qfai.config.yaml
242
241
  spec.md
243
242
  delta.md
244
243
  scenario.feature
245
- rules/
246
- conventions.md
247
- pnpm.md
248
244
  promptpack/
249
245
  constitution.md
250
246
  steering/
251
- compatibility-vs-change.md
252
247
  traceability.md
253
248
  naming.md
254
249
  commands/
@@ -260,9 +255,6 @@ qfai.config.yaml
260
255
  qa.md
261
256
  spec.md
262
257
  test.md
263
- modes/
264
- compatibility.md
265
- change.md
266
258
  prompts/
267
259
  README.md
268
260
  makeOverview.md
@@ -271,7 +263,6 @@ qfai.config.yaml
271
263
  qfai-generate-test-globs.md
272
264
  qfai-maintain-traceability.md
273
265
  qfai-maintain-contracts.md
274
- qfai-classify-change.md
275
266
  prompts.local/
276
267
  README.md
277
268
  contracts/
@@ -24,20 +24,18 @@ npx qfai report
24
24
  - `specs/` : Spec Pack(spec.md / delta.md / scenario.feature)
25
25
  - `contracts/` : UI / API / DB 契約を置く場所
26
26
  - `require/` : 既存要件の集約(validate 対象外)
27
- - `rules/` : 規約・運用ルール
28
27
  - `prompts/` : QFAI 標準のプロンプト資産(自動読取はしない。更新や再 init で上書きされ得る)
29
- - `samples/` : analyze 等の手動運用で使う成果物テンプレ(create-only)
30
28
  - `prompts.local/` : 利用者カスタムのプロンプト資産(存在する場合は overlay でこちらを優先して読む運用)
31
29
  - `promptpack/` : PromptPack(SSOT、運用ルール/観点の正本)
32
30
  - `out/` : `validate` / `report` の出力先(gitignore 推奨)
33
31
 
34
32
  詳細は各 README を参照してください。
35
33
 
34
+ - analyze の入力束に迷う場合は、PR テンプレの「検証/証跡」に validate/report の結果を貼る運用を推奨します。
35
+
36
36
  - `specs/README.md`
37
37
  - `contracts/README.md`
38
38
  - `require/README.md`
39
- - `rules/conventions.md`
40
- - `rules/pnpm.md`
41
39
  - `prompts/README.md`
42
40
  - `prompts/analyze/README.md`
43
41
  - `prompts.local/README.md`
@@ -45,9 +43,6 @@ npx qfai report
45
43
  - `prompts/qfai-generate-test-globs.md`
46
44
  - `prompts/qfai-maintain-traceability.md`
47
45
  - `prompts/qfai-maintain-contracts.md`
48
- - `prompts/qfai-classify-change.md`
49
- - `samples/analyze/analysis.md`
50
- - `samples/analyze/input_bundle.md`
51
46
  - `prompts/analyze/spec_to_scenario.md`
52
47
  - `prompts/analyze/spec_to_contract.md`
53
48
  - `prompts/analyze/scenario_to_test.md`
@@ -8,4 +8,4 @@
8
8
  - テスト方針
9
9
  - リスクと確認点
10
10
  - testFileGlobs が未整備なら `prompts/qfai-generate-test-globs.md` を使う
11
- - Compatibility/Change が不明なら `prompts/qfai-classify-change.md` で整理する
11
+ - 受入観点が曖昧なら QA 観点で整理する
@@ -1,7 +1,6 @@
1
1
  # Review
2
2
 
3
3
  - Spec/Scenario/Contracts と実装の整合
4
- - 互換維持/変更の区分が delta.md に記録されているか
5
- - 区分が曖昧なら `prompts/qfai-classify-change.md` で再整理する
4
+ - delta.md に変更内容/受入観点が記録されているか
6
5
  - 影響範囲とテスト結果の妥当性
7
6
  - セキュリティ/運用上の懸念がないか
@@ -5,7 +5,7 @@ PromptPack はプロジェクト内の SSOT(Single Source of Truth)として
5
5
  ## 基本原則
6
6
 
7
7
  - spec/scenario/delta/BR/SC を最優先で読む
8
- - 変更は delta.md に記録し、互換維持/変更の区分を明示する
8
+ - 変更は delta.md に記録し、受入観点と影響範囲を明示する
9
9
  - validate を通すことを必須とする(通らないなら仕様/運用が破綻している)
10
10
  - 不確実性(仮説/未確定/TODO)は残し方針を統一する
11
11
 
@@ -8,7 +8,7 @@
8
8
  ## 目的
9
9
 
10
10
  - Spec から overview / Business Flow を生成するための素材
11
- - トレーサビリティ/契約/変更区分の運用支援(CIで止めない領域)
11
+ - トレーサビリティ/契約の運用支援(CIで止めない領域)
12
12
  - 意味矛盾(解釈/前提/用語/受入条件の齟齬)のレビュー補助(analyze)
13
13
  - 将来の CLI 連携に備えた配布物(現時点では手動利用のみ)
14
14
 
@@ -27,7 +27,6 @@
27
27
  - `qfai-generate-test-globs.md`: テストファイル glob の生成支援(`qfai.config.yaml` 更新)
28
28
  - `qfai-maintain-traceability.md`: 参照切れの修復(Spec/Scenario/Test)
29
29
  - `qfai-maintain-contracts.md`: 契約 ID と参照の整合
30
- - `qfai-classify-change.md`: Compatibility / Change 分類支援
31
30
  - `analyze/README.md`: analyze の目的/入力/出力フォーマット
32
31
  - `analyze/spec_to_scenario.md`: Spec ↔ Scenario の意味整合
33
32
  - `analyze/spec_to_contract.md`: Spec ↔ Contract の対応漏れ/参照不整合
@@ -39,7 +38,6 @@
39
38
  | ------------------------------- | ---------------- | --------------------------------------------- | ------------------------------ | ------------------- |
40
39
  | `qfai-maintain-traceability.md` | 参照切れの修復 | spec/delta/scenario + validate/report + tests | 修正方針 + diff + 再実行手順 | ID形式崩し/SSOT無視 |
41
40
  | `qfai-maintain-contracts.md` | 契約と参照の整合 | contracts + spec + report | 採番案 + 参照更新案 + diff | ID変更の無断実施 |
42
- | `qfai-classify-change.md` | 変更区分の判断 | delta.md + 変更差分 | 分類 + 根拠 + 影響範囲 | 根拠なし分類 |
43
41
  | `qfai-generate-test-globs.md` | テストglob生成 | package.json/設定/テスト配置 | glob案 + 更新案 + サンプル確認 | glob過剰/不足 |
44
42
  | `makeOverview.md` | Spec一覧生成 | spec.md | 一覧テーブル/サマリ | spec未読 |
45
43
  | `makeBusinessFlow.md` | 業務フロー整理 | spec.md/要件 | フロー手順/根拠 | 要件の飛ばし |
@@ -5,7 +5,7 @@
5
5
  ## 目的
6
6
 
7
7
  - Spec/Scenario/Test の ID 参照が壊れた箇所を特定し、整合させる
8
- - 互換維持/変更(Compatibility/Change)の区分を明確にする
8
+ - 修正の影響と受入観点を整理する
9
9
 
10
10
  ## 必須入力
11
11
 
@@ -18,7 +18,7 @@
18
18
 
19
19
  1. validate/report の結果から、壊れている参照(Spec/BR/SC/Contract/Test)を列挙する。
20
20
  2. Spec Pack(spec/delta/scenario)を読み、ID と参照の意図を把握する。
21
- 3. 修正が Compatibility か Change かを判断し、根拠を整理する。
21
+ 3. 修正の影響と受入観点を整理する。
22
22
  4. 参照切れを解消する最小修正案(Spec/Scenario/Test)を作る。
23
23
  5. 変更後の validate / report 手順を示す。
24
24
 
@@ -30,7 +30,7 @@
30
30
 
31
31
  ## 出力フォーマット
32
32
 
33
- - 変更区分(Compatibility / Change)と根拠
33
+ - 変更内容と受入観点
34
34
  - 修正対象一覧(ファイル/ID/理由)
35
35
  - 提案 diff(またはパッチ単位)
36
36
  - 再実行コマンド(`qfai validate` / `qfai report` / テスト)
@@ -27,8 +27,7 @@
27
27
  - 各 Scenario は `@SC-xxxx` を **ちょうど1つ**、`@BR-xxxx` を **1つ以上**持つこと。
28
28
  - 契約ファイルには `QFAI-CONTRACT-ID: <ID>` を宣言する。
29
29
  - 契約 ID(UI/API/DB)を Scenario で参照する場合はタグまたは本文に明示する。
30
- - `delta.md` の「変更区分」は **Compatibility / Change/Improvement のいずれか1つにチェック**する。
31
- - 判断できない場合は `Compatibility` を選び、`TBD` を理由欄に記載する。
30
+ - `delta.md` に変更内容/受入観点/影響範囲を記載する。
32
31
 
33
32
  ## Output Format
34
33
 
@@ -39,8 +39,7 @@ QFAI-CONTRACT-REF: UI-0001, API-0001, DB-0001, THEMA-001
39
39
 
40
40
  ## Delta(delta.md)
41
41
 
42
- - 互換維持 / 仕様変更の **どちらか1つ**に必ずチェックする
43
- - 根拠と影響範囲を明記する
42
+ - 変更の要約・根拠・影響範囲・受入観点を明記する
44
43
 
45
44
  ## Scenario(scenario.feature)最小要件
46
45
 
@@ -54,7 +53,7 @@ QFAI-CONTRACT-REF: UI-0001, API-0001, DB-0001, THEMA-001
54
53
  ## CI でチェックされること(抜粋)
55
54
 
56
55
  - Spec: 必須セクション、SPEC/BR ID、BR Priority、ID 形式、Contract 参照の実在性、Contract 参照の必須宣言
57
- - Delta: 変更区分(互換/変更)のチェック状態
56
+ - Delta: delta.md の存在
58
57
  - Scenario: Feature/Scenario の存在、タグ要件、Given/When/Then、契約参照の宣言/形式
59
58
  - Traceability: BR→SC、Spec→Contract、SC→Test の接続、BR の所属 SPEC 整合
60
59
  - IDs: 定義 ID の重複検知(Spec/Scenario/Contracts)
@@ -1,10 +1,5 @@
1
1
  # Delta: SPEC-0001
2
2
 
3
- ## 変更区分
4
-
5
- - [x] Compatibility(互換維持: 既存仕様と整合)
6
- - [ ] Change/Improvement(改善/仕様変更: 期待値の変更を含む)
7
-
8
3
  ## 変更の要約(What)
9
4
 
10
5
  - ...
@@ -1,7 +1,6 @@
1
1
  paths:
2
2
  specsDir: .qfai/specs
3
3
  contractsDir: .qfai/contracts
4
- rulesDir: .qfai/rules
5
4
  outDir: .qfai/out
6
5
  promptsDir: .qfai/prompts
7
6
  srcDir: src
@@ -245,7 +245,6 @@ var defaultConfig = {
245
245
  paths: {
246
246
  contractsDir: ".qfai/contracts",
247
247
  specsDir: ".qfai/specs",
248
- rulesDir: ".qfai/rules",
249
248
  outDir: ".qfai/out",
250
249
  promptsDir: ".qfai/prompts",
251
250
  srcDir: "src",
@@ -358,13 +357,6 @@ function normalizePaths(raw, configPath, issues) {
358
357
  configPath,
359
358
  issues
360
359
  ),
361
- rulesDir: readString(
362
- raw.rulesDir,
363
- base.rulesDir,
364
- "paths.rulesDir",
365
- configPath,
366
- issues
367
- ),
368
360
  outDir: readString(
369
361
  raw.outDir,
370
362
  base.outDir,
@@ -1074,6 +1066,7 @@ function getInitAssetsDir() {
1074
1066
  }
1075
1067
 
1076
1068
  // src/core/promptsIntegrity.ts
1069
+ var LEGACY_OK_EXTRA = /* @__PURE__ */ new Set(["qfai-classify-change.md"]);
1077
1070
  async function diffProjectPromptsAgainstInitAssets(root) {
1078
1071
  const promptsDir = import_node_path9.default.resolve(root, ".qfai", "prompts");
1079
1072
  let templateDir;
@@ -1122,6 +1115,7 @@ async function diffProjectPromptsAgainstInitAssets(root) {
1122
1115
  extra.push(rel);
1123
1116
  }
1124
1117
  }
1118
+ const filteredExtra = extra.filter((rel) => !LEGACY_OK_EXTRA.has(rel));
1125
1119
  const common = intersectKeys(templateByRel, projectByRel);
1126
1120
  for (const rel of common) {
1127
1121
  const templateAbs = templateByRel.get(rel);
@@ -1141,13 +1135,13 @@ async function diffProjectPromptsAgainstInitAssets(root) {
1141
1135
  changed.push(rel);
1142
1136
  }
1143
1137
  }
1144
- const status = missing.length > 0 || extra.length > 0 || changed.length > 0 ? "modified" : "ok";
1138
+ const status = missing.length > 0 || filteredExtra.length > 0 || changed.length > 0 ? "modified" : "ok";
1145
1139
  return {
1146
1140
  status,
1147
1141
  promptsDir,
1148
1142
  templateDir,
1149
1143
  missing: missing.sort(),
1150
- extra: extra.sort(),
1144
+ extra: filteredExtra.sort(),
1151
1145
  changed: changed.sort()
1152
1146
  };
1153
1147
  }
@@ -1173,8 +1167,8 @@ var import_promises8 = require("fs/promises");
1173
1167
  var import_node_path10 = __toESM(require("path"), 1);
1174
1168
  var import_node_url2 = require("url");
1175
1169
  async function resolveToolVersion() {
1176
- if ("1.0.3".length > 0) {
1177
- return "1.0.3";
1170
+ if ("1.0.4".length > 0) {
1171
+ return "1.0.4";
1178
1172
  }
1179
1173
  try {
1180
1174
  const packagePath = resolvePackageJsonPath();
@@ -1264,7 +1258,6 @@ async function createDoctorData(options) {
1264
1258
  "outDir",
1265
1259
  "srcDir",
1266
1260
  "testsDir",
1267
- "rulesDir",
1268
1261
  "promptsDir"
1269
1262
  ];
1270
1263
  for (const key of pathKeys) {
@@ -2836,11 +2829,6 @@ function issue(code, message, severity, file, rule, refs, category = "compatibil
2836
2829
  // src/core/validators/delta.ts
2837
2830
  var import_promises14 = require("fs/promises");
2838
2831
  var import_node_path18 = __toESM(require("path"), 1);
2839
- var SECTION_RE = /^##\s+変更区分/m;
2840
- var COMPAT_LINE_RE = /^\s*-\s*\[[ xX]\]\s*Compatibility\b/m;
2841
- var CHANGE_LINE_RE = /^\s*-\s*\[[ xX]\]\s*Change\/Improvement\b/m;
2842
- var COMPAT_CHECKED_RE = /^\s*-\s*\[[xX]\]\s*Compatibility\b/m;
2843
- var CHANGE_CHECKED_RE = /^\s*-\s*\[[xX]\]\s*Change\/Improvement\b/m;
2844
2832
  async function validateDeltas(root, config) {
2845
2833
  const specsRoot = resolvePath(root, config, "specsDir");
2846
2834
  const packs = await collectSpecPackDirs(specsRoot);
@@ -2850,9 +2838,8 @@ async function validateDeltas(root, config) {
2850
2838
  const issues = [];
2851
2839
  for (const pack of packs) {
2852
2840
  const deltaPath = import_node_path18.default.join(pack, "delta.md");
2853
- let text;
2854
2841
  try {
2855
- text = await (0, import_promises14.readFile)(deltaPath, "utf-8");
2842
+ await (0, import_promises14.readFile)(deltaPath, "utf-8");
2856
2843
  } catch (error2) {
2857
2844
  if (isMissingFileError2(error2)) {
2858
2845
  issues.push(
@@ -2861,41 +2848,16 @@ async function validateDeltas(root, config) {
2861
2848
  "delta.md \u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002",
2862
2849
  "error",
2863
2850
  deltaPath,
2864
- "delta.exists"
2851
+ "delta.exists",
2852
+ void 0,
2853
+ "change",
2854
+ "spec-xxxx/delta.md \u3092\u4F5C\u6210\u3057\u3066\u304F\u3060\u3055\u3044\uFF08\u30C6\u30F3\u30D7\u30EC\u306F init \u751F\u6210\u7269\u3092\u53C2\u7167\u3057\u3066\u304F\u3060\u3055\u3044\uFF09\u3002"
2865
2855
  )
2866
2856
  );
2867
2857
  continue;
2868
2858
  }
2869
2859
  throw error2;
2870
2860
  }
2871
- const hasSection = SECTION_RE.test(text);
2872
- const hasCompatibility = COMPAT_LINE_RE.test(text);
2873
- const hasChange = CHANGE_LINE_RE.test(text);
2874
- if (!hasSection || !hasCompatibility || !hasChange) {
2875
- issues.push(
2876
- issue2(
2877
- "QFAI-DELTA-002",
2878
- "delta.md \u306E\u5909\u66F4\u533A\u5206\u304C\u4E0D\u8DB3\u3057\u3066\u3044\u307E\u3059\u3002`## \u5909\u66F4\u533A\u5206` \u3068\u30C1\u30A7\u30C3\u30AF\u30DC\u30C3\u30AF\u30B9\uFF08Compatibility / Change/Improvement\uFF09\u3092\u8FFD\u52A0\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
2879
- "error",
2880
- deltaPath,
2881
- "delta.section"
2882
- )
2883
- );
2884
- continue;
2885
- }
2886
- const compatibilityChecked = COMPAT_CHECKED_RE.test(text);
2887
- const changeChecked = CHANGE_CHECKED_RE.test(text);
2888
- if (compatibilityChecked === changeChecked) {
2889
- issues.push(
2890
- issue2(
2891
- "QFAI-DELTA-003",
2892
- "delta.md \u306E\u5909\u66F4\u533A\u5206\u306F\u3069\u3061\u3089\u304B1\u3064\u3060\u3051\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044\uFF08\u4E21\u65B9ON/\u4E21\u65B9OFF\u306F\u7121\u52B9\u3067\u3059\uFF09\u3002",
2893
- "error",
2894
- deltaPath,
2895
- "delta.classification"
2896
- )
2897
- );
2898
- }
2899
2861
  }
2900
2862
  return issues;
2901
2863
  }
@@ -4437,12 +4399,8 @@ function formatReportMarkdown(data, options = {}) {
4437
4399
  "- issue \u306F\u691C\u51FA\u3055\u308C\u307E\u305B\u3093\u3067\u3057\u305F\u3002\u904B\u7528\u30C6\u30F3\u30D7\u30EC\u306B\u6CBF\u3063\u3066\u7D99\u7D9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002"
4438
4400
  );
4439
4401
  }
4440
- lines.push(
4441
- "- \u5909\u66F4\u533A\u5206\uFF08Compatibility / Change/Improvement\uFF09\u306F `.qfai/specs/*/delta.md` \u306B\u8A18\u9332\u3057\u307E\u3059\u3002"
4442
- );
4443
- lines.push(
4444
- "- \u53C2\u7167\u30EB\u30FC\u30EB\u306E\u6B63\u672C: `.qfai/promptpack/steering/traceability.md` / `.qfai/promptpack/steering/compatibility-vs-change.md`"
4445
- );
4402
+ lines.push("- \u5909\u66F4\u5185\u5BB9\u30FB\u53D7\u5165\u89B3\u70B9\u306F `.qfai/specs/*/delta.md` \u306B\u8A18\u9332\u3057\u307E\u3059\u3002");
4403
+ lines.push("- \u53C2\u7167\u30EB\u30FC\u30EB\u306E\u6B63\u672C: `.qfai/promptpack/steering/traceability.md`");
4446
4404
  return lines.join("\n");
4447
4405
  }
4448
4406
  function formatReportJson(data) {