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,73 @@
1
+ import { runInit } from "./commands/init.js";
2
+ import { runReport } from "./commands/report.js";
3
+ import { runValidate } from "./commands/validate.js";
4
+ import { parseArgs } from "./lib/args.js";
5
+ import { error, info } from "./lib/logger.js";
6
+ export async function run(argv, cwd) {
7
+ const { command, options } = parseArgs(argv, cwd);
8
+ if (!command || options.help) {
9
+ info(usage());
10
+ return;
11
+ }
12
+ switch (command) {
13
+ case "init":
14
+ await runInit({
15
+ dir: options.dir,
16
+ force: options.force,
17
+ dryRun: options.dryRun,
18
+ yes: options.yes,
19
+ });
20
+ return;
21
+ case "validate":
22
+ process.exitCode = await runValidate({
23
+ root: options.root,
24
+ strict: options.strict,
25
+ format: options.validateFormat,
26
+ ...(options.failOn !== undefined ? { failOn: options.failOn } : {}),
27
+ ...(options.jsonPath !== undefined
28
+ ? { jsonPath: options.jsonPath }
29
+ : {}),
30
+ });
31
+ return;
32
+ case "report":
33
+ await runReport({
34
+ root: options.root,
35
+ format: options.reportFormat,
36
+ ...(options.jsonPath !== undefined
37
+ ? { jsonPath: options.jsonPath }
38
+ : {}),
39
+ ...(options.reportOut !== undefined
40
+ ? { outPath: options.reportOut }
41
+ : {}),
42
+ });
43
+ return;
44
+ default:
45
+ error(`Unknown command: ${command}`);
46
+ info(usage());
47
+ return;
48
+ }
49
+ }
50
+ function usage() {
51
+ return `qfai <command> [options]
52
+
53
+ Commands:
54
+ init テンプレを生成
55
+ validate 仕様/契約/参照の検査
56
+ report 検証結果と集計を出力
57
+
58
+ Options:
59
+ --root <path> 対象ディレクトリ
60
+ --dir <path> init の出力先
61
+ --force 既存ファイルを上書き
62
+ --yes init: 非対話でデフォルトを採用(現在は非対話が既定、将来の対話導入時も自動Yes)
63
+ --dry-run 変更を行わず表示のみ
64
+ --format <text|json|github> validate の出力形式
65
+ --format <md|json> report の出力形式
66
+ --strict validate: warning 以上で exit 1
67
+ --fail-on <error|warning|never> validate: 失敗条件
68
+ --json-path <path> validate: JSON 出力先 / report: validate JSON 入力
69
+ --out <path> report: 出力先
70
+ -h, --help ヘルプ表示
71
+ `;
72
+ }
73
+ //# sourceMappingURL=main.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.js","sourceRoot":"","sources":["../../src/cli/main.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAE9C,MAAM,CAAC,KAAK,UAAU,GAAG,CAAC,IAAc,EAAE,GAAW;IACnD,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,SAAS,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAElD,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QAC7B,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;QACd,OAAO;IACT,CAAC;IAED,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,MAAM;YACT,MAAM,OAAO,CAAC;gBACZ,GAAG,EAAE,OAAO,CAAC,GAAG;gBAChB,KAAK,EAAE,OAAO,CAAC,KAAK;gBACpB,MAAM,EAAE,OAAO,CAAC,MAAM;gBACtB,GAAG,EAAE,OAAO,CAAC,GAAG;aACjB,CAAC,CAAC;YACH,OAAO;QACT,KAAK,UAAU;YACb,OAAO,CAAC,QAAQ,GAAG,MAAM,WAAW,CAAC;gBACnC,IAAI,EAAE,OAAO,CAAC,IAAI;gBAClB,MAAM,EAAE,OAAO,CAAC,MAAM;gBACtB,MAAM,EAAE,OAAO,CAAC,cAAc;gBAC9B,GAAG,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACnE,GAAG,CAAC,OAAO,CAAC,QAAQ,KAAK,SAAS;oBAChC,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE;oBAChC,CAAC,CAAC,EAAE,CAAC;aACR,CAAC,CAAC;YACH,OAAO;QACT,KAAK,QAAQ;YACX,MAAM,SAAS,CAAC;gBACd,IAAI,EAAE,OAAO,CAAC,IAAI;gBAClB,MAAM,EAAE,OAAO,CAAC,YAAY;gBAC5B,GAAG,CAAC,OAAO,CAAC,QAAQ,KAAK,SAAS;oBAChC,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE;oBAChC,CAAC,CAAC,EAAE,CAAC;gBACP,GAAG,CAAC,OAAO,CAAC,SAAS,KAAK,SAAS;oBACjC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,SAAS,EAAE;oBAChC,CAAC,CAAC,EAAE,CAAC;aACR,CAAC,CAAC;YACH,OAAO;QACT;YACE,KAAK,CAAC,oBAAoB,OAAO,EAAE,CAAC,CAAC;YACrC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;YACd,OAAO;IACX,CAAC;AACH,CAAC;AAED,SAAS,KAAK;IACZ,OAAO;;;;;;;;;;;;;;;;;;;;CAoBR,CAAC;AACF,CAAC"}
@@ -0,0 +1,46 @@
1
+ import type { Issue } from "./types.js";
2
+ export type FailOn = "never" | "warning" | "error";
3
+ export type OutputFormat = "text" | "json" | "github";
4
+ export type QfaiPaths = {
5
+ specDir: string;
6
+ decisionsDir: string;
7
+ scenariosDir: string;
8
+ rulesDir: string;
9
+ contractsDir: string;
10
+ uiContractsDir: string;
11
+ apiContractsDir: string;
12
+ dataContractsDir: string;
13
+ srcDir: string;
14
+ testsDir: string;
15
+ };
16
+ export type QfaiValidationConfig = {
17
+ failOn: FailOn;
18
+ require: {
19
+ specSections: string[];
20
+ };
21
+ traceability: {
22
+ brMustHaveSc: boolean;
23
+ scMustTouchContracts: boolean;
24
+ allowOrphanContracts: boolean;
25
+ };
26
+ };
27
+ export type QfaiOutputConfig = {
28
+ format: OutputFormat;
29
+ jsonPath: string;
30
+ };
31
+ export type QfaiConfig = {
32
+ paths: QfaiPaths;
33
+ validation: QfaiValidationConfig;
34
+ output: QfaiOutputConfig;
35
+ };
36
+ export type ConfigPathKey = keyof QfaiPaths;
37
+ export type ConfigLoadResult = {
38
+ config: QfaiConfig;
39
+ issues: Issue[];
40
+ configPath: string;
41
+ };
42
+ export declare const defaultConfig: QfaiConfig;
43
+ export declare function getConfigPath(root: string): string;
44
+ export declare function loadConfig(root: string): Promise<ConfigLoadResult>;
45
+ export declare function resolvePath(root: string, config: QfaiConfig, key: ConfigPathKey): string;
46
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC,MAAM,MAAM,MAAM,GAAG,OAAO,GAAG,SAAS,GAAG,OAAO,CAAC;AACnD,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,CAAC;AAEtD,MAAM,MAAM,SAAS,GAAG;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE;QACP,YAAY,EAAE,MAAM,EAAE,CAAC;KACxB,CAAC;IACF,YAAY,EAAE;QACZ,YAAY,EAAE,OAAO,CAAC;QACtB,oBAAoB,EAAE,OAAO,CAAC;QAC9B,oBAAoB,EAAE,OAAO,CAAC;KAC/B,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,EAAE,YAAY,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,KAAK,EAAE,SAAS,CAAC;IACjB,UAAU,EAAE,oBAAoB,CAAC;IACjC,MAAM,EAAE,gBAAgB,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG,MAAM,SAAS,CAAC;AAE5C,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,EAAE,UAAU,CAAC;IACnB,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,UAoC3B,CAAC;AAEF,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAElD;AAED,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAkBxE;AAED,wBAAgB,WAAW,CACzB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,UAAU,EAClB,GAAG,EAAE,aAAa,GACjB,MAAM,CAER"}
@@ -0,0 +1,224 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { parse as parseYaml } from "yaml";
4
+ export const defaultConfig = {
5
+ paths: {
6
+ specDir: "qfai/spec",
7
+ decisionsDir: "qfai/spec/decisions",
8
+ scenariosDir: "qfai/spec",
9
+ rulesDir: "qfai/rules",
10
+ contractsDir: "qfai/contracts",
11
+ uiContractsDir: "qfai/contracts/ui",
12
+ apiContractsDir: "qfai/contracts/api",
13
+ dataContractsDir: "qfai/contracts/db",
14
+ srcDir: "src",
15
+ testsDir: "tests",
16
+ },
17
+ validation: {
18
+ failOn: "error",
19
+ require: {
20
+ specSections: [
21
+ "背景",
22
+ "スコープ",
23
+ "非ゴール",
24
+ "用語",
25
+ "前提",
26
+ "決定事項",
27
+ "業務ルール",
28
+ ],
29
+ },
30
+ traceability: {
31
+ brMustHaveSc: true,
32
+ scMustTouchContracts: true,
33
+ allowOrphanContracts: false,
34
+ },
35
+ },
36
+ output: {
37
+ format: "text",
38
+ jsonPath: ".qfai/out/validate.json",
39
+ },
40
+ };
41
+ export function getConfigPath(root) {
42
+ return path.join(root, "qfai.config.yaml");
43
+ }
44
+ export async function loadConfig(root) {
45
+ const configPath = getConfigPath(root);
46
+ const issues = [];
47
+ let parsed;
48
+ try {
49
+ const raw = await readFile(configPath, "utf-8");
50
+ parsed = parseYaml(raw);
51
+ }
52
+ catch (error) {
53
+ if (isMissingFile(error)) {
54
+ return { config: defaultConfig, issues, configPath };
55
+ }
56
+ issues.push(configIssue(configPath, formatError(error)));
57
+ return { config: defaultConfig, issues, configPath };
58
+ }
59
+ const normalized = normalizeConfig(parsed, configPath, issues);
60
+ return { config: normalized, issues, configPath };
61
+ }
62
+ export function resolvePath(root, config, key) {
63
+ return path.resolve(root, config.paths[key]);
64
+ }
65
+ function normalizeConfig(raw, configPath, issues) {
66
+ if (!isRecord(raw)) {
67
+ issues.push(configIssue(configPath, "設定ファイルの形式が不正です。"));
68
+ return defaultConfig;
69
+ }
70
+ return {
71
+ paths: normalizePaths(raw.paths, configPath, issues),
72
+ validation: normalizeValidation(raw.validation, configPath, issues),
73
+ output: normalizeOutput(raw.output, configPath, issues),
74
+ };
75
+ }
76
+ function normalizePaths(raw, configPath, issues) {
77
+ const base = defaultConfig.paths;
78
+ if (!raw) {
79
+ return base;
80
+ }
81
+ if (!isRecord(raw)) {
82
+ issues.push(configIssue(configPath, "paths はオブジェクトである必要があります。"));
83
+ return base;
84
+ }
85
+ return {
86
+ specDir: readString(raw.specDir, base.specDir, "paths.specDir", configPath, issues),
87
+ decisionsDir: readString(raw.decisionsDir, base.decisionsDir, "paths.decisionsDir", configPath, issues),
88
+ scenariosDir: readString(raw.scenariosDir, base.scenariosDir, "paths.scenariosDir", configPath, issues),
89
+ rulesDir: readString(raw.rulesDir, base.rulesDir, "paths.rulesDir", configPath, issues),
90
+ contractsDir: readString(raw.contractsDir, base.contractsDir, "paths.contractsDir", configPath, issues),
91
+ uiContractsDir: readString(raw.uiContractsDir, base.uiContractsDir, "paths.uiContractsDir", configPath, issues),
92
+ apiContractsDir: readString(raw.apiContractsDir, base.apiContractsDir, "paths.apiContractsDir", configPath, issues),
93
+ dataContractsDir: readString(raw.dataContractsDir, base.dataContractsDir, "paths.dataContractsDir", configPath, issues),
94
+ srcDir: readString(raw.srcDir, base.srcDir, "paths.srcDir", configPath, issues),
95
+ testsDir: readString(raw.testsDir, base.testsDir, "paths.testsDir", configPath, issues),
96
+ };
97
+ }
98
+ function normalizeValidation(raw, configPath, issues) {
99
+ const base = defaultConfig.validation;
100
+ if (!raw) {
101
+ return base;
102
+ }
103
+ if (!isRecord(raw)) {
104
+ issues.push(configIssue(configPath, "validation はオブジェクトである必要があります。"));
105
+ return base;
106
+ }
107
+ let requireRaw;
108
+ if (raw.require === undefined) {
109
+ requireRaw = undefined;
110
+ }
111
+ else if (isRecord(raw.require)) {
112
+ requireRaw = raw.require;
113
+ }
114
+ else {
115
+ issues.push(configIssue(configPath, "validation.require はオブジェクトである必要があります。"));
116
+ requireRaw = undefined;
117
+ }
118
+ let traceabilityRaw;
119
+ if (raw.traceability === undefined) {
120
+ traceabilityRaw = undefined;
121
+ }
122
+ else if (isRecord(raw.traceability)) {
123
+ traceabilityRaw = raw.traceability;
124
+ }
125
+ else {
126
+ issues.push(configIssue(configPath, "validation.traceability はオブジェクトである必要があります。"));
127
+ traceabilityRaw = undefined;
128
+ }
129
+ return {
130
+ failOn: readFailOn(raw.failOn, base.failOn, "validation.failOn", configPath, issues),
131
+ require: {
132
+ specSections: readStringArray(requireRaw?.specSections, base.require.specSections, "validation.require.specSections", configPath, issues),
133
+ },
134
+ traceability: {
135
+ brMustHaveSc: readBoolean(traceabilityRaw?.brMustHaveSc, base.traceability.brMustHaveSc, "validation.traceability.brMustHaveSc", configPath, issues),
136
+ scMustTouchContracts: readBoolean(traceabilityRaw?.scMustTouchContracts, base.traceability.scMustTouchContracts, "validation.traceability.scMustTouchContracts", configPath, issues),
137
+ allowOrphanContracts: readBoolean(traceabilityRaw?.allowOrphanContracts, base.traceability.allowOrphanContracts, "validation.traceability.allowOrphanContracts", configPath, issues),
138
+ },
139
+ };
140
+ }
141
+ function normalizeOutput(raw, configPath, issues) {
142
+ const base = defaultConfig.output;
143
+ if (!raw) {
144
+ return base;
145
+ }
146
+ if (!isRecord(raw)) {
147
+ issues.push(configIssue(configPath, "output はオブジェクトである必要があります。"));
148
+ return base;
149
+ }
150
+ return {
151
+ format: readOutputFormat(raw.format, base.format, "output.format", configPath, issues),
152
+ jsonPath: readString(raw.jsonPath, base.jsonPath, "output.jsonPath", configPath, issues),
153
+ };
154
+ }
155
+ function readString(value, fallback, label, configPath, issues) {
156
+ if (typeof value === "string" && value.trim().length > 0) {
157
+ return value;
158
+ }
159
+ if (value !== undefined) {
160
+ issues.push(configIssue(configPath, `${label} は文字列である必要があります。`));
161
+ }
162
+ return fallback;
163
+ }
164
+ function readStringArray(value, fallback, label, configPath, issues) {
165
+ if (Array.isArray(value) && value.every((item) => typeof item === "string")) {
166
+ return value;
167
+ }
168
+ if (value !== undefined) {
169
+ issues.push(configIssue(configPath, `${label} は文字列配列である必要があります。`));
170
+ }
171
+ return fallback;
172
+ }
173
+ function readBoolean(value, fallback, label, configPath, issues) {
174
+ if (typeof value === "boolean") {
175
+ return value;
176
+ }
177
+ if (value !== undefined) {
178
+ issues.push(configIssue(configPath, `${label} は真偽値である必要があります。`));
179
+ }
180
+ return fallback;
181
+ }
182
+ function readFailOn(value, fallback, label, configPath, issues) {
183
+ if (value === "never" || value === "warning" || value === "error") {
184
+ return value;
185
+ }
186
+ if (value !== undefined) {
187
+ issues.push(configIssue(configPath, `${label} は never|warning|error のいずれかである必要があります。`));
188
+ }
189
+ return fallback;
190
+ }
191
+ function readOutputFormat(value, fallback, label, configPath, issues) {
192
+ if (value === "text" || value === "json" || value === "github") {
193
+ return value;
194
+ }
195
+ if (value !== undefined) {
196
+ issues.push(configIssue(configPath, `${label} は text|json|github のいずれかである必要があります。`));
197
+ }
198
+ return fallback;
199
+ }
200
+ function configIssue(file, message) {
201
+ return {
202
+ code: "QFAI_CONFIG_INVALID",
203
+ severity: "error",
204
+ message,
205
+ file,
206
+ rule: "config.invalid",
207
+ };
208
+ }
209
+ function isMissingFile(error) {
210
+ if (error && typeof error === "object" && "code" in error) {
211
+ return error.code === "ENOENT";
212
+ }
213
+ return false;
214
+ }
215
+ function formatError(error) {
216
+ if (error instanceof Error) {
217
+ return error.message;
218
+ }
219
+ return String(error);
220
+ }
221
+ function isRecord(value) {
222
+ return value !== null && typeof value === "object" && !Array.isArray(value);
223
+ }
224
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ export type ContractFiles = {
2
+ api: string[];
3
+ ui: string[];
4
+ db: string[];
5
+ };
6
+ export declare function collectSpecFiles(specRoot: string): Promise<string[]>;
7
+ export declare function collectUiContractFiles(uiRoot: string): Promise<string[]>;
8
+ export declare function collectApiContractFiles(apiRoot: string): Promise<string[]>;
9
+ export declare function collectDataContractFiles(dataRoot: string): Promise<string[]>;
10
+ export declare function collectContractFiles(uiRoot: string, apiRoot: string, dataRoot: string): Promise<ContractFiles>;
11
+ //# sourceMappingURL=discovery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../src/core/discovery.ts"],"names":[],"mappings":"AAQA,MAAM,MAAM,aAAa,GAAG;IAC1B,GAAG,EAAE,MAAM,EAAE,CAAC;IACd,EAAE,EAAE,MAAM,EAAE,CAAC;IACb,EAAE,EAAE,MAAM,EAAE,CAAC;CACd,CAAC;AAEF,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAG1E;AAED,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,MAAM,EAAE,CAAC,CAEnB;AAED,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,EAAE,CAAC,CAEnB;AAED,wBAAsB,wBAAwB,CAC5C,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,EAAE,CAAC,CAEnB;AAED,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,aAAa,CAAC,CAOxB"}
@@ -0,0 +1,31 @@
1
+ import path from "node:path";
2
+ import { collectFiles } from "./fs.js";
3
+ const LEGACY_SPEC_NAME = "spec.md";
4
+ // Four-digit, zero-padded spec number (e.g. spec-0001-...); basename is lowercased before match.
5
+ const SPEC_NAMED_PATTERN = /^spec-\d{4}-[^/\\]+\.md$/;
6
+ export async function collectSpecFiles(specRoot) {
7
+ const files = await collectFiles(specRoot, { extensions: [".md"] });
8
+ return files.filter((file) => isSpecFile(file));
9
+ }
10
+ export async function collectUiContractFiles(uiRoot) {
11
+ return collectFiles(uiRoot, { extensions: [".yaml", ".yml"] });
12
+ }
13
+ export async function collectApiContractFiles(apiRoot) {
14
+ return collectFiles(apiRoot, { extensions: [".yaml", ".yml", ".json"] });
15
+ }
16
+ export async function collectDataContractFiles(dataRoot) {
17
+ return collectFiles(dataRoot, { extensions: [".sql"] });
18
+ }
19
+ export async function collectContractFiles(uiRoot, apiRoot, dataRoot) {
20
+ const [ui, api, db] = await Promise.all([
21
+ collectUiContractFiles(uiRoot),
22
+ collectApiContractFiles(apiRoot),
23
+ collectDataContractFiles(dataRoot),
24
+ ]);
25
+ return { ui, api, db };
26
+ }
27
+ function isSpecFile(filePath) {
28
+ const name = path.basename(filePath).toLowerCase();
29
+ return name === LEGACY_SPEC_NAME || SPEC_NAMED_PATTERN.test(name);
30
+ }
31
+ //# sourceMappingURL=discovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery.js","sourceRoot":"","sources":["../../src/core/discovery.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvC,MAAM,gBAAgB,GAAG,SAAS,CAAC;AACnC,iGAAiG;AACjG,MAAM,kBAAkB,GAAG,0BAA0B,CAAC;AAQtD,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,QAAgB;IACrD,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,QAAQ,EAAE,EAAE,UAAU,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACpE,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;AAClD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,MAAc;IAEd,OAAO,YAAY,CAAC,MAAM,EAAE,EAAE,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;AACjE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,OAAe;IAEf,OAAO,YAAY,CAAC,OAAO,EAAE,EAAE,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;AAC3E,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,QAAgB;IAEhB,OAAO,YAAY,CAAC,QAAQ,EAAE,EAAE,UAAU,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AAC1D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,MAAc,EACd,OAAe,EACf,QAAgB;IAEhB,MAAM,CAAC,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QACtC,sBAAsB,CAAC,MAAM,CAAC;QAC9B,uBAAuB,CAAC,OAAO,CAAC;QAChC,wBAAwB,CAAC,QAAQ,CAAC;KACnC,CAAC,CAAC;IACH,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC;AACzB,CAAC;AAED,SAAS,UAAU,CAAC,QAAgB;IAClC,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;IACnD,OAAO,IAAI,KAAK,gBAAgB,IAAI,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACpE,CAAC"}
@@ -0,0 +1,6 @@
1
+ export type CollectFilesOptions = {
2
+ extensions?: string[];
3
+ ignoreDirs?: string[];
4
+ };
5
+ export declare function collectFiles(root: string, options?: CollectFilesOptions): Promise<string[]>;
6
+ //# sourceMappingURL=fs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fs.d.ts","sourceRoot":"","sources":["../../src/core/fs.ts"],"names":[],"mappings":"AAYA,MAAM,MAAM,mBAAmB,GAAG;IAChC,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB,CAAC;AAEF,wBAAsB,YAAY,CAChC,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,MAAM,EAAE,CAAC,CAcnB"}
@@ -0,0 +1,55 @@
1
+ import { access, readdir } from "node:fs/promises";
2
+ import path from "node:path";
3
+ const DEFAULT_IGNORE_DIRS = new Set([
4
+ "node_modules",
5
+ ".git",
6
+ "dist",
7
+ ".pnpm",
8
+ "tmp",
9
+ ".mcp-tools",
10
+ ]);
11
+ export async function collectFiles(root, options = {}) {
12
+ const entries = [];
13
+ if (!(await exists(root))) {
14
+ return entries;
15
+ }
16
+ const ignoreDirs = new Set([
17
+ ...DEFAULT_IGNORE_DIRS,
18
+ ...(options.ignoreDirs ?? []),
19
+ ]);
20
+ const extensions = options.extensions?.map((ext) => ext.toLowerCase()) ?? [];
21
+ await walk(root, root, ignoreDirs, extensions, entries);
22
+ return entries;
23
+ }
24
+ async function walk(base, current, ignoreDirs, extensions, out) {
25
+ const items = await readdir(current, { withFileTypes: true });
26
+ for (const item of items) {
27
+ const fullPath = path.join(current, item.name);
28
+ if (item.isDirectory()) {
29
+ if (ignoreDirs.has(item.name)) {
30
+ continue;
31
+ }
32
+ await walk(base, fullPath, ignoreDirs, extensions, out);
33
+ continue;
34
+ }
35
+ if (item.isFile()) {
36
+ if (extensions.length > 0) {
37
+ const ext = path.extname(item.name).toLowerCase();
38
+ if (!extensions.includes(ext)) {
39
+ continue;
40
+ }
41
+ }
42
+ out.push(fullPath);
43
+ }
44
+ }
45
+ }
46
+ async function exists(target) {
47
+ try {
48
+ await access(target);
49
+ return true;
50
+ }
51
+ catch {
52
+ return false;
53
+ }
54
+ }
55
+ //# sourceMappingURL=fs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fs.js","sourceRoot":"","sources":["../../src/core/fs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,mBAAmB,GAAG,IAAI,GAAG,CAAC;IAClC,cAAc;IACd,MAAM;IACN,MAAM;IACN,OAAO;IACP,KAAK;IACL,YAAY;CACb,CAAC,CAAC;AAOH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,IAAY,EACZ,UAA+B,EAAE;IAEjC,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,IAAI,CAAC,CAAC,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;QAC1B,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC;QACzB,GAAG,mBAAmB;QACtB,GAAG,CAAC,OAAO,CAAC,UAAU,IAAI,EAAE,CAAC;KAC9B,CAAC,CAAC;IACH,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC;IAE7E,MAAM,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;IACxD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,KAAK,UAAU,IAAI,CACjB,IAAY,EACZ,OAAe,EACf,UAAuB,EACvB,UAAoB,EACpB,GAAa;IAEb,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,OAAO,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAE9D,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QAE/C,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;YACvB,IAAI,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC9B,SAAS;YACX,CAAC;YACD,MAAM,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC;YACxD,SAAS;QACX,CAAC;QAED,IAAI,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;YAClB,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC1B,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;gBAClD,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;oBAC9B,SAAS;gBACX,CAAC;YACH,CAAC;YACD,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACrB,CAAC;IACH,CAAC;AACH,CAAC;AAED,KAAK,UAAU,MAAM,CAAC,MAAc;IAClC,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,MAAM,CAAC,CAAC;QACrB,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
@@ -0,0 +1,5 @@
1
+ export type IdPrefix = "SPEC" | "BR" | "SC" | "UI" | "API" | "DATA";
2
+ export declare function extractIds(text: string, prefix: IdPrefix): string[];
3
+ export declare function extractAllIds(text: string): string[];
4
+ export declare function extractInvalidIds(text: string, prefixes: IdPrefix[]): string[];
5
+ //# sourceMappingURL=ids.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ids.d.ts","sourceRoot":"","sources":["../../src/core/ids.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,KAAK,GAAG,MAAM,CAAC;AAoBpE,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,GAAG,MAAM,EAAE,CAInE;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAMpD;AAED,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,QAAQ,EAAE,GACnB,MAAM,EAAE,CAWV"}
@@ -0,0 +1,49 @@
1
+ const ID_PATTERNS = {
2
+ SPEC: /\bSPEC-[A-Z0-9-]+\b/g,
3
+ BR: /\bBR-[A-Z0-9-]+\b/g,
4
+ SC: /\bSC-[A-Z0-9-]+\b/g,
5
+ UI: /\bUI-[A-Z0-9-]+\b/g,
6
+ API: /\bAPI-[A-Z0-9-]+\b/g,
7
+ DATA: /\bDATA-[A-Z0-9-]+\b/g,
8
+ };
9
+ const LOOSE_ID_PATTERNS = {
10
+ SPEC: /\bSPEC-[A-Za-z0-9_-]+\b/gi,
11
+ BR: /\bBR-[A-Za-z0-9_-]+\b/gi,
12
+ SC: /\bSC-[A-Za-z0-9_-]+\b/gi,
13
+ UI: /\bUI-[A-Za-z0-9_-]+\b/gi,
14
+ API: /\bAPI-[A-Za-z0-9_-]+\b/gi,
15
+ DATA: /\bDATA-[A-Za-z0-9_-]+\b/gi,
16
+ };
17
+ export function extractIds(text, prefix) {
18
+ const pattern = ID_PATTERNS[prefix];
19
+ const matches = text.match(pattern);
20
+ return unique(matches ?? []);
21
+ }
22
+ export function extractAllIds(text) {
23
+ const all = [];
24
+ Object.keys(ID_PATTERNS).forEach((prefix) => {
25
+ all.push(...extractIds(text, prefix));
26
+ });
27
+ return unique(all);
28
+ }
29
+ export function extractInvalidIds(text, prefixes) {
30
+ const invalid = [];
31
+ for (const prefix of prefixes) {
32
+ const candidates = text.match(LOOSE_ID_PATTERNS[prefix]) ?? [];
33
+ for (const candidate of candidates) {
34
+ if (!isValidId(candidate, prefix)) {
35
+ invalid.push(candidate);
36
+ }
37
+ }
38
+ }
39
+ return unique(invalid);
40
+ }
41
+ function unique(values) {
42
+ return Array.from(new Set(values));
43
+ }
44
+ function isValidId(value, prefix) {
45
+ const pattern = ID_PATTERNS[prefix];
46
+ const strict = new RegExp(pattern.source);
47
+ return strict.test(value);
48
+ }
49
+ //# sourceMappingURL=ids.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ids.js","sourceRoot":"","sources":["../../src/core/ids.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,GAA6B;IAC5C,IAAI,EAAE,sBAAsB;IAC5B,EAAE,EAAE,oBAAoB;IACxB,EAAE,EAAE,oBAAoB;IACxB,EAAE,EAAE,oBAAoB;IACxB,GAAG,EAAE,qBAAqB;IAC1B,IAAI,EAAE,sBAAsB;CAC7B,CAAC;AAEF,MAAM,iBAAiB,GAA6B;IAClD,IAAI,EAAE,2BAA2B;IACjC,EAAE,EAAE,yBAAyB;IAC7B,EAAE,EAAE,yBAAyB;IAC7B,EAAE,EAAE,yBAAyB;IAC7B,GAAG,EAAE,0BAA0B;IAC/B,IAAI,EAAE,2BAA2B;CAClC,CAAC;AAEF,MAAM,UAAU,UAAU,CAAC,IAAY,EAAE,MAAgB;IACvD,MAAM,OAAO,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;IACpC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACpC,OAAO,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,MAAM,GAAG,GAAa,EAAE,CAAC;IACxB,MAAM,CAAC,IAAI,CAAC,WAAW,CAAgB,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE;QAC1D,GAAG,CAAC,IAAI,CAAC,GAAG,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;IACH,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,IAAY,EACZ,QAAoB;IAEpB,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,KAAK,MAAM,MAAM,IAAI,QAAQ,EAAE,CAAC;QAC9B,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;QAC/D,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;YACnC,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,MAAM,CAAC,EAAE,CAAC;gBAClC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAC1B,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC;AACzB,CAAC;AAED,SAAS,MAAM,CAAC,MAAgB;IAC9B,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;AACrC,CAAC;AAED,SAAS,SAAS,CAAC,KAAa,EAAE,MAAgB;IAChD,MAAM,OAAO,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;IACpC,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAC1C,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC5B,CAAC"}
@@ -0,0 +1,11 @@
1
+ export * from "./config.js";
2
+ export * from "./ids.js";
3
+ export * from "./report.js";
4
+ export * from "./types.js";
5
+ export * from "./validate.js";
6
+ export * from "./version.js";
7
+ export * from "./validators/contracts.js";
8
+ export * from "./validators/scenario.js";
9
+ export * from "./validators/spec.js";
10
+ export * from "./validators/traceability.js";
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC;AACzC,cAAc,sBAAsB,CAAC;AACrC,cAAc,8BAA8B,CAAC"}
@@ -0,0 +1,11 @@
1
+ export * from "./config.js";
2
+ export * from "./ids.js";
3
+ export * from "./report.js";
4
+ export * from "./types.js";
5
+ export * from "./validate.js";
6
+ export * from "./version.js";
7
+ export * from "./validators/contracts.js";
8
+ export * from "./validators/scenario.js";
9
+ export * from "./validators/spec.js";
10
+ export * from "./validators/traceability.js";
11
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC;AACzC,cAAc,sBAAsB,CAAC;AACrC,cAAc,8BAA8B,CAAC"}
@@ -0,0 +1,41 @@
1
+ import { type ConfigLoadResult } from "./config.js";
2
+ import type { Issue, ValidationCounts, ValidationResult } from "./types.js";
3
+ export type ReportSummary = {
4
+ specs: number;
5
+ scenarios: number;
6
+ decisions: number;
7
+ rules: number;
8
+ contracts: {
9
+ api: number;
10
+ ui: number;
11
+ db: number;
12
+ };
13
+ counts: ValidationCounts;
14
+ };
15
+ export type ReportIds = {
16
+ spec: string[];
17
+ br: string[];
18
+ sc: string[];
19
+ ui: string[];
20
+ api: string[];
21
+ data: string[];
22
+ };
23
+ export type ReportTraceability = {
24
+ upstreamIdsFound: number;
25
+ referencedInCodeOrTests: boolean;
26
+ };
27
+ export type ReportData = {
28
+ tool: "qfai";
29
+ version: string;
30
+ generatedAt: string;
31
+ root: string;
32
+ configPath: string;
33
+ summary: ReportSummary;
34
+ ids: ReportIds;
35
+ traceability: ReportTraceability;
36
+ issues: Issue[];
37
+ };
38
+ export declare function createReportData(root: string, validation?: ValidationResult, configResult?: ConfigLoadResult): Promise<ReportData>;
39
+ export declare function formatReportMarkdown(data: ReportData): string;
40
+ export declare function formatReportJson(data: ReportData): string;
41
+ //# sourceMappingURL=report.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../src/core/report.ts"],"names":[],"mappings":"AACA,OAAO,EAA2B,KAAK,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAI7E,OAAO,KAAK,EAAE,KAAK,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAI5E,MAAM,MAAM,aAAa,GAAG;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE;QACT,GAAG,EAAE,MAAM,CAAC;QACZ,EAAE,EAAE,MAAM,CAAC;QACX,EAAE,EAAE,MAAM,CAAC;KACZ,CAAC;IACF,MAAM,EAAE,gBAAgB,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG;IACtB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,EAAE,EAAE,MAAM,EAAE,CAAC;IACb,EAAE,EAAE,MAAM,EAAE,CAAC;IACb,EAAE,EAAE,MAAM,EAAE,CAAC;IACb,GAAG,EAAE,MAAM,EAAE,CAAC;IACd,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,gBAAgB,EAAE,MAAM,CAAC;IACzB,uBAAuB,EAAE,OAAO,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,aAAa,CAAC;IACvB,GAAG,EAAE,SAAS,CAAC;IACf,YAAY,EAAE,kBAAkB,CAAC;IACjC,MAAM,EAAE,KAAK,EAAE,CAAC;CACjB,CAAC;AAIF,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,MAAM,EACZ,UAAU,CAAC,EAAE,gBAAgB,EAC7B,YAAY,CAAC,EAAE,gBAAgB,GAC9B,OAAO,CAAC,UAAU,CAAC,CAqFrB;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAsF7D;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAEzD"}