qfai 0.2.5

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 (120) hide show
  1. package/README.md +28 -0
  2. package/assets/init/qfai/README.md +6 -0
  3. package/assets/init/qfai/contracts/api/api-0001-sample.yaml +14 -0
  4. package/assets/init/qfai/contracts/db/db-0001-sample.sql +5 -0
  5. package/assets/init/qfai/contracts/ui/ui-0001-sample.yaml +4 -0
  6. package/assets/init/qfai/prompts/makeBusinessFlow.md +34 -0
  7. package/assets/init/qfai/prompts/makeOverview.md +27 -0
  8. package/assets/init/qfai/spec/decisions/ADR-0001.md +7 -0
  9. package/assets/init/qfai/spec/scenarios.feature +6 -0
  10. package/assets/init/qfai/spec/spec-0001-sample.md +29 -0
  11. package/assets/init/root/.github/workflows/qfai.yml +22 -0
  12. package/assets/init/root/qfai.config.yaml +29 -0
  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 +8 -0
  18. package/dist/cli/commands/report.d.ts.map +1 -0
  19. package/dist/cli/commands/report.js +83 -0
  20. package/dist/cli/commands/report.js.map +1 -0
  21. package/dist/cli/commands/validate.d.ts +10 -0
  22. package/dist/cli/commands/validate.d.ts.map +1 -0
  23. package/dist/cli/commands/validate.js +66 -0
  24. package/dist/cli/commands/validate.js.map +1 -0
  25. package/dist/cli/index.cjs +2003 -0
  26. package/dist/cli/index.cjs.map +1 -0
  27. package/dist/cli/index.d.cts +1 -0
  28. package/dist/cli/index.d.ts +3 -0
  29. package/dist/cli/index.d.ts.map +1 -0
  30. package/dist/cli/index.js +7 -0
  31. package/dist/cli/index.js.map +1 -0
  32. package/dist/cli/index.mjs +1980 -0
  33. package/dist/cli/index.mjs.map +1 -0
  34. package/dist/cli/lib/args.d.ts +19 -0
  35. package/dist/cli/lib/args.d.ts.map +1 -0
  36. package/dist/cli/lib/args.js +107 -0
  37. package/dist/cli/lib/args.js.map +1 -0
  38. package/dist/cli/lib/assets.d.ts +2 -0
  39. package/dist/cli/lib/assets.d.ts.map +1 -0
  40. package/dist/cli/lib/assets.js +8 -0
  41. package/dist/cli/lib/assets.js.map +1 -0
  42. package/dist/cli/lib/failOn.d.ts +5 -0
  43. package/dist/cli/lib/failOn.d.ts.map +1 -0
  44. package/dist/cli/lib/failOn.js +10 -0
  45. package/dist/cli/lib/failOn.js.map +1 -0
  46. package/dist/cli/lib/fs.d.ts +11 -0
  47. package/dist/cli/lib/fs.d.ts.map +1 -0
  48. package/dist/cli/lib/fs.js +91 -0
  49. package/dist/cli/lib/fs.js.map +1 -0
  50. package/dist/cli/lib/logger.d.ts +4 -0
  51. package/dist/cli/lib/logger.d.ts.map +1 -0
  52. package/dist/cli/lib/logger.js +10 -0
  53. package/dist/cli/lib/logger.js.map +1 -0
  54. package/dist/cli/main.d.ts +2 -0
  55. package/dist/cli/main.d.ts.map +1 -0
  56. package/dist/cli/main.js +73 -0
  57. package/dist/cli/main.js.map +1 -0
  58. package/dist/core/config.d.ts +46 -0
  59. package/dist/core/config.d.ts.map +1 -0
  60. package/dist/core/config.js +224 -0
  61. package/dist/core/config.js.map +1 -0
  62. package/dist/core/discovery.d.ts +11 -0
  63. package/dist/core/discovery.d.ts.map +1 -0
  64. package/dist/core/discovery.js +31 -0
  65. package/dist/core/discovery.js.map +1 -0
  66. package/dist/core/fs.d.ts +6 -0
  67. package/dist/core/fs.d.ts.map +1 -0
  68. package/dist/core/fs.js +55 -0
  69. package/dist/core/fs.js.map +1 -0
  70. package/dist/core/ids.d.ts +5 -0
  71. package/dist/core/ids.d.ts.map +1 -0
  72. package/dist/core/ids.js +49 -0
  73. package/dist/core/ids.js.map +1 -0
  74. package/dist/core/index.d.ts +11 -0
  75. package/dist/core/index.d.ts.map +1 -0
  76. package/dist/core/index.js +11 -0
  77. package/dist/core/index.js.map +1 -0
  78. package/dist/core/report.d.ts +41 -0
  79. package/dist/core/report.d.ts.map +1 -0
  80. package/dist/core/report.js +238 -0
  81. package/dist/core/report.js.map +1 -0
  82. package/dist/core/types.d.ts +27 -0
  83. package/dist/core/types.d.ts.map +1 -0
  84. package/dist/core/types.js +2 -0
  85. package/dist/core/types.js.map +1 -0
  86. package/dist/core/validate.d.ts +4 -0
  87. package/dist/core/validate.d.ts.map +1 -0
  88. package/dist/core/validate.js +32 -0
  89. package/dist/core/validate.js.map +1 -0
  90. package/dist/core/validators/contracts.d.ts +5 -0
  91. package/dist/core/validators/contracts.d.ts.map +1 -0
  92. package/dist/core/validators/contracts.js +157 -0
  93. package/dist/core/validators/contracts.js.map +1 -0
  94. package/dist/core/validators/scenario.d.ts +5 -0
  95. package/dist/core/validators/scenario.d.ts.map +1 -0
  96. package/dist/core/validators/scenario.js +82 -0
  97. package/dist/core/validators/scenario.js.map +1 -0
  98. package/dist/core/validators/spec.d.ts +5 -0
  99. package/dist/core/validators/spec.d.ts.map +1 -0
  100. package/dist/core/validators/spec.js +69 -0
  101. package/dist/core/validators/spec.js.map +1 -0
  102. package/dist/core/validators/traceability.d.ts +4 -0
  103. package/dist/core/validators/traceability.d.ts.map +1 -0
  104. package/dist/core/validators/traceability.js +148 -0
  105. package/dist/core/validators/traceability.js.map +1 -0
  106. package/dist/core/version.d.ts +2 -0
  107. package/dist/core/version.d.ts.map +1 -0
  108. package/dist/core/version.js +25 -0
  109. package/dist/core/version.js.map +1 -0
  110. package/dist/index.cjs +1579 -0
  111. package/dist/index.cjs.map +1 -0
  112. package/dist/index.d.cts +132 -0
  113. package/dist/index.d.ts +2 -0
  114. package/dist/index.d.ts.map +1 -0
  115. package/dist/index.js +2 -0
  116. package/dist/index.js.map +1 -0
  117. package/dist/index.mjs +1523 -0
  118. package/dist/index.mjs.map +1 -0
  119. package/dist/tsconfig.tsbuildinfo +1 -0
  120. package/package.json +38 -0
