qfai 0.4.4 → 0.4.6

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.
@@ -1,6 +1,6 @@
1
1
  # Contracts (UI / API / DB)
2
2
 
3
- 契約は「システム外部との約束」を明文化する場所です。Scenario または Spec から参照される前提で作成します。
3
+ 契約は「システム外部との約束」を明文化する場所です。Spec(spec.md)の `QFAI-CONTRACT-REF` による参照が必須で、これが Spec→Contract 対応の SSOT になります。Scenario からの参照は任意です。
4
4
 
5
5
  ## 置くべきファイル
6
6
 
@@ -11,6 +11,7 @@
11
11
  ## 契約ID宣言(必須)
12
12
 
13
13
  - 1ファイル = 1ID
14
+ - 契約IDの正は契約ファイル側(`QFAI-CONTRACT-ID` が SSOT)
14
15
  - ファイル内に `QFAI-CONTRACT-ID: <ID>` をコメント行で宣言する
15
16
  - 例: `# QFAI-CONTRACT-ID: API-0001` / `// QFAI-CONTRACT-ID: UI-0001` / `-- QFAI-CONTRACT-ID: DB-0001`
16
17
 
@@ -61,10 +62,10 @@ CREATE TABLE sample_table (
61
62
 
62
63
  ## 依存関係
63
64
 
64
- - Spec → Contracts(`QFAI-CONTRACT-REF` で宣言、`none` 可)
65
- - Scenario → Contracts(UI/API/DB の参照は任意)
65
+ - Spec → Contracts(spec.md に `QFAI-CONTRACT-REF` を必ず1行以上宣言、0件は `none`。この行が SSOT)
66
+ - Scenario → Contracts(UI/API/DB の参照は任意。付けるなら関連が強い箇所に限定)
66
67
 
67
68
  ## 良い例 / 悪い例
68
69
 
69
- - 良い例: `@SC-xxxx` から `UI-xxxx` が参照されている
70
- - 悪い例: 契約が Scenario から一切参照されない
70
+ - 良い例: Spec で契約を参照し、必要に応じて Scenario でも参照している
71
+ - 悪い例: Spec が契約を参照しておらず orphan contract が発生する(allowOrphanContracts=false で error)
@@ -1,9 +1,10 @@
1
1
  # Traceability
2
2
 
3
- 参照は下流→上流のみを許可する。
3
+ 参照は下流→上流のみを許可する(下流参照禁止の対象はテスト/実装)。
4
4
 
5
- - SCBR を参照する
6
- - テスト/コードは SC を参照する
7
- - Spec は契約/テストを参照しない
5
+ - SpecQFAI-CONTRACT-REF で契約IDを宣言する(none可、宣言行は必須)
6
+ - Scenario は @SPEC-xxxx / @SC-xxxx / @BR-xxxx を持つ(契約ID参照は任意)
7
+ - テスト/コードは QFAI:SC-xxxx で SC を参照する
8
+ - Spec はテスト/実装(src/tests)を参照しない
8
9
 
9
10
  違反は CI で検出される前提で運用する。
@@ -18,7 +18,7 @@
18
18
  - Spec本文に書かれていないことは推測しない(不明は `TBD` と書く)。
19
19
  - SpecのIDとタイトルは、本文先頭の `# SPEC-xxxx ...` を正とし、ファイル名は補助。
20
20
  - 各Specについて最低限以下を表にする:
21
- - SPEC-ID / Title / Outcome(1行) / Status / SC / UI / API / DB(or DATA) / Tags
21
+ - SPEC-ID / Title / Outcome(1行) / Status / SC / UI / API / DB / Tags
22
22
  - 参照が欠けている場合(例: SCが未記載)は “欠落一覧” に列挙する。
23
23
 
24
24
  ## Format
@@ -3,7 +3,7 @@ Feature: 注文登録
3
3
 
4
4
  Rule: 承認者が存在する
5
5
 
6
- @SC-0001 @BR-0001 @UI-0001 @API-0001 @DATA-0001
6
+ @SC-0001 @BR-0001 @UI-0001 @API-0001 @DB-0001
7
7
  Scenario: 承認者が承認するまで注文は確定しない
8
8
  Given ...
9
9
  When ...
@@ -66,9 +66,37 @@ function isValidationResult(value) {
66
66
  if (!counts) {
67
67
  return false;
68
68
  }
69
- return (typeof counts.info === "number" &&
70
- typeof counts.warning === "number" &&
71
- typeof counts.error === "number");
69
+ if (typeof counts.info !== "number" ||
70
+ typeof counts.warning !== "number" ||
71
+ typeof counts.error !== "number") {
72
+ return false;
73
+ }
74
+ const traceability = record.traceability;
75
+ if (!traceability || typeof traceability !== "object") {
76
+ return false;
77
+ }
78
+ const sc = traceability.sc;
79
+ const testFiles = traceability.testFiles;
80
+ if (!sc || !testFiles) {
81
+ return false;
82
+ }
83
+ if (typeof sc.total !== "number" ||
84
+ typeof sc.covered !== "number" ||
85
+ typeof sc.missing !== "number") {
86
+ return false;
87
+ }
88
+ if (!Array.isArray(sc.missingIds)) {
89
+ return false;
90
+ }
91
+ if (!sc.refs || typeof sc.refs !== "object") {
92
+ return false;
93
+ }
94
+ if (!Array.isArray(testFiles.globs) ||
95
+ !Array.isArray(testFiles.excludeGlobs) ||
96
+ typeof testFiles.matchedFileCount !== "number") {
97
+ return false;
98
+ }
99
+ return true;
72
100
  }
73
101
  function isMissingFileError(error) {
74
102
  if (!error || typeof error !== "object") {
@@ -1 +1 @@
1
- {"version":3,"file":"report.js","sourceRoot":"","sources":["../../../src/cli/commands/report.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"report.js","sourceRoot":"","sources":["../../../src/cli/commands/report.ts"],"names":[],"mappings":"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"}
@@ -667,14 +667,14 @@ async function collectUiContractFiles(uiRoot) {
667
667
  async function collectApiContractFiles(apiRoot) {
668
668
  return collectFiles(apiRoot, { extensions: [".yaml", ".yml", ".json"] });
669
669
  }
670
- async function collectDataContractFiles(dataRoot) {
671
- return collectFiles(dataRoot, { extensions: [".sql"] });
670
+ async function collectDbContractFiles(dbRoot) {
671
+ return collectFiles(dbRoot, { extensions: [".sql"] });
672
672
  }
673
- async function collectContractFiles(uiRoot, apiRoot, dataRoot) {
673
+ async function collectContractFiles(uiRoot, apiRoot, dbRoot) {
674
674
  const [ui, api, db] = await Promise.all([
675
675
  collectUiContractFiles(uiRoot),
676
676
  collectApiContractFiles(apiRoot),
677
- collectDataContractFiles(dataRoot)
677
+ collectDbContractFiles(dbRoot)
678
678
  ]);
679
679
  return { ui, api, db };
680
680
  }
@@ -722,7 +722,7 @@ async function buildContractIndex(root, config) {
722
722
  const [uiFiles, apiFiles, dbFiles] = await Promise.all([
723
723
  collectUiContractFiles(uiRoot),
724
724
  collectApiContractFiles(apiRoot),
725
- collectDataContractFiles(dbRoot)
725
+ collectDbContractFiles(dbRoot)
726
726
  ]);
727
727
  const index = {
728
728
  ids: /* @__PURE__ */ new Set(),
@@ -1280,8 +1280,8 @@ var import_promises8 = require("fs/promises");
1280
1280
  var import_node_path9 = __toESM(require("path"), 1);
1281
1281
  var import_node_url2 = require("url");
1282
1282
  async function resolveToolVersion() {
1283
- if ("0.4.4".length > 0) {
1284
- return "0.4.4";
1283
+ if ("0.4.6".length > 0) {
1284
+ return "0.4.6";
1285
1285
  }
1286
1286
  try {
1287
1287
  const packagePath = resolvePackageJsonPath();
@@ -1329,7 +1329,7 @@ async function validateContracts(root, config) {
1329
1329
  const contractsRoot = resolvePath(root, config, "contractsDir");
1330
1330
  issues.push(...await validateUiContracts(import_node_path11.default.join(contractsRoot, "ui")));
1331
1331
  issues.push(...await validateApiContracts(import_node_path11.default.join(contractsRoot, "api")));
1332
- issues.push(...await validateDataContracts(import_node_path11.default.join(contractsRoot, "db")));
1332
+ issues.push(...await validateDbContracts(import_node_path11.default.join(contractsRoot, "db")));
1333
1333
  const contractIndex = await buildContractIndex(root, config);
1334
1334
  issues.push(...validateDuplicateContractIds(contractIndex));
1335
1335
  return issues;
@@ -1457,15 +1457,15 @@ async function validateApiContracts(apiRoot) {
1457
1457
  }
1458
1458
  return issues;
1459
1459
  }
1460
- async function validateDataContracts(dataRoot) {
1461
- const files = await collectDataContractFiles(dataRoot);
1460
+ async function validateDbContracts(dbRoot) {
1461
+ const files = await collectDbContractFiles(dbRoot);
1462
1462
  if (files.length === 0) {
1463
1463
  return [
1464
1464
  issue(
1465
1465
  "QFAI-DB-000",
1466
1466
  "DB \u5951\u7D04\u30D5\u30A1\u30A4\u30EB\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002",
1467
1467
  "info",
1468
- dataRoot,
1468
+ dbRoot,
1469
1469
  "contracts.db.files"
1470
1470
  )
1471
1471
  ];
@@ -3086,7 +3086,31 @@ function isValidationResult(value) {
3086
3086
  if (!counts) {
3087
3087
  return false;
3088
3088
  }
3089
- return typeof counts.info === "number" && typeof counts.warning === "number" && typeof counts.error === "number";
3089
+ if (typeof counts.info !== "number" || typeof counts.warning !== "number" || typeof counts.error !== "number") {
3090
+ return false;
3091
+ }
3092
+ const traceability = record2.traceability;
3093
+ if (!traceability || typeof traceability !== "object") {
3094
+ return false;
3095
+ }
3096
+ const sc = traceability.sc;
3097
+ const testFiles = traceability.testFiles;
3098
+ if (!sc || !testFiles) {
3099
+ return false;
3100
+ }
3101
+ if (typeof sc.total !== "number" || typeof sc.covered !== "number" || typeof sc.missing !== "number") {
3102
+ return false;
3103
+ }
3104
+ if (!Array.isArray(sc.missingIds)) {
3105
+ return false;
3106
+ }
3107
+ if (!sc.refs || typeof sc.refs !== "object") {
3108
+ return false;
3109
+ }
3110
+ if (!Array.isArray(testFiles.globs) || !Array.isArray(testFiles.excludeGlobs) || typeof testFiles.matchedFileCount !== "number") {
3111
+ return false;
3112
+ }
3113
+ return true;
3090
3114
  }
3091
3115
  function isMissingFileError5(error2) {
3092
3116
  if (!error2 || typeof error2 !== "object") {