qfai 0.6.3 → 0.7.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 +13 -2
- package/assets/init/.qfai/README.md +9 -1
- package/assets/init/.qfai/prompts/README.md +10 -0
- package/assets/init/.qfai/prompts.local/README.md +25 -0
- package/dist/cli/index.cjs +35 -6
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.mjs +35 -6
- package/dist/cli/index.mjs.map +1 -1
- package/dist/index.cjs +2 -2
- package/dist/index.mjs +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -48,7 +48,7 @@ npx qfai report
|
|
|
48
48
|
|
|
49
49
|
## できること
|
|
50
50
|
|
|
51
|
-
- `npx qfai init` によるテンプレート生成(specs/contracts に加え、`.qfai/require/README.md`、`.qfai/rules/pnpm.md`、`.qfai/prompts
|
|
51
|
+
- `npx qfai init` によるテンプレート生成(specs/contracts に加え、`.qfai/require/README.md`、`.qfai/rules/pnpm.md`、`.qfai/prompts/**`、`.qfai/prompts.local/README.md`、`.qfai/promptpack/` を含む)
|
|
52
52
|
- `npx qfai validate` による `.qfai/` 内ドキュメントの整合性・トレーサビリティ検査
|
|
53
53
|
- `npx qfai validate` による SC→Test 参照の検証(`validation.traceability.testFileGlobs` に一致するテストファイルから `QFAI:SC-xxxx` を抽出)
|
|
54
54
|
- `npx qfai doctor` による設定/探索/パス/glob/validate.json の事前診断
|
|
@@ -61,6 +61,15 @@ npx qfai report
|
|
|
61
61
|
`validate` は `--fail-on` / `--strict` によって CI ゲート化できます。`validate` は常に `.qfai/out/validate.json`(`output.validateJsonPath`)へ JSON を出力します。`--format` は画面表示(text/github)のみを制御します。`--format github` はアノテーションの上限と重複排除を行い、先頭にサマリを出します(全量は `validate.json` か `--format text` を参照)。
|
|
62
62
|
`report` は `.qfai/out/validate.json` を既定入力とし、`--in` で上書きできます(優先順位: CLI > config)。`--run-validate` を指定すると validate を実行してから report を生成します。出力先は `--out` で変更できます(`--format json` の場合は `.qfai/out/report.json`)。
|
|
63
63
|
`doctor` は validate/report の前段で設定/探索/パス/glob/validate.json を診断します。`--format text|json`、`--out` をサポートし、診断のみ(修復はしません)。`--fail-on warning|error` を指定すると該当 severity 以上で exit 1(未指定は常に exit 0)になります。
|
|
64
|
+
|
|
65
|
+
### Prompts Overlay(v0.7 以降の方針)
|
|
66
|
+
|
|
67
|
+
QFAI が提供するプロンプト資産は次の 2 つに分離します。
|
|
68
|
+
|
|
69
|
+
- `.qfai/prompts/**`: QFAI 標準資産(更新や `qfai init` 再実行で上書きされ得る。利用者編集は非推奨・非サポート)
|
|
70
|
+
- `.qfai/prompts.local/**`: 利用者カスタム資産(QFAI はここを上書きしない)
|
|
71
|
+
|
|
72
|
+
同じ相対パスのファイルがある場合は `.qfai/prompts.local` を優先して参照する運用とします。
|
|
64
73
|
`report.json` は非契約(experimental / internal)として扱います。外部 consumer は依存しないでください。フィールドは例であり固定ではありません。短い例:
|
|
65
74
|
|
|
66
75
|
```json
|
|
@@ -80,7 +89,7 @@ doctor(text)の例:
|
|
|
80
89
|
```text
|
|
81
90
|
qfai doctor: root=. config=qfai.config.yaml (found)
|
|
82
91
|
[ok] config.search: qfai.config.yaml found
|
|
83
|
-
summary: ok=10 warning=2 error=0
|
|
92
|
+
summary: ok=10 info=1 warning=2 error=0
|
|
84
93
|
```
|
|
85
94
|
|
|
86
95
|
doctor の JSON も非契約(内部形式。将来予告なく変更あり)です。フィールドは例であり固定ではありません。短い例:
|
|
@@ -221,6 +230,8 @@ qfai.config.yaml
|
|
|
221
230
|
qfai-maintain-traceability.md
|
|
222
231
|
qfai-maintain-contracts.md
|
|
223
232
|
qfai-classify-change.md
|
|
233
|
+
prompts.local/
|
|
234
|
+
README.md
|
|
224
235
|
contracts/
|
|
225
236
|
README.md
|
|
226
237
|
api/
|
|
@@ -24,7 +24,8 @@ npx qfai report
|
|
|
24
24
|
- `contracts/` : UI / API / DB 契約を置く場所
|
|
25
25
|
- `require/` : 既存要件の集約(validate 対象外)
|
|
26
26
|
- `rules/` : 規約・運用ルール
|
|
27
|
-
- `prompts/` :
|
|
27
|
+
- `prompts/` : QFAI 標準のプロンプト資産(自動読取はしない。更新や再 init で上書きされ得る)
|
|
28
|
+
- `prompts.local/` : 利用者カスタムのプロンプト資産(存在する場合は overlay でこちらを優先して読む運用)
|
|
28
29
|
- `promptpack/` : PromptPack(SSOT、運用ルール/観点の正本)
|
|
29
30
|
- `out/` : `validate` / `report` の出力先(gitignore 推奨)
|
|
30
31
|
|
|
@@ -36,6 +37,7 @@ npx qfai report
|
|
|
36
37
|
- `rules/conventions.md`
|
|
37
38
|
- `rules/pnpm.md`
|
|
38
39
|
- `prompts/README.md`
|
|
40
|
+
- `prompts.local/README.md`
|
|
39
41
|
- `prompts/require-to-spec.md`
|
|
40
42
|
- `prompts/qfai-generate-test-globs.md`
|
|
41
43
|
- `prompts/qfai-maintain-traceability.md`
|
|
@@ -54,6 +56,12 @@ npx qfai report
|
|
|
54
56
|
|
|
55
57
|
`prompts/` は **人間が手動で使う資産**です。現時点では自動読取は行いません(将来のバージョンで CLI 連携を検討します)。
|
|
56
58
|
|
|
59
|
+
v0.7 以降、プロンプト資産のカスタマイズは `.qfai/prompts.local/**` に集約します(overlay 運用)。
|
|
60
|
+
|
|
61
|
+
- `.qfai/prompts/**` は QFAI 標準資産であり、更新や `qfai init` 再実行で上書きされ得ます
|
|
62
|
+
- 利用者が `.qfai/prompts/**` を直接編集することは非推奨・非サポートです
|
|
63
|
+
- 変更したい場合は同一相対パスで `.qfai/prompts.local/**` に置いて上書きしてください
|
|
64
|
+
|
|
57
65
|
例:
|
|
58
66
|
|
|
59
67
|
- Copilot: `.github/copilot-instructions.md` に要旨を転記
|
|
@@ -2,12 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
このディレクトリのプロンプトは **手動で使う資産**です。現時点では自動読取は行いません(将来のバージョンで CLI 連携を検討します)。
|
|
4
4
|
|
|
5
|
+
重要: `.qfai/prompts/**` は **QFAI 標準資産**です。QFAI のアップデートや `qfai init` の再実行により **上書きされ得ます**。
|
|
6
|
+
利用者が直接編集することは **非推奨・非サポート(ほぼ禁止)**です。変更したい場合は `.qfai/prompts.local/**` に同一相対パスで置いて overlay してください。
|
|
7
|
+
|
|
5
8
|
## 目的
|
|
6
9
|
|
|
7
10
|
- Spec から overview / Business Flow を生成するための素材
|
|
8
11
|
- トレーサビリティ/契約/変更区分の運用支援(CIで止めない領域)
|
|
9
12
|
- 将来(v0.9)の adapter/emit 実装に備えた配布物
|
|
10
13
|
|
|
14
|
+
## Overlay(prompts.local)
|
|
15
|
+
|
|
16
|
+
カスタムしたい場合は、次の優先順位で参照する運用とします。
|
|
17
|
+
|
|
18
|
+
1. `.qfai/prompts.local/<relativePath>`
|
|
19
|
+
2. `.qfai/prompts/<relativePath>`
|
|
20
|
+
|
|
11
21
|
## プロンプト一覧
|
|
12
22
|
|
|
13
23
|
- `makeOverview.md`: Spec 一覧(overview)生成
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Prompts Local(利用者カスタム / Overlay)
|
|
2
|
+
|
|
3
|
+
このディレクトリは **利用者が自由に編集・追加できるプロンプト資産**の置き場です。
|
|
4
|
+
|
|
5
|
+
QFAI v0.7 以降は、プロンプト資産のカスタマイズ手段を **overlay(prompts.local 優先)**に一本化します。
|
|
6
|
+
|
|
7
|
+
## Overlay ルール(重要)
|
|
8
|
+
|
|
9
|
+
同じ相対パスのファイルが存在する場合、次の優先順位で参照する運用とします。
|
|
10
|
+
|
|
11
|
+
1. `.qfai/prompts.local/<relativePath>`(存在すればこちらを優先)
|
|
12
|
+
2. `.qfai/prompts/<relativePath>`(無ければ base を参照)
|
|
13
|
+
|
|
14
|
+
例:
|
|
15
|
+
|
|
16
|
+
- base: `.qfai/prompts/require-to-spec.md`
|
|
17
|
+
- local override: `.qfai/prompts.local/require-to-spec.md`
|
|
18
|
+
|
|
19
|
+
→ `prompts.local` に同じ相対パスで置けば、以降は local を読む運用にできます。
|
|
20
|
+
|
|
21
|
+
## 重要な注意(サポート境界)
|
|
22
|
+
|
|
23
|
+
- `.qfai/prompts/**` は **QFAI 標準資産**です(更新や `qfai init` の再実行で上書きされ得ます)。
|
|
24
|
+
- 利用者が `.qfai/prompts/**` を直接編集することは **非推奨・非サポート(ほぼ禁止)**です。
|
|
25
|
+
- 変更したい場合は、対象ファイルを `prompts.local` にコピーして上書きしてください。
|
package/dist/cli/index.cjs
CHANGED
|
@@ -889,8 +889,8 @@ var import_promises6 = require("fs/promises");
|
|
|
889
889
|
var import_node_path6 = __toESM(require("path"), 1);
|
|
890
890
|
var import_node_url = require("url");
|
|
891
891
|
async function resolveToolVersion() {
|
|
892
|
-
if ("0.
|
|
893
|
-
return "0.
|
|
892
|
+
if ("0.7.1".length > 0) {
|
|
893
|
+
return "0.7.1";
|
|
894
894
|
}
|
|
895
895
|
try {
|
|
896
896
|
const packagePath = resolvePackageJsonPath();
|
|
@@ -921,7 +921,7 @@ function addCheck(checks, check) {
|
|
|
921
921
|
checks.push(check);
|
|
922
922
|
}
|
|
923
923
|
function summarize(checks) {
|
|
924
|
-
const summary = { ok: 0, warning: 0, error: 0 };
|
|
924
|
+
const summary = { ok: 0, info: 0, warning: 0, error: 0 };
|
|
925
925
|
for (const check of checks) {
|
|
926
926
|
summary[check.severity] += 1;
|
|
927
927
|
}
|
|
@@ -993,6 +993,20 @@ async function createDoctorData(options) {
|
|
|
993
993
|
message: ok ? `${key} exists` : `${key} is missing (did you run 'qfai init'?)`,
|
|
994
994
|
details: { path: toRelativePath(root, resolved) }
|
|
995
995
|
});
|
|
996
|
+
if (key === "promptsDir") {
|
|
997
|
+
const promptsLocalDir = import_node_path7.default.join(
|
|
998
|
+
import_node_path7.default.dirname(resolved),
|
|
999
|
+
`${import_node_path7.default.basename(resolved)}.local`
|
|
1000
|
+
);
|
|
1001
|
+
const found = await exists4(promptsLocalDir);
|
|
1002
|
+
addCheck(checks, {
|
|
1003
|
+
id: "paths.promptsLocalDir",
|
|
1004
|
+
severity: "info",
|
|
1005
|
+
title: "Prompts overlay (prompts.local)",
|
|
1006
|
+
message: found ? "prompts.local exists (overlay can be used)" : "prompts.local is optional (create it to override prompts)",
|
|
1007
|
+
details: { path: toRelativePath(root, promptsLocalDir) }
|
|
1008
|
+
});
|
|
1009
|
+
}
|
|
996
1010
|
}
|
|
997
1011
|
const specsRoot = resolvePath(root, config, "specsDir");
|
|
998
1012
|
const entries = await collectSpecEntries(specsRoot);
|
|
@@ -1191,7 +1205,7 @@ function formatDoctorText(data) {
|
|
|
1191
1205
|
lines.push(`[${check.severity}] ${check.id}: ${check.message}`);
|
|
1192
1206
|
}
|
|
1193
1207
|
lines.push(
|
|
1194
|
-
`summary: ok=${data.summary.ok} warning=${data.summary.warning} error=${data.summary.error}`
|
|
1208
|
+
`summary: ok=${data.summary.ok} info=${data.summary.info} warning=${data.summary.warning} error=${data.summary.error}`
|
|
1195
1209
|
);
|
|
1196
1210
|
return lines.join("\n");
|
|
1197
1211
|
}
|
|
@@ -1240,9 +1254,22 @@ async function copyFiles(files, sourceRoot, destRoot, options) {
|
|
|
1240
1254
|
const copied = [];
|
|
1241
1255
|
const skipped = [];
|
|
1242
1256
|
const conflicts = [];
|
|
1257
|
+
const protectPrefixes = (options.protect ?? []).map((p) => p.replace(/^[\\/]+/, "").replace(/[\\/]+$/, "")).filter((p) => p.length > 0).map((p) => p + import_node_path9.default.sep);
|
|
1258
|
+
const isProtectedRelative = (relative) => {
|
|
1259
|
+
if (protectPrefixes.length === 0) {
|
|
1260
|
+
return false;
|
|
1261
|
+
}
|
|
1262
|
+
const normalized = relative.replace(/[\\/]+/g, import_node_path9.default.sep);
|
|
1263
|
+
return protectPrefixes.some(
|
|
1264
|
+
(prefix) => normalized === prefix.slice(0, -1) || normalized.startsWith(prefix)
|
|
1265
|
+
);
|
|
1266
|
+
};
|
|
1243
1267
|
if (!options.force) {
|
|
1244
1268
|
for (const file of files) {
|
|
1245
1269
|
const relative = import_node_path9.default.relative(sourceRoot, file);
|
|
1270
|
+
if (isProtectedRelative(relative)) {
|
|
1271
|
+
continue;
|
|
1272
|
+
}
|
|
1246
1273
|
const dest = import_node_path9.default.join(destRoot, relative);
|
|
1247
1274
|
if (!await shouldWrite(dest, options.force)) {
|
|
1248
1275
|
conflicts.push(dest);
|
|
@@ -1255,7 +1282,8 @@ async function copyFiles(files, sourceRoot, destRoot, options) {
|
|
|
1255
1282
|
for (const file of files) {
|
|
1256
1283
|
const relative = import_node_path9.default.relative(sourceRoot, file);
|
|
1257
1284
|
const dest = import_node_path9.default.join(destRoot, relative);
|
|
1258
|
-
|
|
1285
|
+
const forceForThisFile = isProtectedRelative(relative) ? false : options.force;
|
|
1286
|
+
if (!await shouldWrite(dest, forceForThisFile)) {
|
|
1259
1287
|
skipped.push(dest);
|
|
1260
1288
|
continue;
|
|
1261
1289
|
}
|
|
@@ -1350,7 +1378,8 @@ async function runInit(options) {
|
|
|
1350
1378
|
});
|
|
1351
1379
|
const qfaiResult = await copyTemplateTree(qfaiAssets, destQfai, {
|
|
1352
1380
|
force: options.force,
|
|
1353
|
-
dryRun: options.dryRun
|
|
1381
|
+
dryRun: options.dryRun,
|
|
1382
|
+
protect: ["prompts.local"]
|
|
1354
1383
|
});
|
|
1355
1384
|
report(
|
|
1356
1385
|
[...rootResult.copied, ...qfaiResult.copied],
|