@@ -0,0 +1,238 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { loadConfig, resolvePath } from "./config.js";
3
+ import { collectContractFiles, collectSpecFiles } from "./discovery.js";
4
+ import { collectFiles } from "./fs.js";
5
+ import { extractAllIds, extractIds } from "./ids.js";
6
+ import { validateProject } from "./validate.js";
7
+ import { resolveToolVersion } from "./version.js";
8
+ const ID_PREFIXES = ["SPEC", "BR", "SC", "UI", "API", "DATA"];
9
+ export async function createReportData(root, validation, configResult) {
10
+ const resolved = configResult ?? (await loadConfig(root));
11
+ const config = resolved.config;
12
+ const configPath = resolved.configPath;
13
+ const specRoot = resolvePath(root, config, "specDir");
14
+ const decisionsRoot = resolvePath(root, config, "decisionsDir");
15
+ const scenariosRoot = resolvePath(root, config, "scenariosDir");
16
+ const rulesRoot = resolvePath(root, config, "rulesDir");
17
+ const apiRoot = resolvePath(root, config, "apiContractsDir");
18
+ const uiRoot = resolvePath(root, config, "uiContractsDir");
19
+ const dbRoot = resolvePath(root, config, "dataContractsDir");
20
+ const srcRoot = resolvePath(root, config, "srcDir");
21
+ const testsRoot = resolvePath(root, config, "testsDir");
22
+ const specFiles = await collectSpecFiles(specRoot);
23
+ const scenarioFiles = await collectFiles(scenariosRoot, {
24
+ extensions: [".feature"],
25
+ });
26
+ const decisionFiles = await collectFiles(decisionsRoot, {
27
+ extensions: [".md"],
28
+ });
29
+ const ruleFiles = await collectFiles(rulesRoot, { extensions: [".md"] });
30
+ const { api: apiFiles, ui: uiFiles, db: dbFiles, } = await collectContractFiles(uiRoot, apiRoot, dbRoot);
31
+ const idsByPrefix = await collectIds([
32
+ ...specFiles,
33
+ ...scenarioFiles,
34
+ ...decisionFiles,
35
+ ...ruleFiles,
36
+ ...apiFiles,
37
+ ...uiFiles,
38
+ ...dbFiles,
39
+ ]);
40
+ const upstreamIds = await collectUpstreamIds([
41
+ ...specFiles,
42
+ ...scenarioFiles,
43
+ ]);
44
+ const traceability = await evaluateTraceability(upstreamIds, srcRoot, testsRoot);
45
+ const resolvedValidation = validation ?? (await validateProject(root, resolved));
46
+ const version = await resolveToolVersion();
47
+ return {
48
+ tool: "qfai",
49
+ version,
50
+ generatedAt: new Date().toISOString(),
51
+ root,
52
+ configPath,
53
+ summary: {
54
+ specs: specFiles.length,
55
+ scenarios: scenarioFiles.length,
56
+ decisions: decisionFiles.length,
57
+ rules: ruleFiles.length,
58
+ contracts: {
59
+ api: apiFiles.length,
60
+ ui: uiFiles.length,
61
+ db: dbFiles.length,
62
+ },
63
+ counts: resolvedValidation.counts,
64
+ },
65
+ ids: {
66
+ spec: idsByPrefix.SPEC,
67
+ br: idsByPrefix.BR,
68
+ sc: idsByPrefix.SC,
69
+ ui: idsByPrefix.UI,
70
+ api: idsByPrefix.API,
71
+ data: idsByPrefix.DATA,
72
+ },
73
+ traceability: {
74
+ upstreamIdsFound: upstreamIds.size,
75
+ referencedInCodeOrTests: traceability,
76
+ },
77
+ issues: resolvedValidation.issues,
78
+ };
79
+ }
80
+ export function formatReportMarkdown(data) {
81
+ const lines = [];
82
+ lines.push("# QFAI Report");
83
+ lines.push(`- 生成日時: ${data.generatedAt}`);
84
+ lines.push(`- ルート: ${data.root}`);
85
+ lines.push(`- 設定: ${data.configPath}`);
86
+ lines.push(`- 版: ${data.version}`);
87
+ lines.push("");
88
+ lines.push("## 概要");
89
+ lines.push(`- specs: ${data.summary.specs}`);
90
+ lines.push(`- scenarios: ${data.summary.scenarios}`);
91
+ lines.push(`- decisions: ${data.summary.decisions}`);
92
+ lines.push(`- rules: ${data.summary.rules}`);
93
+ lines.push(`- contracts: api ${data.summary.contracts.api} / ui ${data.summary.contracts.ui} / db ${data.summary.contracts.db}`);
94
+ lines.push(`- issues: info ${data.summary.counts.info} / warning ${data.summary.counts.warning} / error ${data.summary.counts.error}`);
95
+ lines.push("");
96
+ lines.push("## ID集計");
97
+ lines.push(formatIdLine("SPEC", data.ids.spec));
98
+ lines.push(formatIdLine("BR", data.ids.br));
99
+ lines.push(formatIdLine("SC", data.ids.sc));
100
+ lines.push(formatIdLine("UI", data.ids.ui));
101
+ lines.push(formatIdLine("API", data.ids.api));
102
+ lines.push(formatIdLine("DATA", data.ids.data));
103
+ lines.push("");
104
+ lines.push("## トレーサビリティ");
105
+ lines.push(`- 上流ID検出数: ${data.traceability.upstreamIdsFound}`);
106
+ lines.push(`- コード/テスト参照: ${data.traceability.referencedInCodeOrTests ? "あり" : "なし"}`);
107
+ lines.push("");
108
+ lines.push("## Hotspots");
109
+ const hotspots = buildHotspots(data.issues);
110
+ if (hotspots.length === 0) {
111
+ lines.push("- (none)");
112
+ }
113
+ else {
114
+ for (const spot of hotspots) {
115
+ lines.push(`- ${spot.file}: total ${spot.total} (error ${spot.error} / warning ${spot.warning} / info ${spot.info})`);
116
+ }
117
+ }
118
+ lines.push("");
119
+ lines.push("## トレーサビリティ(検証)");
120
+ const traceIssues = data.issues.filter((item) => item.rule?.startsWith("traceability.") ||
121
+ item.code.startsWith("QFAI_TRACE") ||
122
+ item.code === "QFAI_CONTRACT_ORPHAN");
123
+ if (traceIssues.length === 0) {
124
+ lines.push("- (none)");
125
+ }
126
+ else {
127
+ for (const item of traceIssues) {
128
+ const location = item.file ? ` (${item.file})` : "";
129
+ lines.push(`- ${item.severity.toUpperCase()} [${item.code}] ${item.message}${location}`);
130
+ }
131
+ }
132
+ lines.push("");
133
+ lines.push("## 検証結果");
134
+ if (data.issues.length === 0) {
135
+ lines.push("- (none)");
136
+ }
137
+ else {
138
+ for (const item of data.issues) {
139
+ const location = item.file ? ` (${item.file})` : "";
140
+ const refs = item.refs && item.refs.length > 0 ? ` refs=${item.refs.join(",")}` : "";
141
+ lines.push(`- ${item.severity.toUpperCase()} [${item.code}] ${item.message}${location}${refs}`);
142
+ }
143
+ }
144
+ return lines.join("\n");
145
+ }
146
+ export function formatReportJson(data) {
147
+ return JSON.stringify(data, null, 2);
148
+ }
149
+ async function collectIds(files) {
150
+ const result = {
151
+ SPEC: new Set(),
152
+ BR: new Set(),
153
+ SC: new Set(),
154
+ UI: new Set(),
155
+ API: new Set(),
156
+ DATA: new Set(),
157
+ };
158
+ for (const file of files) {
159
+ const text = await readFile(file, "utf-8");
160
+ for (const prefix of ID_PREFIXES) {
161
+ const ids = extractIds(text, prefix);
162
+ ids.forEach((id) => result[prefix].add(id));
163
+ }
164
+ }
165
+ return {
166
+ SPEC: toSortedArray(result.SPEC),
167
+ BR: toSortedArray(result.BR),
168
+ SC: toSortedArray(result.SC),
169
+ UI: toSortedArray(result.UI),
170
+ API: toSortedArray(result.API),
171
+ DATA: toSortedArray(result.DATA),
172
+ };
173
+ }
174
+ async function collectUpstreamIds(files) {
175
+ const ids = new Set();
176
+ for (const file of files) {
177
+ const text = await readFile(file, "utf-8");
178
+ extractAllIds(text).forEach((id) => ids.add(id));
179
+ }
180
+ return ids;
181
+ }
182
+ async function evaluateTraceability(upstreamIds, srcRoot, testsRoot) {
183
+ if (upstreamIds.size === 0) {
184
+ return false;
185
+ }
186
+ const codeFiles = await collectFiles(srcRoot, {
187
+ extensions: [".ts", ".tsx", ".js", ".jsx"],
188
+ });
189
+ const testFiles = await collectFiles(testsRoot, {
190
+ extensions: [".ts", ".tsx", ".js", ".jsx"],
191
+ });
192
+ const targetFiles = [...codeFiles, ...testFiles];
193
+ if (targetFiles.length === 0) {
194
+ return false;
195
+ }
196
+ const pattern = buildIdPattern(Array.from(upstreamIds));
197
+ for (const file of targetFiles) {
198
+ const text = await readFile(file, "utf-8");
199
+ if (pattern.test(text)) {
200
+ return true;
201
+ }
202
+ }
203
+ return false;
204
+ }
205
+ function buildIdPattern(ids) {
206
+ const escaped = ids.map((id) => id.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"));
207
+ return new RegExp(`\\b(${escaped.join("|")})\\b`);
208
+ }
209
+ function formatIdLine(label, values) {
210
+ if (values.length === 0) {
211
+ return `- ${label}: (none)`;
212
+ }
213
+ return `- ${label}: ${values.join(", ")}`;
214
+ }
215
+ function toSortedArray(values) {
216
+ return Array.from(values).sort((a, b) => a.localeCompare(b));
217
+ }
218
+ function buildHotspots(issues) {
219
+ const map = new Map();
220
+ for (const issue of issues) {
221
+ if (!issue.file) {
222
+ continue;
223
+ }
224
+ const current = map.get(issue.file) ??
225
+ {
226
+ file: issue.file,
227
+ total: 0,
228
+ error: 0,
229
+ warning: 0,
230
+ info: 0,
231
+ };
232
+ current.total += 1;
233
+ current[issue.severity] += 1;
234
+ map.set(issue.file, current);
235
+ }
236
+ return Array.from(map.values()).sort((a, b) => b.total !== a.total ? b.total - a.total : a.file.localeCompare(b.file));
237
+ }
238
+ //# sourceMappingURL=report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.js","sourceRoot":"","sources":["../../src/core/report.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ export type IssueSeverity = "info" | "warning" | "error";
2
+ export declare const VALIDATION_SCHEMA_VERSION: "0.2";
3
+ export type IssueLocation = {
4
+ line: number;
5
+ column?: number;
6
+ };
7
+ export type Issue = {
8
+ code: string;
9
+ severity: IssueSeverity;
10
+ message: string;
11
+ file?: string;
12
+ refs?: string[];
13
+ rule?: string;
14
+ loc?: IssueLocation;
15
+ };
16
+ export type ValidationCounts = {
17
+ info: number;
18
+ warning: number;
19
+ error: number;
20
+ };
21
+ export type ValidationResult = {
22
+ schemaVersion: typeof VALIDATION_SCHEMA_VERSION;
23
+ toolVersion: string;
24
+ issues: Issue[];
25
+ counts: ValidationCounts;
26
+ };
27
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC;AAEzD,eAAO,MAAM,yBAAyB,EAAG,KAAc,CAAC;AAExD,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,KAAK,GAAG;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,aAAa,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,aAAa,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,aAAa,EAAE,OAAO,yBAAyB,CAAC;IAChD,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,MAAM,EAAE,gBAAgB,CAAC;CAC1B,CAAC"}
@@ -0,0 +1,2 @@
1
+ export const VALIDATION_SCHEMA_VERSION = "0.2";
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,yBAAyB,GAAG,KAAc,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { type ConfigLoadResult } from "./config.js";
2
+ import type { ValidationResult } from "./types.js";
3
+ export declare function validateProject(root: string, configResult?: ConfigLoadResult): Promise<ValidationResult>;
4
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/core/validate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAChE,OAAO,KAAK,EAA2B,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAQ5E,wBAAsB,eAAe,CACnC,IAAI,EAAE,MAAM,EACZ,YAAY,CAAC,EAAE,gBAAgB,GAC9B,OAAO,CAAC,gBAAgB,CAAC,CAkB3B"}
@@ -0,0 +1,32 @@
1
+ import { loadConfig } from "./config.js";
2
+ import { VALIDATION_SCHEMA_VERSION } from "./types.js";
3
+ import { resolveToolVersion } from "./version.js";
4
+ import { validateContracts } from "./validators/contracts.js";
5
+ import { validateScenarios } from "./validators/scenario.js";
6
+ import { validateSpecs } from "./validators/spec.js";
7
+ import { validateTraceability } from "./validators/traceability.js";
8
+ export async function validateProject(root, configResult) {
9
+ const resolved = configResult ?? (await loadConfig(root));
10
+ const { config, issues: configIssues } = resolved;
11
+ const issues = [
12
+ ...configIssues,
13
+ ...(await validateSpecs(root, config)),
14
+ ...(await validateScenarios(root, config)),
15
+ ...(await validateContracts(root, config)),
16
+ ...(await validateTraceability(root, config)),
17
+ ];
18
+ const toolVersion = await resolveToolVersion();
19
+ return {
20
+ schemaVersion: VALIDATION_SCHEMA_VERSION,
21
+ toolVersion,
22
+ issues,
23
+ counts: countIssues(issues),
24
+ };
25
+ }
26
+ function countIssues(issues) {
27
+ return issues.reduce((acc, issue) => {
28
+ acc[issue.severity] += 1;
29
+ return acc;
30
+ }, { info: 0, warning: 0, error: 0 });
31
+ }
32
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/core/validate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAyB,MAAM,aAAa,CAAC;AAEhE,OAAO,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AAEpE,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,IAAY,EACZ,YAA+B;IAE/B,MAAM,QAAQ,GAAG,YAAY,IAAI,CAAC,MAAM,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;IAC1D,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,GAAG,QAAQ,CAAC;IAClD,MAAM,MAAM,GAAG;QACb,GAAG,YAAY;QACf,GAAG,CAAC,MAAM,aAAa,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACtC,GAAG,CAAC,MAAM,iBAAiB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAC1C,GAAG,CAAC,MAAM,iBAAiB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAC1C,GAAG,CAAC,MAAM,oBAAoB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;KAC9C,CAAC;IAEF,MAAM,WAAW,GAAG,MAAM,kBAAkB,EAAE,CAAC;IAC/C,OAAO;QACL,aAAa,EAAE,yBAAyB;QACxC,WAAW;QACX,MAAM;QACN,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC;KAC5B,CAAC;AACJ,CAAC;AAED,SAAS,WAAW,CAAC,MAAe;IAClC,OAAO,MAAM,CAAC,MAAM,CAClB,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE;QACb,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACzB,OAAO,GAAG,CAAC;IACb,CAAC,EACD,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAClC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { QfaiConfig } from "../config.js";
2
+ import type { Issue } from "../types.js";
3
+ export declare function validateContracts(root: string, config: QfaiConfig): Promise<Issue[]>;
4
+ export declare function lintSql(text: string, file: string): Issue[];
5
+ //# sourceMappingURL=contracts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contracts.d.ts","sourceRoot":"","sources":["../../../src/core/validators/contracts.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAQ/C,OAAO,KAAK,EAAE,KAAK,EAAiB,MAAM,aAAa,CAAC;AAYxD,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC,KAAK,EAAE,CAAC,CAkBlB;AAkLD,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,KAAK,EAAE,CAgB3D"}
@@ -0,0 +1,157 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { parse as parseYaml } from "yaml";
4
+ import { resolvePath } from "../config.js";
5
+ import { collectApiContractFiles, collectDataContractFiles, collectUiContractFiles, } from "../discovery.js";
6
+ import { extractInvalidIds } from "../ids.js";
7
+ const SQL_DANGEROUS_PATTERNS = [
8
+ { pattern: /\bDROP\s+TABLE\b/i, label: "DROP TABLE" },
9
+ { pattern: /\bDROP\s+DATABASE\b/i, label: "DROP DATABASE" },
10
+ { pattern: /\bTRUNCATE\b/i, label: "TRUNCATE" },
11
+ {
12
+ pattern: /\bALTER\s+TABLE\b[\s\S]*\bDROP\b/i,
13
+ label: "ALTER TABLE ... DROP",
14
+ },
15
+ ];
16
+ export async function validateContracts(root, config) {
17
+ const issues = [];
18
+ issues.push(...(await validateUiContracts(resolvePath(root, config, "uiContractsDir"))));
19
+ issues.push(...(await validateApiContracts(resolvePath(root, config, "apiContractsDir"))));
20
+ issues.push(...(await validateDataContracts(resolvePath(root, config, "dataContractsDir"))));
21
+ return issues;
22
+ }
23
+ async function validateUiContracts(uiRoot) {
24
+ const files = await collectUiContractFiles(uiRoot);
25
+ if (files.length === 0) {
26
+ return [
27
+ issue("QFAI-UI-000", "UI 契約ファイルが見つかりません。", "info", uiRoot, "contracts.ui.files"),
28
+ ];
29
+ }
30
+ const issues = [];
31
+ for (const file of files) {
32
+ const text = await readFile(file, "utf-8");
33
+ const invalidIds = extractInvalidIds(text, [
34
+ "SPEC",
35
+ "BR",
36
+ "SC",
37
+ "UI",
38
+ "API",
39
+ "DATA",
40
+ ]);
41
+ if (invalidIds.length > 0) {
42
+ issues.push(issue("QFAI_ID_INVALID_FORMAT", `ID フォーマットが不正です: ${invalidIds.join(", ")}`, "error", file, "id.format", invalidIds));
43
+ }
44
+ try {
45
+ const doc = parseYaml(text);
46
+ const id = typeof doc.id === "string" ? doc.id : "";
47
+ if (!id.startsWith("UI-")) {
48
+ issues.push(issue("QFAI-UI-001", "UI 契約の id は UI- で始まる必要があります。", "error", file, "contracts.ui.id"));
49
+ }
50
+ }
51
+ catch (error) {
52
+ issues.push(issue("QFAI-UI-002", `UI YAML の解析に失敗しました: ${formatError(error)}`, "error", file, "contracts.ui.parse"));
53
+ }
54
+ }
55
+ return issues;
56
+ }
57
+ async function validateApiContracts(apiRoot) {
58
+ const files = await collectApiContractFiles(apiRoot);
59
+ if (files.length === 0) {
60
+ return [
61
+ issue("QFAI-API-000", "API 契約ファイルが見つかりません。", "info", apiRoot, "contracts.api.files"),
62
+ ];
63
+ }
64
+ const issues = [];
65
+ for (const file of files) {
66
+ const text = await readFile(file, "utf-8");
67
+ const invalidIds = extractInvalidIds(text, [
68
+ "SPEC",
69
+ "BR",
70
+ "SC",
71
+ "UI",
72
+ "API",
73
+ "DATA",
74
+ ]);
75
+ if (invalidIds.length > 0) {
76
+ issues.push(issue("QFAI_ID_INVALID_FORMAT", `ID フォーマットが不正です: ${invalidIds.join(", ")}`, "error", file, "id.format", invalidIds));
77
+ }
78
+ try {
79
+ const doc = parseStructured(file, text);
80
+ if (!doc || !hasOpenApi(doc)) {
81
+ issues.push(issue("QFAI-API-001", "OpenAPI 定義が見つかりません。", "error", file, "contracts.api.openapi"));
82
+ }
83
+ }
84
+ catch (error) {
85
+ issues.push(issue("QFAI-API-002", `API 定義の解析に失敗しました: ${formatError(error)}`, "error", file, "contracts.api.parse"));
86
+ }
87
+ }
88
+ return issues;
89
+ }
90
+ async function validateDataContracts(dataRoot) {
91
+ const files = await collectDataContractFiles(dataRoot);
92
+ if (files.length === 0) {
93
+ return [
94
+ issue("QFAI-DATA-000", "DATA 契約ファイルが見つかりません。", "info", dataRoot, "contracts.data.files"),
95
+ ];
96
+ }
97
+ const issues = [];
98
+ for (const file of files) {
99
+ const text = await readFile(file, "utf-8");
100
+ const invalidIds = extractInvalidIds(text, [
101
+ "SPEC",
102
+ "BR",
103
+ "SC",
104
+ "UI",
105
+ "API",
106
+ "DATA",
107
+ ]);
108
+ if (invalidIds.length > 0) {
109
+ issues.push(issue("QFAI_ID_INVALID_FORMAT", `ID フォーマットが不正です: ${invalidIds.join(", ")}`, "error", file, "id.format", invalidIds));
110
+ }
111
+ issues.push(...lintSql(text, file));
112
+ }
113
+ return issues;
114
+ }
115
+ export function lintSql(text, file) {
116
+ const issues = [];
117
+ for (const { pattern, label } of SQL_DANGEROUS_PATTERNS) {
118
+ if (pattern.test(text)) {
119
+ issues.push(issue("QFAI-DATA-001", `危険な SQL 操作が含まれています: ${label}`, "warning", file, "contracts.data.sql"));
120
+ }
121
+ }
122
+ return issues;
123
+ }
124
+ function parseStructured(file, text) {
125
+ const ext = path.extname(file).toLowerCase();
126
+ if (ext === ".json") {
127
+ return JSON.parse(text);
128
+ }
129
+ return parseYaml(text);
130
+ }
131
+ function hasOpenApi(doc) {
132
+ return typeof doc.openapi === "string" && doc.openapi.length > 0;
133
+ }
134
+ function formatError(error) {
135
+ if (error instanceof Error) {
136
+ return error.message;
137
+ }
138
+ return String(error);
139
+ }
140
+ function issue(code, message, severity, file, rule, refs) {
141
+ const issue = {
142
+ code,
143
+ severity,
144
+ message,
145
+ };
146
+ if (file) {
147
+ issue.file = file;
148
+ }
149
+ if (rule) {
150
+ issue.rule = rule;
151
+ }
152
+ if (refs && refs.length > 0) {
153
+ issue.refs = refs;
154
+ }
155
+ return issue;
156
+ }
157
+ //# sourceMappingURL=contracts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contracts.js","sourceRoot":"","sources":["../../../src/core/validators/contracts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { QfaiConfig } from "../config.js";
2
+ import type { Issue } from "../types.js";
3
+ export declare function validateScenarios(root: string, config: QfaiConfig): Promise<Issue[]>;
4
+ export declare function validateScenarioContent(text: string, file: string): Issue[];
5
+ //# sourceMappingURL=scenario.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scenario.d.ts","sourceRoot":"","sources":["../../../src/core/validators/scenario.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAI/C,OAAO,KAAK,EAAE,KAAK,EAAiB,MAAM,aAAa,CAAC;AAMxD,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC,KAAK,EAAE,CAAC,CAyBlB;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,KAAK,EAAE,CAsF3E"}
@@ -0,0 +1,82 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { resolvePath } from "../config.js";
3
+ import { collectFiles } from "../fs.js";
4
+ import { extractIds, extractInvalidIds } from "../ids.js";
5
+ const GIVEN_PATTERN = /\bGiven\b/;
6
+ const WHEN_PATTERN = /\bWhen\b/;
7
+ const THEN_PATTERN = /\bThen\b/;
8
+ export async function validateScenarios(root, config) {
9
+ const scenariosRoot = resolvePath(root, config, "scenariosDir");
10
+ const files = await collectFiles(scenariosRoot, {
11
+ extensions: [".feature"],
12
+ });
13
+ if (files.length === 0) {
14
+ return [
15
+ issue("QFAI-SC-000", "Scenario ファイルが見つかりません。", "info", scenariosRoot, "scenario.files"),
16
+ ];
17
+ }
18
+ const issues = [];
19
+ for (const file of files) {
20
+ const text = await readFile(file, "utf-8");
21
+ issues.push(...validateScenarioContent(text, file));
22
+ }
23
+ return issues;
24
+ }
25
+ export function validateScenarioContent(text, file) {
26
+ const issues = [];
27
+ const invalidIds = extractInvalidIds(text, [
28
+ "SPEC",
29
+ "BR",
30
+ "SC",
31
+ "UI",
32
+ "API",
33
+ "DATA",
34
+ ]);
35
+ if (invalidIds.length > 0) {
36
+ issues.push(issue("QFAI_ID_INVALID_FORMAT", `ID フォーマットが不正です: ${invalidIds.join(", ")}`, "error", file, "id.format", invalidIds));
37
+ }
38
+ const scIds = extractIds(text, "SC");
39
+ if (scIds.length === 0) {
40
+ issues.push(issue("QFAI-SC-001", "SC ID が見つかりません。", "error", file, "scenario.id"));
41
+ }
42
+ const specIds = extractIds(text, "SPEC");
43
+ if (specIds.length === 0) {
44
+ issues.push(issue("QFAI-SC-002", "SC は SPEC を参照する必要があります。", "error", file, "scenario.spec"));
45
+ }
46
+ const brIds = extractIds(text, "BR");
47
+ if (brIds.length === 0) {
48
+ issues.push(issue("QFAI-SC-003", "SC は BR を参照する必要があります。", "error", file, "scenario.br"));
49
+ }
50
+ const missingSteps = [];
51
+ if (!GIVEN_PATTERN.test(text)) {
52
+ missingSteps.push("Given");
53
+ }
54
+ if (!WHEN_PATTERN.test(text)) {
55
+ missingSteps.push("When");
56
+ }
57
+ if (!THEN_PATTERN.test(text)) {
58
+ missingSteps.push("Then");
59
+ }
60
+ if (missingSteps.length > 0) {
61
+ issues.push(issue("QFAI-SC-005", `Given/When/Then が不足しています: ${missingSteps.join(", ")}`, "warning", file, "scenario.steps"));
62
+ }
63
+ return issues;
64
+ }
65
+ function issue(code, message, severity, file, rule, refs) {
66
+ const issue = {
67
+ code,
68
+ severity,
69
+ message,
70
+ };
71
+ if (file) {
72
+ issue.file = file;
73
+ }
74
+ if (rule) {
75
+ issue.rule = rule;
76
+ }
77
+ if (refs && refs.length > 0) {
78
+ issue.refs = refs;
79
+ }
80
+ return issue;
81
+ }
82
+ //# sourceMappingURL=scenario.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scenario.js","sourceRoot":"","sources":["../../../src/core/validators/scenario.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAG5C,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAG1D,MAAM,aAAa,GAAG,WAAW,CAAC;AAClC,MAAM,YAAY,GAAG,UAAU,CAAC;AAChC,MAAM,YAAY,GAAG,UAAU,CAAC;AAEhC,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,IAAY,EACZ,MAAkB;IAElB,MAAM,aAAa,GAAG,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,cAAc,CAAC,CAAC;IAChE,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,aAAa,EAAE;QAC9C,UAAU,EAAE,CAAC,UAAU,CAAC;KACzB,CAAC,CAAC;IAEH,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO;YACL,KAAK,CACH,aAAa,EACb,wBAAwB,EACxB,MAAM,EACN,aAAa,EACb,gBAAgB,CACjB;SACF,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAY,EAAE,CAAC;IAC3B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC3C,MAAM,CAAC,IAAI,CAAC,GAAG,uBAAuB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;IACtD,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,IAAY,EAAE,IAAY;IAChE,MAAM,MAAM,GAAY,EAAE,CAAC;IAE3B,MAAM,UAAU,GAAG,iBAAiB,CAAC,IAAI,EAAE;QACzC,MAAM;QACN,IAAI;QACJ,IAAI;QACJ,IAAI;QACJ,KAAK;QACL,MAAM;KACP,CAAC,CAAC;IACH,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,MAAM,CAAC,IAAI,CACT,KAAK,CACH,wBAAwB,EACxB,mBAAmB,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAC1C,OAAO,EACP,IAAI,EACJ,WAAW,EACX,UAAU,CACX,CACF,CAAC;IACJ,CAAC;IAED,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACrC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,MAAM,CAAC,IAAI,CACT,KAAK,CACH,aAAa,EACb,iBAAiB,EACjB,OAAO,EACP,IAAI,EACJ,aAAa,CACd,CACF,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAAG,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACzC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,CAAC,IAAI,CACT,KAAK,CACH,aAAa,EACb,yBAAyB,EACzB,OAAO,EACP,IAAI,EACJ,eAAe,CAChB,CACF,CAAC;IACJ,CAAC;IAED,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACrC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,MAAM,CAAC,IAAI,CACT,KAAK,CACH,aAAa,EACb,uBAAuB,EACvB,OAAO,EACP,IAAI,EACJ,aAAa,CACd,CACF,CAAC;IACJ,CAAC;IAED,MAAM,YAAY,GAAa,EAAE,CAAC;IAClC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAC9B,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;IACD,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAC7B,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC5B,CAAC;IACD,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAC7B,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC5B,CAAC;IACD,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5B,MAAM,CAAC,IAAI,CACT,KAAK,CACH,aAAa,EACb,6BAA6B,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EACtD,SAAS,EACT,IAAI,EACJ,gBAAgB,CACjB,CACF,CAAC;IACJ,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,KAAK,CACZ,IAAY,EACZ,OAAe,EACf,QAAuB,EACvB,IAAa,EACb,IAAa,EACb,IAAe;IAEf,MAAM,KAAK,GAAU;QACnB,IAAI;QACJ,QAAQ;QACR,OAAO;KACR,CAAC;IACF,IAAI,IAAI,EAAE,CAAC;QACT,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC;IACpB,CAAC;IACD,IAAI,IAAI,EAAE,CAAC;QACT,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC;IACpB,CAAC;IACD,IAAI,IAAI,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5B,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC;IACpB,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { QfaiConfig } from "../config.js";
2
+ import type { Issue } from "../types.js";
3
+ export declare function validateSpecs(root: string, config: QfaiConfig): Promise<Issue[]>;
4
+ export declare function validateSpecContent(text: string, file: string, requiredSections: string[]): Issue[];
5
+ //# sourceMappingURL=spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spec.d.ts","sourceRoot":"","sources":["../../../src/core/validators/spec.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAI/C,OAAO,KAAK,EAAE,KAAK,EAAiB,MAAM,aAAa,CAAC;AAExD,wBAAsB,aAAa,CACjC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC,KAAK,EAAE,CAAC,CA6BlB;AAED,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,gBAAgB,EAAE,MAAM,EAAE,GACzB,KAAK,EAAE,CA+ET"}