qfai 0.5.0 → 0.6.0

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 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/core/config.ts","../src/core/ids.ts","../src/core/report.ts","../src/core/contractIndex.ts","../src/core/discovery.ts","../src/core/fs.ts","../src/core/specLayout.ts","../src/core/contractsDecl.ts","../src/core/parse/markdown.ts","../src/core/parse/spec.ts","../src/core/traceability.ts","../src/core/gherkin/parse.ts","../src/core/scenarioModel.ts","../src/core/version.ts","../src/core/validators/contracts.ts","../src/core/contracts.ts","../src/core/validators/delta.ts","../src/core/validators/ids.ts","../src/core/validators/scenario.ts","../src/core/validators/spec.ts","../src/core/validators/traceability.ts","../src/core/validate.ts"],"sourcesContent":["export * from \"./core/index.js\";\n","import { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport { parse as parseYaml } from \"yaml\";\n\nimport type { Issue } from \"./types.js\";\n\nexport type FailOn = \"never\" | \"warning\" | \"error\";\nexport type OutputFormat = \"text\" | \"github\";\nexport type TraceabilitySeverity = \"warning\" | \"error\";\n\nexport type QfaiPaths = {\n contractsDir: string;\n specsDir: string;\n rulesDir: string;\n outDir: string;\n promptsDir: string;\n srcDir: string;\n testsDir: string;\n};\n\nexport type QfaiValidationConfig = {\n failOn: FailOn;\n require: {\n specSections: string[];\n };\n traceability: {\n brMustHaveSc: boolean;\n scMustHaveTest: boolean;\n testFileGlobs: string[];\n testFileExcludeGlobs: string[];\n scNoTestSeverity: TraceabilitySeverity;\n allowOrphanContracts: boolean;\n unknownContractIdSeverity: TraceabilitySeverity;\n };\n};\n\nexport type QfaiOutputConfig = {\n validateJsonPath: string;\n};\n\nexport type QfaiConfig = {\n paths: QfaiPaths;\n validation: QfaiValidationConfig;\n output: QfaiOutputConfig;\n};\n\nexport type ConfigPathKey = keyof QfaiPaths;\n\nexport type ConfigLoadResult = {\n config: QfaiConfig;\n issues: Issue[];\n configPath: string;\n};\n\nexport const defaultConfig: QfaiConfig = {\n paths: {\n contractsDir: \".qfai/contracts\",\n specsDir: \".qfai/specs\",\n rulesDir: \".qfai/rules\",\n outDir: \".qfai/out\",\n promptsDir: \".qfai/prompts\",\n srcDir: \"src\",\n testsDir: \"tests\",\n },\n validation: {\n failOn: \"error\",\n require: {\n specSections: [\n \"背景\",\n \"スコープ\",\n \"非ゴール\",\n \"用語\",\n \"前提\",\n \"決定事項\",\n \"業務ルール\",\n ],\n },\n traceability: {\n brMustHaveSc: true,\n scMustHaveTest: true,\n testFileGlobs: [],\n testFileExcludeGlobs: [],\n scNoTestSeverity: \"error\",\n allowOrphanContracts: false,\n unknownContractIdSeverity: \"error\",\n },\n },\n output: {\n validateJsonPath: \".qfai/out/validate.json\",\n },\n};\n\nexport function getConfigPath(root: string): string {\n return path.join(root, \"qfai.config.yaml\");\n}\n\nexport async function loadConfig(root: string): Promise<ConfigLoadResult> {\n const configPath = getConfigPath(root);\n const issues: Issue[] = [];\n\n let parsed: unknown;\n try {\n const raw = await readFile(configPath, \"utf-8\");\n parsed = parseYaml(raw);\n } catch (error) {\n if (isMissingFile(error)) {\n return { config: defaultConfig, issues, configPath };\n }\n issues.push(configIssue(configPath, formatError(error)));\n return { config: defaultConfig, issues, configPath };\n }\n\n const normalized = normalizeConfig(parsed, configPath, issues);\n return { config: normalized, issues, configPath };\n}\n\nexport function resolvePath(\n root: string,\n config: QfaiConfig,\n key: ConfigPathKey,\n): string {\n return path.resolve(root, config.paths[key]);\n}\n\nfunction normalizeConfig(\n raw: unknown,\n configPath: string,\n issues: Issue[],\n): QfaiConfig {\n if (!isRecord(raw)) {\n issues.push(configIssue(configPath, \"設定ファイルの形式が不正です。\"));\n return defaultConfig;\n }\n\n return {\n paths: normalizePaths(raw.paths, configPath, issues),\n validation: normalizeValidation(raw.validation, configPath, issues),\n output: normalizeOutput(raw.output, configPath, issues),\n };\n}\n\nfunction normalizePaths(\n raw: unknown,\n configPath: string,\n issues: Issue[],\n): QfaiPaths {\n const base = defaultConfig.paths;\n if (!raw) {\n return base;\n }\n if (!isRecord(raw)) {\n issues.push(\n configIssue(configPath, \"paths はオブジェクトである必要があります。\"),\n );\n return base;\n }\n\n return {\n contractsDir: readString(\n raw.contractsDir,\n base.contractsDir,\n \"paths.contractsDir\",\n configPath,\n issues,\n ),\n specsDir: readString(\n raw.specsDir,\n base.specsDir,\n \"paths.specsDir\",\n configPath,\n issues,\n ),\n rulesDir: readString(\n raw.rulesDir,\n base.rulesDir,\n \"paths.rulesDir\",\n configPath,\n issues,\n ),\n outDir: readString(\n raw.outDir,\n base.outDir,\n \"paths.outDir\",\n configPath,\n issues,\n ),\n promptsDir: readString(\n raw.promptsDir,\n base.promptsDir,\n \"paths.promptsDir\",\n configPath,\n issues,\n ),\n srcDir: readString(\n raw.srcDir,\n base.srcDir,\n \"paths.srcDir\",\n configPath,\n issues,\n ),\n testsDir: readString(\n raw.testsDir,\n base.testsDir,\n \"paths.testsDir\",\n configPath,\n issues,\n ),\n };\n}\n\nfunction normalizeValidation(\n raw: unknown,\n configPath: string,\n issues: Issue[],\n): QfaiValidationConfig {\n const base = defaultConfig.validation;\n if (!raw) {\n return base;\n }\n if (!isRecord(raw)) {\n issues.push(\n configIssue(\n configPath,\n \"validation はオブジェクトである必要があります。\",\n ),\n );\n return base;\n }\n\n let requireRaw: Record<string, unknown> | undefined;\n if (raw.require === undefined) {\n requireRaw = undefined;\n } else if (isRecord(raw.require)) {\n requireRaw = raw.require;\n } else {\n issues.push(\n configIssue(\n configPath,\n \"validation.require はオブジェクトである必要があります。\",\n ),\n );\n requireRaw = undefined;\n }\n\n let traceabilityRaw: Record<string, unknown> | undefined;\n if (raw.traceability === undefined) {\n traceabilityRaw = undefined;\n } else if (isRecord(raw.traceability)) {\n traceabilityRaw = raw.traceability;\n } else {\n issues.push(\n configIssue(\n configPath,\n \"validation.traceability はオブジェクトである必要があります。\",\n ),\n );\n traceabilityRaw = undefined;\n }\n\n return {\n failOn: readFailOn(\n raw.failOn,\n base.failOn,\n \"validation.failOn\",\n configPath,\n issues,\n ),\n require: {\n specSections: readStringArray(\n requireRaw?.specSections,\n base.require.specSections,\n \"validation.require.specSections\",\n configPath,\n issues,\n ),\n },\n traceability: {\n brMustHaveSc: readBoolean(\n traceabilityRaw?.brMustHaveSc,\n base.traceability.brMustHaveSc,\n \"validation.traceability.brMustHaveSc\",\n configPath,\n issues,\n ),\n scMustHaveTest: readBoolean(\n traceabilityRaw?.scMustHaveTest,\n base.traceability.scMustHaveTest,\n \"validation.traceability.scMustHaveTest\",\n configPath,\n issues,\n ),\n testFileGlobs: readStringArray(\n traceabilityRaw?.testFileGlobs,\n base.traceability.testFileGlobs,\n \"validation.traceability.testFileGlobs\",\n configPath,\n issues,\n ),\n testFileExcludeGlobs: readStringArray(\n traceabilityRaw?.testFileExcludeGlobs,\n base.traceability.testFileExcludeGlobs,\n \"validation.traceability.testFileExcludeGlobs\",\n configPath,\n issues,\n ),\n scNoTestSeverity: readTraceabilitySeverity(\n traceabilityRaw?.scNoTestSeverity,\n base.traceability.scNoTestSeverity,\n \"validation.traceability.scNoTestSeverity\",\n configPath,\n issues,\n ),\n allowOrphanContracts: readBoolean(\n traceabilityRaw?.allowOrphanContracts,\n base.traceability.allowOrphanContracts,\n \"validation.traceability.allowOrphanContracts\",\n configPath,\n issues,\n ),\n unknownContractIdSeverity: readTraceabilitySeverity(\n traceabilityRaw?.unknownContractIdSeverity,\n base.traceability.unknownContractIdSeverity,\n \"validation.traceability.unknownContractIdSeverity\",\n configPath,\n issues,\n ),\n },\n };\n}\n\nfunction normalizeOutput(\n raw: unknown,\n configPath: string,\n issues: Issue[],\n): QfaiOutputConfig {\n const base = defaultConfig.output;\n if (!raw) {\n return base;\n }\n if (!isRecord(raw)) {\n issues.push(\n configIssue(configPath, \"output はオブジェクトである必要があります。\"),\n );\n return base;\n }\n\n return {\n validateJsonPath: readString(\n raw.validateJsonPath,\n base.validateJsonPath,\n \"output.validateJsonPath\",\n configPath,\n issues,\n ),\n };\n}\n\nfunction readString(\n value: unknown,\n fallback: string,\n label: string,\n configPath: string,\n issues: Issue[],\n): string {\n if (typeof value === \"string\" && value.trim().length > 0) {\n return value;\n }\n if (value !== undefined) {\n issues.push(\n configIssue(configPath, `${label} は文字列である必要があります。`),\n );\n }\n return fallback;\n}\n\nfunction readStringArray(\n value: unknown,\n fallback: string[],\n label: string,\n configPath: string,\n issues: Issue[],\n): string[] {\n if (Array.isArray(value) && value.every((item) => typeof item === \"string\")) {\n return value;\n }\n if (value !== undefined) {\n issues.push(\n configIssue(configPath, `${label} は文字列配列である必要があります。`),\n );\n }\n return fallback;\n}\n\nfunction readBoolean(\n value: unknown,\n fallback: boolean,\n label: string,\n configPath: string,\n issues: Issue[],\n): boolean {\n if (typeof value === \"boolean\") {\n return value;\n }\n if (value !== undefined) {\n issues.push(\n configIssue(configPath, `${label} は真偽値である必要があります。`),\n );\n }\n return fallback;\n}\n\nfunction readFailOn(\n value: unknown,\n fallback: FailOn,\n label: string,\n configPath: string,\n issues: Issue[],\n): FailOn {\n if (value === \"never\" || value === \"warning\" || value === \"error\") {\n return value;\n }\n if (value !== undefined) {\n issues.push(\n configIssue(\n configPath,\n `${label} は never|warning|error のいずれかである必要があります。`,\n ),\n );\n }\n return fallback;\n}\n\nfunction readTraceabilitySeverity(\n value: unknown,\n fallback: TraceabilitySeverity,\n label: string,\n configPath: string,\n issues: Issue[],\n): TraceabilitySeverity {\n if (value === \"warning\" || value === \"error\") {\n return value;\n }\n if (value !== undefined) {\n issues.push(\n configIssue(\n configPath,\n `${label} は warning|error のいずれかである必要があります。`,\n ),\n );\n }\n return fallback;\n}\n\nfunction configIssue(file: string, message: string): Issue {\n return {\n code: \"QFAI_CONFIG_INVALID\",\n severity: \"error\",\n message,\n file,\n rule: \"config.invalid\",\n };\n}\n\nfunction isMissingFile(error: unknown): boolean {\n if (error && typeof error === \"object\" && \"code\" in error) {\n return (error as { code?: string }).code === \"ENOENT\";\n }\n return false;\n}\n\nfunction formatError(error: unknown): string {\n if (error instanceof Error) {\n return error.message;\n }\n return String(error);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n","export type IdPrefix = \"SPEC\" | \"BR\" | \"SC\" | \"UI\" | \"API\" | \"DB\";\nexport type IdFormatPrefix = IdPrefix | \"ADR\";\n\nconst ID_PREFIXES: IdPrefix[] = [\"SPEC\", \"BR\", \"SC\", \"UI\", \"API\", \"DB\"];\n\nconst STRICT_ID_PATTERNS: Record<IdFormatPrefix, RegExp> = {\n SPEC: /\\bSPEC-\\d{4}\\b/g,\n BR: /\\bBR-\\d{4}\\b/g,\n SC: /\\bSC-\\d{4}\\b/g,\n UI: /\\bUI-\\d{4}\\b/g,\n API: /\\bAPI-\\d{4}\\b/g,\n DB: /\\bDB-\\d{4}\\b/g,\n ADR: /\\bADR-\\d{4}\\b/g,\n};\n\nconst LOOSE_ID_PATTERNS: Record<IdFormatPrefix, RegExp> = {\n SPEC: /\\bSPEC-[A-Za-z0-9_-]+\\b/gi,\n BR: /\\bBR-[A-Za-z0-9_-]+\\b/gi,\n SC: /\\bSC-[A-Za-z0-9_-]+\\b/gi,\n UI: /\\bUI-[A-Za-z0-9_-]+\\b/gi,\n API: /\\bAPI-[A-Za-z0-9_-]+\\b/gi,\n DB: /\\bDB-[A-Za-z0-9_-]+\\b/gi,\n ADR: /\\bADR-[A-Za-z0-9_-]+\\b/gi,\n};\n\nexport function extractIds(text: string, prefix: IdPrefix): string[] {\n const pattern = STRICT_ID_PATTERNS[prefix];\n const matches = text.match(pattern);\n return unique(matches ?? []);\n}\n\nexport function extractAllIds(text: string): string[] {\n const all: string[] = [];\n ID_PREFIXES.forEach((prefix) => {\n all.push(...extractIds(text, prefix));\n });\n return unique(all);\n}\n\nexport function extractInvalidIds(\n text: string,\n prefixes: IdFormatPrefix[],\n): string[] {\n const invalid: string[] = [];\n for (const prefix of prefixes) {\n const candidates = text.match(LOOSE_ID_PATTERNS[prefix]) ?? [];\n for (const candidate of candidates) {\n if (!isValidId(candidate, prefix)) {\n invalid.push(candidate);\n }\n }\n }\n return unique(invalid);\n}\n\nfunction unique(values: string[]): string[] {\n return Array.from(new Set(values));\n}\n\nfunction isValidId(value: string, prefix: IdFormatPrefix): boolean {\n const pattern = STRICT_ID_PATTERNS[prefix];\n const strict = new RegExp(pattern.source);\n return strict.test(value);\n}\n","import { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { buildContractIndex } from \"./contractIndex.js\";\nimport { loadConfig, resolvePath, type ConfigLoadResult } from \"./config.js\";\nimport {\n collectContractFiles,\n collectScenarioFiles,\n collectSpecFiles,\n} from \"./discovery.js\";\nimport { collectFiles } from \"./fs.js\";\nimport { extractAllIds, extractIds, type IdPrefix } from \"./ids.js\";\nimport { parseSpec } from \"./parse/spec.js\";\nimport {\n buildScCoverage,\n collectScIdsFromScenarioFiles,\n collectScIdSourcesFromScenarioFiles,\n collectScTestReferences,\n type ScCoverage,\n type TestFileScan,\n} from \"./traceability.js\";\nimport type { Issue, ValidationCounts, ValidationResult } from \"./types.js\";\nimport { validateProject } from \"./validate.js\";\nimport { resolveToolVersion } from \"./version.js\";\n\nexport type ReportSummary = {\n specs: number;\n scenarios: number;\n contracts: {\n api: number;\n ui: number;\n db: number;\n };\n counts: ValidationCounts;\n};\n\nexport type ReportIds = {\n spec: string[];\n br: string[];\n sc: string[];\n ui: string[];\n api: string[];\n db: string[];\n};\n\nexport type ReportContractCoverage = {\n total: number;\n referenced: number;\n orphan: number;\n idToSpecs: Record<string, string[]>;\n};\n\nexport type ReportSpecCoverage = {\n contractRefMissing: number;\n missingRefSpecs: string[];\n specToContractIds: Record<string, string[]>;\n};\n\nexport type ReportTraceability = {\n upstreamIdsFound: number;\n referencedInCodeOrTests: boolean;\n sc: ScCoverage;\n scSources: Record<string, string[]>;\n testFiles: TestFileScan;\n contracts: ReportContractCoverage;\n specs: ReportSpecCoverage;\n};\n\nexport type ReportData = {\n tool: \"qfai\";\n version: string;\n generatedAt: string;\n root: string;\n configPath: string;\n summary: ReportSummary;\n ids: ReportIds;\n traceability: ReportTraceability;\n issues: Issue[];\n};\n\nconst ID_PREFIXES: IdPrefix[] = [\"SPEC\", \"BR\", \"SC\", \"UI\", \"API\", \"DB\"];\n\nexport async function createReportData(\n root: string,\n validation?: ValidationResult,\n configResult?: ConfigLoadResult,\n): Promise<ReportData> {\n const resolved = configResult ?? (await loadConfig(root));\n const config = resolved.config;\n const configPath = resolved.configPath;\n\n const specsRoot = resolvePath(root, config, \"specsDir\");\n const contractsRoot = resolvePath(root, config, \"contractsDir\");\n const apiRoot = path.join(contractsRoot, \"api\");\n const uiRoot = path.join(contractsRoot, \"ui\");\n const dbRoot = path.join(contractsRoot, \"db\");\n const srcRoot = resolvePath(root, config, \"srcDir\");\n const testsRoot = resolvePath(root, config, \"testsDir\");\n\n const specFiles = await collectSpecFiles(specsRoot);\n const scenarioFiles = await collectScenarioFiles(specsRoot);\n const {\n api: apiFiles,\n ui: uiFiles,\n db: dbFiles,\n } = await collectContractFiles(uiRoot, apiRoot, dbRoot);\n const contractIndex = await buildContractIndex(root, config);\n const contractIdList = Array.from(contractIndex.ids);\n const specContractRefs = await collectSpecContractRefs(\n specFiles,\n contractIdList,\n );\n const referencedContracts = new Set<string>();\n for (const ids of specContractRefs.specToContractIds.values()) {\n ids.forEach((id) => referencedContracts.add(id));\n }\n const referencedContractCount = contractIdList.filter((id) =>\n referencedContracts.has(id),\n ).length;\n const orphanContractCount = contractIdList.filter(\n (id) => !referencedContracts.has(id),\n ).length;\n const contractIdToSpecsRecord = mapToSortedRecord(specContractRefs.idToSpecs);\n const specToContractIdsRecord = mapToSortedRecord(\n specContractRefs.specToContractIds,\n );\n\n const idsByPrefix = await collectIds([\n ...specFiles,\n ...scenarioFiles,\n ...apiFiles,\n ...uiFiles,\n ...dbFiles,\n ]);\n\n const upstreamIds = await collectUpstreamIds([\n ...specFiles,\n ...scenarioFiles,\n ]);\n const traceability = await evaluateTraceability(\n upstreamIds,\n srcRoot,\n testsRoot,\n );\n const scIds = await collectScIdsFromScenarioFiles(scenarioFiles);\n const scRefsResult = await collectScTestReferences(\n root,\n config.validation.traceability.testFileGlobs,\n config.validation.traceability.testFileExcludeGlobs,\n );\n const scCoverage =\n validation?.traceability?.sc ?? buildScCoverage(scIds, scRefsResult.refs);\n const testFiles = validation?.traceability?.testFiles ?? scRefsResult.scan;\n const scSources = await collectScIdSourcesFromScenarioFiles(scenarioFiles);\n const scSourceRecord = mapToSortedRecord(scSources);\n\n const resolvedValidation =\n validation ?? (await validateProject(root, resolved));\n const version = await resolveToolVersion();\n\n return {\n tool: \"qfai\",\n version,\n generatedAt: new Date().toISOString(),\n root,\n configPath,\n summary: {\n specs: specFiles.length,\n scenarios: scenarioFiles.length,\n contracts: {\n api: apiFiles.length,\n ui: uiFiles.length,\n db: dbFiles.length,\n },\n counts: resolvedValidation.counts,\n },\n ids: {\n spec: idsByPrefix.SPEC,\n br: idsByPrefix.BR,\n sc: idsByPrefix.SC,\n ui: idsByPrefix.UI,\n api: idsByPrefix.API,\n db: idsByPrefix.DB,\n },\n traceability: {\n upstreamIdsFound: upstreamIds.size,\n referencedInCodeOrTests: traceability,\n sc: scCoverage,\n scSources: scSourceRecord,\n testFiles,\n contracts: {\n total: contractIdList.length,\n referenced: referencedContractCount,\n orphan: orphanContractCount,\n idToSpecs: contractIdToSpecsRecord,\n },\n specs: {\n contractRefMissing: specContractRefs.missingRefSpecs.size,\n missingRefSpecs: toSortedArray(specContractRefs.missingRefSpecs),\n specToContractIds: specToContractIdsRecord,\n },\n },\n issues: resolvedValidation.issues,\n };\n}\n\nexport function formatReportMarkdown(data: ReportData): string {\n const lines: string[] = [];\n\n lines.push(\"# QFAI Report\");\n lines.push(`- 生成日時: ${data.generatedAt}`);\n lines.push(`- ルート: ${data.root}`);\n lines.push(`- 設定: ${data.configPath}`);\n lines.push(`- 版: ${data.version}`);\n lines.push(\"\");\n\n lines.push(\"## 概要\");\n lines.push(`- specs: ${data.summary.specs}`);\n lines.push(`- scenarios: ${data.summary.scenarios}`);\n lines.push(\n `- contracts: api ${data.summary.contracts.api} / ui ${data.summary.contracts.ui} / db ${data.summary.contracts.db}`,\n );\n lines.push(\n `- issues: info ${data.summary.counts.info} / warning ${data.summary.counts.warning} / error ${data.summary.counts.error}`,\n );\n lines.push(\"\");\n\n lines.push(\"## ID集計\");\n lines.push(formatIdLine(\"SPEC\", data.ids.spec));\n lines.push(formatIdLine(\"BR\", data.ids.br));\n lines.push(formatIdLine(\"SC\", data.ids.sc));\n lines.push(formatIdLine(\"UI\", data.ids.ui));\n lines.push(formatIdLine(\"API\", data.ids.api));\n lines.push(formatIdLine(\"DB\", data.ids.db));\n lines.push(\"\");\n\n lines.push(\"## トレーサビリティ\");\n lines.push(`- 上流ID検出数: ${data.traceability.upstreamIdsFound}`);\n lines.push(\n `- コード/テスト参照: ${data.traceability.referencedInCodeOrTests ? \"あり\" : \"なし\"}`,\n );\n lines.push(\"\");\n\n lines.push(\"## 契約カバレッジ\");\n lines.push(`- total: ${data.traceability.contracts.total}`);\n lines.push(`- referenced: ${data.traceability.contracts.referenced}`);\n lines.push(`- orphan: ${data.traceability.contracts.orphan}`);\n lines.push(\n `- specContractRefMissing: ${data.traceability.specs.contractRefMissing}`,\n );\n lines.push(\"\");\n\n lines.push(\"## 契約→Spec\");\n const contractToSpecs = data.traceability.contracts.idToSpecs;\n const contractIds = Object.keys(contractToSpecs).sort((a, b) =>\n a.localeCompare(b),\n );\n if (contractIds.length === 0) {\n lines.push(\"- (none)\");\n } else {\n for (const contractId of contractIds) {\n const specs = contractToSpecs[contractId] ?? [];\n if (specs.length === 0) {\n lines.push(`- ${contractId}: (none)`);\n } else {\n lines.push(`- ${contractId}: ${specs.join(\", \")}`);\n }\n }\n }\n lines.push(\"\");\n\n lines.push(\"## Spec→契約\");\n const specToContracts = data.traceability.specs.specToContractIds;\n const specIds = Object.keys(specToContracts).sort((a, b) =>\n a.localeCompare(b),\n );\n if (specIds.length === 0) {\n lines.push(\"- (none)\");\n } else {\n for (const specId of specIds) {\n const contractIds = specToContracts[specId] ?? [];\n if (contractIds.length === 0) {\n lines.push(`- ${specId}: (none)`);\n } else {\n lines.push(`- ${specId}: ${contractIds.join(\", \")}`);\n }\n }\n }\n lines.push(\"\");\n\n lines.push(\"## Specで contract-ref 未宣言\");\n const missingRefSpecs = data.traceability.specs.missingRefSpecs;\n if (missingRefSpecs.length === 0) {\n lines.push(\"- (none)\");\n } else {\n for (const specId of missingRefSpecs) {\n lines.push(`- ${specId}`);\n }\n }\n lines.push(\"\");\n\n lines.push(\"## SCカバレッジ\");\n lines.push(`- total: ${data.traceability.sc.total}`);\n lines.push(`- covered: ${data.traceability.sc.covered}`);\n lines.push(`- missing: ${data.traceability.sc.missing}`);\n lines.push(\n `- testFileGlobs: ${formatList(data.traceability.testFiles.globs)}`,\n );\n lines.push(\n `- testFileExcludeGlobs: ${formatList(\n data.traceability.testFiles.excludeGlobs,\n )}`,\n );\n lines.push(\n `- testFileCount: ${data.traceability.testFiles.matchedFileCount}`,\n );\n if (data.traceability.sc.missingIds.length === 0) {\n lines.push(\"- missingIds: (none)\");\n } else {\n const sources = data.traceability.scSources;\n const missingWithSources = data.traceability.sc.missingIds.map((id) => {\n const files = sources[id] ?? [];\n if (files.length === 0) {\n return id;\n }\n return `${id} (${files.join(\", \")})`;\n });\n lines.push(`- missingIds: ${missingWithSources.join(\", \")}`);\n }\n lines.push(\"\");\n\n lines.push(\"## SC→参照テスト\");\n const scRefs = data.traceability.sc.refs;\n const scIds = Object.keys(scRefs).sort((a, b) => a.localeCompare(b));\n if (scIds.length === 0) {\n lines.push(\"- (none)\");\n } else {\n for (const scId of scIds) {\n const refs = scRefs[scId] ?? [];\n if (refs.length === 0) {\n lines.push(`- ${scId}: (none)`);\n } else {\n lines.push(`- ${scId}: ${refs.join(\", \")}`);\n }\n }\n }\n lines.push(\"\");\n\n lines.push(\"## Spec:SC=1:1 違反\");\n const specScIssues = data.issues.filter(\n (item) => item.code === \"QFAI-TRACE-012\",\n );\n if (specScIssues.length === 0) {\n lines.push(\"- (none)\");\n } else {\n for (const item of specScIssues) {\n const location = item.file ?? \"(unknown)\";\n const refs =\n item.refs && item.refs.length > 0 ? item.refs.join(\", \") : item.message;\n lines.push(`- ${location}: ${refs}`);\n }\n }\n lines.push(\"\");\n\n lines.push(\"## Hotspots\");\n const hotspots = buildHotspots(data.issues);\n if (hotspots.length === 0) {\n lines.push(\"- (none)\");\n } else {\n for (const spot of hotspots) {\n lines.push(\n `- ${spot.file}: total ${spot.total} (error ${spot.error} / warning ${spot.warning} / info ${spot.info})`,\n );\n }\n }\n lines.push(\"\");\n\n lines.push(\"## トレーサビリティ(検証)\");\n const traceIssues = data.issues.filter(\n (item) =>\n item.rule?.startsWith(\"traceability.\") ||\n item.code.startsWith(\"QFAI_TRACE\") ||\n item.code.startsWith(\"QFAI-TRACE-\"),\n );\n if (traceIssues.length === 0) {\n lines.push(\"- (none)\");\n } else {\n for (const item of traceIssues) {\n const location = item.file ? ` (${item.file})` : \"\";\n lines.push(\n `- ${item.severity.toUpperCase()} [${item.code}] ${item.message}${location}`,\n );\n }\n }\n lines.push(\"\");\n\n lines.push(\"## 検証結果\");\n if (data.issues.length === 0) {\n lines.push(\"- (none)\");\n } else {\n for (const item of data.issues) {\n const location = item.file ? ` (${item.file})` : \"\";\n const refs =\n item.refs && item.refs.length > 0 ? ` refs=${item.refs.join(\",\")}` : \"\";\n lines.push(\n `- ${item.severity.toUpperCase()} [${item.code}] ${item.message}${location}${refs}`,\n );\n }\n }\n\n return lines.join(\"\\n\");\n}\n\nexport function formatReportJson(data: ReportData): string {\n return JSON.stringify(data, null, 2);\n}\n\ntype SpecContractRefsResult = {\n specToContractIds: Map<string, Set<string>>;\n idToSpecs: Map<string, Set<string>>;\n missingRefSpecs: Set<string>;\n};\n\nasync function collectSpecContractRefs(\n specFiles: string[],\n contractIdList: string[],\n): Promise<SpecContractRefsResult> {\n const specToContractIds = new Map<string, Set<string>>();\n const idToSpecs = new Map<string, Set<string>>();\n const missingRefSpecs = new Set<string>();\n\n for (const contractId of contractIdList) {\n idToSpecs.set(contractId, new Set<string>());\n }\n\n for (const file of specFiles) {\n const text = await readFile(file, \"utf-8\");\n const parsed = parseSpec(text, file);\n const specKey = parsed.specId ?? file;\n const refs = parsed.contractRefs;\n\n if (refs.lines.length === 0) {\n missingRefSpecs.add(specKey);\n continue;\n }\n\n const currentContracts =\n specToContractIds.get(specKey) ?? new Set<string>();\n for (const id of refs.ids) {\n currentContracts.add(id);\n const specs = idToSpecs.get(id);\n if (specs) {\n specs.add(specKey);\n }\n }\n specToContractIds.set(specKey, currentContracts);\n }\n\n return {\n specToContractIds,\n idToSpecs,\n missingRefSpecs,\n };\n}\n\nasync function collectIds(\n files: string[],\n): Promise<Record<IdPrefix, string[]>> {\n const result: Record<IdPrefix, Set<string>> = {\n SPEC: new Set(),\n BR: new Set(),\n SC: new Set(),\n UI: new Set(),\n API: new Set(),\n DB: new Set(),\n };\n\n for (const file of files) {\n const text = await readFile(file, \"utf-8\");\n for (const prefix of ID_PREFIXES) {\n const ids = extractIds(text, prefix);\n ids.forEach((id) => result[prefix].add(id));\n }\n }\n\n return {\n SPEC: toSortedArray(result.SPEC),\n BR: toSortedArray(result.BR),\n SC: toSortedArray(result.SC),\n UI: toSortedArray(result.UI),\n API: toSortedArray(result.API),\n DB: toSortedArray(result.DB),\n };\n}\n\nasync function collectUpstreamIds(files: string[]): Promise<Set<string>> {\n const ids = new Set<string>();\n for (const file of files) {\n const text = await readFile(file, \"utf-8\");\n extractAllIds(text).forEach((id) => ids.add(id));\n }\n return ids;\n}\n\nasync function evaluateTraceability(\n upstreamIds: Set<string>,\n srcRoot: string,\n testsRoot: string,\n): Promise<boolean> {\n if (upstreamIds.size === 0) {\n return false;\n }\n\n const codeFiles = await collectFiles(srcRoot, {\n extensions: [\".ts\", \".tsx\", \".js\", \".jsx\"],\n });\n const testFiles = await collectFiles(testsRoot, {\n extensions: [\".ts\", \".tsx\", \".js\", \".jsx\"],\n });\n const targetFiles = [...codeFiles, ...testFiles];\n\n if (targetFiles.length === 0) {\n return false;\n }\n\n const pattern = buildIdPattern(Array.from(upstreamIds));\n\n for (const file of targetFiles) {\n const text = await readFile(file, \"utf-8\");\n if (pattern.test(text)) {\n return true;\n }\n }\n\n return false;\n}\n\nfunction buildIdPattern(ids: string[]): RegExp {\n const escaped = ids.map((id) => id.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\"));\n return new RegExp(`\\\\b(${escaped.join(\"|\")})\\\\b`);\n}\n\nfunction formatIdLine(label: string, values: string[]): string {\n if (values.length === 0) {\n return `- ${label}: (none)`;\n }\n return `- ${label}: ${values.join(\", \")}`;\n}\n\nfunction formatList(values: string[]): string {\n if (values.length === 0) {\n return \"(none)\";\n }\n return values.join(\", \");\n}\n\nfunction toSortedArray(values: Set<string>): string[] {\n return Array.from(values).sort((a, b) => a.localeCompare(b));\n}\n\nfunction mapToSortedRecord(\n values: Map<string, Set<string>>,\n): Record<string, string[]> {\n const record: Record<string, string[]> = {};\n for (const [key, files] of values.entries()) {\n record[key] = Array.from(files).sort((a, b) => a.localeCompare(b));\n }\n return record;\n}\n\ntype Hotspot = {\n file: string;\n total: number;\n error: number;\n warning: number;\n info: number;\n};\n\nfunction buildHotspots(issues: Issue[]): Hotspot[] {\n const map = new Map<string, Hotspot>();\n for (const issue of issues) {\n if (!issue.file) {\n continue;\n }\n const current =\n map.get(issue.file) ??\n ({\n file: issue.file,\n total: 0,\n error: 0,\n warning: 0,\n info: 0,\n } satisfies Hotspot);\n current.total += 1;\n current[issue.severity] += 1;\n map.set(issue.file, current);\n }\n\n return Array.from(map.values()).sort((a, b) =>\n b.total !== a.total ? b.total - a.total : a.file.localeCompare(b.file),\n );\n}\n","import { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport type { QfaiConfig } from \"./config.js\";\nimport { resolvePath } from \"./config.js\";\nimport {\n collectApiContractFiles,\n collectDbContractFiles,\n collectUiContractFiles,\n} from \"./discovery.js\";\nimport { extractDeclaredContractIds } from \"./contractsDecl.js\";\n\nexport type ContractIndex = {\n ids: Set<string>;\n idToFiles: Map<string, Set<string>>;\n files: { ui: string[]; api: string[]; db: string[] };\n};\n\nexport async function buildContractIndex(\n root: string,\n config: QfaiConfig,\n): Promise<ContractIndex> {\n const contractsRoot = resolvePath(root, config, \"contractsDir\");\n const uiRoot = path.join(contractsRoot, \"ui\");\n const apiRoot = path.join(contractsRoot, \"api\");\n const dbRoot = path.join(contractsRoot, \"db\");\n\n const [uiFiles, apiFiles, dbFiles] = await Promise.all([\n collectUiContractFiles(uiRoot),\n collectApiContractFiles(apiRoot),\n collectDbContractFiles(dbRoot),\n ]);\n\n const index: ContractIndex = {\n ids: new Set<string>(),\n idToFiles: new Map<string, Set<string>>(),\n files: { ui: uiFiles, api: apiFiles, db: dbFiles },\n };\n\n await indexContractFiles(uiFiles, index);\n await indexContractFiles(apiFiles, index);\n await indexContractFiles(dbFiles, index);\n\n return index;\n}\n\nasync function indexContractFiles(\n files: string[],\n index: ContractIndex,\n): Promise<void> {\n for (const file of files) {\n const text = await readFile(file, \"utf-8\");\n extractDeclaredContractIds(text).forEach((id) => record(index, id, file));\n }\n}\n\nfunction record(index: ContractIndex, id: string, file: string): void {\n index.ids.add(id);\n const current = index.idToFiles.get(id) ?? new Set<string>();\n current.add(file);\n index.idToFiles.set(id, current);\n}\n","import { access } from \"node:fs/promises\";\n\nimport { collectFiles } from \"./fs.js\";\nimport { collectSpecEntries } from \"./specLayout.js\";\n\nexport type ContractFiles = {\n api: string[];\n ui: string[];\n db: string[];\n};\n\nexport async function collectSpecPackDirs(\n specsRoot: string,\n): Promise<string[]> {\n const entries = await collectSpecEntries(specsRoot);\n return entries.map((entry) => entry.dir);\n}\n\nexport async function collectSpecFiles(specsRoot: string): Promise<string[]> {\n const entries = await collectSpecEntries(specsRoot);\n return filterExisting(entries.map((entry) => entry.specPath));\n}\n\nexport async function collectDeltaFiles(specsRoot: string): Promise<string[]> {\n const entries = await collectSpecEntries(specsRoot);\n return filterExisting(entries.map((entry) => entry.deltaPath));\n}\n\nexport async function collectScenarioFiles(\n specsRoot: string,\n): Promise<string[]> {\n const entries = await collectSpecEntries(specsRoot);\n return filterExisting(entries.map((entry) => entry.scenarioPath));\n}\n\nexport async function collectUiContractFiles(\n uiRoot: string,\n): Promise<string[]> {\n return collectFiles(uiRoot, { extensions: [\".yaml\", \".yml\"] });\n}\n\nexport async function collectApiContractFiles(\n apiRoot: string,\n): Promise<string[]> {\n return collectFiles(apiRoot, { extensions: [\".yaml\", \".yml\", \".json\"] });\n}\n\nexport async function collectDbContractFiles(\n dbRoot: string,\n): Promise<string[]> {\n return collectFiles(dbRoot, { extensions: [\".sql\"] });\n}\n\nexport async function collectContractFiles(\n uiRoot: string,\n apiRoot: string,\n dbRoot: string,\n): Promise<ContractFiles> {\n const [ui, api, db] = await Promise.all([\n collectUiContractFiles(uiRoot),\n collectApiContractFiles(apiRoot),\n collectDbContractFiles(dbRoot),\n ]);\n return { ui, api, db };\n}\n\nasync function filterExisting(files: string[]): Promise<string[]> {\n const existing: string[] = [];\n for (const file of files) {\n if (await exists(file)) {\n existing.push(file);\n }\n }\n return existing;\n}\n\nasync function exists(target: string): Promise<boolean> {\n try {\n await access(target);\n return true;\n } catch {\n return false;\n }\n}\n","import { access, readdir } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport fg from \"fast-glob\";\n\nconst DEFAULT_IGNORE_DIRS = new Set([\n \"node_modules\",\n \".git\",\n \"dist\",\n \".pnpm\",\n \"tmp\",\n \".mcp-tools\",\n]);\n\nexport type CollectFilesOptions = {\n extensions?: string[];\n ignoreDirs?: string[];\n};\n\nexport type CollectFilesByGlobOptions = {\n globs: string[];\n ignore?: string[];\n};\n\nexport async function collectFiles(\n root: string,\n options: CollectFilesOptions = {},\n): Promise<string[]> {\n const entries: string[] = [];\n if (!(await exists(root))) {\n return entries;\n }\n\n const ignoreDirs = new Set([\n ...DEFAULT_IGNORE_DIRS,\n ...(options.ignoreDirs ?? []),\n ]);\n const extensions = options.extensions?.map((ext) => ext.toLowerCase()) ?? [];\n\n await walk(root, root, ignoreDirs, extensions, entries);\n return entries;\n}\n\nexport async function collectFilesByGlobs(\n root: string,\n options: CollectFilesByGlobOptions,\n): Promise<string[]> {\n if (options.globs.length === 0) {\n return [];\n }\n return fg(options.globs, {\n cwd: root,\n ignore: options.ignore ?? [],\n onlyFiles: true,\n absolute: true,\n unique: true,\n });\n}\n\nasync function walk(\n base: string,\n current: string,\n ignoreDirs: Set<string>,\n extensions: string[],\n out: string[],\n): Promise<void> {\n const items = await readdir(current, { withFileTypes: true });\n\n for (const item of items) {\n const fullPath = path.join(current, item.name);\n\n if (item.isDirectory()) {\n if (ignoreDirs.has(item.name)) {\n continue;\n }\n await walk(base, fullPath, ignoreDirs, extensions, out);\n continue;\n }\n\n if (item.isFile()) {\n if (extensions.length > 0) {\n const ext = path.extname(item.name).toLowerCase();\n if (!extensions.includes(ext)) {\n continue;\n }\n }\n out.push(fullPath);\n }\n }\n}\n\nasync function exists(target: string): Promise<boolean> {\n try {\n await access(target);\n return true;\n } catch {\n return false;\n }\n}\n","import { readdir } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nconst SPEC_DIR_RE = /^spec-\\d{4}$/;\n\nexport type SpecEntry = {\n dir: string;\n specPath: string;\n deltaPath: string;\n scenarioPath: string;\n};\n\nexport async function collectSpecEntries(\n specsRoot: string,\n): Promise<SpecEntry[]> {\n const dirs = await listSpecDirs(specsRoot);\n const entries = dirs.map((dir) => ({\n dir,\n specPath: path.join(dir, \"spec.md\"),\n deltaPath: path.join(dir, \"delta.md\"),\n scenarioPath: path.join(dir, \"scenario.md\"),\n }));\n return entries.sort((a, b) => a.dir.localeCompare(b.dir));\n}\n\nasync function listSpecDirs(specsRoot: string): Promise<string[]> {\n try {\n const items = await readdir(specsRoot, { withFileTypes: true });\n return items\n .filter((item) => item.isDirectory())\n .map((item) => item.name)\n .filter((name) => SPEC_DIR_RE.test(name.toLowerCase()))\n .map((name) => path.join(specsRoot, name));\n } catch (error) {\n if (isMissingFileError(error)) {\n return [];\n }\n throw error;\n }\n}\n\nfunction isMissingFileError(error: unknown): boolean {\n if (!error || typeof error !== \"object\") {\n return false;\n }\n return (error as { code?: string }).code === \"ENOENT\";\n}\n","const CONTRACT_DECLARATION_RE =\n /^\\s*(?:#|\\/\\/|--|\\/\\*+|\\*+)?\\s*QFAI-CONTRACT-ID:\\s*((?:API|UI|DB)-\\d{4})\\s*(?:\\*\\/)?\\s*$/gm;\nconst CONTRACT_DECLARATION_LINE_RE =\n /^\\s*(?:#|\\/\\/|--|\\/\\*+|\\*+)?\\s*QFAI-CONTRACT-ID:\\s*(?:API|UI|DB)-\\d{4}\\s*(?:\\*\\/)?\\s*$/;\n\nexport function extractDeclaredContractIds(text: string): string[] {\n const ids: string[] = [];\n for (const match of text.matchAll(CONTRACT_DECLARATION_RE)) {\n const id = match[1];\n if (id) {\n ids.push(id);\n }\n }\n return ids;\n}\n\nexport function stripContractDeclarationLines(text: string): string {\n return text\n .split(/\\r?\\n/)\n .filter((line) => !CONTRACT_DECLARATION_LINE_RE.test(line))\n .join(\"\\n\");\n}\n","export type Heading = { level: number; title: string; line: number };\n\nexport type H2Section = {\n title: string;\n startLine: number;\n endLine: number;\n body: string;\n};\n\nconst HEADING_RE = /^(#{1,6})\\s+(.+?)\\s*$/;\n\nexport function parseHeadings(md: string): Heading[] {\n const lines = md.split(/\\r?\\n/);\n const headings: Heading[] = [];\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i] ?? \"\";\n const match = line.match(HEADING_RE);\n if (!match) continue;\n const levelToken = match[1];\n const title = match[2];\n if (!levelToken || !title) continue;\n headings.push({\n level: levelToken.length,\n title: title.trim(),\n line: i + 1,\n });\n }\n return headings;\n}\n\nexport function extractH2Sections(md: string): Map<string, H2Section> {\n const lines = md.split(/\\r?\\n/);\n const headings = parseHeadings(md).filter((heading) => heading.level === 2);\n const sections = new Map<string, H2Section>();\n\n for (let i = 0; i < headings.length; i++) {\n const current = headings[i];\n if (!current) continue;\n const next = headings[i + 1];\n const startLine = current.line + 1;\n const endLine = (next?.line ?? lines.length + 1) - 1;\n const body =\n startLine <= endLine\n ? lines.slice(startLine - 1, endLine).join(\"\\n\")\n : \"\";\n\n sections.set(current.title.trim(), {\n title: current.title.trim(),\n startLine,\n endLine,\n body,\n });\n }\n\n return sections;\n}\n","import { extractH2Sections, parseHeadings } from \"./markdown.js\";\n\nexport type BrPriority = \"P0\" | \"P1\" | \"P2\" | \"P3\";\n\nexport type ParsedBr = {\n id: string;\n priority: BrPriority;\n text: string;\n line: number;\n};\n\nexport type ParsedBrWithoutPriority = {\n id: string;\n text: string;\n line: number;\n};\n\nexport type ParsedBrWithInvalidPriority = {\n id: string;\n priority: string;\n text: string;\n line: number;\n};\n\nexport type ParsedSpec = {\n file: string;\n specId?: string;\n sections: Set<string>;\n brs: ParsedBr[];\n brsWithoutPriority: ParsedBrWithoutPriority[];\n brsWithInvalidPriority: ParsedBrWithInvalidPriority[];\n contractRefs: ParsedContractRefs;\n};\n\nexport type ParsedContractRefs = {\n lines: string[];\n ids: string[];\n invalidTokens: string[];\n hasNone: boolean;\n};\n\nconst SPEC_ID_RE = /\\bSPEC-\\d{4}\\b/;\nconst BR_LINE_RE = /^\\s*(?:[-*]\\s*)?\\[(BR-\\d{4})\\]\\[(P[0-3])\\]\\s*(.+)$/;\nconst BR_LINE_ANY_PRIORITY_RE =\n /^\\s*(?:[-*]\\s*)?\\[(BR-\\d{4})\\]\\[(P[^\\]]+)\\]\\s*(.+)$/;\nconst BR_LINE_NO_PRIORITY_RE =\n /^\\s*(?:[-*]\\s*)?\\[(BR-\\d{4})\\](?!\\s*\\[P)\\s*(.*\\S.*)$/;\nconst CONTRACT_REF_LINE_RE =\n /^[ \\t]*QFAI-CONTRACT-REF:[ \\t]*([^\\r\\n]*)[ \\t]*$/gm;\nconst CONTRACT_REF_ID_RE = /^(?:API|UI|DB)-\\d{4}$/;\n\nconst BR_SECTION_TITLE = \"業務ルール\";\nconst VALID_PRIORITIES = new Set<BrPriority>([\"P0\", \"P1\", \"P2\", \"P3\"]);\n\nexport function parseSpec(md: string, file: string): ParsedSpec {\n const headings = parseHeadings(md);\n const h1 = headings.find((heading) => heading.level === 1);\n const specId = h1?.title.match(SPEC_ID_RE)?.[0];\n\n const sections = extractH2Sections(md);\n const sectionNames = new Set(Array.from(sections.keys()));\n const brSection = sections.get(BR_SECTION_TITLE);\n const brLines = brSection ? brSection.body.split(/\\r?\\n/) : [];\n const startLine = brSection?.startLine ?? 1;\n\n const brs: ParsedBr[] = [];\n const brsWithoutPriority: ParsedBrWithoutPriority[] = [];\n const brsWithInvalidPriority: ParsedBrWithInvalidPriority[] = [];\n\n for (let i = 0; i < brLines.length; i++) {\n const lineText = brLines[i] ?? \"\";\n const lineNumber = startLine + i;\n\n const validMatch = lineText.match(BR_LINE_RE);\n if (validMatch) {\n const id = validMatch[1];\n const priority = validMatch[2];\n const text = validMatch[3];\n if (!id || !priority || !text) continue;\n brs.push({\n id,\n priority: priority as BrPriority,\n text: text.trim(),\n line: lineNumber,\n });\n continue;\n }\n\n const anyPriorityMatch = lineText.match(BR_LINE_ANY_PRIORITY_RE);\n if (anyPriorityMatch) {\n const id = anyPriorityMatch[1];\n const priority = anyPriorityMatch[2];\n const text = anyPriorityMatch[3];\n if (!id || !priority || !text) continue;\n if (!VALID_PRIORITIES.has(priority as BrPriority)) {\n brsWithInvalidPriority.push({\n id,\n priority,\n text: text.trim(),\n line: lineNumber,\n });\n }\n continue;\n }\n\n const noPriorityMatch = lineText.match(BR_LINE_NO_PRIORITY_RE);\n if (noPriorityMatch) {\n const id = noPriorityMatch[1];\n const text = noPriorityMatch[2];\n if (!id || !text) continue;\n brsWithoutPriority.push({\n id,\n text: text.trim(),\n line: lineNumber,\n });\n }\n }\n\n const parsed: ParsedSpec = {\n file,\n sections: sectionNames,\n brs,\n brsWithoutPriority,\n brsWithInvalidPriority,\n contractRefs: parseContractRefs(md),\n };\n if (specId) {\n parsed.specId = specId;\n }\n return parsed;\n}\n\nexport function parseContractRefs(md: string): ParsedContractRefs {\n const lines: string[] = [];\n for (const match of md.matchAll(CONTRACT_REF_LINE_RE)) {\n lines.push((match[1] ?? \"\").trim());\n }\n\n const ids: string[] = [];\n const invalidTokens: string[] = [];\n let hasNone = false;\n\n for (const line of lines) {\n if (line.length === 0) {\n invalidTokens.push(\"(empty)\");\n continue;\n }\n const tokens = line.split(\",\").map((token) => token.trim());\n for (const token of tokens) {\n if (token.length === 0) {\n invalidTokens.push(\"(empty)\");\n continue;\n }\n if (token === \"none\") {\n hasNone = true;\n continue;\n }\n if (CONTRACT_REF_ID_RE.test(token)) {\n ids.push(token);\n continue;\n }\n invalidTokens.push(token);\n }\n }\n\n return {\n lines,\n ids: unique(ids),\n invalidTokens: unique(invalidTokens),\n hasNone,\n };\n}\n\nfunction unique(values: string[]): string[] {\n return Array.from(new Set(values));\n}\n","import { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport { collectFilesByGlobs } from \"./fs.js\";\nimport { parseScenarioDocument } from \"./scenarioModel.js\";\n\nexport const SC_TAG_RE = /^SC-\\d{4}$/;\nexport const SC_TEST_ANNOTATION_RE = /\\bQFAI:SC-(\\d{4})\\b/g;\nexport const DEFAULT_TEST_FILE_EXCLUDE_GLOBS = [\n \"**/node_modules/**\",\n \"**/.git/**\",\n \"**/.qfai/**\",\n \"**/dist/**\",\n \"**/build/**\",\n \"**/coverage/**\",\n \"**/.next/**\",\n \"**/out/**\",\n];\n\nexport type ScCoverage = {\n total: number;\n covered: number;\n missing: number;\n missingIds: string[];\n refs: Record<string, string[]>;\n};\n\nexport type TestFileScan = {\n globs: string[];\n excludeGlobs: string[];\n matchedFileCount: number;\n};\n\nexport type ScTestReferenceResult = {\n refs: Map<string, Set<string>>;\n scan: TestFileScan;\n error?: string;\n};\n\nexport function extractAnnotatedScIds(text: string): string[] {\n const ids = new Set<string>();\n for (const match of text.matchAll(SC_TEST_ANNOTATION_RE)) {\n const suffix = match[1];\n if (suffix) {\n ids.add(`SC-${suffix}`);\n }\n }\n return Array.from(ids);\n}\n\nexport async function collectScIdsFromScenarioFiles(\n scenarioFiles: string[],\n): Promise<Set<string>> {\n const scIds = new Set<string>();\n for (const file of scenarioFiles) {\n const text = await readFile(file, \"utf-8\");\n const { document, errors } = parseScenarioDocument(text, file);\n if (!document || errors.length > 0) {\n continue;\n }\n\n for (const scenario of document.scenarios) {\n for (const tag of scenario.tags) {\n if (SC_TAG_RE.test(tag)) {\n scIds.add(tag);\n }\n }\n }\n }\n return scIds;\n}\n\nexport async function collectScIdSourcesFromScenarioFiles(\n scenarioFiles: string[],\n): Promise<Map<string, Set<string>>> {\n const sources = new Map<string, Set<string>>();\n for (const file of scenarioFiles) {\n const text = await readFile(file, \"utf-8\");\n const { document, errors } = parseScenarioDocument(text, file);\n if (!document || errors.length > 0) {\n continue;\n }\n\n for (const scenario of document.scenarios) {\n for (const tag of scenario.tags) {\n if (!SC_TAG_RE.test(tag)) {\n continue;\n }\n const current = sources.get(tag) ?? new Set<string>();\n current.add(file);\n sources.set(tag, current);\n }\n }\n }\n return sources;\n}\n\nexport async function collectScTestReferences(\n root: string,\n globs: string[],\n excludeGlobs: string[],\n): Promise<ScTestReferenceResult> {\n const refs = new Map<string, Set<string>>();\n const normalizedGlobs = normalizeGlobs(globs);\n const normalizedExcludeGlobs = normalizeGlobs(excludeGlobs);\n const mergedExcludeGlobs = Array.from(\n new Set([...DEFAULT_TEST_FILE_EXCLUDE_GLOBS, ...normalizedExcludeGlobs]),\n );\n if (normalizedGlobs.length === 0) {\n return {\n refs,\n scan: {\n globs: normalizedGlobs,\n excludeGlobs: mergedExcludeGlobs,\n matchedFileCount: 0,\n },\n };\n }\n\n let files: string[] = [];\n try {\n files = await collectFilesByGlobs(root, {\n globs: normalizedGlobs,\n ignore: mergedExcludeGlobs,\n });\n } catch (error) {\n return {\n refs,\n scan: {\n globs: normalizedGlobs,\n excludeGlobs: mergedExcludeGlobs,\n matchedFileCount: 0,\n },\n error: formatError(error),\n };\n }\n\n const normalizedFiles = Array.from(\n new Set(files.map((file) => path.normalize(file))),\n );\n for (const file of normalizedFiles) {\n const text = await readFile(file, \"utf-8\");\n const scIds = extractAnnotatedScIds(text);\n if (scIds.length === 0) {\n continue;\n }\n for (const scId of scIds) {\n const current = refs.get(scId) ?? new Set<string>();\n current.add(file);\n refs.set(scId, current);\n }\n }\n\n return {\n refs,\n scan: {\n globs: normalizedGlobs,\n excludeGlobs: mergedExcludeGlobs,\n matchedFileCount: normalizedFiles.length,\n },\n };\n}\n\nexport function buildScCoverage(\n scIds: Iterable<string>,\n refs: Map<string, Set<string>>,\n): ScCoverage {\n const sortedScIds = toSortedArray(scIds);\n const refsRecord: Record<string, string[]> = {};\n const missingIds: string[] = [];\n let covered = 0;\n\n for (const scId of sortedScIds) {\n const files = refs.get(scId);\n const sortedFiles = files ? toSortedArray(files) : [];\n refsRecord[scId] = sortedFiles;\n if (sortedFiles.length === 0) {\n missingIds.push(scId);\n } else {\n covered += 1;\n }\n }\n\n return {\n total: sortedScIds.length,\n covered,\n missing: missingIds.length,\n missingIds,\n refs: refsRecord,\n };\n}\n\nfunction toSortedArray(values: Iterable<string>): string[] {\n return Array.from(new Set(values)).sort((a, b) => a.localeCompare(b));\n}\n\nfunction normalizeGlobs(globs: string[]): string[] {\n return globs.map((glob) => glob.trim()).filter((glob) => glob.length > 0);\n}\n\nfunction formatError(error: unknown): string {\n if (error instanceof Error) {\n return error.message;\n }\n return String(error);\n}\n","import {\n AstBuilder,\n GherkinClassicTokenMatcher,\n Parser,\n} from \"@cucumber/gherkin\";\nimport type { GherkinDocument } from \"@cucumber/messages\";\nimport { randomUUID } from \"node:crypto\";\n\nexport type ParsedGherkin = {\n gherkinDocument: GherkinDocument | null;\n errors: string[];\n};\n\nexport function parseGherkin(source: string, uri: string): ParsedGherkin {\n const errors: string[] = [];\n const uuidFn = () => randomUUID();\n const builder = new AstBuilder(uuidFn);\n const matcher = new GherkinClassicTokenMatcher();\n const parser = new Parser(builder, matcher);\n\n try {\n const gherkinDocument = parser.parse(source);\n gherkinDocument.uri = uri;\n return { gherkinDocument, errors };\n } catch (error) {\n errors.push(formatError(error));\n return { gherkinDocument: null, errors };\n }\n}\n\nfunction formatError(error: unknown): string {\n if (error instanceof Error) {\n return error.message;\n }\n return String(error);\n}\n","import type * as Messages from \"@cucumber/messages\";\n\nimport { parseGherkin } from \"./gherkin/parse.js\";\nimport { extractIds } from \"./ids.js\";\n\nconst SPEC_TAG_RE = /^SPEC-\\d{4}$/;\nconst SC_TAG_RE = /^SC-\\d{4}$/;\nconst BR_TAG_RE = /^BR-\\d{4}$/;\nconst UI_TAG_RE = /^UI-\\d{4}$/;\nconst API_TAG_RE = /^API-\\d{4}$/;\nconst DB_TAG_RE = /^DB-\\d{4}$/;\n\nexport type ScenarioKind = \"Scenario\" | \"ScenarioOutline\";\n\nexport type ScenarioNode = {\n name: string;\n kind: ScenarioKind;\n line?: number;\n tags: string[];\n steps: readonly Messages.Step[];\n};\n\nexport type ScenarioDocument = {\n uri: string;\n featureName?: string;\n featureTags: string[];\n scenarios: ScenarioNode[];\n};\n\nexport type ScenarioParseResult = {\n document: ScenarioDocument | null;\n errors: string[];\n};\n\nexport type ScenarioAtom = {\n uri: string;\n featureName: string;\n scenarioName: string;\n kind: ScenarioKind;\n specId?: string;\n scId?: string;\n brIds: string[];\n contractIds: string[];\n line?: number;\n};\n\nexport function parseScenarioDocument(\n text: string,\n uri: string,\n): ScenarioParseResult {\n const { gherkinDocument, errors } = parseGherkin(text, uri);\n if (!gherkinDocument) {\n return { document: null, errors };\n }\n\n const feature = gherkinDocument.feature;\n if (!feature) {\n return {\n document: { uri, featureTags: [], scenarios: [] },\n errors,\n };\n }\n\n const featureTags = collectTagNames(feature.tags);\n const scenarios = collectScenarioNodes(feature, featureTags);\n return {\n document: {\n uri,\n featureName: feature.name,\n featureTags,\n scenarios,\n },\n errors,\n };\n}\n\nexport function buildScenarioAtoms(document: ScenarioDocument): ScenarioAtom[] {\n return document.scenarios.map((scenario) => {\n const specIds = scenario.tags.filter((tag) => SPEC_TAG_RE.test(tag));\n const scIds = scenario.tags.filter((tag) => SC_TAG_RE.test(tag));\n const brIds = unique(scenario.tags.filter((tag) => BR_TAG_RE.test(tag)));\n\n const contractIds = new Set<string>();\n scenario.tags.forEach((tag) => {\n if (UI_TAG_RE.test(tag) || API_TAG_RE.test(tag) || DB_TAG_RE.test(tag)) {\n contractIds.add(tag);\n }\n });\n\n for (const step of scenario.steps) {\n for (const text of collectStepTexts(step)) {\n extractIds(text, \"UI\").forEach((id) => contractIds.add(id));\n extractIds(text, \"API\").forEach((id) => contractIds.add(id));\n extractIds(text, \"DB\").forEach((id) => contractIds.add(id));\n }\n }\n\n const atom: ScenarioAtom = {\n uri: document.uri,\n featureName: document.featureName ?? \"\",\n scenarioName: scenario.name,\n kind: scenario.kind,\n brIds,\n contractIds: Array.from(contractIds).sort(),\n };\n\n if (scenario.line !== undefined) {\n atom.line = scenario.line;\n }\n if (specIds.length === 1) {\n const specId = specIds[0];\n if (specId) {\n atom.specId = specId;\n }\n }\n if (scIds.length === 1) {\n const scId = scIds[0];\n if (scId) {\n atom.scId = scId;\n }\n }\n\n return atom;\n });\n}\n\nfunction collectScenarioNodes(\n feature: Messages.Feature,\n featureTags: string[],\n): ScenarioNode[] {\n const scenarios: ScenarioNode[] = [];\n\n for (const child of feature.children) {\n if (child.scenario) {\n scenarios.push(buildScenarioNode(child.scenario, featureTags, []));\n }\n if (child.rule) {\n const ruleTags = collectTagNames(child.rule.tags);\n for (const ruleChild of child.rule.children) {\n if (ruleChild.scenario) {\n scenarios.push(\n buildScenarioNode(ruleChild.scenario, featureTags, ruleTags),\n );\n }\n }\n }\n }\n\n return scenarios;\n}\n\nfunction buildScenarioNode(\n scenario: Messages.Scenario,\n featureTags: string[],\n ruleTags: string[],\n): ScenarioNode {\n const tags = [...featureTags, ...ruleTags, ...collectTagNames(scenario.tags)];\n const kind: ScenarioKind =\n scenario.examples.length > 0 ? \"ScenarioOutline\" : \"Scenario\";\n return {\n name: scenario.name,\n kind,\n line: scenario.location?.line,\n tags,\n steps: scenario.steps,\n };\n}\n\nfunction collectTagNames(tags: readonly Messages.Tag[]): string[] {\n return tags.map((tag) => tag.name.replace(/^@/, \"\"));\n}\n\nfunction collectStepTexts(step: Messages.Step): string[] {\n const texts: string[] = [];\n if (step.text) {\n texts.push(step.text);\n }\n if (step.docString?.content) {\n texts.push(step.docString.content);\n }\n if (step.dataTable?.rows) {\n for (const row of step.dataTable.rows) {\n for (const cell of row.cells) {\n texts.push(cell.value);\n }\n }\n }\n return texts;\n}\n\nfunction unique(values: string[]): string[] {\n return Array.from(new Set(values));\n}\n","import { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\ndeclare const __QFAI_TOOL_VERSION__: string | undefined;\n\nexport async function resolveToolVersion(): Promise<string> {\n if (\n typeof __QFAI_TOOL_VERSION__ === \"string\" &&\n __QFAI_TOOL_VERSION__.length > 0\n ) {\n return __QFAI_TOOL_VERSION__;\n }\n\n try {\n const packagePath = resolvePackageJsonPath();\n const raw = await readFile(packagePath, \"utf-8\");\n const parsed = JSON.parse(raw) as { version?: unknown };\n const version = typeof parsed.version === \"string\" ? parsed.version : \"\";\n return version.length > 0 ? version : \"unknown\";\n } catch {\n return \"unknown\";\n }\n}\n\nfunction resolvePackageJsonPath(): string {\n const base = import.meta.url;\n const basePath = base.startsWith(\"file:\") ? fileURLToPath(base) : base;\n return path.resolve(path.dirname(basePath), \"../../package.json\");\n}\n","import { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport type { QfaiConfig } from \"../config.js\";\nimport { resolvePath } from \"../config.js\";\nimport { parseStructuredContract } from \"../contracts.js\";\nimport { buildContractIndex } from \"../contractIndex.js\";\nimport {\n extractDeclaredContractIds,\n stripContractDeclarationLines,\n} from \"../contractsDecl.js\";\nimport {\n collectApiContractFiles,\n collectDbContractFiles,\n collectUiContractFiles,\n} from \"../discovery.js\";\nimport { extractInvalidIds } from \"../ids.js\";\nimport type { Issue, IssueSeverity } from \"../types.js\";\n\nconst SQL_DANGEROUS_PATTERNS: Array<{ pattern: RegExp; label: string }> = [\n { pattern: /\\bDROP\\s+TABLE\\b/i, label: \"DROP TABLE\" },\n { pattern: /\\bDROP\\s+DATABASE\\b/i, label: \"DROP DATABASE\" },\n { pattern: /\\bTRUNCATE\\b/i, label: \"TRUNCATE\" },\n {\n pattern: /\\bALTER\\s+TABLE\\b[\\s\\S]*\\bDROP\\b/i,\n label: \"ALTER TABLE ... DROP\",\n },\n];\n\nexport async function validateContracts(\n root: string,\n config: QfaiConfig,\n): Promise<Issue[]> {\n const issues: Issue[] = [];\n const contractsRoot = resolvePath(root, config, \"contractsDir\");\n\n issues.push(...(await validateUiContracts(path.join(contractsRoot, \"ui\"))));\n issues.push(...(await validateApiContracts(path.join(contractsRoot, \"api\"))));\n issues.push(...(await validateDbContracts(path.join(contractsRoot, \"db\"))));\n const contractIndex = await buildContractIndex(root, config);\n issues.push(...validateDuplicateContractIds(contractIndex));\n\n return issues;\n}\n\nasync function validateUiContracts(uiRoot: string): Promise<Issue[]> {\n const files = await collectUiContractFiles(uiRoot);\n if (files.length === 0) {\n return [\n issue(\n \"QFAI-UI-000\",\n \"UI 契約ファイルが見つかりません。\",\n \"info\",\n uiRoot,\n \"contracts.ui.files\",\n ),\n ];\n }\n\n const issues: Issue[] = [];\n for (const file of files) {\n const text = await readFile(file, \"utf-8\");\n const invalidIds = extractInvalidIds(text, [\n \"SPEC\",\n \"BR\",\n \"SC\",\n \"UI\",\n \"API\",\n \"DB\",\n \"ADR\",\n ]);\n if (invalidIds.length > 0) {\n issues.push(\n issue(\n \"QFAI-ID-002\",\n `ID フォーマットが不正です: ${invalidIds.join(\", \")}`,\n \"error\",\n file,\n \"id.format\",\n invalidIds,\n ),\n );\n }\n const declaredIds = extractDeclaredContractIds(text);\n issues.push(...validateDeclaredContractIds(declaredIds, file, \"UI\"));\n try {\n parseStructuredContract(file, stripContractDeclarationLines(text));\n } catch (error) {\n issues.push(\n issue(\n \"QFAI-CONTRACT-001\",\n `UI 契約ファイルの解析に失敗しました: ${file} (${formatError(error)})`,\n \"error\",\n file,\n \"contracts.ui.parse\",\n ),\n );\n }\n }\n\n return issues;\n}\n\nasync function validateApiContracts(apiRoot: string): Promise<Issue[]> {\n const files = await collectApiContractFiles(apiRoot);\n if (files.length === 0) {\n return [\n issue(\n \"QFAI-API-000\",\n \"API 契約ファイルが見つかりません。\",\n \"info\",\n apiRoot,\n \"contracts.api.files\",\n ),\n ];\n }\n\n const issues: Issue[] = [];\n for (const file of files) {\n const text = await readFile(file, \"utf-8\");\n const invalidIds = extractInvalidIds(text, [\n \"SPEC\",\n \"BR\",\n \"SC\",\n \"UI\",\n \"API\",\n \"DB\",\n \"ADR\",\n ]);\n if (invalidIds.length > 0) {\n issues.push(\n issue(\n \"QFAI-ID-002\",\n `ID フォーマットが不正です: ${invalidIds.join(\", \")}`,\n \"error\",\n file,\n \"id.format\",\n invalidIds,\n ),\n );\n }\n const declaredIds = extractDeclaredContractIds(text);\n issues.push(...validateDeclaredContractIds(declaredIds, file, \"API\"));\n let doc: Record<string, unknown>;\n try {\n doc = parseStructuredContract(file, stripContractDeclarationLines(text));\n } catch (error) {\n issues.push(\n issue(\n \"QFAI-CONTRACT-001\",\n `API 契約ファイルの解析に失敗しました: ${file} (${formatError(error)})`,\n \"error\",\n file,\n \"contracts.api.parse\",\n ),\n );\n continue;\n }\n\n if (!hasOpenApi(doc)) {\n issues.push(\n issue(\n \"QFAI-API-001\",\n \"OpenAPI 定義が見つかりません。\",\n \"error\",\n file,\n \"contracts.api.openapi\",\n ),\n );\n }\n }\n\n return issues;\n}\n\nasync function validateDbContracts(dbRoot: string): Promise<Issue[]> {\n const files = await collectDbContractFiles(dbRoot);\n if (files.length === 0) {\n return [\n issue(\n \"QFAI-DB-000\",\n \"DB 契約ファイルが見つかりません。\",\n \"info\",\n dbRoot,\n \"contracts.db.files\",\n ),\n ];\n }\n\n const issues: Issue[] = [];\n for (const file of files) {\n const text = await readFile(file, \"utf-8\");\n const invalidIds = extractInvalidIds(text, [\n \"SPEC\",\n \"BR\",\n \"SC\",\n \"UI\",\n \"API\",\n \"DB\",\n \"ADR\",\n ]);\n if (invalidIds.length > 0) {\n issues.push(\n issue(\n \"QFAI-ID-002\",\n `ID フォーマットが不正です: ${invalidIds.join(\", \")}`,\n \"error\",\n file,\n \"id.format\",\n invalidIds,\n ),\n );\n }\n const declaredIds = extractDeclaredContractIds(text);\n issues.push(...validateDeclaredContractIds(declaredIds, file, \"DB\"));\n issues.push(...lintSql(text, file));\n }\n\n return issues;\n}\n\nexport function lintSql(text: string, file: string): Issue[] {\n const issues: Issue[] = [];\n for (const { pattern, label } of SQL_DANGEROUS_PATTERNS) {\n if (pattern.test(text)) {\n issues.push(\n issue(\n \"QFAI-DB-001\",\n `危険な SQL 操作が含まれています: ${label}`,\n \"warning\",\n file,\n \"contracts.db.sql\",\n ),\n );\n }\n }\n return issues;\n}\n\ntype ContractKind = \"UI\" | \"API\" | \"DB\";\n\nfunction validateDeclaredContractIds(\n ids: string[],\n file: string,\n kind: ContractKind,\n): Issue[] {\n const issues: Issue[] = [];\n if (ids.length === 0) {\n issues.push(\n issue(\n \"QFAI-CONTRACT-010\",\n `契約ファイルに QFAI-CONTRACT-ID がありません: ${file}`,\n \"error\",\n file,\n \"contracts.declaration\",\n ),\n );\n return issues;\n }\n if (ids.length > 1) {\n issues.push(\n issue(\n \"QFAI-CONTRACT-011\",\n `契約ファイルに複数の QFAI-CONTRACT-ID が宣言されています: ${ids.join(\n \", \",\n )}`,\n \"error\",\n file,\n \"contracts.declaration\",\n ids,\n ),\n );\n return issues;\n }\n\n const [id] = ids;\n if (id && !id.startsWith(`${kind}-`)) {\n issues.push(\n issue(\n \"QFAI-CONTRACT-013\",\n `契約ファイルの QFAI-CONTRACT-ID が ${kind}- ではありません: ${id}`,\n \"error\",\n file,\n \"contracts.declarationPrefix\",\n [id],\n ),\n );\n }\n\n return issues;\n}\n\nfunction validateDuplicateContractIds(contractIndex: {\n idToFiles: Map<string, Set<string>>;\n}): Issue[] {\n const issues: Issue[] = [];\n for (const [id, files] of contractIndex.idToFiles.entries()) {\n if (files.size <= 1) {\n continue;\n }\n const sortedFiles = Array.from(files).sort((a, b) => a.localeCompare(b));\n issues.push(\n issue(\n \"QFAI-CONTRACT-012\",\n `契約 ID が複数ファイルで宣言されています: ${id} (${sortedFiles.join(\n \", \",\n )})`,\n \"error\",\n sortedFiles[0],\n \"contracts.idDuplicate\",\n [id],\n ),\n );\n }\n return issues;\n}\n\nfunction hasOpenApi(doc: Record<string, unknown>): boolean {\n return typeof doc.openapi === \"string\" && doc.openapi.length > 0;\n}\n\nfunction formatError(error: unknown): string {\n if (error instanceof Error) {\n return error.message;\n }\n return String(error);\n}\n\nfunction issue(\n code: string,\n message: string,\n severity: IssueSeverity,\n file?: string,\n rule?: string,\n refs?: string[],\n): Issue {\n const issue: Issue = {\n code,\n severity,\n message,\n };\n if (file) {\n issue.file = file;\n }\n if (rule) {\n issue.rule = rule;\n }\n if (refs && refs.length > 0) {\n issue.refs = refs;\n }\n return issue;\n}\n","import path from \"node:path\";\n\nimport { parse as parseYaml } from \"yaml\";\n\nimport { extractIds } from \"./ids.js\";\n\nexport function parseStructuredContract(\n file: string,\n text: string,\n): Record<string, unknown> {\n const ext = path.extname(file).toLowerCase();\n if (ext === \".json\") {\n return JSON.parse(text) as Record<string, unknown>;\n }\n return parseYaml(text) as Record<string, unknown>;\n}\n\nexport function extractUiContractIds(doc: Record<string, unknown>): string[] {\n const id = typeof doc.id === \"string\" ? doc.id : \"\";\n return extractIds(id, \"UI\");\n}\n\nexport function extractApiContractIds(doc: Record<string, unknown>): string[] {\n const operationIds = new Set<string>();\n collectOperationIds(doc, operationIds);\n\n const ids = new Set<string>();\n for (const operationId of operationIds) {\n extractIds(operationId, \"API\").forEach((id) => ids.add(id));\n }\n return Array.from(ids);\n}\n\nexport function collectOperationIds(value: unknown, out: Set<string>): void {\n if (!value || typeof value !== \"object\") {\n return;\n }\n if (Array.isArray(value)) {\n for (const item of value) {\n collectOperationIds(item, out);\n }\n return;\n }\n\n for (const [key, entry] of Object.entries(value)) {\n if (key === \"operationId\" && typeof entry === \"string\") {\n out.add(entry);\n continue;\n }\n collectOperationIds(entry, out);\n }\n}\n","import { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport type { QfaiConfig } from \"../config.js\";\nimport { resolvePath } from \"../config.js\";\nimport { collectSpecPackDirs } from \"../discovery.js\";\nimport type { Issue, IssueSeverity } from \"../types.js\";\n\nconst SECTION_RE = /^##\\s+変更区分/m;\nconst COMPAT_LINE_RE = /^\\s*-\\s*\\[[ xX]\\]\\s*Compatibility\\b/m;\nconst CHANGE_LINE_RE = /^\\s*-\\s*\\[[ xX]\\]\\s*Change\\/Improvement\\b/m;\nconst COMPAT_CHECKED_RE = /^\\s*-\\s*\\[[xX]\\]\\s*Compatibility\\b/m;\nconst CHANGE_CHECKED_RE = /^\\s*-\\s*\\[[xX]\\]\\s*Change\\/Improvement\\b/m;\n\nexport async function validateDeltas(\n root: string,\n config: QfaiConfig,\n): Promise<Issue[]> {\n const specsRoot = resolvePath(root, config, \"specsDir\");\n const packs = await collectSpecPackDirs(specsRoot);\n if (packs.length === 0) {\n return [];\n }\n\n const issues: Issue[] = [];\n for (const pack of packs) {\n const deltaPath = path.join(pack, \"delta.md\");\n let text: string;\n try {\n text = await readFile(deltaPath, \"utf-8\");\n } catch (error) {\n if (isMissingFileError(error)) {\n issues.push(\n issue(\n \"QFAI-DELTA-001\",\n \"delta.md が見つかりません。\",\n \"error\",\n deltaPath,\n \"delta.exists\",\n ),\n );\n continue;\n }\n throw error;\n }\n\n const hasSection = SECTION_RE.test(text);\n const hasCompatibility = COMPAT_LINE_RE.test(text);\n const hasChange = CHANGE_LINE_RE.test(text);\n if (!hasSection || !hasCompatibility || !hasChange) {\n issues.push(\n issue(\n \"QFAI-DELTA-002\",\n \"delta.md の変更区分が不足しています。\",\n \"error\",\n deltaPath,\n \"delta.section\",\n ),\n );\n continue;\n }\n\n const compatibilityChecked = COMPAT_CHECKED_RE.test(text);\n const changeChecked = CHANGE_CHECKED_RE.test(text);\n if (compatibilityChecked === changeChecked) {\n issues.push(\n issue(\n \"QFAI-DELTA-003\",\n \"delta.md の変更区分はどちらか1つだけ選択してください(両方ON/両方OFFは無効です)。\",\n \"error\",\n deltaPath,\n \"delta.classification\",\n ),\n );\n }\n }\n\n return issues;\n}\n\nfunction isMissingFileError(error: unknown): boolean {\n if (!error || typeof error !== \"object\") {\n return false;\n }\n return (error as { code?: string }).code === \"ENOENT\";\n}\n\nfunction issue(\n code: string,\n message: string,\n severity: IssueSeverity,\n file?: string,\n rule?: string,\n refs?: string[],\n): Issue {\n const issue: Issue = {\n code,\n severity,\n message,\n };\n if (file) {\n issue.file = file;\n }\n if (rule) {\n issue.rule = rule;\n }\n if (refs && refs.length > 0) {\n issue.refs = refs;\n }\n return issue;\n}\n","import { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport type { QfaiConfig } from \"../config.js\";\nimport { resolvePath } from \"../config.js\";\nimport { buildContractIndex } from \"../contractIndex.js\";\nimport { collectScenarioFiles, collectSpecFiles } from \"../discovery.js\";\nimport { parseSpec } from \"../parse/spec.js\";\nimport { parseScenarioDocument } from \"../scenarioModel.js\";\nimport type { Issue, IssueSeverity } from \"../types.js\";\n\nconst SC_TAG_RE = /^SC-\\d{4}$/;\n\nexport async function validateDefinedIds(\n root: string,\n config: QfaiConfig,\n): Promise<Issue[]> {\n const issues: Issue[] = [];\n const specsRoot = resolvePath(root, config, \"specsDir\");\n\n const specFiles = await collectSpecFiles(specsRoot);\n const scenarioFiles = await collectScenarioFiles(specsRoot);\n\n const defined = new Map<string, Set<string>>();\n\n await collectSpecDefinitionIds(specFiles, defined);\n await collectScenarioDefinitionIds(scenarioFiles, defined);\n const contractIndex = await buildContractIndex(root, config);\n for (const [id, files] of contractIndex.idToFiles.entries()) {\n for (const file of files) {\n recordId(defined, id, file);\n }\n }\n\n for (const [id, files] of defined.entries()) {\n if (files.size <= 1) {\n continue;\n }\n const sorted = Array.from(files).sort();\n issues.push(\n issue(\n \"QFAI-ID-001\",\n `ID が重複しています: ${id} (${formatFileList(sorted, root)})`,\n \"error\",\n sorted[0],\n \"id.duplicate\",\n ),\n );\n }\n\n return issues;\n}\n\nasync function collectSpecDefinitionIds(\n files: string[],\n out: Map<string, Set<string>>,\n): Promise<void> {\n for (const file of files) {\n const text = await readFile(file, \"utf-8\");\n const parsed = parseSpec(text, file);\n if (parsed.specId) {\n recordId(out, parsed.specId, file);\n }\n parsed.brs.forEach((br) => recordId(out, br.id, file));\n }\n}\n\nasync function collectScenarioDefinitionIds(\n files: string[],\n out: Map<string, Set<string>>,\n): Promise<void> {\n for (const file of files) {\n const text = await readFile(file, \"utf-8\");\n const { document, errors } = parseScenarioDocument(text, file);\n if (!document || errors.length > 0) {\n continue;\n }\n for (const scenario of document.scenarios) {\n for (const tag of scenario.tags) {\n if (SC_TAG_RE.test(tag)) {\n recordId(out, tag, file);\n }\n }\n }\n }\n}\n\nfunction recordId(\n out: Map<string, Set<string>>,\n id: string,\n file: string,\n): void {\n const current = out.get(id) ?? new Set<string>();\n current.add(file);\n out.set(id, current);\n}\n\nfunction formatFileList(files: string[], root: string): string {\n return files\n .map((file) => {\n const relative = path.relative(root, file);\n return relative.length > 0 ? relative : file;\n })\n .join(\", \");\n}\n\nfunction issue(\n code: string,\n message: string,\n severity: IssueSeverity,\n file?: string,\n rule?: string,\n refs?: string[],\n): Issue {\n const issue: Issue = {\n code,\n severity,\n message,\n };\n if (file) {\n issue.file = file;\n }\n if (rule) {\n issue.rule = rule;\n }\n if (refs && refs.length > 0) {\n issue.refs = refs;\n }\n return issue;\n}\n","import { readFile } from \"node:fs/promises\";\n\nimport type { QfaiConfig } from \"../config.js\";\nimport { resolvePath } from \"../config.js\";\nimport { extractInvalidIds } from \"../ids.js\";\nimport { collectSpecEntries } from \"../specLayout.js\";\nimport { parseScenarioDocument } from \"../scenarioModel.js\";\nimport type { Issue, IssueSeverity } from \"../types.js\";\n\nconst GIVEN_PATTERN = /\\bGiven\\b/;\nconst WHEN_PATTERN = /\\bWhen\\b/;\nconst THEN_PATTERN = /\\bThen\\b/;\nconst SC_TAG_RE = /^SC-\\d{4}$/;\nconst SPEC_TAG_RE = /^SPEC-\\d{4}$/;\n\nexport async function validateScenarios(\n root: string,\n config: QfaiConfig,\n): Promise<Issue[]> {\n const specsRoot = resolvePath(root, config, \"specsDir\");\n const entries = await collectSpecEntries(specsRoot);\n\n if (entries.length === 0) {\n const expected = \"spec-0001/scenario.md\";\n const legacy = \"spec-001/scenario.md\";\n return [\n issue(\n \"QFAI-SC-000\",\n `Scenario ファイルが見つかりません。配置場所: ${config.paths.specsDir} / 期待パターン: ${expected} (${legacy} は非対応)`,\n \"info\",\n specsRoot,\n \"scenario.files\",\n ),\n ];\n }\n\n const issues: Issue[] = [];\n for (const entry of entries) {\n let text: string;\n try {\n text = await readFile(entry.scenarioPath, \"utf-8\");\n } catch (error) {\n if (isMissingFileError(error)) {\n issues.push(\n issue(\n \"QFAI-SC-001\",\n \"scenario.md が見つかりません。\",\n \"error\",\n entry.scenarioPath,\n \"scenario.exists\",\n ),\n );\n continue;\n }\n throw error;\n }\n issues.push(...validateScenarioContent(text, entry.scenarioPath));\n }\n\n return issues;\n}\n\nexport function validateScenarioContent(text: string, file: string): Issue[] {\n const issues: Issue[] = [];\n\n const invalidIds = extractInvalidIds(text, [\n \"SPEC\",\n \"BR\",\n \"SC\",\n \"UI\",\n \"API\",\n \"DB\",\n \"ADR\",\n ]);\n if (invalidIds.length > 0) {\n issues.push(\n issue(\n \"QFAI-ID-002\",\n `ID フォーマットが不正です: ${invalidIds.join(\", \")}`,\n \"error\",\n file,\n \"id.format\",\n invalidIds,\n ),\n );\n }\n\n const { document, errors } = parseScenarioDocument(text, file);\n if (!document || errors.length > 0) {\n issues.push(\n issue(\n \"QFAI-SC-010\",\n `Gherkin の解析に失敗しました: ${errors.join(\", \") || \"unknown\"}`,\n \"error\",\n file,\n \"scenario.parse\",\n ),\n );\n return issues;\n }\n\n const featureSpecTags = document.featureTags.filter((tag) =>\n SPEC_TAG_RE.test(tag),\n );\n if (featureSpecTags.length > 1) {\n issues.push(\n issue(\n \"QFAI-SC-009\",\n `Feature の SPEC タグが複数あります: ${featureSpecTags.join(\", \")}`,\n \"error\",\n file,\n \"scenario.featureSpec\",\n featureSpecTags,\n ),\n );\n }\n\n const missingStructure: string[] = [];\n if (!document.featureName) missingStructure.push(\"Feature\");\n if (document.scenarios.length === 0) missingStructure.push(\"Scenario\");\n if (missingStructure.length > 0) {\n issues.push(\n issue(\n \"QFAI-SC-006\",\n `Scenario ファイルに必要な構造がありません: ${missingStructure.join(\n \", \",\n )}`,\n \"error\",\n file,\n \"scenario.structure\",\n ),\n );\n }\n\n for (const scenario of document.scenarios) {\n if (scenario.tags.length === 0) {\n issues.push(\n issue(\n \"QFAI-SC-007\",\n `Scenario タグが見つかりません: ${scenario.name}`,\n \"error\",\n file,\n \"scenario.tags\",\n ),\n );\n continue;\n }\n\n const missingTags: string[] = [];\n const scTags = scenario.tags.filter((tag) => SC_TAG_RE.test(tag));\n if (scTags.length === 0) {\n missingTags.push(\"SC(0件)\");\n } else if (scTags.length > 1) {\n missingTags.push(`SC(${scTags.length}件/1件必須)`);\n }\n if (missingTags.length > 0) {\n issues.push(\n issue(\n \"QFAI-SC-008\",\n `Scenario タグに不足があります: ${missingTags.join(\", \")} (${\n scenario.name\n })`,\n \"error\",\n file,\n \"scenario.tagIds\",\n ),\n );\n }\n }\n\n for (const scenario of document.scenarios) {\n const missingSteps: string[] = [];\n const keywords = scenario.steps.map((step) => step.keyword.trim());\n if (!keywords.some((keyword) => GIVEN_PATTERN.test(keyword))) {\n missingSteps.push(\"Given\");\n }\n if (!keywords.some((keyword) => WHEN_PATTERN.test(keyword))) {\n missingSteps.push(\"When\");\n }\n if (!keywords.some((keyword) => THEN_PATTERN.test(keyword))) {\n missingSteps.push(\"Then\");\n }\n if (missingSteps.length > 0) {\n issues.push(\n issue(\n \"QFAI-SC-005\",\n `Given/When/Then が不足しています: ${missingSteps.join(\", \")} (${\n scenario.name\n })`,\n \"warning\",\n file,\n \"scenario.steps\",\n ),\n );\n }\n }\n\n return issues;\n}\n\nfunction issue(\n code: string,\n message: string,\n severity: IssueSeverity,\n file?: string,\n rule?: string,\n refs?: string[],\n): Issue {\n const issue: Issue = {\n code,\n severity,\n message,\n };\n if (file) {\n issue.file = file;\n }\n if (rule) {\n issue.rule = rule;\n }\n if (refs && refs.length > 0) {\n issue.refs = refs;\n }\n return issue;\n}\n\nfunction isMissingFileError(error: unknown): boolean {\n if (!error || typeof error !== \"object\") {\n return false;\n }\n return (error as { code?: string }).code === \"ENOENT\";\n}\n","import { readFile } from \"node:fs/promises\";\nimport type { QfaiConfig } from \"../config.js\";\nimport { resolvePath } from \"../config.js\";\nimport { extractIds, extractInvalidIds } from \"../ids.js\";\nimport { parseSpec } from \"../parse/spec.js\";\nimport { collectSpecEntries } from \"../specLayout.js\";\nimport type { Issue, IssueSeverity } from \"../types.js\";\n\nexport async function validateSpecs(\n root: string,\n config: QfaiConfig,\n): Promise<Issue[]> {\n const specsRoot = resolvePath(root, config, \"specsDir\");\n const entries = await collectSpecEntries(specsRoot);\n\n if (entries.length === 0) {\n const expected = \"spec-0001/spec.md\";\n const legacy = \"spec-001/spec.md\";\n return [\n issue(\n \"QFAI-SPEC-000\",\n `Spec ファイルが見つかりません。配置場所: ${config.paths.specsDir} / 期待パターン: ${expected} (${legacy} は非対応)`,\n \"info\",\n specsRoot,\n \"spec.files\",\n ),\n ];\n }\n\n const issues: Issue[] = [];\n for (const entry of entries) {\n let text: string;\n try {\n text = await readFile(entry.specPath, \"utf-8\");\n } catch (error) {\n if (isMissingFileError(error)) {\n issues.push(\n issue(\n \"QFAI-SPEC-005\",\n \"spec.md が見つかりません。\",\n \"error\",\n entry.specPath,\n \"spec.exists\",\n ),\n );\n continue;\n }\n throw error;\n }\n issues.push(\n ...validateSpecContent(\n text,\n entry.specPath,\n config.validation.require.specSections,\n ),\n );\n }\n\n return issues;\n}\n\nexport function validateSpecContent(\n text: string,\n file: string,\n requiredSections: string[],\n): Issue[] {\n const issues: Issue[] = [];\n\n const parsed = parseSpec(text, file);\n\n const invalidIds = extractInvalidIds(text, [\n \"SPEC\",\n \"BR\",\n \"SC\",\n \"UI\",\n \"API\",\n \"DB\",\n \"ADR\",\n ]);\n if (invalidIds.length > 0) {\n issues.push(\n issue(\n \"QFAI-ID-002\",\n `ID フォーマットが不正です: ${invalidIds.join(\", \")}`,\n \"error\",\n file,\n \"id.format\",\n invalidIds,\n ),\n );\n }\n\n if (!parsed.specId) {\n issues.push(\n issue(\n \"QFAI-SPEC-001\",\n \"SPEC ID が見つかりません。\",\n \"error\",\n file,\n \"spec.id\",\n ),\n );\n }\n\n if (parsed.brs.length === 0) {\n issues.push(\n issue(\n \"QFAI-SPEC-002\",\n \"BR ID が見つかりません。\",\n \"error\",\n file,\n \"spec.br\",\n ),\n );\n }\n\n for (const br of parsed.brsWithoutPriority) {\n issues.push(\n issue(\n \"QFAI-BR-001\",\n `BR 行に Priority がありません: ${br.id}`,\n \"error\",\n file,\n \"spec.brPriority\",\n [br.id],\n ),\n );\n }\n\n for (const br of parsed.brsWithInvalidPriority) {\n issues.push(\n issue(\n \"QFAI-BR-002\",\n `BR Priority が不正です: ${br.id} (${br.priority})`,\n \"error\",\n file,\n \"spec.brPriority\",\n [br.id],\n ),\n );\n }\n\n const scIds = extractIds(text, \"SC\");\n if (scIds.length > 0) {\n issues.push(\n issue(\n \"QFAI-SPEC-003\",\n \"Spec は SC を参照しないルールです。\",\n \"warning\",\n file,\n \"spec.noSc\",\n scIds,\n ),\n );\n }\n\n for (const section of requiredSections) {\n if (!parsed.sections.has(section)) {\n issues.push(\n issue(\n \"QFAI-SPEC-004\",\n `必須セクションが不足しています: ${section}`,\n \"error\",\n file,\n \"spec.requiredSection\",\n ),\n );\n }\n }\n\n return issues;\n}\n\nfunction issue(\n code: string,\n message: string,\n severity: IssueSeverity,\n file?: string,\n rule?: string,\n refs?: string[],\n): Issue {\n const issue: Issue = {\n code,\n severity,\n message,\n };\n if (file) {\n issue.file = file;\n }\n if (rule) {\n issue.rule = rule;\n }\n if (refs && refs.length > 0) {\n issue.refs = refs;\n }\n return issue;\n}\n\nfunction isMissingFileError(error: unknown): boolean {\n if (!error || typeof error !== \"object\") {\n return false;\n }\n return (error as { code?: string }).code === \"ENOENT\";\n}\n","import { readFile } from \"node:fs/promises\";\n\nimport type { QfaiConfig } from \"../config.js\";\nimport { resolvePath } from \"../config.js\";\nimport { buildContractIndex } from \"../contractIndex.js\";\nimport { collectScenarioFiles, collectSpecFiles } from \"../discovery.js\";\nimport { collectFiles } from \"../fs.js\";\nimport { extractAllIds } from \"../ids.js\";\nimport { parseSpec } from \"../parse/spec.js\";\nimport { buildScenarioAtoms, parseScenarioDocument } from \"../scenarioModel.js\";\nimport { SC_TAG_RE, collectScTestReferences } from \"../traceability.js\";\nimport type { Issue, IssueSeverity } from \"../types.js\";\n\nconst SPEC_TAG_RE = /^SPEC-\\d{4}$/;\nconst BR_TAG_RE = /^BR-\\d{4}$/;\n\nexport async function validateTraceability(\n root: string,\n config: QfaiConfig,\n): Promise<Issue[]> {\n const issues: Issue[] = [];\n const specsRoot = resolvePath(root, config, \"specsDir\");\n const srcRoot = resolvePath(root, config, \"srcDir\");\n const testsRoot = resolvePath(root, config, \"testsDir\");\n\n const specFiles = await collectSpecFiles(specsRoot);\n const scenarioFiles = await collectScenarioFiles(specsRoot);\n\n const upstreamIds = new Set<string>();\n const specIds = new Set<string>();\n const brIdsInSpecs = new Set<string>();\n const brIdsInScenarios = new Set<string>();\n const scIdsInScenarios = new Set<string>();\n const specContractIds = new Set<string>();\n const specToBrIds = new Map<string, Set<string>>();\n const contractIndex = await buildContractIndex(root, config);\n const contractIds = contractIndex.ids;\n\n for (const file of specFiles) {\n const text = await readFile(file, \"utf-8\");\n extractAllIds(text).forEach((id) => upstreamIds.add(id));\n\n const parsed = parseSpec(text, file);\n if (parsed.specId) {\n specIds.add(parsed.specId);\n }\n\n const brIds = parsed.brs.map((br) => br.id);\n brIds.forEach((id) => brIdsInSpecs.add(id));\n\n if (parsed.specId) {\n const current = specToBrIds.get(parsed.specId) ?? new Set<string>();\n brIds.forEach((id) => current.add(id));\n specToBrIds.set(parsed.specId, current);\n }\n\n const contractRefs = parsed.contractRefs;\n if (contractRefs.lines.length === 0) {\n issues.push(\n issue(\n \"QFAI-TRACE-020\",\n \"Spec に QFAI-CONTRACT-REF がありません。\",\n \"error\",\n file,\n \"traceability.specContractRefRequired\",\n ),\n );\n } else {\n if (contractRefs.hasNone && contractRefs.ids.length > 0) {\n issues.push(\n issue(\n \"QFAI-TRACE-021\",\n \"Spec の QFAI-CONTRACT-REF に none と契約 ID が混在しています。\",\n \"error\",\n file,\n \"traceability.specContractRefFormat\",\n ),\n );\n }\n if (contractRefs.invalidTokens.length > 0) {\n issues.push(\n issue(\n \"QFAI-TRACE-021\",\n `Spec の契約 ID が不正です: ${contractRefs.invalidTokens.join(\n \", \",\n )}`,\n \"error\",\n file,\n \"traceability.specContractRefFormat\",\n contractRefs.invalidTokens,\n ),\n );\n }\n }\n\n contractRefs.ids.forEach((id) => {\n specContractIds.add(id);\n });\n\n const unknownContractIds = contractRefs.ids.filter(\n (id) => !contractIds.has(id),\n );\n if (unknownContractIds.length > 0) {\n issues.push(\n issue(\n \"QFAI-TRACE-021\",\n `Spec が未知の契約 ID を参照しています: ${unknownContractIds.join(\n \", \",\n )}`,\n \"error\",\n file,\n \"traceability.specContractExists\",\n unknownContractIds,\n ),\n );\n }\n }\n\n for (const file of scenarioFiles) {\n const text = await readFile(file, \"utf-8\");\n extractAllIds(text).forEach((id) => upstreamIds.add(id));\n\n const { document, errors } = parseScenarioDocument(text, file);\n if (!document || errors.length > 0) {\n continue;\n }\n\n const atoms = buildScenarioAtoms(document);\n const scIdsInFile = new Set<string>();\n\n for (const [index, scenario] of document.scenarios.entries()) {\n const atom = atoms[index];\n if (!atom) {\n continue;\n }\n\n const specTags = scenario.tags.filter((tag) => SPEC_TAG_RE.test(tag));\n const brTags = scenario.tags.filter((tag) => BR_TAG_RE.test(tag));\n const scTags = scenario.tags.filter((tag) => SC_TAG_RE.test(tag));\n\n if (specTags.length === 0) {\n issues.push(\n issue(\n \"QFAI-TRACE-014\",\n `Scenario が SPEC タグを持っていません: ${scenario.name}`,\n \"error\",\n file,\n \"traceability.scenarioSpecRequired\",\n ),\n );\n }\n if (brTags.length === 0) {\n issues.push(\n issue(\n \"QFAI-TRACE-015\",\n `Scenario が BR タグを持っていません: ${scenario.name}`,\n \"error\",\n file,\n \"traceability.scenarioBrRequired\",\n ),\n );\n }\n\n brTags.forEach((id) => brIdsInScenarios.add(id));\n scTags.forEach((id) => {\n scIdsInScenarios.add(id);\n scIdsInFile.add(id);\n });\n const unknownSpecIds = specTags.filter((id) => !specIds.has(id));\n if (unknownSpecIds.length > 0) {\n issues.push(\n issue(\n \"QFAI-TRACE-005\",\n `Scenario が存在しない SPEC を参照しています: ${unknownSpecIds.join(\n \", \",\n )} (${scenario.name})`,\n \"error\",\n file,\n \"traceability.scenarioSpecExists\",\n unknownSpecIds,\n ),\n );\n }\n\n const unknownBrIds = brTags.filter((id) => !brIdsInSpecs.has(id));\n if (unknownBrIds.length > 0) {\n issues.push(\n issue(\n \"QFAI-TRACE-006\",\n `Scenario が存在しない BR を参照しています: ${unknownBrIds.join(\n \", \",\n )} (${scenario.name})`,\n \"error\",\n file,\n \"traceability.scenarioBrExists\",\n unknownBrIds,\n ),\n );\n }\n\n const unknownContractIds = atom.contractIds.filter(\n (id) => !contractIds.has(id),\n );\n if (unknownContractIds.length > 0) {\n issues.push(\n issue(\n \"QFAI-TRACE-008\",\n `Scenario が存在しない契約 ID を参照しています: ${unknownContractIds.join(\n \", \",\n )} (${scenario.name})`,\n config.validation.traceability.unknownContractIdSeverity,\n file,\n \"traceability.scenarioContractExists\",\n unknownContractIds,\n ),\n );\n }\n\n if (specTags.length > 0 && brTags.length > 0) {\n const allowedBrIds = new Set<string>();\n for (const specId of specTags) {\n const brIdsForSpec = specToBrIds.get(specId);\n if (!brIdsForSpec) {\n continue;\n }\n brIdsForSpec.forEach((id) => allowedBrIds.add(id));\n }\n const invalidBrIds = brTags.filter((id) => !allowedBrIds.has(id));\n if (invalidBrIds.length > 0) {\n issues.push(\n issue(\n \"QFAI-TRACE-007\",\n `Scenario の BR が参照 SPEC に属していません: ${invalidBrIds.join(\n \", \",\n )} (SPEC: ${specTags.join(\", \")}) (${scenario.name})`,\n \"error\",\n file,\n \"traceability.scenarioBrUnderSpec\",\n invalidBrIds,\n ),\n );\n }\n }\n }\n\n if (scIdsInFile.size !== 1) {\n const invalidScIds = Array.from(scIdsInFile).sort((a, b) =>\n a.localeCompare(b),\n );\n const detail =\n invalidScIds.length === 0\n ? \"SC が見つかりません\"\n : `複数の SC が存在します: ${invalidScIds.join(\", \")}`;\n issues.push(\n issue(\n \"QFAI-TRACE-012\",\n `Spec entry が Spec:SC=1:1 を満たしていません: ${detail}`,\n \"error\",\n file,\n \"traceability.specScOneToOne\",\n invalidScIds,\n ),\n );\n }\n }\n\n if (upstreamIds.size === 0) {\n return [\n issue(\n \"QFAI-TRACE-000\",\n \"上流 ID が見つかりません。\",\n \"info\",\n specsRoot,\n \"traceability.upstream\",\n ),\n ];\n }\n\n if (config.validation.traceability.brMustHaveSc && brIdsInSpecs.size > 0) {\n const orphanBrIds = Array.from(brIdsInSpecs).filter(\n (id) => !brIdsInScenarios.has(id),\n );\n if (orphanBrIds.length > 0) {\n issues.push(\n issue(\n \"QFAI_TRACE_BR_ORPHAN\",\n `BR が SC に紐づいていません: ${orphanBrIds.join(\", \")}`,\n \"error\",\n specsRoot,\n \"traceability.brMustHaveSc\",\n orphanBrIds,\n ),\n );\n }\n }\n\n const scRefsResult = await collectScTestReferences(\n root,\n config.validation.traceability.testFileGlobs,\n config.validation.traceability.testFileExcludeGlobs,\n );\n const scTestRefs = scRefsResult.refs;\n const testFileScan = scRefsResult.scan;\n const hasScenarios = scIdsInScenarios.size > 0;\n const hasGlobConfig = testFileScan.globs.length > 0;\n const hasMatchedTests = testFileScan.matchedFileCount > 0;\n\n if (\n hasScenarios &&\n (!hasGlobConfig || !hasMatchedTests || scRefsResult.error)\n ) {\n const detail = scRefsResult.error ? `(詳細: ${scRefsResult.error})` : \"\";\n issues.push(\n issue(\n \"QFAI-TRACE-013\",\n `テスト探索 glob が未設定/不正/一致ファイル0のため SC→Test を判定できません。${detail}`,\n \"error\",\n testsRoot,\n \"traceability.testFileGlobs\",\n ),\n );\n } else {\n if (\n config.validation.traceability.scMustHaveTest &&\n scIdsInScenarios.size\n ) {\n const scWithoutTests = Array.from(scIdsInScenarios).filter((id) => {\n const refs = scTestRefs.get(id);\n return !refs || refs.size === 0;\n });\n if (scWithoutTests.length > 0) {\n issues.push(\n issue(\n \"QFAI-TRACE-010\",\n `SC がテストで参照されていません: ${scWithoutTests.join(\n \", \",\n )}。testFileGlobs に一致するテストファイルへ QFAI:SC-xxxx を記載してください。`,\n config.validation.traceability.scNoTestSeverity,\n testsRoot,\n \"traceability.scMustHaveTest\",\n scWithoutTests,\n ),\n );\n }\n }\n\n const unknownScIds = Array.from(scTestRefs.keys()).filter(\n (id) => !scIdsInScenarios.has(id),\n );\n if (unknownScIds.length > 0) {\n issues.push(\n issue(\n \"QFAI-TRACE-011\",\n `テストが未知の SC をアノテーション参照しています: ${unknownScIds.join(\n \", \",\n )}`,\n \"error\",\n testsRoot,\n \"traceability.scUnknownInTests\",\n unknownScIds,\n ),\n );\n }\n }\n\n if (!config.validation.traceability.allowOrphanContracts) {\n if (contractIds.size > 0) {\n const orphanContracts = Array.from(contractIds).filter(\n (id) => !specContractIds.has(id),\n );\n if (orphanContracts.length > 0) {\n issues.push(\n issue(\n \"QFAI-TRACE-022\",\n `契約が Spec から参照されていません: ${orphanContracts.join(\", \")}`,\n \"error\",\n specsRoot,\n \"traceability.contractCoverage\",\n orphanContracts,\n ),\n );\n }\n }\n }\n\n issues.push(\n ...(await validateCodeReferences(upstreamIds, srcRoot, testsRoot)),\n );\n return issues;\n}\n\nasync function validateCodeReferences(\n upstreamIds: Set<string>,\n srcRoot: string,\n testsRoot: string,\n): Promise<Issue[]> {\n const issues: Issue[] = [];\n const codeFiles = await collectFiles(srcRoot, {\n extensions: [\".ts\", \".tsx\", \".js\", \".jsx\"],\n });\n const testFiles = await collectFiles(testsRoot, {\n extensions: [\".ts\", \".tsx\", \".js\", \".jsx\"],\n });\n const targetFiles = [...codeFiles, ...testFiles];\n\n if (targetFiles.length === 0) {\n issues.push(\n issue(\n \"QFAI-TRACE-001\",\n \"参照対象のコード/テストが見つかりません。\",\n \"info\",\n srcRoot,\n \"traceability.codeReferences\",\n ),\n );\n return issues;\n }\n\n const pattern = buildIdPattern(Array.from(upstreamIds));\n let found = false;\n\n for (const file of targetFiles) {\n const text = await readFile(file, \"utf-8\");\n if (pattern.test(text)) {\n found = true;\n break;\n }\n }\n\n if (!found) {\n issues.push(\n issue(\n \"QFAI-TRACE-002\",\n \"上流 ID がコード/テストに参照されていません(参考情報)。\",\n \"info\",\n srcRoot,\n \"traceability.codeReferences\",\n ),\n );\n }\n\n return issues;\n}\n\nfunction buildIdPattern(ids: string[]): RegExp {\n const escaped = ids.map((id) => id.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\"));\n return new RegExp(`\\\\b(${escaped.join(\"|\")})\\\\b`);\n}\n\nfunction issue(\n code: string,\n message: string,\n severity: IssueSeverity,\n file?: string,\n rule?: string,\n refs?: string[],\n): Issue {\n const issue: Issue = {\n code,\n severity,\n message,\n };\n if (file) {\n issue.file = file;\n }\n if (rule) {\n issue.rule = rule;\n }\n if (refs && refs.length > 0) {\n issue.refs = refs;\n }\n return issue;\n}\n","import { loadConfig, resolvePath, type ConfigLoadResult } from \"./config.js\";\nimport { collectScenarioFiles } from \"./discovery.js\";\nimport {\n buildScCoverage,\n collectScIdsFromScenarioFiles,\n collectScTestReferences,\n} from \"./traceability.js\";\nimport type { Issue, ValidationCounts, ValidationResult } from \"./types.js\";\nimport { resolveToolVersion } from \"./version.js\";\nimport { validateContracts } from \"./validators/contracts.js\";\nimport { validateDeltas } from \"./validators/delta.js\";\nimport { validateDefinedIds } from \"./validators/ids.js\";\nimport { validateScenarios } from \"./validators/scenario.js\";\nimport { validateSpecs } from \"./validators/spec.js\";\nimport { validateTraceability } from \"./validators/traceability.js\";\n\nexport async function validateProject(\n root: string,\n configResult?: ConfigLoadResult,\n): Promise<ValidationResult> {\n const resolved = configResult ?? (await loadConfig(root));\n const { config, issues: configIssues } = resolved;\n const issues = [\n ...configIssues,\n ...(await validateSpecs(root, config)),\n ...(await validateDeltas(root, config)),\n ...(await validateScenarios(root, config)),\n ...(await validateContracts(root, config)),\n ...(await validateDefinedIds(root, config)),\n ...(await validateTraceability(root, config)),\n ];\n\n const specsRoot = resolvePath(root, config, \"specsDir\");\n const scenarioFiles = await collectScenarioFiles(specsRoot);\n const scIds = await collectScIdsFromScenarioFiles(scenarioFiles);\n const { refs: scTestRefs, scan: testFiles } = await collectScTestReferences(\n root,\n config.validation.traceability.testFileGlobs,\n config.validation.traceability.testFileExcludeGlobs,\n );\n const scCoverage = buildScCoverage(scIds, scTestRefs);\n\n const toolVersion = await resolveToolVersion();\n return {\n toolVersion,\n issues,\n counts: countIssues(issues),\n traceability: {\n sc: scCoverage,\n testFiles,\n },\n };\n}\n\nfunction countIssues(issues: Issue[]): ValidationCounts {\n return issues.reduce<ValidationCounts>(\n (acc, issue) => {\n acc[issue.severity] += 1;\n return acc;\n },\n { info: 0, warning: 0, error: 0 },\n );\n}\n"],"mappings":"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","names":["path","parseYaml","import_promises","import_node_path","import_promises","import_node_path","import_promises","import_promises","import_node_path","fg","path","import_promises","import_node_path","path","exists","path","unique","import_promises","import_node_path","formatError","unique","SC_TAG_RE","formatError","path","import_promises","import_node_path","path","import_promises","import_node_path","import_node_path","import_yaml","path","parseYaml","path","formatError","issue","import_promises","import_node_path","path","isMissingFileError","issue","import_promises","import_node_path","SC_TAG_RE","issue","path","import_promises","SC_TAG_RE","SPEC_TAG_RE","issue","isMissingFileError","import_promises","issue","isMissingFileError","import_promises","SPEC_TAG_RE","BR_TAG_RE","issue","SC_TAG_RE","issue","ID_PREFIXES","path","toSortedArray","contractIds","buildIdPattern","record","issue"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/core/config.ts","../src/core/ids.ts","../src/core/report.ts","../src/core/contractIndex.ts","../src/core/discovery.ts","../src/core/fs.ts","../src/core/specLayout.ts","../src/core/contractsDecl.ts","../src/core/paths.ts","../src/core/normalize.ts","../src/core/parse/contractRefs.ts","../src/core/parse/markdown.ts","../src/core/parse/spec.ts","../src/core/traceability.ts","../src/core/gherkin/parse.ts","../src/core/scenarioModel.ts","../src/core/version.ts","../src/core/validators/contracts.ts","../src/core/contracts.ts","../src/core/validators/delta.ts","../src/core/validators/ids.ts","../src/core/validators/scenario.ts","../src/core/validators/spec.ts","../src/core/validators/traceability.ts","../src/core/validate.ts"],"sourcesContent":["export * from \"./core/index.js\";\n","import { access, readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport { parse as parseYaml } from \"yaml\";\n\nimport type { Issue } from \"./types.js\";\n\nexport type FailOn = \"never\" | \"warning\" | \"error\";\nexport type OutputFormat = \"text\" | \"github\";\nexport type TraceabilitySeverity = \"warning\" | \"error\";\nexport type OrphanContractsPolicy = \"error\" | \"warning\" | \"allow\";\n\nexport type QfaiPaths = {\n contractsDir: string;\n specsDir: string;\n rulesDir: string;\n outDir: string;\n promptsDir: string;\n srcDir: string;\n testsDir: string;\n};\n\nexport type QfaiValidationConfig = {\n failOn: FailOn;\n require: {\n specSections: string[];\n };\n traceability: {\n brMustHaveSc: boolean;\n scMustHaveTest: boolean;\n testFileGlobs: string[];\n testFileExcludeGlobs: string[];\n scNoTestSeverity: TraceabilitySeverity;\n orphanContractsPolicy: OrphanContractsPolicy;\n unknownContractIdSeverity: TraceabilitySeverity;\n };\n};\n\nexport type QfaiOutputConfig = {\n validateJsonPath: string;\n};\n\nexport type QfaiConfig = {\n paths: QfaiPaths;\n validation: QfaiValidationConfig;\n output: QfaiOutputConfig;\n};\n\nexport type ConfigPathKey = keyof QfaiPaths;\n\nexport type ConfigLoadResult = {\n config: QfaiConfig;\n issues: Issue[];\n configPath: string;\n};\n\nexport type ConfigSearchResult = {\n root: string;\n configPath: string;\n found: boolean;\n};\n\nexport const defaultConfig: QfaiConfig = {\n paths: {\n contractsDir: \".qfai/contracts\",\n specsDir: \".qfai/specs\",\n rulesDir: \".qfai/rules\",\n outDir: \".qfai/out\",\n promptsDir: \".qfai/prompts\",\n srcDir: \"src\",\n testsDir: \"tests\",\n },\n validation: {\n failOn: \"error\",\n require: {\n specSections: [\n \"背景\",\n \"スコープ\",\n \"非ゴール\",\n \"用語\",\n \"前提\",\n \"決定事項\",\n \"業務ルール\",\n ],\n },\n traceability: {\n brMustHaveSc: true,\n scMustHaveTest: true,\n testFileGlobs: [],\n testFileExcludeGlobs: [],\n scNoTestSeverity: \"error\",\n orphanContractsPolicy: \"error\",\n unknownContractIdSeverity: \"error\",\n },\n },\n output: {\n validateJsonPath: \".qfai/out/validate.json\",\n },\n};\n\nexport function getConfigPath(root: string): string {\n return path.join(root, \"qfai.config.yaml\");\n}\n\nexport async function findConfigRoot(\n startDir: string,\n): Promise<ConfigSearchResult> {\n const resolvedStart = path.resolve(startDir);\n let current = resolvedStart;\n\n while (true) {\n const configPath = getConfigPath(current);\n if (await exists(configPath)) {\n return { root: current, configPath, found: true };\n }\n const parent = path.dirname(current);\n if (parent === current) {\n break;\n }\n current = parent;\n }\n\n return {\n root: resolvedStart,\n configPath: getConfigPath(resolvedStart),\n found: false,\n };\n}\n\nexport async function loadConfig(root: string): Promise<ConfigLoadResult> {\n const configPath = getConfigPath(root);\n const issues: Issue[] = [];\n\n let parsed: unknown;\n try {\n const raw = await readFile(configPath, \"utf-8\");\n parsed = parseYaml(raw);\n } catch (error) {\n if (isMissingFile(error)) {\n return { config: defaultConfig, issues, configPath };\n }\n issues.push(configIssue(configPath, formatError(error)));\n return { config: defaultConfig, issues, configPath };\n }\n\n const normalized = normalizeConfig(parsed, configPath, issues);\n return { config: normalized, issues, configPath };\n}\n\nexport function resolvePath(\n root: string,\n config: QfaiConfig,\n key: ConfigPathKey,\n): string {\n return path.resolve(root, config.paths[key]);\n}\n\nfunction normalizeConfig(\n raw: unknown,\n configPath: string,\n issues: Issue[],\n): QfaiConfig {\n if (!isRecord(raw)) {\n issues.push(configIssue(configPath, \"設定ファイルの形式が不正です。\"));\n return defaultConfig;\n }\n\n return {\n paths: normalizePaths(raw.paths, configPath, issues),\n validation: normalizeValidation(raw.validation, configPath, issues),\n output: normalizeOutput(raw.output, configPath, issues),\n };\n}\n\nfunction normalizePaths(\n raw: unknown,\n configPath: string,\n issues: Issue[],\n): QfaiPaths {\n const base = defaultConfig.paths;\n if (!raw) {\n return base;\n }\n if (!isRecord(raw)) {\n issues.push(\n configIssue(configPath, \"paths はオブジェクトである必要があります。\"),\n );\n return base;\n }\n\n return {\n contractsDir: readString(\n raw.contractsDir,\n base.contractsDir,\n \"paths.contractsDir\",\n configPath,\n issues,\n ),\n specsDir: readString(\n raw.specsDir,\n base.specsDir,\n \"paths.specsDir\",\n configPath,\n issues,\n ),\n rulesDir: readString(\n raw.rulesDir,\n base.rulesDir,\n \"paths.rulesDir\",\n configPath,\n issues,\n ),\n outDir: readString(\n raw.outDir,\n base.outDir,\n \"paths.outDir\",\n configPath,\n issues,\n ),\n promptsDir: readString(\n raw.promptsDir,\n base.promptsDir,\n \"paths.promptsDir\",\n configPath,\n issues,\n ),\n srcDir: readString(\n raw.srcDir,\n base.srcDir,\n \"paths.srcDir\",\n configPath,\n issues,\n ),\n testsDir: readString(\n raw.testsDir,\n base.testsDir,\n \"paths.testsDir\",\n configPath,\n issues,\n ),\n };\n}\n\nfunction normalizeValidation(\n raw: unknown,\n configPath: string,\n issues: Issue[],\n): QfaiValidationConfig {\n const base = defaultConfig.validation;\n if (!raw) {\n return base;\n }\n if (!isRecord(raw)) {\n issues.push(\n configIssue(\n configPath,\n \"validation はオブジェクトである必要があります。\",\n ),\n );\n return base;\n }\n\n let requireRaw: Record<string, unknown> | undefined;\n if (raw.require === undefined) {\n requireRaw = undefined;\n } else if (isRecord(raw.require)) {\n requireRaw = raw.require;\n } else {\n issues.push(\n configIssue(\n configPath,\n \"validation.require はオブジェクトである必要があります。\",\n ),\n );\n requireRaw = undefined;\n }\n\n let traceabilityRaw: Record<string, unknown> | undefined;\n if (raw.traceability === undefined) {\n traceabilityRaw = undefined;\n } else if (isRecord(raw.traceability)) {\n traceabilityRaw = raw.traceability;\n } else {\n issues.push(\n configIssue(\n configPath,\n \"validation.traceability はオブジェクトである必要があります。\",\n ),\n );\n traceabilityRaw = undefined;\n }\n\n return {\n failOn: readFailOn(\n raw.failOn,\n base.failOn,\n \"validation.failOn\",\n configPath,\n issues,\n ),\n require: {\n specSections: readStringArray(\n requireRaw?.specSections,\n base.require.specSections,\n \"validation.require.specSections\",\n configPath,\n issues,\n ),\n },\n traceability: {\n brMustHaveSc: readBoolean(\n traceabilityRaw?.brMustHaveSc,\n base.traceability.brMustHaveSc,\n \"validation.traceability.brMustHaveSc\",\n configPath,\n issues,\n ),\n scMustHaveTest: readBoolean(\n traceabilityRaw?.scMustHaveTest,\n base.traceability.scMustHaveTest,\n \"validation.traceability.scMustHaveTest\",\n configPath,\n issues,\n ),\n testFileGlobs: readStringArray(\n traceabilityRaw?.testFileGlobs,\n base.traceability.testFileGlobs,\n \"validation.traceability.testFileGlobs\",\n configPath,\n issues,\n ),\n testFileExcludeGlobs: readStringArray(\n traceabilityRaw?.testFileExcludeGlobs,\n base.traceability.testFileExcludeGlobs,\n \"validation.traceability.testFileExcludeGlobs\",\n configPath,\n issues,\n ),\n scNoTestSeverity: readTraceabilitySeverity(\n traceabilityRaw?.scNoTestSeverity,\n base.traceability.scNoTestSeverity,\n \"validation.traceability.scNoTestSeverity\",\n configPath,\n issues,\n ),\n orphanContractsPolicy: readOrphanContractsPolicy(\n traceabilityRaw?.orphanContractsPolicy,\n base.traceability.orphanContractsPolicy,\n \"validation.traceability.orphanContractsPolicy\",\n configPath,\n issues,\n ),\n unknownContractIdSeverity: readTraceabilitySeverity(\n traceabilityRaw?.unknownContractIdSeverity,\n base.traceability.unknownContractIdSeverity,\n \"validation.traceability.unknownContractIdSeverity\",\n configPath,\n issues,\n ),\n },\n };\n}\n\nfunction normalizeOutput(\n raw: unknown,\n configPath: string,\n issues: Issue[],\n): QfaiOutputConfig {\n const base = defaultConfig.output;\n if (!raw) {\n return base;\n }\n if (!isRecord(raw)) {\n issues.push(\n configIssue(configPath, \"output はオブジェクトである必要があります。\"),\n );\n return base;\n }\n\n return {\n validateJsonPath: readString(\n raw.validateJsonPath,\n base.validateJsonPath,\n \"output.validateJsonPath\",\n configPath,\n issues,\n ),\n };\n}\n\nfunction readString(\n value: unknown,\n fallback: string,\n label: string,\n configPath: string,\n issues: Issue[],\n): string {\n if (typeof value === \"string\" && value.trim().length > 0) {\n return value;\n }\n if (value !== undefined) {\n issues.push(\n configIssue(configPath, `${label} は文字列である必要があります。`),\n );\n }\n return fallback;\n}\n\nfunction readStringArray(\n value: unknown,\n fallback: string[],\n label: string,\n configPath: string,\n issues: Issue[],\n): string[] {\n if (Array.isArray(value) && value.every((item) => typeof item === \"string\")) {\n return value;\n }\n if (value !== undefined) {\n issues.push(\n configIssue(configPath, `${label} は文字列配列である必要があります。`),\n );\n }\n return fallback;\n}\n\nfunction readBoolean(\n value: unknown,\n fallback: boolean,\n label: string,\n configPath: string,\n issues: Issue[],\n): boolean {\n if (typeof value === \"boolean\") {\n return value;\n }\n if (value !== undefined) {\n issues.push(\n configIssue(configPath, `${label} は真偽値である必要があります。`),\n );\n }\n return fallback;\n}\n\nfunction readFailOn(\n value: unknown,\n fallback: FailOn,\n label: string,\n configPath: string,\n issues: Issue[],\n): FailOn {\n if (value === \"never\" || value === \"warning\" || value === \"error\") {\n return value;\n }\n if (value !== undefined) {\n issues.push(\n configIssue(\n configPath,\n `${label} は never|warning|error のいずれかである必要があります。`,\n ),\n );\n }\n return fallback;\n}\n\nfunction readTraceabilitySeverity(\n value: unknown,\n fallback: TraceabilitySeverity,\n label: string,\n configPath: string,\n issues: Issue[],\n): TraceabilitySeverity {\n if (value === \"warning\" || value === \"error\") {\n return value;\n }\n if (value !== undefined) {\n issues.push(\n configIssue(\n configPath,\n `${label} は warning|error のいずれかである必要があります。`,\n ),\n );\n }\n return fallback;\n}\n\nfunction readOrphanContractsPolicy(\n value: unknown,\n fallback: OrphanContractsPolicy,\n label: string,\n configPath: string,\n issues: Issue[],\n): OrphanContractsPolicy {\n if (value === \"error\" || value === \"warning\" || value === \"allow\") {\n return value;\n }\n if (value !== undefined) {\n issues.push(\n configIssue(\n configPath,\n `${label} は error|warning|allow のいずれかである必要があります。`,\n ),\n );\n }\n return fallback;\n}\n\nfunction configIssue(file: string, message: string): Issue {\n return {\n code: \"QFAI_CONFIG_INVALID\",\n severity: \"error\",\n message,\n file,\n rule: \"config.invalid\",\n };\n}\n\nfunction isMissingFile(error: unknown): boolean {\n if (error && typeof error === \"object\" && \"code\" in error) {\n return (error as { code?: string }).code === \"ENOENT\";\n }\n return false;\n}\n\nasync function exists(target: string): Promise<boolean> {\n try {\n await access(target);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction formatError(error: unknown): string {\n if (error instanceof Error) {\n return error.message;\n }\n return String(error);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n","export type IdPrefix = \"SPEC\" | \"BR\" | \"SC\" | \"UI\" | \"API\" | \"DB\";\nexport type IdFormatPrefix = IdPrefix | \"ADR\";\n\nconst ID_PREFIXES: IdPrefix[] = [\"SPEC\", \"BR\", \"SC\", \"UI\", \"API\", \"DB\"];\n\nconst STRICT_ID_PATTERNS: Record<IdFormatPrefix, RegExp> = {\n SPEC: /\\bSPEC-\\d{4}\\b/g,\n BR: /\\bBR-\\d{4}\\b/g,\n SC: /\\bSC-\\d{4}\\b/g,\n UI: /\\bUI-\\d{4}\\b/g,\n API: /\\bAPI-\\d{4}\\b/g,\n DB: /\\bDB-\\d{4}\\b/g,\n ADR: /\\bADR-\\d{4}\\b/g,\n};\n\nconst LOOSE_ID_PATTERNS: Record<IdFormatPrefix, RegExp> = {\n SPEC: /\\bSPEC-[A-Za-z0-9_-]+\\b/gi,\n BR: /\\bBR-[A-Za-z0-9_-]+\\b/gi,\n SC: /\\bSC-[A-Za-z0-9_-]+\\b/gi,\n UI: /\\bUI-[A-Za-z0-9_-]+\\b/gi,\n API: /\\bAPI-[A-Za-z0-9_-]+\\b/gi,\n DB: /\\bDB-[A-Za-z0-9_-]+\\b/gi,\n ADR: /\\bADR-[A-Za-z0-9_-]+\\b/gi,\n};\n\nexport function extractIds(text: string, prefix: IdPrefix): string[] {\n const pattern = STRICT_ID_PATTERNS[prefix];\n const matches = text.match(pattern);\n return unique(matches ?? []);\n}\n\nexport function extractAllIds(text: string): string[] {\n const all: string[] = [];\n ID_PREFIXES.forEach((prefix) => {\n all.push(...extractIds(text, prefix));\n });\n return unique(all);\n}\n\nexport function extractInvalidIds(\n text: string,\n prefixes: IdFormatPrefix[],\n): string[] {\n const invalid: string[] = [];\n for (const prefix of prefixes) {\n const candidates = text.match(LOOSE_ID_PATTERNS[prefix]) ?? [];\n for (const candidate of candidates) {\n if (!isValidId(candidate, prefix)) {\n invalid.push(candidate);\n }\n }\n }\n return unique(invalid);\n}\n\nfunction unique(values: string[]): string[] {\n return Array.from(new Set(values));\n}\n\nfunction isValidId(value: string, prefix: IdFormatPrefix): boolean {\n const pattern = STRICT_ID_PATTERNS[prefix];\n const strict = new RegExp(pattern.source);\n return strict.test(value);\n}\n","import { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { buildContractIndex } from \"./contractIndex.js\";\nimport { loadConfig, resolvePath, type ConfigLoadResult } from \"./config.js\";\nimport {\n collectContractFiles,\n collectScenarioFiles,\n collectSpecFiles,\n} from \"./discovery.js\";\nimport { collectFiles } from \"./fs.js\";\nimport { extractAllIds, extractIds, type IdPrefix } from \"./ids.js\";\nimport { normalizeValidationResult } from \"./normalize.js\";\nimport { parseSpec } from \"./parse/spec.js\";\nimport { toRelativePath } from \"./paths.js\";\nimport {\n collectScIdSourcesFromScenarioFiles,\n type ScCoverage,\n type TestFileScan,\n} from \"./traceability.js\";\nimport type { Issue, ValidationCounts, ValidationResult } from \"./types.js\";\nimport { validateProject } from \"./validate.js\";\nimport { resolveToolVersion } from \"./version.js\";\n\nexport type ReportSummary = {\n specs: number;\n scenarios: number;\n contracts: {\n api: number;\n ui: number;\n db: number;\n };\n counts: ValidationCounts;\n};\n\nexport type ReportIds = {\n spec: string[];\n br: string[];\n sc: string[];\n ui: string[];\n api: string[];\n db: string[];\n};\n\nexport type ReportContractCoverage = {\n total: number;\n referenced: number;\n orphan: number;\n idToSpecs: Record<string, string[]>;\n};\n\nexport type ReportSpecCoverage = {\n contractRefMissing: number;\n missingRefSpecs: string[];\n specToContracts: Record<string, ReportSpecContractRefs>;\n};\n\nexport type ReportSpecContractRefs = {\n status: \"missing\" | \"declared\";\n ids: string[];\n};\n\nexport type ReportTraceability = {\n upstreamIdsFound: number;\n referencedInCodeOrTests: boolean;\n sc: ScCoverage;\n scSources: Record<string, string[]>;\n testFiles: TestFileScan;\n contracts: ReportContractCoverage;\n specs: ReportSpecCoverage;\n};\n\nexport type ReportData = {\n tool: \"qfai\";\n version: string;\n reportFormatVersion: number;\n generatedAt: string;\n root: string;\n configPath: string;\n summary: ReportSummary;\n ids: ReportIds;\n traceability: ReportTraceability;\n issues: Issue[];\n};\n\nconst ID_PREFIXES: IdPrefix[] = [\"SPEC\", \"BR\", \"SC\", \"UI\", \"API\", \"DB\"];\n\nexport async function createReportData(\n root: string,\n validation?: ValidationResult,\n configResult?: ConfigLoadResult,\n): Promise<ReportData> {\n const resolvedRoot = path.resolve(root);\n const resolved = configResult ?? (await loadConfig(resolvedRoot));\n const config = resolved.config;\n const configPath = resolved.configPath;\n\n const specsRoot = resolvePath(resolvedRoot, config, \"specsDir\");\n const contractsRoot = resolvePath(resolvedRoot, config, \"contractsDir\");\n const apiRoot = path.join(contractsRoot, \"api\");\n const uiRoot = path.join(contractsRoot, \"ui\");\n const dbRoot = path.join(contractsRoot, \"db\");\n const srcRoot = resolvePath(resolvedRoot, config, \"srcDir\");\n const testsRoot = resolvePath(resolvedRoot, config, \"testsDir\");\n\n const specFiles = await collectSpecFiles(specsRoot);\n const scenarioFiles = await collectScenarioFiles(specsRoot);\n const {\n api: apiFiles,\n ui: uiFiles,\n db: dbFiles,\n } = await collectContractFiles(uiRoot, apiRoot, dbRoot);\n const contractIndex = await buildContractIndex(resolvedRoot, config);\n const contractIdList = Array.from(contractIndex.ids);\n const specContractRefs = await collectSpecContractRefs(\n specFiles,\n contractIdList,\n );\n const referencedContracts = new Set<string>();\n for (const entry of specContractRefs.specToContracts.values()) {\n entry.ids.forEach((id) => referencedContracts.add(id));\n }\n const referencedContractCount = contractIdList.filter((id) =>\n referencedContracts.has(id),\n ).length;\n const orphanContractCount = contractIdList.filter(\n (id) => !referencedContracts.has(id),\n ).length;\n const contractIdToSpecsRecord = mapToSortedRecord(specContractRefs.idToSpecs);\n const specToContractsRecord = mapToSpecContractRecord(\n specContractRefs.specToContracts,\n );\n\n const idsByPrefix = await collectIds([\n ...specFiles,\n ...scenarioFiles,\n ...apiFiles,\n ...uiFiles,\n ...dbFiles,\n ]);\n\n const upstreamIds = await collectUpstreamIds([\n ...specFiles,\n ...scenarioFiles,\n ]);\n const traceability = await evaluateTraceability(\n upstreamIds,\n srcRoot,\n testsRoot,\n );\n const resolvedValidationRaw =\n validation ?? (await validateProject(resolvedRoot, resolved));\n const normalizedValidation = normalizeValidationResult(\n resolvedRoot,\n resolvedValidationRaw,\n );\n const scCoverage = normalizedValidation.traceability.sc;\n const testFiles = normalizedValidation.traceability.testFiles;\n const scSources = await collectScIdSourcesFromScenarioFiles(scenarioFiles);\n const scSourceRecord = mapToSortedRecord(\n normalizeScSources(resolvedRoot, scSources),\n );\n\n const version = await resolveToolVersion();\n const reportFormatVersion = 1;\n const displayRoot = toRelativePath(resolvedRoot, resolvedRoot);\n const displayConfigPath = toRelativePath(resolvedRoot, configPath);\n\n return {\n tool: \"qfai\",\n version,\n reportFormatVersion,\n generatedAt: new Date().toISOString(),\n root: displayRoot,\n configPath: displayConfigPath,\n summary: {\n specs: specFiles.length,\n scenarios: scenarioFiles.length,\n contracts: {\n api: apiFiles.length,\n ui: uiFiles.length,\n db: dbFiles.length,\n },\n counts: normalizedValidation.counts,\n },\n ids: {\n spec: idsByPrefix.SPEC,\n br: idsByPrefix.BR,\n sc: idsByPrefix.SC,\n ui: idsByPrefix.UI,\n api: idsByPrefix.API,\n db: idsByPrefix.DB,\n },\n traceability: {\n upstreamIdsFound: upstreamIds.size,\n referencedInCodeOrTests: traceability,\n sc: scCoverage,\n scSources: scSourceRecord,\n testFiles,\n contracts: {\n total: contractIdList.length,\n referenced: referencedContractCount,\n orphan: orphanContractCount,\n idToSpecs: contractIdToSpecsRecord,\n },\n specs: {\n contractRefMissing: specContractRefs.missingRefSpecs.size,\n missingRefSpecs: toSortedArray(specContractRefs.missingRefSpecs),\n specToContracts: specToContractsRecord,\n },\n },\n issues: normalizedValidation.issues,\n };\n}\n\nexport function formatReportMarkdown(data: ReportData): string {\n const lines: string[] = [];\n\n lines.push(\"# QFAI Report\");\n lines.push(\"\");\n lines.push(`- 生成日時: ${data.generatedAt}`);\n lines.push(`- ルート: ${data.root}`);\n lines.push(`- 設定: ${data.configPath}`);\n lines.push(`- 版: ${data.version}`);\n lines.push(\"\");\n\n lines.push(\"## 概要\");\n lines.push(\"\");\n lines.push(`- specs: ${data.summary.specs}`);\n lines.push(`- scenarios: ${data.summary.scenarios}`);\n lines.push(\n `- contracts: api ${data.summary.contracts.api} / ui ${data.summary.contracts.ui} / db ${data.summary.contracts.db}`,\n );\n lines.push(\n `- issues: info ${data.summary.counts.info} / warning ${data.summary.counts.warning} / error ${data.summary.counts.error}`,\n );\n lines.push(\"\");\n\n lines.push(\"## ID集計\");\n lines.push(\"\");\n lines.push(formatIdLine(\"SPEC\", data.ids.spec));\n lines.push(formatIdLine(\"BR\", data.ids.br));\n lines.push(formatIdLine(\"SC\", data.ids.sc));\n lines.push(formatIdLine(\"UI\", data.ids.ui));\n lines.push(formatIdLine(\"API\", data.ids.api));\n lines.push(formatIdLine(\"DB\", data.ids.db));\n lines.push(\"\");\n\n lines.push(\"## トレーサビリティ\");\n lines.push(\"\");\n lines.push(`- 上流ID検出数: ${data.traceability.upstreamIdsFound}`);\n lines.push(\n `- コード/テスト参照: ${data.traceability.referencedInCodeOrTests ? \"あり\" : \"なし\"}`,\n );\n lines.push(\"\");\n\n lines.push(\"## 契約カバレッジ\");\n lines.push(\"\");\n lines.push(`- total: ${data.traceability.contracts.total}`);\n lines.push(`- referenced: ${data.traceability.contracts.referenced}`);\n lines.push(`- orphan: ${data.traceability.contracts.orphan}`);\n lines.push(\n `- specContractRefMissing: ${data.traceability.specs.contractRefMissing}`,\n );\n lines.push(\"\");\n\n lines.push(\"## 契約→Spec\");\n lines.push(\"\");\n const contractToSpecs = data.traceability.contracts.idToSpecs;\n const contractIds = Object.keys(contractToSpecs).sort((a, b) =>\n a.localeCompare(b),\n );\n if (contractIds.length === 0) {\n lines.push(\"- (none)\");\n } else {\n for (const contractId of contractIds) {\n const specs = contractToSpecs[contractId] ?? [];\n if (specs.length === 0) {\n lines.push(`- ${contractId}: (none)`);\n } else {\n lines.push(`- ${contractId}: ${specs.join(\", \")}`);\n }\n }\n }\n lines.push(\"\");\n\n lines.push(\"## Spec→契約\");\n lines.push(\"\");\n const specToContracts = data.traceability.specs.specToContracts;\n const specIds = Object.keys(specToContracts).sort((a, b) =>\n a.localeCompare(b),\n );\n if (specIds.length === 0) {\n lines.push(\"- (none)\");\n } else {\n const rows = specIds.map((specId) => {\n const entry = specToContracts[specId];\n const contracts =\n entry?.status === \"missing\"\n ? \"(missing)\"\n : entry && entry.ids.length > 0\n ? entry.ids.join(\", \")\n : \"(none)\";\n const status = entry?.status ?? \"missing\";\n return [specId, status, contracts];\n });\n lines.push(...formatMarkdownTable([\"Spec\", \"Status\", \"Contracts\"], rows));\n }\n lines.push(\"\");\n\n lines.push(\"## Specで contract-ref 未宣言\");\n lines.push(\"\");\n const missingRefSpecs = data.traceability.specs.missingRefSpecs;\n if (missingRefSpecs.length === 0) {\n lines.push(\"- (none)\");\n } else {\n for (const specId of missingRefSpecs) {\n lines.push(`- ${specId}`);\n }\n }\n lines.push(\"\");\n\n lines.push(\"## SCカバレッジ\");\n lines.push(\"\");\n lines.push(`- total: ${data.traceability.sc.total}`);\n lines.push(`- covered: ${data.traceability.sc.covered}`);\n lines.push(`- missing: ${data.traceability.sc.missing}`);\n lines.push(\n `- testFileGlobs: ${formatList(data.traceability.testFiles.globs)}`,\n );\n lines.push(\n `- testFileExcludeGlobs: ${formatList(\n data.traceability.testFiles.excludeGlobs,\n )}`,\n );\n lines.push(\n `- testFileCount: ${data.traceability.testFiles.matchedFileCount}`,\n );\n if (data.traceability.sc.missingIds.length === 0) {\n lines.push(\"- missingIds: (none)\");\n } else {\n const sources = data.traceability.scSources;\n const missingWithSources = data.traceability.sc.missingIds.map((id) => {\n const files = sources[id] ?? [];\n if (files.length === 0) {\n return id;\n }\n return `${id} (${files.join(\", \")})`;\n });\n lines.push(`- missingIds: ${missingWithSources.join(\", \")}`);\n }\n lines.push(\"\");\n\n lines.push(\"## SC→参照テスト\");\n lines.push(\"\");\n const scRefs = data.traceability.sc.refs;\n const scIds = Object.keys(scRefs).sort((a, b) => a.localeCompare(b));\n if (scIds.length === 0) {\n lines.push(\"- (none)\");\n } else {\n for (const scId of scIds) {\n const refs = scRefs[scId] ?? [];\n if (refs.length === 0) {\n lines.push(`- ${scId}: (none)`);\n } else {\n lines.push(`- ${scId}: ${refs.join(\", \")}`);\n }\n }\n }\n lines.push(\"\");\n\n lines.push(\"## Spec:SC=1:1 違反\");\n lines.push(\"\");\n const specScIssues = data.issues.filter(\n (item) => item.code === \"QFAI-TRACE-012\",\n );\n if (specScIssues.length === 0) {\n lines.push(\"- (none)\");\n } else {\n for (const item of specScIssues) {\n const location = item.file ?? \"(unknown)\";\n const refs =\n item.refs && item.refs.length > 0 ? item.refs.join(\", \") : item.message;\n lines.push(`- ${location}: ${refs}`);\n }\n }\n lines.push(\"\");\n\n lines.push(\"## Hotspots\");\n lines.push(\"\");\n const hotspots = buildHotspots(data.issues);\n if (hotspots.length === 0) {\n lines.push(\"- (none)\");\n } else {\n for (const spot of hotspots) {\n lines.push(\n `- ${spot.file}: total ${spot.total} (error ${spot.error} / warning ${spot.warning} / info ${spot.info})`,\n );\n }\n }\n lines.push(\"\");\n\n lines.push(\"## トレーサビリティ(検証)\");\n lines.push(\"\");\n const traceIssues = data.issues.filter(\n (item) =>\n item.rule?.startsWith(\"traceability.\") ||\n item.code.startsWith(\"QFAI_TRACE\") ||\n item.code.startsWith(\"QFAI-TRACE-\"),\n );\n if (traceIssues.length === 0) {\n lines.push(\"- (none)\");\n } else {\n for (const item of traceIssues) {\n const location = item.file ? ` (${item.file})` : \"\";\n lines.push(\n `- ${item.severity.toUpperCase()} [${item.code}] ${item.message}${location}`,\n );\n }\n }\n lines.push(\"\");\n\n lines.push(\"## 検証結果\");\n lines.push(\"\");\n if (data.issues.length === 0) {\n lines.push(\"- (none)\");\n } else {\n for (const item of data.issues) {\n const location = item.file ? ` (${item.file})` : \"\";\n const refs =\n item.refs && item.refs.length > 0 ? ` refs=${item.refs.join(\",\")}` : \"\";\n lines.push(\n `- ${item.severity.toUpperCase()} [${item.code}] ${item.message}${location}${refs}`,\n );\n }\n }\n\n return lines.join(\"\\n\");\n}\n\nexport function formatReportJson(data: ReportData): string {\n return JSON.stringify(data, null, 2);\n}\n\ntype SpecContractRefsResult = {\n specToContracts: Map<string, SpecContractRefEntry>;\n idToSpecs: Map<string, Set<string>>;\n missingRefSpecs: Set<string>;\n};\n\ntype SpecContractRefEntry = {\n status: \"missing\" | \"declared\";\n ids: Set<string>;\n};\n\nasync function collectSpecContractRefs(\n specFiles: string[],\n contractIdList: string[],\n): Promise<SpecContractRefsResult> {\n const specToContracts = new Map<string, SpecContractRefEntry>();\n const idToSpecs = new Map<string, Set<string>>();\n const missingRefSpecs = new Set<string>();\n\n for (const contractId of contractIdList) {\n idToSpecs.set(contractId, new Set<string>());\n }\n\n for (const file of specFiles) {\n const text = await readFile(file, \"utf-8\");\n const parsed = parseSpec(text, file);\n const specKey = parsed.specId;\n if (!specKey) {\n continue;\n }\n const refs = parsed.contractRefs;\n\n if (refs.lines.length === 0) {\n missingRefSpecs.add(specKey);\n specToContracts.set(specKey, { status: \"missing\", ids: new Set() });\n continue;\n }\n\n const current =\n specToContracts.get(specKey) ??\n ({\n status: \"declared\",\n ids: new Set<string>(),\n } satisfies SpecContractRefEntry);\n for (const id of refs.ids) {\n current.ids.add(id);\n const specs = idToSpecs.get(id);\n if (specs) {\n specs.add(specKey);\n }\n }\n specToContracts.set(specKey, current);\n }\n\n return {\n specToContracts,\n idToSpecs,\n missingRefSpecs,\n };\n}\n\nasync function collectIds(\n files: string[],\n): Promise<Record<IdPrefix, string[]>> {\n const result: Record<IdPrefix, Set<string>> = {\n SPEC: new Set(),\n BR: new Set(),\n SC: new Set(),\n UI: new Set(),\n API: new Set(),\n DB: new Set(),\n };\n\n for (const file of files) {\n const text = await readFile(file, \"utf-8\");\n for (const prefix of ID_PREFIXES) {\n const ids = extractIds(text, prefix);\n ids.forEach((id) => result[prefix].add(id));\n }\n }\n\n return {\n SPEC: toSortedArray(result.SPEC),\n BR: toSortedArray(result.BR),\n SC: toSortedArray(result.SC),\n UI: toSortedArray(result.UI),\n API: toSortedArray(result.API),\n DB: toSortedArray(result.DB),\n };\n}\n\nasync function collectUpstreamIds(files: string[]): Promise<Set<string>> {\n const ids = new Set<string>();\n for (const file of files) {\n const text = await readFile(file, \"utf-8\");\n extractAllIds(text).forEach((id) => ids.add(id));\n }\n return ids;\n}\n\nasync function evaluateTraceability(\n upstreamIds: Set<string>,\n srcRoot: string,\n testsRoot: string,\n): Promise<boolean> {\n if (upstreamIds.size === 0) {\n return false;\n }\n\n const codeFiles = await collectFiles(srcRoot, {\n extensions: [\".ts\", \".tsx\", \".js\", \".jsx\"],\n });\n const testFiles = await collectFiles(testsRoot, {\n extensions: [\".ts\", \".tsx\", \".js\", \".jsx\"],\n });\n const targetFiles = [...codeFiles, ...testFiles];\n\n if (targetFiles.length === 0) {\n return false;\n }\n\n const pattern = buildIdPattern(Array.from(upstreamIds));\n\n for (const file of targetFiles) {\n const text = await readFile(file, \"utf-8\");\n if (pattern.test(text)) {\n return true;\n }\n }\n\n return false;\n}\n\nfunction buildIdPattern(ids: string[]): RegExp {\n const escaped = ids.map((id) => id.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\"));\n return new RegExp(`\\\\b(${escaped.join(\"|\")})\\\\b`);\n}\n\nfunction formatIdLine(label: string, values: string[]): string {\n if (values.length === 0) {\n return `- ${label}: (none)`;\n }\n return `- ${label}: ${values.join(\", \")}`;\n}\n\nfunction formatList(values: string[]): string {\n if (values.length === 0) {\n return \"(none)\";\n }\n return values.join(\", \");\n}\n\nfunction formatMarkdownTable(headers: string[], rows: string[][]): string[] {\n const widths = headers.map((header, index) => {\n const candidates = rows.map((row) => row[index] ?? \"\");\n return Math.max(header.length, ...candidates.map((item) => item.length));\n });\n\n const formatRow = (cells: string[]): string => {\n const padded = cells.map((cell, index) =>\n (cell ?? \"\").padEnd(widths[index] ?? 0),\n );\n return `| ${padded.join(\" | \")} |`;\n };\n\n const separator = `| ${widths.map((width) => \"-\".repeat(width)).join(\" | \")} |`;\n\n return [formatRow(headers), separator, ...rows.map(formatRow)];\n}\n\nfunction toSortedArray(values: Set<string>): string[] {\n return Array.from(values).sort((a, b) => a.localeCompare(b));\n}\n\nfunction mapToSortedRecord(\n values: Map<string, Set<string>>,\n): Record<string, string[]> {\n const record: Record<string, string[]> = {};\n for (const [key, files] of values.entries()) {\n record[key] = Array.from(files).sort((a, b) => a.localeCompare(b));\n }\n return record;\n}\n\nfunction mapToSpecContractRecord(\n values: Map<string, SpecContractRefEntry>,\n): Record<string, ReportSpecContractRefs> {\n const record: Record<string, ReportSpecContractRefs> = {};\n for (const [key, entry] of values.entries()) {\n record[key] = {\n status: entry.status,\n ids: toSortedArray(entry.ids),\n };\n }\n return record;\n}\n\nfunction normalizeScSources(\n root: string,\n sources: Map<string, Set<string>>,\n): Map<string, Set<string>> {\n const normalized = new Map<string, Set<string>>();\n for (const [id, files] of sources.entries()) {\n const mapped = new Set<string>();\n for (const file of files) {\n mapped.add(toRelativePath(root, file));\n }\n normalized.set(id, mapped);\n }\n return normalized;\n}\n\ntype Hotspot = {\n file: string;\n total: number;\n error: number;\n warning: number;\n info: number;\n};\n\nfunction buildHotspots(issues: Issue[]): Hotspot[] {\n const map = new Map<string, Hotspot>();\n for (const issue of issues) {\n if (!issue.file) {\n continue;\n }\n const current =\n map.get(issue.file) ??\n ({\n file: issue.file,\n total: 0,\n error: 0,\n warning: 0,\n info: 0,\n } satisfies Hotspot);\n current.total += 1;\n current[issue.severity] += 1;\n map.set(issue.file, current);\n }\n\n return Array.from(map.values()).sort((a, b) =>\n b.total !== a.total ? b.total - a.total : a.file.localeCompare(b.file),\n );\n}\n","import { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport type { QfaiConfig } from \"./config.js\";\nimport { resolvePath } from \"./config.js\";\nimport {\n collectApiContractFiles,\n collectDbContractFiles,\n collectUiContractFiles,\n} from \"./discovery.js\";\nimport { extractDeclaredContractIds } from \"./contractsDecl.js\";\n\nexport type ContractIndex = {\n ids: Set<string>;\n idToFiles: Map<string, Set<string>>;\n files: { ui: string[]; api: string[]; db: string[] };\n};\n\nexport async function buildContractIndex(\n root: string,\n config: QfaiConfig,\n): Promise<ContractIndex> {\n const contractsRoot = resolvePath(root, config, \"contractsDir\");\n const uiRoot = path.join(contractsRoot, \"ui\");\n const apiRoot = path.join(contractsRoot, \"api\");\n const dbRoot = path.join(contractsRoot, \"db\");\n\n const [uiFiles, apiFiles, dbFiles] = await Promise.all([\n collectUiContractFiles(uiRoot),\n collectApiContractFiles(apiRoot),\n collectDbContractFiles(dbRoot),\n ]);\n\n const index: ContractIndex = {\n ids: new Set<string>(),\n idToFiles: new Map<string, Set<string>>(),\n files: { ui: uiFiles, api: apiFiles, db: dbFiles },\n };\n\n await indexContractFiles(uiFiles, index);\n await indexContractFiles(apiFiles, index);\n await indexContractFiles(dbFiles, index);\n\n return index;\n}\n\nasync function indexContractFiles(\n files: string[],\n index: ContractIndex,\n): Promise<void> {\n for (const file of files) {\n const text = await readFile(file, \"utf-8\");\n extractDeclaredContractIds(text).forEach((id) => record(index, id, file));\n }\n}\n\nfunction record(index: ContractIndex, id: string, file: string): void {\n index.ids.add(id);\n const current = index.idToFiles.get(id) ?? new Set<string>();\n current.add(file);\n index.idToFiles.set(id, current);\n}\n","import { access } from \"node:fs/promises\";\n\nimport { collectFiles } from \"./fs.js\";\nimport { collectSpecEntries } from \"./specLayout.js\";\n\nexport type ContractFiles = {\n api: string[];\n ui: string[];\n db: string[];\n};\n\nexport async function collectSpecPackDirs(\n specsRoot: string,\n): Promise<string[]> {\n const entries = await collectSpecEntries(specsRoot);\n return entries.map((entry) => entry.dir);\n}\n\nexport async function collectSpecFiles(specsRoot: string): Promise<string[]> {\n const entries = await collectSpecEntries(specsRoot);\n return filterExisting(entries.map((entry) => entry.specPath));\n}\n\nexport async function collectDeltaFiles(specsRoot: string): Promise<string[]> {\n const entries = await collectSpecEntries(specsRoot);\n return filterExisting(entries.map((entry) => entry.deltaPath));\n}\n\nexport async function collectScenarioFiles(\n specsRoot: string,\n): Promise<string[]> {\n const entries = await collectSpecEntries(specsRoot);\n return filterExisting(entries.map((entry) => entry.scenarioPath));\n}\n\nexport async function collectUiContractFiles(\n uiRoot: string,\n): Promise<string[]> {\n return collectFiles(uiRoot, { extensions: [\".yaml\", \".yml\"] });\n}\n\nexport async function collectApiContractFiles(\n apiRoot: string,\n): Promise<string[]> {\n return collectFiles(apiRoot, { extensions: [\".yaml\", \".yml\", \".json\"] });\n}\n\nexport async function collectDbContractFiles(\n dbRoot: string,\n): Promise<string[]> {\n return collectFiles(dbRoot, { extensions: [\".sql\"] });\n}\n\nexport async function collectContractFiles(\n uiRoot: string,\n apiRoot: string,\n dbRoot: string,\n): Promise<ContractFiles> {\n const [ui, api, db] = await Promise.all([\n collectUiContractFiles(uiRoot),\n collectApiContractFiles(apiRoot),\n collectDbContractFiles(dbRoot),\n ]);\n return { ui, api, db };\n}\n\nasync function filterExisting(files: string[]): Promise<string[]> {\n const existing: string[] = [];\n for (const file of files) {\n if (await exists(file)) {\n existing.push(file);\n }\n }\n return existing;\n}\n\nasync function exists(target: string): Promise<boolean> {\n try {\n await access(target);\n return true;\n } catch {\n return false;\n }\n}\n","import { access, readdir } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport fg from \"fast-glob\";\n\nconst DEFAULT_IGNORE_DIRS = new Set([\n \"node_modules\",\n \".git\",\n \"dist\",\n \".pnpm\",\n \"tmp\",\n \".mcp-tools\",\n]);\n\nexport type CollectFilesOptions = {\n extensions?: string[];\n ignoreDirs?: string[];\n};\n\nexport type CollectFilesByGlobOptions = {\n globs: string[];\n ignore?: string[];\n};\n\nexport async function collectFiles(\n root: string,\n options: CollectFilesOptions = {},\n): Promise<string[]> {\n const entries: string[] = [];\n if (!(await exists(root))) {\n return entries;\n }\n\n const ignoreDirs = new Set([\n ...DEFAULT_IGNORE_DIRS,\n ...(options.ignoreDirs ?? []),\n ]);\n const extensions = options.extensions?.map((ext) => ext.toLowerCase()) ?? [];\n\n await walk(root, root, ignoreDirs, extensions, entries);\n return entries;\n}\n\nexport async function collectFilesByGlobs(\n root: string,\n options: CollectFilesByGlobOptions,\n): Promise<string[]> {\n if (options.globs.length === 0) {\n return [];\n }\n return fg(options.globs, {\n cwd: root,\n ignore: options.ignore ?? [],\n onlyFiles: true,\n absolute: true,\n unique: true,\n });\n}\n\nasync function walk(\n base: string,\n current: string,\n ignoreDirs: Set<string>,\n extensions: string[],\n out: string[],\n): Promise<void> {\n const items = await readdir(current, { withFileTypes: true });\n\n for (const item of items) {\n const fullPath = path.join(current, item.name);\n\n if (item.isDirectory()) {\n if (ignoreDirs.has(item.name)) {\n continue;\n }\n await walk(base, fullPath, ignoreDirs, extensions, out);\n continue;\n }\n\n if (item.isFile()) {\n if (extensions.length > 0) {\n const ext = path.extname(item.name).toLowerCase();\n if (!extensions.includes(ext)) {\n continue;\n }\n }\n out.push(fullPath);\n }\n }\n}\n\nasync function exists(target: string): Promise<boolean> {\n try {\n await access(target);\n return true;\n } catch {\n return false;\n }\n}\n","import { readdir } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nconst SPEC_DIR_RE = /^spec-\\d{4}$/;\n\nexport type SpecEntry = {\n dir: string;\n specPath: string;\n deltaPath: string;\n scenarioPath: string;\n};\n\nexport async function collectSpecEntries(\n specsRoot: string,\n): Promise<SpecEntry[]> {\n const dirs = await listSpecDirs(specsRoot);\n const entries = dirs.map((dir) => ({\n dir,\n specPath: path.join(dir, \"spec.md\"),\n deltaPath: path.join(dir, \"delta.md\"),\n scenarioPath: path.join(dir, \"scenario.md\"),\n }));\n return entries.sort((a, b) => a.dir.localeCompare(b.dir));\n}\n\nasync function listSpecDirs(specsRoot: string): Promise<string[]> {\n try {\n const items = await readdir(specsRoot, { withFileTypes: true });\n return items\n .filter((item) => item.isDirectory())\n .map((item) => item.name)\n .filter((name) => SPEC_DIR_RE.test(name.toLowerCase()))\n .map((name) => path.join(specsRoot, name));\n } catch (error) {\n if (isMissingFileError(error)) {\n return [];\n }\n throw error;\n }\n}\n\nfunction isMissingFileError(error: unknown): boolean {\n if (!error || typeof error !== \"object\") {\n return false;\n }\n return (error as { code?: string }).code === \"ENOENT\";\n}\n","const CONTRACT_DECLARATION_RE =\n /^\\s*(?:#|\\/\\/|--|\\/\\*+|\\*+)?\\s*QFAI-CONTRACT-ID:\\s*((?:API|UI|DB)-\\d{4})\\s*(?:\\*\\/)?\\s*$/gm;\nconst CONTRACT_DECLARATION_LINE_RE =\n /^\\s*(?:#|\\/\\/|--|\\/\\*+|\\*+)?\\s*QFAI-CONTRACT-ID:\\s*(?:API|UI|DB)-\\d{4}\\s*(?:\\*\\/)?\\s*$/;\n\nexport function extractDeclaredContractIds(text: string): string[] {\n const ids: string[] = [];\n for (const match of text.matchAll(CONTRACT_DECLARATION_RE)) {\n const id = match[1];\n if (id) {\n ids.push(id);\n }\n }\n return ids;\n}\n\nexport function stripContractDeclarationLines(text: string): string {\n return text\n .split(/\\r?\\n/)\n .filter((line) => !CONTRACT_DECLARATION_LINE_RE.test(line))\n .join(\"\\n\");\n}\n","import path from \"node:path\";\n\nexport function toRelativePath(root: string, target: string): string {\n if (!target) {\n return target;\n }\n if (!path.isAbsolute(target)) {\n return toPosixPath(target);\n }\n const relative = path.relative(root, target);\n if (!relative) {\n return \".\";\n }\n return toPosixPath(relative);\n}\n\nfunction toPosixPath(value: string): string {\n return value.replace(/\\\\/g, \"/\");\n}\n","import type { ScCoverage } from \"./traceability.js\";\nimport type { Issue, ValidationResult } from \"./types.js\";\nimport { toRelativePath } from \"./paths.js\";\n\nexport function normalizeIssuePaths(root: string, issues: Issue[]): Issue[] {\n return issues.map((issue) => {\n if (!issue.file) {\n return issue;\n }\n const normalized = toRelativePath(root, issue.file);\n if (normalized === issue.file) {\n return issue;\n }\n return {\n ...issue,\n file: normalized,\n };\n });\n}\n\nexport function normalizeScCoverage(root: string, sc: ScCoverage): ScCoverage {\n const refs: Record<string, string[]> = {};\n for (const [scId, files] of Object.entries(sc.refs)) {\n refs[scId] = files.map((file) => toRelativePath(root, file));\n }\n return {\n ...sc,\n refs,\n };\n}\n\nexport function normalizeValidationResult(\n root: string,\n result: ValidationResult,\n): ValidationResult {\n return {\n ...result,\n issues: normalizeIssuePaths(root, result.issues),\n traceability: {\n ...result.traceability,\n sc: normalizeScCoverage(root, result.traceability.sc),\n },\n };\n}\n","export type ParsedContractRefs = {\n lines: string[];\n ids: string[];\n invalidTokens: string[];\n hasNone: boolean;\n};\n\nexport type ContractRefParseOptions = {\n allowCommentPrefix?: boolean;\n};\n\nconst CONTRACT_REF_ID_RE = /^(?:API|UI|DB)-\\d{4}$/;\n\nexport function parseContractRefs(\n text: string,\n options: ContractRefParseOptions = {},\n): ParsedContractRefs {\n const linePattern = buildLinePattern(options);\n const lines: string[] = [];\n for (const match of text.matchAll(linePattern)) {\n lines.push((match[1] ?? \"\").trim());\n }\n\n const ids: string[] = [];\n const invalidTokens: string[] = [];\n let hasNone = false;\n\n for (const line of lines) {\n if (line.length === 0) {\n invalidTokens.push(\"(empty)\");\n continue;\n }\n const tokens = line.split(\",\").map((token) => token.trim());\n for (const token of tokens) {\n if (token.length === 0) {\n invalidTokens.push(\"(empty)\");\n continue;\n }\n if (token === \"none\") {\n hasNone = true;\n continue;\n }\n if (CONTRACT_REF_ID_RE.test(token)) {\n ids.push(token);\n continue;\n }\n invalidTokens.push(token);\n }\n }\n\n return {\n lines,\n ids: unique(ids),\n invalidTokens: unique(invalidTokens),\n hasNone,\n };\n}\n\nfunction buildLinePattern(options: ContractRefParseOptions): RegExp {\n // Scenario uses a comment line, so require \"#\" when the comment prefix is enabled.\n const prefix = options.allowCommentPrefix ? \"#\" : \"\";\n return new RegExp(\n `^[ \\\\t]*${prefix}[ \\\\t]*QFAI-CONTRACT-REF:[ \\\\t]*([^\\\\r\\\\n]*)[ \\\\t]*$`,\n \"gm\",\n );\n}\n\nfunction unique(values: string[]): string[] {\n return Array.from(new Set(values));\n}\n","export type Heading = { level: number; title: string; line: number };\n\nexport type H2Section = {\n title: string;\n startLine: number;\n endLine: number;\n body: string;\n};\n\nconst HEADING_RE = /^(#{1,6})\\s+(.+?)\\s*$/;\n\nexport function parseHeadings(md: string): Heading[] {\n const lines = md.split(/\\r?\\n/);\n const headings: Heading[] = [];\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i] ?? \"\";\n const match = line.match(HEADING_RE);\n if (!match) continue;\n const levelToken = match[1];\n const title = match[2];\n if (!levelToken || !title) continue;\n headings.push({\n level: levelToken.length,\n title: title.trim(),\n line: i + 1,\n });\n }\n return headings;\n}\n\nexport function extractH2Sections(md: string): Map<string, H2Section> {\n const lines = md.split(/\\r?\\n/);\n const headings = parseHeadings(md).filter((heading) => heading.level === 2);\n const sections = new Map<string, H2Section>();\n\n for (let i = 0; i < headings.length; i++) {\n const current = headings[i];\n if (!current) continue;\n const next = headings[i + 1];\n const startLine = current.line + 1;\n const endLine = (next?.line ?? lines.length + 1) - 1;\n const body =\n startLine <= endLine\n ? lines.slice(startLine - 1, endLine).join(\"\\n\")\n : \"\";\n\n sections.set(current.title.trim(), {\n title: current.title.trim(),\n startLine,\n endLine,\n body,\n });\n }\n\n return sections;\n}\n","import { parseContractRefs, type ParsedContractRefs } from \"./contractRefs.js\";\nimport { extractH2Sections, parseHeadings } from \"./markdown.js\";\n\nexport type BrPriority = \"P0\" | \"P1\" | \"P2\" | \"P3\";\n\nexport type ParsedBr = {\n id: string;\n priority: BrPriority;\n text: string;\n line: number;\n};\n\nexport type ParsedBrWithoutPriority = {\n id: string;\n text: string;\n line: number;\n};\n\nexport type ParsedBrWithInvalidPriority = {\n id: string;\n priority: string;\n text: string;\n line: number;\n};\n\nexport type ParsedSpec = {\n file: string;\n specId?: string;\n sections: Set<string>;\n brs: ParsedBr[];\n brsWithoutPriority: ParsedBrWithoutPriority[];\n brsWithInvalidPriority: ParsedBrWithInvalidPriority[];\n contractRefs: ParsedContractRefs;\n};\n\nconst SPEC_ID_RE = /\\bSPEC-\\d{4}\\b/;\nconst BR_LINE_RE = /^\\s*(?:[-*]\\s*)?\\[(BR-\\d{4})\\]\\[(P[0-3])\\]\\s*(.+)$/;\nconst BR_LINE_ANY_PRIORITY_RE =\n /^\\s*(?:[-*]\\s*)?\\[(BR-\\d{4})\\]\\[(P[^\\]]+)\\]\\s*(.+)$/;\nconst BR_LINE_NO_PRIORITY_RE =\n /^\\s*(?:[-*]\\s*)?\\[(BR-\\d{4})\\](?!\\s*\\[P)\\s*(.*\\S.*)$/;\nconst BR_SECTION_TITLE = \"業務ルール\";\nconst VALID_PRIORITIES = new Set<BrPriority>([\"P0\", \"P1\", \"P2\", \"P3\"]);\n\nexport function parseSpec(md: string, file: string): ParsedSpec {\n const headings = parseHeadings(md);\n const h1 = headings.find((heading) => heading.level === 1);\n const specId = h1?.title.match(SPEC_ID_RE)?.[0];\n\n const sections = extractH2Sections(md);\n const sectionNames = new Set(Array.from(sections.keys()));\n const brSection = sections.get(BR_SECTION_TITLE);\n const brLines = brSection ? brSection.body.split(/\\r?\\n/) : [];\n const startLine = brSection?.startLine ?? 1;\n\n const brs: ParsedBr[] = [];\n const brsWithoutPriority: ParsedBrWithoutPriority[] = [];\n const brsWithInvalidPriority: ParsedBrWithInvalidPriority[] = [];\n\n for (let i = 0; i < brLines.length; i++) {\n const lineText = brLines[i] ?? \"\";\n const lineNumber = startLine + i;\n\n const validMatch = lineText.match(BR_LINE_RE);\n if (validMatch) {\n const id = validMatch[1];\n const priority = validMatch[2];\n const text = validMatch[3];\n if (!id || !priority || !text) continue;\n brs.push({\n id,\n priority: priority as BrPriority,\n text: text.trim(),\n line: lineNumber,\n });\n continue;\n }\n\n const anyPriorityMatch = lineText.match(BR_LINE_ANY_PRIORITY_RE);\n if (anyPriorityMatch) {\n const id = anyPriorityMatch[1];\n const priority = anyPriorityMatch[2];\n const text = anyPriorityMatch[3];\n if (!id || !priority || !text) continue;\n if (!VALID_PRIORITIES.has(priority as BrPriority)) {\n brsWithInvalidPriority.push({\n id,\n priority,\n text: text.trim(),\n line: lineNumber,\n });\n }\n continue;\n }\n\n const noPriorityMatch = lineText.match(BR_LINE_NO_PRIORITY_RE);\n if (noPriorityMatch) {\n const id = noPriorityMatch[1];\n const text = noPriorityMatch[2];\n if (!id || !text) continue;\n brsWithoutPriority.push({\n id,\n text: text.trim(),\n line: lineNumber,\n });\n }\n }\n\n const parsed: ParsedSpec = {\n file,\n sections: sectionNames,\n brs,\n brsWithoutPriority,\n brsWithInvalidPriority,\n contractRefs: parseContractRefs(md),\n };\n if (specId) {\n parsed.specId = specId;\n }\n return parsed;\n}\n","import { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport { collectFilesByGlobs } from \"./fs.js\";\nimport { parseScenarioDocument } from \"./scenarioModel.js\";\n\nexport const SC_TAG_RE = /^SC-\\d{4}$/;\nexport const SC_TEST_ANNOTATION_RE = /\\bQFAI:SC-(\\d{4})\\b/g;\nexport const DEFAULT_TEST_FILE_EXCLUDE_GLOBS = [\n \"**/node_modules/**\",\n \"**/.git/**\",\n \"**/.qfai/**\",\n \"**/dist/**\",\n \"**/build/**\",\n \"**/coverage/**\",\n \"**/.next/**\",\n \"**/out/**\",\n];\n\nexport type ScCoverage = {\n total: number;\n covered: number;\n missing: number;\n missingIds: string[];\n refs: Record<string, string[]>;\n};\n\nexport type TestFileScan = {\n globs: string[];\n excludeGlobs: string[];\n matchedFileCount: number;\n};\n\nexport type ScTestReferenceResult = {\n refs: Map<string, Set<string>>;\n scan: TestFileScan;\n error?: string;\n};\n\nexport function extractAnnotatedScIds(text: string): string[] {\n const ids = new Set<string>();\n for (const match of text.matchAll(SC_TEST_ANNOTATION_RE)) {\n const suffix = match[1];\n if (suffix) {\n ids.add(`SC-${suffix}`);\n }\n }\n return Array.from(ids);\n}\n\nexport async function collectScIdsFromScenarioFiles(\n scenarioFiles: string[],\n): Promise<Set<string>> {\n const scIds = new Set<string>();\n for (const file of scenarioFiles) {\n const text = await readFile(file, \"utf-8\");\n const { document, errors } = parseScenarioDocument(text, file);\n if (!document || errors.length > 0) {\n continue;\n }\n\n for (const scenario of document.scenarios) {\n for (const tag of scenario.tags) {\n if (SC_TAG_RE.test(tag)) {\n scIds.add(tag);\n }\n }\n }\n }\n return scIds;\n}\n\nexport async function collectScIdSourcesFromScenarioFiles(\n scenarioFiles: string[],\n): Promise<Map<string, Set<string>>> {\n const sources = new Map<string, Set<string>>();\n for (const file of scenarioFiles) {\n const text = await readFile(file, \"utf-8\");\n const { document, errors } = parseScenarioDocument(text, file);\n if (!document || errors.length > 0) {\n continue;\n }\n\n for (const scenario of document.scenarios) {\n for (const tag of scenario.tags) {\n if (!SC_TAG_RE.test(tag)) {\n continue;\n }\n const current = sources.get(tag) ?? new Set<string>();\n current.add(file);\n sources.set(tag, current);\n }\n }\n }\n return sources;\n}\n\nexport async function collectScTestReferences(\n root: string,\n globs: string[],\n excludeGlobs: string[],\n): Promise<ScTestReferenceResult> {\n const refs = new Map<string, Set<string>>();\n const normalizedGlobs = normalizeGlobs(globs);\n const normalizedExcludeGlobs = normalizeGlobs(excludeGlobs);\n const mergedExcludeGlobs = Array.from(\n new Set([...DEFAULT_TEST_FILE_EXCLUDE_GLOBS, ...normalizedExcludeGlobs]),\n );\n if (normalizedGlobs.length === 0) {\n return {\n refs,\n scan: {\n globs: normalizedGlobs,\n excludeGlobs: mergedExcludeGlobs,\n matchedFileCount: 0,\n },\n };\n }\n\n let files: string[] = [];\n try {\n files = await collectFilesByGlobs(root, {\n globs: normalizedGlobs,\n ignore: mergedExcludeGlobs,\n });\n } catch (error) {\n return {\n refs,\n scan: {\n globs: normalizedGlobs,\n excludeGlobs: mergedExcludeGlobs,\n matchedFileCount: 0,\n },\n error: formatError(error),\n };\n }\n\n const normalizedFiles = Array.from(\n new Set(files.map((file) => path.normalize(file))),\n );\n for (const file of normalizedFiles) {\n const text = await readFile(file, \"utf-8\");\n const scIds = extractAnnotatedScIds(text);\n if (scIds.length === 0) {\n continue;\n }\n for (const scId of scIds) {\n const current = refs.get(scId) ?? new Set<string>();\n current.add(file);\n refs.set(scId, current);\n }\n }\n\n return {\n refs,\n scan: {\n globs: normalizedGlobs,\n excludeGlobs: mergedExcludeGlobs,\n matchedFileCount: normalizedFiles.length,\n },\n };\n}\n\nexport function buildScCoverage(\n scIds: Iterable<string>,\n refs: Map<string, Set<string>>,\n): ScCoverage {\n const sortedScIds = toSortedArray(scIds);\n const refsRecord: Record<string, string[]> = {};\n const missingIds: string[] = [];\n let covered = 0;\n\n for (const scId of sortedScIds) {\n const files = refs.get(scId);\n const sortedFiles = files ? toSortedArray(files) : [];\n refsRecord[scId] = sortedFiles;\n if (sortedFiles.length === 0) {\n missingIds.push(scId);\n } else {\n covered += 1;\n }\n }\n\n return {\n total: sortedScIds.length,\n covered,\n missing: missingIds.length,\n missingIds,\n refs: refsRecord,\n };\n}\n\nfunction toSortedArray(values: Iterable<string>): string[] {\n return Array.from(new Set(values)).sort((a, b) => a.localeCompare(b));\n}\n\nfunction normalizeGlobs(globs: string[]): string[] {\n return globs.map((glob) => glob.trim()).filter((glob) => glob.length > 0);\n}\n\nfunction formatError(error: unknown): string {\n if (error instanceof Error) {\n return error.message;\n }\n return String(error);\n}\n","import {\n AstBuilder,\n GherkinClassicTokenMatcher,\n Parser,\n} from \"@cucumber/gherkin\";\nimport type { GherkinDocument } from \"@cucumber/messages\";\nimport { randomUUID } from \"node:crypto\";\n\nexport type ParsedGherkin = {\n gherkinDocument: GherkinDocument | null;\n errors: string[];\n};\n\nexport function parseGherkin(source: string, uri: string): ParsedGherkin {\n const errors: string[] = [];\n const uuidFn = () => randomUUID();\n const builder = new AstBuilder(uuidFn);\n const matcher = new GherkinClassicTokenMatcher();\n const parser = new Parser(builder, matcher);\n\n try {\n const gherkinDocument = parser.parse(source);\n gherkinDocument.uri = uri;\n return { gherkinDocument, errors };\n } catch (error) {\n errors.push(formatError(error));\n return { gherkinDocument: null, errors };\n }\n}\n\nfunction formatError(error: unknown): string {\n if (error instanceof Error) {\n return error.message;\n }\n return String(error);\n}\n","import type * as Messages from \"@cucumber/messages\";\n\nimport { parseGherkin } from \"./gherkin/parse.js\";\n\nconst SPEC_TAG_RE = /^SPEC-\\d{4}$/;\nconst SC_TAG_RE = /^SC-\\d{4}$/;\nconst BR_TAG_RE = /^BR-\\d{4}$/;\nexport type ScenarioKind = \"Scenario\" | \"ScenarioOutline\";\n\nexport type ScenarioNode = {\n name: string;\n kind: ScenarioKind;\n line?: number;\n tags: string[];\n steps: readonly Messages.Step[];\n};\n\nexport type ScenarioDocument = {\n uri: string;\n featureName?: string;\n featureTags: string[];\n scenarios: ScenarioNode[];\n};\n\nexport type ScenarioParseResult = {\n document: ScenarioDocument | null;\n errors: string[];\n};\n\nexport type ScenarioAtom = {\n uri: string;\n featureName: string;\n scenarioName: string;\n kind: ScenarioKind;\n specId?: string;\n scId?: string;\n brIds: string[];\n contractIds: string[];\n line?: number;\n};\n\nexport function parseScenarioDocument(\n text: string,\n uri: string,\n): ScenarioParseResult {\n const { gherkinDocument, errors } = parseGherkin(text, uri);\n if (!gherkinDocument) {\n return { document: null, errors };\n }\n\n const feature = gherkinDocument.feature;\n if (!feature) {\n return {\n document: { uri, featureTags: [], scenarios: [] },\n errors,\n };\n }\n\n const featureTags = collectTagNames(feature.tags);\n const scenarios = collectScenarioNodes(feature, featureTags);\n return {\n document: {\n uri,\n featureName: feature.name,\n featureTags,\n scenarios,\n },\n errors,\n };\n}\n\nexport function buildScenarioAtoms(\n document: ScenarioDocument,\n contractIds: string[] = [],\n): ScenarioAtom[] {\n const uniqueContractIds = unique(contractIds).sort((a, b) =>\n a.localeCompare(b),\n );\n return document.scenarios.map((scenario) => {\n const specIds = scenario.tags.filter((tag) => SPEC_TAG_RE.test(tag));\n const scIds = scenario.tags.filter((tag) => SC_TAG_RE.test(tag));\n const brIds = unique(scenario.tags.filter((tag) => BR_TAG_RE.test(tag)));\n\n const atom: ScenarioAtom = {\n uri: document.uri,\n featureName: document.featureName ?? \"\",\n scenarioName: scenario.name,\n kind: scenario.kind,\n brIds,\n contractIds: uniqueContractIds,\n };\n\n if (scenario.line !== undefined) {\n atom.line = scenario.line;\n }\n if (specIds.length === 1) {\n const specId = specIds[0];\n if (specId) {\n atom.specId = specId;\n }\n }\n if (scIds.length === 1) {\n const scId = scIds[0];\n if (scId) {\n atom.scId = scId;\n }\n }\n\n return atom;\n });\n}\n\nfunction collectScenarioNodes(\n feature: Messages.Feature,\n featureTags: string[],\n): ScenarioNode[] {\n const scenarios: ScenarioNode[] = [];\n\n for (const child of feature.children) {\n if (child.scenario) {\n scenarios.push(buildScenarioNode(child.scenario, featureTags, []));\n }\n if (child.rule) {\n const ruleTags = collectTagNames(child.rule.tags);\n for (const ruleChild of child.rule.children) {\n if (ruleChild.scenario) {\n scenarios.push(\n buildScenarioNode(ruleChild.scenario, featureTags, ruleTags),\n );\n }\n }\n }\n }\n\n return scenarios;\n}\n\nfunction buildScenarioNode(\n scenario: Messages.Scenario,\n featureTags: string[],\n ruleTags: string[],\n): ScenarioNode {\n const tags = [...featureTags, ...ruleTags, ...collectTagNames(scenario.tags)];\n const kind: ScenarioKind =\n scenario.examples.length > 0 ? \"ScenarioOutline\" : \"Scenario\";\n return {\n name: scenario.name,\n kind,\n line: scenario.location?.line,\n tags,\n steps: scenario.steps,\n };\n}\n\nfunction collectTagNames(tags: readonly Messages.Tag[]): string[] {\n return tags.map((tag) => tag.name.replace(/^@/, \"\"));\n}\n\nfunction unique(values: string[]): string[] {\n return Array.from(new Set(values));\n}\n","import { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\ndeclare const __QFAI_TOOL_VERSION__: string | undefined;\n\nexport async function resolveToolVersion(): Promise<string> {\n if (\n typeof __QFAI_TOOL_VERSION__ === \"string\" &&\n __QFAI_TOOL_VERSION__.length > 0\n ) {\n return __QFAI_TOOL_VERSION__;\n }\n\n try {\n const packagePath = resolvePackageJsonPath();\n const raw = await readFile(packagePath, \"utf-8\");\n const parsed = JSON.parse(raw) as { version?: unknown };\n const version = typeof parsed.version === \"string\" ? parsed.version : \"\";\n return version.length > 0 ? version : \"unknown\";\n } catch {\n return \"unknown\";\n }\n}\n\nfunction resolvePackageJsonPath(): string {\n const base = import.meta.url;\n const basePath = base.startsWith(\"file:\") ? fileURLToPath(base) : base;\n return path.resolve(path.dirname(basePath), \"../../package.json\");\n}\n","import { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport type { QfaiConfig } from \"../config.js\";\nimport { resolvePath } from \"../config.js\";\nimport { parseStructuredContract } from \"../contracts.js\";\nimport { buildContractIndex } from \"../contractIndex.js\";\nimport {\n extractDeclaredContractIds,\n stripContractDeclarationLines,\n} from \"../contractsDecl.js\";\nimport {\n collectApiContractFiles,\n collectDbContractFiles,\n collectUiContractFiles,\n} from \"../discovery.js\";\nimport { extractInvalidIds } from \"../ids.js\";\nimport type { Issue, IssueSeverity } from \"../types.js\";\n\nconst SQL_DANGEROUS_PATTERNS: Array<{ pattern: RegExp; label: string }> = [\n { pattern: /\\bDROP\\s+TABLE\\b/i, label: \"DROP TABLE\" },\n { pattern: /\\bDROP\\s+DATABASE\\b/i, label: \"DROP DATABASE\" },\n { pattern: /\\bTRUNCATE\\b/i, label: \"TRUNCATE\" },\n {\n pattern: /\\bALTER\\s+TABLE\\b[\\s\\S]*\\bDROP\\b/i,\n label: \"ALTER TABLE ... DROP\",\n },\n];\n\nexport async function validateContracts(\n root: string,\n config: QfaiConfig,\n): Promise<Issue[]> {\n const issues: Issue[] = [];\n const contractsRoot = resolvePath(root, config, \"contractsDir\");\n\n issues.push(...(await validateUiContracts(path.join(contractsRoot, \"ui\"))));\n issues.push(...(await validateApiContracts(path.join(contractsRoot, \"api\"))));\n issues.push(...(await validateDbContracts(path.join(contractsRoot, \"db\"))));\n const contractIndex = await buildContractIndex(root, config);\n issues.push(...validateDuplicateContractIds(contractIndex));\n\n return issues;\n}\n\nasync function validateUiContracts(uiRoot: string): Promise<Issue[]> {\n const files = await collectUiContractFiles(uiRoot);\n if (files.length === 0) {\n return [\n issue(\n \"QFAI-UI-000\",\n \"UI 契約ファイルが見つかりません。\",\n \"info\",\n uiRoot,\n \"contracts.ui.files\",\n ),\n ];\n }\n\n const issues: Issue[] = [];\n for (const file of files) {\n const text = await readFile(file, \"utf-8\");\n const invalidIds = extractInvalidIds(text, [\n \"SPEC\",\n \"BR\",\n \"SC\",\n \"UI\",\n \"API\",\n \"DB\",\n \"ADR\",\n ]);\n if (invalidIds.length > 0) {\n issues.push(\n issue(\n \"QFAI-ID-002\",\n `ID フォーマットが不正です: ${invalidIds.join(\", \")}`,\n \"error\",\n file,\n \"id.format\",\n invalidIds,\n ),\n );\n }\n const declaredIds = extractDeclaredContractIds(text);\n issues.push(...validateDeclaredContractIds(declaredIds, file, \"UI\"));\n try {\n parseStructuredContract(file, stripContractDeclarationLines(text));\n } catch (error) {\n issues.push(\n issue(\n \"QFAI-CONTRACT-001\",\n `UI 契約ファイルの解析に失敗しました: ${file} (${formatError(error)})`,\n \"error\",\n file,\n \"contracts.ui.parse\",\n ),\n );\n }\n }\n\n return issues;\n}\n\nasync function validateApiContracts(apiRoot: string): Promise<Issue[]> {\n const files = await collectApiContractFiles(apiRoot);\n if (files.length === 0) {\n return [\n issue(\n \"QFAI-API-000\",\n \"API 契約ファイルが見つかりません。\",\n \"info\",\n apiRoot,\n \"contracts.api.files\",\n ),\n ];\n }\n\n const issues: Issue[] = [];\n for (const file of files) {\n const text = await readFile(file, \"utf-8\");\n const invalidIds = extractInvalidIds(text, [\n \"SPEC\",\n \"BR\",\n \"SC\",\n \"UI\",\n \"API\",\n \"DB\",\n \"ADR\",\n ]);\n if (invalidIds.length > 0) {\n issues.push(\n issue(\n \"QFAI-ID-002\",\n `ID フォーマットが不正です: ${invalidIds.join(\", \")}`,\n \"error\",\n file,\n \"id.format\",\n invalidIds,\n ),\n );\n }\n const declaredIds = extractDeclaredContractIds(text);\n issues.push(...validateDeclaredContractIds(declaredIds, file, \"API\"));\n let doc: Record<string, unknown>;\n try {\n doc = parseStructuredContract(file, stripContractDeclarationLines(text));\n } catch (error) {\n issues.push(\n issue(\n \"QFAI-CONTRACT-001\",\n `API 契約ファイルの解析に失敗しました: ${file} (${formatError(error)})`,\n \"error\",\n file,\n \"contracts.api.parse\",\n ),\n );\n continue;\n }\n\n if (!hasOpenApi(doc)) {\n issues.push(\n issue(\n \"QFAI-API-001\",\n \"OpenAPI 定義が見つかりません。\",\n \"error\",\n file,\n \"contracts.api.openapi\",\n ),\n );\n }\n }\n\n return issues;\n}\n\nasync function validateDbContracts(dbRoot: string): Promise<Issue[]> {\n const files = await collectDbContractFiles(dbRoot);\n if (files.length === 0) {\n return [\n issue(\n \"QFAI-DB-000\",\n \"DB 契約ファイルが見つかりません。\",\n \"info\",\n dbRoot,\n \"contracts.db.files\",\n ),\n ];\n }\n\n const issues: Issue[] = [];\n for (const file of files) {\n const text = await readFile(file, \"utf-8\");\n const invalidIds = extractInvalidIds(text, [\n \"SPEC\",\n \"BR\",\n \"SC\",\n \"UI\",\n \"API\",\n \"DB\",\n \"ADR\",\n ]);\n if (invalidIds.length > 0) {\n issues.push(\n issue(\n \"QFAI-ID-002\",\n `ID フォーマットが不正です: ${invalidIds.join(\", \")}`,\n \"error\",\n file,\n \"id.format\",\n invalidIds,\n ),\n );\n }\n const declaredIds = extractDeclaredContractIds(text);\n issues.push(...validateDeclaredContractIds(declaredIds, file, \"DB\"));\n issues.push(...lintSql(text, file));\n }\n\n return issues;\n}\n\nexport function lintSql(text: string, file: string): Issue[] {\n const issues: Issue[] = [];\n for (const { pattern, label } of SQL_DANGEROUS_PATTERNS) {\n if (pattern.test(text)) {\n issues.push(\n issue(\n \"QFAI-DB-001\",\n `危険な SQL 操作が含まれています: ${label}`,\n \"warning\",\n file,\n \"contracts.db.sql\",\n ),\n );\n }\n }\n return issues;\n}\n\ntype ContractKind = \"UI\" | \"API\" | \"DB\";\n\nfunction validateDeclaredContractIds(\n ids: string[],\n file: string,\n kind: ContractKind,\n): Issue[] {\n const issues: Issue[] = [];\n if (ids.length === 0) {\n issues.push(\n issue(\n \"QFAI-CONTRACT-010\",\n `契約ファイルに QFAI-CONTRACT-ID がありません: ${file}`,\n \"error\",\n file,\n \"contracts.declaration\",\n ),\n );\n return issues;\n }\n if (ids.length > 1) {\n issues.push(\n issue(\n \"QFAI-CONTRACT-011\",\n `契約ファイルに複数の QFAI-CONTRACT-ID が宣言されています: ${ids.join(\n \", \",\n )}`,\n \"error\",\n file,\n \"contracts.declaration\",\n ids,\n ),\n );\n return issues;\n }\n\n const [id] = ids;\n if (id && !id.startsWith(`${kind}-`)) {\n issues.push(\n issue(\n \"QFAI-CONTRACT-013\",\n `契約ファイルの QFAI-CONTRACT-ID が ${kind}- ではありません: ${id}`,\n \"error\",\n file,\n \"contracts.declarationPrefix\",\n [id],\n ),\n );\n }\n\n return issues;\n}\n\nfunction validateDuplicateContractIds(contractIndex: {\n idToFiles: Map<string, Set<string>>;\n}): Issue[] {\n const issues: Issue[] = [];\n for (const [id, files] of contractIndex.idToFiles.entries()) {\n if (files.size <= 1) {\n continue;\n }\n const sortedFiles = Array.from(files).sort((a, b) => a.localeCompare(b));\n issues.push(\n issue(\n \"QFAI-CONTRACT-012\",\n `契約 ID が複数ファイルで宣言されています: ${id} (${sortedFiles.join(\n \", \",\n )})`,\n \"error\",\n sortedFiles[0],\n \"contracts.idDuplicate\",\n [id],\n ),\n );\n }\n return issues;\n}\n\nfunction hasOpenApi(doc: Record<string, unknown>): boolean {\n return typeof doc.openapi === \"string\" && doc.openapi.length > 0;\n}\n\nfunction formatError(error: unknown): string {\n if (error instanceof Error) {\n return error.message;\n }\n return String(error);\n}\n\nfunction issue(\n code: string,\n message: string,\n severity: IssueSeverity,\n file?: string,\n rule?: string,\n refs?: string[],\n): Issue {\n const issue: Issue = {\n code,\n severity,\n message,\n };\n if (file) {\n issue.file = file;\n }\n if (rule) {\n issue.rule = rule;\n }\n if (refs && refs.length > 0) {\n issue.refs = refs;\n }\n return issue;\n}\n","import path from \"node:path\";\n\nimport { parse as parseYaml } from \"yaml\";\n\nimport { extractIds } from \"./ids.js\";\n\nexport function parseStructuredContract(\n file: string,\n text: string,\n): Record<string, unknown> {\n const ext = path.extname(file).toLowerCase();\n if (ext === \".json\") {\n return JSON.parse(text) as Record<string, unknown>;\n }\n return parseYaml(text) as Record<string, unknown>;\n}\n\nexport function extractUiContractIds(doc: Record<string, unknown>): string[] {\n const id = typeof doc.id === \"string\" ? doc.id : \"\";\n return extractIds(id, \"UI\");\n}\n\nexport function extractApiContractIds(doc: Record<string, unknown>): string[] {\n const operationIds = new Set<string>();\n collectOperationIds(doc, operationIds);\n\n const ids = new Set<string>();\n for (const operationId of operationIds) {\n extractIds(operationId, \"API\").forEach((id) => ids.add(id));\n }\n return Array.from(ids);\n}\n\nexport function collectOperationIds(value: unknown, out: Set<string>): void {\n if (!value || typeof value !== \"object\") {\n return;\n }\n if (Array.isArray(value)) {\n for (const item of value) {\n collectOperationIds(item, out);\n }\n return;\n }\n\n for (const [key, entry] of Object.entries(value)) {\n if (key === \"operationId\" && typeof entry === \"string\") {\n out.add(entry);\n continue;\n }\n collectOperationIds(entry, out);\n }\n}\n","import { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport type { QfaiConfig } from \"../config.js\";\nimport { resolvePath } from \"../config.js\";\nimport { collectSpecPackDirs } from \"../discovery.js\";\nimport type { Issue, IssueSeverity } from \"../types.js\";\n\nconst SECTION_RE = /^##\\s+変更区分/m;\nconst COMPAT_LINE_RE = /^\\s*-\\s*\\[[ xX]\\]\\s*Compatibility\\b/m;\nconst CHANGE_LINE_RE = /^\\s*-\\s*\\[[ xX]\\]\\s*Change\\/Improvement\\b/m;\nconst COMPAT_CHECKED_RE = /^\\s*-\\s*\\[[xX]\\]\\s*Compatibility\\b/m;\nconst CHANGE_CHECKED_RE = /^\\s*-\\s*\\[[xX]\\]\\s*Change\\/Improvement\\b/m;\n\nexport async function validateDeltas(\n root: string,\n config: QfaiConfig,\n): Promise<Issue[]> {\n const specsRoot = resolvePath(root, config, \"specsDir\");\n const packs = await collectSpecPackDirs(specsRoot);\n if (packs.length === 0) {\n return [];\n }\n\n const issues: Issue[] = [];\n for (const pack of packs) {\n const deltaPath = path.join(pack, \"delta.md\");\n let text: string;\n try {\n text = await readFile(deltaPath, \"utf-8\");\n } catch (error) {\n if (isMissingFileError(error)) {\n issues.push(\n issue(\n \"QFAI-DELTA-001\",\n \"delta.md が見つかりません。\",\n \"error\",\n deltaPath,\n \"delta.exists\",\n ),\n );\n continue;\n }\n throw error;\n }\n\n const hasSection = SECTION_RE.test(text);\n const hasCompatibility = COMPAT_LINE_RE.test(text);\n const hasChange = CHANGE_LINE_RE.test(text);\n if (!hasSection || !hasCompatibility || !hasChange) {\n issues.push(\n issue(\n \"QFAI-DELTA-002\",\n \"delta.md の変更区分が不足しています。\",\n \"error\",\n deltaPath,\n \"delta.section\",\n ),\n );\n continue;\n }\n\n const compatibilityChecked = COMPAT_CHECKED_RE.test(text);\n const changeChecked = CHANGE_CHECKED_RE.test(text);\n if (compatibilityChecked === changeChecked) {\n issues.push(\n issue(\n \"QFAI-DELTA-003\",\n \"delta.md の変更区分はどちらか1つだけ選択してください(両方ON/両方OFFは無効です)。\",\n \"error\",\n deltaPath,\n \"delta.classification\",\n ),\n );\n }\n }\n\n return issues;\n}\n\nfunction isMissingFileError(error: unknown): boolean {\n if (!error || typeof error !== \"object\") {\n return false;\n }\n return (error as { code?: string }).code === \"ENOENT\";\n}\n\nfunction issue(\n code: string,\n message: string,\n severity: IssueSeverity,\n file?: string,\n rule?: string,\n refs?: string[],\n): Issue {\n const issue: Issue = {\n code,\n severity,\n message,\n };\n if (file) {\n issue.file = file;\n }\n if (rule) {\n issue.rule = rule;\n }\n if (refs && refs.length > 0) {\n issue.refs = refs;\n }\n return issue;\n}\n","import { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport type { QfaiConfig } from \"../config.js\";\nimport { resolvePath } from \"../config.js\";\nimport { buildContractIndex } from \"../contractIndex.js\";\nimport { collectScenarioFiles, collectSpecFiles } from \"../discovery.js\";\nimport { parseSpec } from \"../parse/spec.js\";\nimport { parseScenarioDocument } from \"../scenarioModel.js\";\nimport type { Issue, IssueSeverity } from \"../types.js\";\n\nconst SC_TAG_RE = /^SC-\\d{4}$/;\n\nexport async function validateDefinedIds(\n root: string,\n config: QfaiConfig,\n): Promise<Issue[]> {\n const issues: Issue[] = [];\n const specsRoot = resolvePath(root, config, \"specsDir\");\n\n const specFiles = await collectSpecFiles(specsRoot);\n const scenarioFiles = await collectScenarioFiles(specsRoot);\n\n const defined = new Map<string, Set<string>>();\n\n await collectSpecDefinitionIds(specFiles, defined);\n await collectScenarioDefinitionIds(scenarioFiles, defined);\n const contractIndex = await buildContractIndex(root, config);\n for (const [id, files] of contractIndex.idToFiles.entries()) {\n for (const file of files) {\n recordId(defined, id, file);\n }\n }\n\n for (const [id, files] of defined.entries()) {\n if (files.size <= 1) {\n continue;\n }\n const sorted = Array.from(files).sort();\n issues.push(\n issue(\n \"QFAI-ID-001\",\n `ID が重複しています: ${id} (${formatFileList(sorted, root)})`,\n \"error\",\n sorted[0],\n \"id.duplicate\",\n ),\n );\n }\n\n return issues;\n}\n\nasync function collectSpecDefinitionIds(\n files: string[],\n out: Map<string, Set<string>>,\n): Promise<void> {\n for (const file of files) {\n const text = await readFile(file, \"utf-8\");\n const parsed = parseSpec(text, file);\n if (parsed.specId) {\n recordId(out, parsed.specId, file);\n }\n parsed.brs.forEach((br) => recordId(out, br.id, file));\n }\n}\n\nasync function collectScenarioDefinitionIds(\n files: string[],\n out: Map<string, Set<string>>,\n): Promise<void> {\n for (const file of files) {\n const text = await readFile(file, \"utf-8\");\n const { document, errors } = parseScenarioDocument(text, file);\n if (!document || errors.length > 0) {\n continue;\n }\n for (const scenario of document.scenarios) {\n for (const tag of scenario.tags) {\n if (SC_TAG_RE.test(tag)) {\n recordId(out, tag, file);\n }\n }\n }\n }\n}\n\nfunction recordId(\n out: Map<string, Set<string>>,\n id: string,\n file: string,\n): void {\n const current = out.get(id) ?? new Set<string>();\n current.add(file);\n out.set(id, current);\n}\n\nfunction formatFileList(files: string[], root: string): string {\n return files\n .map((file) => {\n const relative = path.relative(root, file);\n return relative.length > 0 ? relative : file;\n })\n .join(\", \");\n}\n\nfunction issue(\n code: string,\n message: string,\n severity: IssueSeverity,\n file?: string,\n rule?: string,\n refs?: string[],\n): Issue {\n const issue: Issue = {\n code,\n severity,\n message,\n };\n if (file) {\n issue.file = file;\n }\n if (rule) {\n issue.rule = rule;\n }\n if (refs && refs.length > 0) {\n issue.refs = refs;\n }\n return issue;\n}\n","import { readFile } from \"node:fs/promises\";\n\nimport type { QfaiConfig } from \"../config.js\";\nimport { resolvePath } from \"../config.js\";\nimport { extractInvalidIds } from \"../ids.js\";\nimport { collectSpecEntries } from \"../specLayout.js\";\nimport { parseScenarioDocument } from \"../scenarioModel.js\";\nimport type { Issue, IssueSeverity } from \"../types.js\";\n\nconst GIVEN_PATTERN = /\\bGiven\\b/;\nconst WHEN_PATTERN = /\\bWhen\\b/;\nconst THEN_PATTERN = /\\bThen\\b/;\nconst SC_TAG_RE = /^SC-\\d{4}$/;\nconst SPEC_TAG_RE = /^SPEC-\\d{4}$/;\n\nexport async function validateScenarios(\n root: string,\n config: QfaiConfig,\n): Promise<Issue[]> {\n const specsRoot = resolvePath(root, config, \"specsDir\");\n const entries = await collectSpecEntries(specsRoot);\n\n if (entries.length === 0) {\n const expected = \"spec-0001/scenario.md\";\n const legacy = \"spec-001/scenario.md\";\n return [\n issue(\n \"QFAI-SC-000\",\n `Scenario ファイルが見つかりません。配置場所: ${config.paths.specsDir} / 期待パターン: ${expected} (${legacy} は非対応)`,\n \"info\",\n specsRoot,\n \"scenario.files\",\n ),\n ];\n }\n\n const issues: Issue[] = [];\n for (const entry of entries) {\n let text: string;\n try {\n text = await readFile(entry.scenarioPath, \"utf-8\");\n } catch (error) {\n if (isMissingFileError(error)) {\n issues.push(\n issue(\n \"QFAI-SC-001\",\n \"scenario.md が見つかりません。\",\n \"error\",\n entry.scenarioPath,\n \"scenario.exists\",\n ),\n );\n continue;\n }\n throw error;\n }\n issues.push(...validateScenarioContent(text, entry.scenarioPath));\n }\n\n return issues;\n}\n\nexport function validateScenarioContent(text: string, file: string): Issue[] {\n const issues: Issue[] = [];\n\n const invalidIds = extractInvalidIds(text, [\n \"SPEC\",\n \"BR\",\n \"SC\",\n \"UI\",\n \"API\",\n \"DB\",\n \"ADR\",\n ]);\n if (invalidIds.length > 0) {\n issues.push(\n issue(\n \"QFAI-ID-002\",\n `ID フォーマットが不正です: ${invalidIds.join(\", \")}`,\n \"error\",\n file,\n \"id.format\",\n invalidIds,\n ),\n );\n }\n\n const { document, errors } = parseScenarioDocument(text, file);\n if (!document || errors.length > 0) {\n issues.push(\n issue(\n \"QFAI-SC-010\",\n `Gherkin の解析に失敗しました: ${errors.join(\", \") || \"unknown\"}`,\n \"error\",\n file,\n \"scenario.parse\",\n ),\n );\n return issues;\n }\n\n const featureSpecTags = document.featureTags.filter((tag) =>\n SPEC_TAG_RE.test(tag),\n );\n if (featureSpecTags.length > 1) {\n issues.push(\n issue(\n \"QFAI-SC-009\",\n `Feature の SPEC タグが複数あります: ${featureSpecTags.join(\", \")}`,\n \"error\",\n file,\n \"scenario.featureSpec\",\n featureSpecTags,\n ),\n );\n }\n\n const missingStructure: string[] = [];\n if (!document.featureName) missingStructure.push(\"Feature\");\n if (document.scenarios.length === 0) missingStructure.push(\"Scenario\");\n if (missingStructure.length > 0) {\n issues.push(\n issue(\n \"QFAI-SC-006\",\n `Scenario ファイルに必要な構造がありません: ${missingStructure.join(\n \", \",\n )}`,\n \"error\",\n file,\n \"scenario.structure\",\n ),\n );\n }\n\n for (const scenario of document.scenarios) {\n if (scenario.tags.length === 0) {\n issues.push(\n issue(\n \"QFAI-SC-007\",\n `Scenario タグが見つかりません: ${scenario.name}`,\n \"error\",\n file,\n \"scenario.tags\",\n ),\n );\n continue;\n }\n\n const missingTags: string[] = [];\n const scTags = scenario.tags.filter((tag) => SC_TAG_RE.test(tag));\n if (scTags.length === 0) {\n missingTags.push(\"SC(0件)\");\n } else if (scTags.length > 1) {\n missingTags.push(`SC(${scTags.length}件/1件必須)`);\n }\n if (missingTags.length > 0) {\n issues.push(\n issue(\n \"QFAI-SC-008\",\n `Scenario タグに不足があります: ${missingTags.join(\", \")} (${\n scenario.name\n })`,\n \"error\",\n file,\n \"scenario.tagIds\",\n ),\n );\n }\n }\n\n for (const scenario of document.scenarios) {\n const missingSteps: string[] = [];\n const keywords = scenario.steps.map((step) => step.keyword.trim());\n if (!keywords.some((keyword) => GIVEN_PATTERN.test(keyword))) {\n missingSteps.push(\"Given\");\n }\n if (!keywords.some((keyword) => WHEN_PATTERN.test(keyword))) {\n missingSteps.push(\"When\");\n }\n if (!keywords.some((keyword) => THEN_PATTERN.test(keyword))) {\n missingSteps.push(\"Then\");\n }\n if (missingSteps.length > 0) {\n issues.push(\n issue(\n \"QFAI-SC-005\",\n `Given/When/Then が不足しています: ${missingSteps.join(\", \")} (${\n scenario.name\n })`,\n \"warning\",\n file,\n \"scenario.steps\",\n ),\n );\n }\n }\n\n return issues;\n}\n\nfunction issue(\n code: string,\n message: string,\n severity: IssueSeverity,\n file?: string,\n rule?: string,\n refs?: string[],\n): Issue {\n const issue: Issue = {\n code,\n severity,\n message,\n };\n if (file) {\n issue.file = file;\n }\n if (rule) {\n issue.rule = rule;\n }\n if (refs && refs.length > 0) {\n issue.refs = refs;\n }\n return issue;\n}\n\nfunction isMissingFileError(error: unknown): boolean {\n if (!error || typeof error !== \"object\") {\n return false;\n }\n return (error as { code?: string }).code === \"ENOENT\";\n}\n","import { readFile } from \"node:fs/promises\";\nimport type { QfaiConfig } from \"../config.js\";\nimport { resolvePath } from \"../config.js\";\nimport { extractIds, extractInvalidIds } from \"../ids.js\";\nimport { parseSpec } from \"../parse/spec.js\";\nimport { collectSpecEntries } from \"../specLayout.js\";\nimport type { Issue, IssueSeverity } from \"../types.js\";\n\nexport async function validateSpecs(\n root: string,\n config: QfaiConfig,\n): Promise<Issue[]> {\n const specsRoot = resolvePath(root, config, \"specsDir\");\n const entries = await collectSpecEntries(specsRoot);\n\n if (entries.length === 0) {\n const expected = \"spec-0001/spec.md\";\n const legacy = \"spec-001/spec.md\";\n return [\n issue(\n \"QFAI-SPEC-000\",\n `Spec ファイルが見つかりません。配置場所: ${config.paths.specsDir} / 期待パターン: ${expected} (${legacy} は非対応)`,\n \"info\",\n specsRoot,\n \"spec.files\",\n ),\n ];\n }\n\n const issues: Issue[] = [];\n for (const entry of entries) {\n let text: string;\n try {\n text = await readFile(entry.specPath, \"utf-8\");\n } catch (error) {\n if (isMissingFileError(error)) {\n issues.push(\n issue(\n \"QFAI-SPEC-005\",\n \"spec.md が見つかりません。\",\n \"error\",\n entry.specPath,\n \"spec.exists\",\n ),\n );\n continue;\n }\n throw error;\n }\n issues.push(\n ...validateSpecContent(\n text,\n entry.specPath,\n config.validation.require.specSections,\n ),\n );\n }\n\n return issues;\n}\n\nexport function validateSpecContent(\n text: string,\n file: string,\n requiredSections: string[],\n): Issue[] {\n const issues: Issue[] = [];\n\n const parsed = parseSpec(text, file);\n\n const invalidIds = extractInvalidIds(text, [\n \"SPEC\",\n \"BR\",\n \"SC\",\n \"UI\",\n \"API\",\n \"DB\",\n \"ADR\",\n ]);\n if (invalidIds.length > 0) {\n issues.push(\n issue(\n \"QFAI-ID-002\",\n `ID フォーマットが不正です: ${invalidIds.join(\", \")}`,\n \"error\",\n file,\n \"id.format\",\n invalidIds,\n ),\n );\n }\n\n if (!parsed.specId) {\n issues.push(\n issue(\n \"QFAI-SPEC-001\",\n \"SPEC ID が見つかりません。\",\n \"error\",\n file,\n \"spec.id\",\n ),\n );\n }\n\n if (parsed.brs.length === 0) {\n issues.push(\n issue(\n \"QFAI-SPEC-002\",\n \"BR ID が見つかりません。\",\n \"error\",\n file,\n \"spec.br\",\n ),\n );\n }\n\n for (const br of parsed.brsWithoutPriority) {\n issues.push(\n issue(\n \"QFAI-BR-001\",\n `BR 行に Priority がありません: ${br.id}`,\n \"error\",\n file,\n \"spec.brPriority\",\n [br.id],\n ),\n );\n }\n\n for (const br of parsed.brsWithInvalidPriority) {\n issues.push(\n issue(\n \"QFAI-BR-002\",\n `BR Priority が不正です: ${br.id} (${br.priority})`,\n \"error\",\n file,\n \"spec.brPriority\",\n [br.id],\n ),\n );\n }\n\n const scIds = extractIds(text, \"SC\");\n if (scIds.length > 0) {\n issues.push(\n issue(\n \"QFAI-SPEC-003\",\n \"Spec は SC を参照しないルールです。\",\n \"warning\",\n file,\n \"spec.noSc\",\n scIds,\n ),\n );\n }\n\n for (const section of requiredSections) {\n if (!parsed.sections.has(section)) {\n issues.push(\n issue(\n \"QFAI-SPEC-004\",\n `必須セクションが不足しています: ${section}`,\n \"error\",\n file,\n \"spec.requiredSection\",\n ),\n );\n }\n }\n\n return issues;\n}\n\nfunction issue(\n code: string,\n message: string,\n severity: IssueSeverity,\n file?: string,\n rule?: string,\n refs?: string[],\n): Issue {\n const issue: Issue = {\n code,\n severity,\n message,\n };\n if (file) {\n issue.file = file;\n }\n if (rule) {\n issue.rule = rule;\n }\n if (refs && refs.length > 0) {\n issue.refs = refs;\n }\n return issue;\n}\n\nfunction isMissingFileError(error: unknown): boolean {\n if (!error || typeof error !== \"object\") {\n return false;\n }\n return (error as { code?: string }).code === \"ENOENT\";\n}\n","import { readFile } from \"node:fs/promises\";\n\nimport type { QfaiConfig } from \"../config.js\";\nimport { resolvePath } from \"../config.js\";\nimport { buildContractIndex } from \"../contractIndex.js\";\nimport { collectScenarioFiles, collectSpecFiles } from \"../discovery.js\";\nimport { collectFiles } from \"../fs.js\";\nimport { extractAllIds } from \"../ids.js\";\nimport { parseContractRefs } from \"../parse/contractRefs.js\";\nimport { parseSpec } from \"../parse/spec.js\";\nimport { buildScenarioAtoms, parseScenarioDocument } from \"../scenarioModel.js\";\nimport { SC_TAG_RE, collectScTestReferences } from \"../traceability.js\";\nimport type { Issue, IssueSeverity } from \"../types.js\";\n\nconst SPEC_TAG_RE = /^SPEC-\\d{4}$/;\nconst BR_TAG_RE = /^BR-\\d{4}$/;\n\nexport async function validateTraceability(\n root: string,\n config: QfaiConfig,\n): Promise<Issue[]> {\n const issues: Issue[] = [];\n const specsRoot = resolvePath(root, config, \"specsDir\");\n const srcRoot = resolvePath(root, config, \"srcDir\");\n const testsRoot = resolvePath(root, config, \"testsDir\");\n\n const specFiles = await collectSpecFiles(specsRoot);\n const scenarioFiles = await collectScenarioFiles(specsRoot);\n\n const upstreamIds = new Set<string>();\n const specIds = new Set<string>();\n const brIdsInSpecs = new Set<string>();\n const brIdsInScenarios = new Set<string>();\n const scIdsInScenarios = new Set<string>();\n const specContractIds = new Set<string>();\n const specToBrIds = new Map<string, Set<string>>();\n const contractIndex = await buildContractIndex(root, config);\n const contractIds = contractIndex.ids;\n\n for (const file of specFiles) {\n const text = await readFile(file, \"utf-8\");\n extractAllIds(text).forEach((id) => upstreamIds.add(id));\n\n const parsed = parseSpec(text, file);\n if (parsed.specId) {\n specIds.add(parsed.specId);\n }\n\n const brIds = parsed.brs.map((br) => br.id);\n brIds.forEach((id) => brIdsInSpecs.add(id));\n\n if (parsed.specId) {\n const current = specToBrIds.get(parsed.specId) ?? new Set<string>();\n brIds.forEach((id) => current.add(id));\n specToBrIds.set(parsed.specId, current);\n }\n\n const contractRefs = parsed.contractRefs;\n if (contractRefs.lines.length === 0) {\n issues.push(\n issue(\n \"QFAI-TRACE-020\",\n \"Spec に QFAI-CONTRACT-REF がありません。\",\n \"error\",\n file,\n \"traceability.specContractRefRequired\",\n ),\n );\n } else {\n if (contractRefs.hasNone && contractRefs.ids.length > 0) {\n issues.push(\n issue(\n \"QFAI-TRACE-023\",\n \"Spec の QFAI-CONTRACT-REF に none と契約 ID が混在しています。\",\n \"error\",\n file,\n \"traceability.specContractRefFormat\",\n ),\n );\n }\n if (contractRefs.invalidTokens.length > 0) {\n issues.push(\n issue(\n \"QFAI-TRACE-021\",\n `Spec の契約 ID が不正です: ${contractRefs.invalidTokens.join(\n \", \",\n )}`,\n \"error\",\n file,\n \"traceability.specContractRefFormat\",\n contractRefs.invalidTokens,\n ),\n );\n }\n }\n\n contractRefs.ids.forEach((id) => {\n specContractIds.add(id);\n });\n\n const unknownContractIds = contractRefs.ids.filter(\n (id) => !contractIds.has(id),\n );\n if (unknownContractIds.length > 0) {\n issues.push(\n issue(\n \"QFAI-TRACE-024\",\n `Spec が未知の契約 ID を参照しています: ${unknownContractIds.join(\n \", \",\n )}`,\n \"error\",\n file,\n \"traceability.specContractExists\",\n unknownContractIds,\n ),\n );\n }\n }\n\n for (const file of scenarioFiles) {\n const text = await readFile(file, \"utf-8\");\n extractAllIds(text).forEach((id) => upstreamIds.add(id));\n\n const scenarioContractRefs = parseContractRefs(text, {\n allowCommentPrefix: true,\n });\n if (scenarioContractRefs.lines.length === 0) {\n issues.push(\n issue(\n \"QFAI-TRACE-031\",\n \"Scenario に QFAI-CONTRACT-REF がありません。\",\n \"error\",\n file,\n \"traceability.scenarioContractRefRequired\",\n ),\n );\n } else {\n if (scenarioContractRefs.hasNone && scenarioContractRefs.ids.length > 0) {\n issues.push(\n issue(\n \"QFAI-TRACE-033\",\n \"Scenario の QFAI-CONTRACT-REF に none と契約 ID が混在しています。\",\n \"error\",\n file,\n \"traceability.scenarioContractRefFormat\",\n ),\n );\n }\n if (scenarioContractRefs.invalidTokens.length > 0) {\n issues.push(\n issue(\n \"QFAI-TRACE-032\",\n `Scenario の契約 ID が不正です: ${scenarioContractRefs.invalidTokens.join(\n \", \",\n )}`,\n \"error\",\n file,\n \"traceability.scenarioContractRefFormat\",\n scenarioContractRefs.invalidTokens,\n ),\n );\n }\n }\n\n const { document, errors } = parseScenarioDocument(text, file);\n if (!document || errors.length > 0) {\n continue;\n }\n\n if (document.scenarios.length !== 1) {\n issues.push(\n issue(\n \"QFAI-TRACE-030\",\n `Scenario ファイルは 1ファイル=1シナリオです。現在: ${document.scenarios.length}件 (file=${file})`,\n \"error\",\n file,\n \"traceability.scenarioOnePerFile\",\n ),\n );\n }\n\n const atoms = buildScenarioAtoms(document, scenarioContractRefs.ids);\n const scIdsInFile = new Set<string>();\n\n for (const [index, scenario] of document.scenarios.entries()) {\n const atom = atoms[index];\n if (!atom) {\n continue;\n }\n\n const specTags = scenario.tags.filter((tag) => SPEC_TAG_RE.test(tag));\n const brTags = scenario.tags.filter((tag) => BR_TAG_RE.test(tag));\n const scTags = scenario.tags.filter((tag) => SC_TAG_RE.test(tag));\n\n if (specTags.length === 0) {\n issues.push(\n issue(\n \"QFAI-TRACE-014\",\n `Scenario が SPEC タグを持っていません: ${scenario.name}`,\n \"error\",\n file,\n \"traceability.scenarioSpecRequired\",\n ),\n );\n }\n if (brTags.length === 0) {\n issues.push(\n issue(\n \"QFAI-TRACE-015\",\n `Scenario が BR タグを持っていません: ${scenario.name}`,\n \"error\",\n file,\n \"traceability.scenarioBrRequired\",\n ),\n );\n }\n\n brTags.forEach((id) => brIdsInScenarios.add(id));\n scTags.forEach((id) => {\n scIdsInScenarios.add(id);\n scIdsInFile.add(id);\n });\n const unknownSpecIds = specTags.filter((id) => !specIds.has(id));\n if (unknownSpecIds.length > 0) {\n issues.push(\n issue(\n \"QFAI-TRACE-005\",\n `Scenario が存在しない SPEC を参照しています: ${unknownSpecIds.join(\n \", \",\n )} (${scenario.name})`,\n \"error\",\n file,\n \"traceability.scenarioSpecExists\",\n unknownSpecIds,\n ),\n );\n }\n\n const unknownBrIds = brTags.filter((id) => !brIdsInSpecs.has(id));\n if (unknownBrIds.length > 0) {\n issues.push(\n issue(\n \"QFAI-TRACE-006\",\n `Scenario が存在しない BR を参照しています: ${unknownBrIds.join(\n \", \",\n )} (${scenario.name})`,\n \"error\",\n file,\n \"traceability.scenarioBrExists\",\n unknownBrIds,\n ),\n );\n }\n\n const unknownContractIds = atom.contractIds.filter(\n (id) => !contractIds.has(id),\n );\n if (unknownContractIds.length > 0) {\n issues.push(\n issue(\n \"QFAI-TRACE-008\",\n `Scenario が存在しない契約 ID を参照しています: ${unknownContractIds.join(\n \", \",\n )} (${scenario.name})`,\n config.validation.traceability.unknownContractIdSeverity,\n file,\n \"traceability.scenarioContractExists\",\n unknownContractIds,\n ),\n );\n }\n\n if (specTags.length > 0 && brTags.length > 0) {\n const allowedBrIds = new Set<string>();\n for (const specId of specTags) {\n const brIdsForSpec = specToBrIds.get(specId);\n if (!brIdsForSpec) {\n continue;\n }\n brIdsForSpec.forEach((id) => allowedBrIds.add(id));\n }\n const invalidBrIds = brTags.filter((id) => !allowedBrIds.has(id));\n if (invalidBrIds.length > 0) {\n issues.push(\n issue(\n \"QFAI-TRACE-007\",\n `Scenario の BR が参照 SPEC に属していません: ${invalidBrIds.join(\n \", \",\n )} (SPEC: ${specTags.join(\", \")}) (${scenario.name})`,\n \"error\",\n file,\n \"traceability.scenarioBrUnderSpec\",\n invalidBrIds,\n ),\n );\n }\n }\n }\n\n if (scIdsInFile.size !== 1) {\n const invalidScIds = Array.from(scIdsInFile).sort((a, b) =>\n a.localeCompare(b),\n );\n const detail =\n invalidScIds.length === 0\n ? \"SC が見つかりません\"\n : `複数の SC が存在します: ${invalidScIds.join(\", \")}`;\n issues.push(\n issue(\n \"QFAI-TRACE-012\",\n `Spec entry が Spec:SC=1:1 を満たしていません: ${detail}`,\n \"error\",\n file,\n \"traceability.specScOneToOne\",\n invalidScIds,\n ),\n );\n }\n }\n\n if (upstreamIds.size === 0) {\n return [\n issue(\n \"QFAI-TRACE-000\",\n \"上流 ID が見つかりません。\",\n \"info\",\n specsRoot,\n \"traceability.upstream\",\n ),\n ];\n }\n\n if (config.validation.traceability.brMustHaveSc && brIdsInSpecs.size > 0) {\n const orphanBrIds = Array.from(brIdsInSpecs).filter(\n (id) => !brIdsInScenarios.has(id),\n );\n if (orphanBrIds.length > 0) {\n issues.push(\n issue(\n \"QFAI-TRACE-009\",\n `BR が SC に紐づいていません: ${orphanBrIds.join(\", \")}`,\n \"error\",\n specsRoot,\n \"traceability.brMustHaveSc\",\n orphanBrIds,\n ),\n );\n }\n }\n\n const scRefsResult = await collectScTestReferences(\n root,\n config.validation.traceability.testFileGlobs,\n config.validation.traceability.testFileExcludeGlobs,\n );\n const scTestRefs = scRefsResult.refs;\n const testFileScan = scRefsResult.scan;\n const hasScenarios = scIdsInScenarios.size > 0;\n const hasGlobConfig = testFileScan.globs.length > 0;\n const hasMatchedTests = testFileScan.matchedFileCount > 0;\n\n if (\n hasScenarios &&\n (!hasGlobConfig || !hasMatchedTests || scRefsResult.error)\n ) {\n const detail = scRefsResult.error ? `(詳細: ${scRefsResult.error})` : \"\";\n issues.push(\n issue(\n \"QFAI-TRACE-013\",\n `テスト探索 glob が未設定/不正/一致ファイル0のため SC→Test を判定できません。${detail}`,\n \"error\",\n testsRoot,\n \"traceability.testFileGlobs\",\n ),\n );\n } else {\n if (\n config.validation.traceability.scMustHaveTest &&\n scIdsInScenarios.size\n ) {\n const scWithoutTests = Array.from(scIdsInScenarios).filter((id) => {\n const refs = scTestRefs.get(id);\n return !refs || refs.size === 0;\n });\n if (scWithoutTests.length > 0) {\n issues.push(\n issue(\n \"QFAI-TRACE-010\",\n `SC がテストで参照されていません: ${scWithoutTests.join(\n \", \",\n )}。testFileGlobs に一致するテストファイルへ QFAI:SC-xxxx を記載してください。`,\n config.validation.traceability.scNoTestSeverity,\n testsRoot,\n \"traceability.scMustHaveTest\",\n scWithoutTests,\n ),\n );\n }\n }\n\n const unknownScIds = Array.from(scTestRefs.keys()).filter(\n (id) => !scIdsInScenarios.has(id),\n );\n if (unknownScIds.length > 0) {\n issues.push(\n issue(\n \"QFAI-TRACE-011\",\n `テストが未知の SC をアノテーション参照しています: ${unknownScIds.join(\n \", \",\n )}`,\n \"error\",\n testsRoot,\n \"traceability.scUnknownInTests\",\n unknownScIds,\n ),\n );\n }\n }\n\n const orphanPolicy = config.validation.traceability.orphanContractsPolicy;\n if (orphanPolicy !== \"allow\") {\n if (contractIds.size > 0) {\n const orphanContracts = Array.from(contractIds).filter(\n (id) => !specContractIds.has(id),\n );\n if (orphanContracts.length > 0) {\n const severity: IssueSeverity =\n orphanPolicy === \"warning\" ? \"warning\" : \"error\";\n issues.push(\n issue(\n \"QFAI-TRACE-022\",\n `契約が Spec から参照されていません: ${orphanContracts.join(\", \")}`,\n severity,\n specsRoot,\n \"traceability.contractCoverage\",\n orphanContracts,\n ),\n );\n }\n }\n }\n\n issues.push(\n ...(await validateCodeReferences(upstreamIds, srcRoot, testsRoot)),\n );\n return issues;\n}\n\nasync function validateCodeReferences(\n upstreamIds: Set<string>,\n srcRoot: string,\n testsRoot: string,\n): Promise<Issue[]> {\n const issues: Issue[] = [];\n const codeFiles = await collectFiles(srcRoot, {\n extensions: [\".ts\", \".tsx\", \".js\", \".jsx\"],\n });\n const testFiles = await collectFiles(testsRoot, {\n extensions: [\".ts\", \".tsx\", \".js\", \".jsx\"],\n });\n const targetFiles = [...codeFiles, ...testFiles];\n\n if (targetFiles.length === 0) {\n issues.push(\n issue(\n \"QFAI-TRACE-001\",\n \"参照対象のコード/テストが見つかりません。\",\n \"info\",\n srcRoot,\n \"traceability.codeReferences\",\n ),\n );\n return issues;\n }\n\n const pattern = buildIdPattern(Array.from(upstreamIds));\n let found = false;\n\n for (const file of targetFiles) {\n const text = await readFile(file, \"utf-8\");\n if (pattern.test(text)) {\n found = true;\n break;\n }\n }\n\n if (!found) {\n issues.push(\n issue(\n \"QFAI-TRACE-002\",\n \"上流 ID がコード/テストに参照されていません(参考情報)。\",\n \"info\",\n srcRoot,\n \"traceability.codeReferences\",\n ),\n );\n }\n\n return issues;\n}\n\nfunction buildIdPattern(ids: string[]): RegExp {\n const escaped = ids.map((id) => id.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\"));\n return new RegExp(`\\\\b(${escaped.join(\"|\")})\\\\b`);\n}\n\nfunction issue(\n code: string,\n message: string,\n severity: IssueSeverity,\n file?: string,\n rule?: string,\n refs?: string[],\n): Issue {\n const issue: Issue = {\n code,\n severity,\n message,\n };\n if (file) {\n issue.file = file;\n }\n if (rule) {\n issue.rule = rule;\n }\n if (refs && refs.length > 0) {\n issue.refs = refs;\n }\n return issue;\n}\n","import { loadConfig, resolvePath, type ConfigLoadResult } from \"./config.js\";\nimport { collectScenarioFiles } from \"./discovery.js\";\nimport {\n buildScCoverage,\n collectScIdsFromScenarioFiles,\n collectScTestReferences,\n} from \"./traceability.js\";\nimport type { Issue, ValidationCounts, ValidationResult } from \"./types.js\";\nimport { resolveToolVersion } from \"./version.js\";\nimport { validateContracts } from \"./validators/contracts.js\";\nimport { validateDeltas } from \"./validators/delta.js\";\nimport { validateDefinedIds } from \"./validators/ids.js\";\nimport { validateScenarios } from \"./validators/scenario.js\";\nimport { validateSpecs } from \"./validators/spec.js\";\nimport { validateTraceability } from \"./validators/traceability.js\";\n\nexport async function validateProject(\n root: string,\n configResult?: ConfigLoadResult,\n): Promise<ValidationResult> {\n const resolved = configResult ?? (await loadConfig(root));\n const { config, issues: configIssues } = resolved;\n const issues = [\n ...configIssues,\n ...(await validateSpecs(root, config)),\n ...(await validateDeltas(root, config)),\n ...(await validateScenarios(root, config)),\n ...(await validateContracts(root, config)),\n ...(await validateDefinedIds(root, config)),\n ...(await validateTraceability(root, config)),\n ];\n\n const specsRoot = resolvePath(root, config, \"specsDir\");\n const scenarioFiles = await collectScenarioFiles(specsRoot);\n const scIds = await collectScIdsFromScenarioFiles(scenarioFiles);\n const { refs: scTestRefs, scan: testFiles } = await collectScTestReferences(\n root,\n config.validation.traceability.testFileGlobs,\n config.validation.traceability.testFileExcludeGlobs,\n );\n const scCoverage = buildScCoverage(scIds, scTestRefs);\n\n const toolVersion = await resolveToolVersion();\n return {\n toolVersion,\n issues,\n counts: countIssues(issues),\n traceability: {\n sc: scCoverage,\n testFiles,\n },\n };\n}\n\nfunction countIssues(issues: Issue[]): ValidationCounts {\n return issues.reduce<ValidationCounts>(\n (acc, issue) => {\n acc[issue.severity] += 1;\n return acc;\n },\n { info: 0, warning: 0, error: 0 },\n );\n}\n"],"mappings":"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","names":["path","parseYaml","import_promises","import_node_path","import_promises","import_node_path","import_promises","import_promises","import_node_path","exists","fg","path","import_promises","import_node_path","path","exists","path","import_node_path","path","issue","unique","import_promises","import_node_path","formatError","unique","SC_TAG_RE","formatError","path","import_promises","import_node_path","path","import_promises","import_node_path","import_node_path","import_yaml","path","parseYaml","path","formatError","issue","import_promises","import_node_path","path","isMissingFileError","issue","import_promises","import_node_path","SC_TAG_RE","issue","path","import_promises","SC_TAG_RE","SPEC_TAG_RE","issue","isMissingFileError","import_promises","issue","isMissingFileError","import_promises","SPEC_TAG_RE","BR_TAG_RE","issue","SC_TAG_RE","issue","ID_PREFIXES","path","toSortedArray","buildIdPattern","record","issue"]}