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 +2 -11
- package/assets/init/.qfai/README.md +2 -7
- package/assets/init/.qfai/promptpack/commands/plan.md +1 -1
- package/assets/init/.qfai/promptpack/commands/review.md +1 -2
- package/assets/init/.qfai/promptpack/constitution.md +1 -1
- package/assets/init/.qfai/prompts/README.md +1 -3
- package/assets/init/.qfai/prompts/qfai-maintain-traceability.md +3 -3
- package/assets/init/.qfai/prompts/require-to-spec.md +1 -2
- package/assets/init/.qfai/specs/README.md +2 -3
- package/assets/init/.qfai/specs/spec-0001/delta.md +0 -5
- package/assets/init/root/qfai.config.yaml +0 -1
- package/dist/cli/index.cjs +13 -55
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.mjs +13 -55
- package/dist/cli/index.mjs.map +1 -1
- package/dist/index.cjs +13 -54
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.mjs +13 -54
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/assets/init/.qfai/promptpack/modes/change.md +0 -5
- package/assets/init/.qfai/promptpack/modes/compatibility.md +0 -6
- package/assets/init/.qfai/promptpack/steering/compatibility-vs-change.md +0 -42
- package/assets/init/.qfai/prompts/qfai-classify-change.md +0 -33
- package/assets/init/.qfai/rules/conventions.md +0 -27
- package/assets/init/.qfai/rules/pnpm.md +0 -29
- package/assets/init/.qfai/samples/analyze/analysis.md +0 -38
- package/assets/init/.qfai/samples/analyze/input_bundle.md +0 -54
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/
|
|
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
|
-
|
|
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,7 +8,7 @@
|
|
|
8
8
|
## 目的
|
|
9
9
|
|
|
10
10
|
- Spec から overview / Business Flow を生成するための素材
|
|
11
|
-
-
|
|
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
|
-
-
|
|
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.
|
|
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
|
-
-
|
|
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`
|
|
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
|
-
-
|
|
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)
|
package/dist/cli/index.cjs
CHANGED
|
@@ -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 ||
|
|
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:
|
|
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.
|
|
1177
|
-
return "1.0.
|
|
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
|
-
|
|
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
|
-
|
|
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) {
|