/** * 需求覆盖检查 — 验证 requirement → task → artifact → verification_run 可追踪关系。 * * 职责边界: * - 负责:遍历 task 的 RequirementContract,检查 evidence_requirements/acceptance_criteria 是否被有效 VerificationRun 覆盖; * 反向检测 orphan artifact(有 valid 验证证据但无 requirement 来源 = 无需求驱动的实现) * - 不负责:deliver 阻断(后续阶段)、HMAC 签名(在 Store)、规则集 staleness(EvidenceEvaluator 已做) * * : 数据源迁 V2 VerificationEvidenceStore(替代 )。读 V2 evidence 经 evidenceToEvidenceView → EvidenceView view。 * verification_run_id 防伪保留(VerificationRunStore 校验 run 绑定不变,不降安全约束)。 * 与 EvidenceEvaluator forged 检测同源(简化版:无 run ref / run.task_id 绑定 / run.result.passed / run.artifact.kind 匹配 → 视为伪造,不计覆盖)。 * * 被谁调用:后续 deliver pipeline 集成、sf_requirement check、测试 * 调用谁:RequirementStore、VerificationEvidenceStore、VerificationRunStore */ import type { DomainContract } from "./types.js"; export type CoverageGapKind = "missing_evidence" | "missing_acceptance" | "orphan_artifact"; export interface CoverageGap { /** orphan_artifact 时为 null(无归属需求) */ requirement_id: string | null; kind: CoverageGapKind; detail: string; } export interface CoverageReport { task_id: string; requirement_count: number; gaps: CoverageGap[]; /** 覆盖完整:gaps 为空(所有需求证据满足 + 无 orphan artifact)。deliver 据此阻断(后续阶段)。 */ covered: boolean; } export declare class RequirementCoverageChecker { private readonly projectRoot; private readonly contractsOverride?; private readonly requirements; private readonly evidence; private readonly runs; constructor(projectRoot: string, contractsOverride?: readonly DomainContract[] | undefined); /** 查 task 在某域是否有某 artifact_kind 的有效 passed 证据。 * 有效 = V2 evidence.passed + 有 verification_run_id + VerificationRun 存在 + task_id/artifact_kind 绑定 + result.passed。 * 手写 evidence(无 run ref)/删 run/binding 不符/result 改 → 视为伪造,不计覆盖(与 EvidenceEvaluator forged 检测同源)。 * : V2 保留历史多条;sort evaluated_at 降序从新到旧找第一条有效(对齐 V1 覆盖式 read 的"最新"语义)。 */ private findValidEvidence; /** 检查 task 的需求覆盖。无 requirement 的 task 返 requirement_count=0 + covered=true(不强制需求,deliver 阻断策略在后续阶段)。 */ check(taskId: string): Promise; }