/** * The evidence report — the artifact a buyer hands to an auditor. * * Derived entirely from state already on disk. That is the bet this whole feature * rests on: if producing the report required a developer to write anything they would * not otherwise write, the remaining feature would be a text file with a command * group around it, and the design's stated fallback would be to ship that instead. * * Three properties are load-bearing, and each exists because its absence would make * the report actively misleading: * * **A checked-only control never carries evidence.** CC8.1 is a control over the * change process, and the artifact trail genuinely demonstrates it. The CC6 and CC7 * controls operate over a running system — no markdown file evidences "the entity * monitors system components for anomalies". Reporting design-intent prose as * evidence of an operating control is the overclaim this feature exists to prevent, * and it would happen in precisely the document least able to survive it. * * **Absence is reported by name.** A control with no evidence appears as absent, not * omitted. A report that silently drops what it could not find reads as a clean bill * of health. * * **The unreviewed-draft notice is emitted from code.** Not copied from pack text: a * notice living only in an installed file can be edited away permanently, because a * locally edited layer is preserved forever by design. * * Read-only. Writes nothing under `.aidlc/`, and reads only from an allowlist. * * Requirements: compliance-packs/AC-30, AC-32, AC-33, AC-34, AC-59, AC-60, AC-61, * AC-83, AC-84, AC-85, AC-90, AC-107 */ import type { Control, PackMeta } from './types.js'; /** Why an instance is outside the report's scope. */ export type ExclusionReason = 'predates-pack' | 'not-complete' | 'filtered'; /** An instance the report deliberately does not cover. */ export interface ExcludedInstance { instance: string; reason: ExclusionReason; detail: string; } /** One finding referenced by a control row. Ids and status only — never bodies. */ export interface ReportFinding { id: string; severity: Control['severity']; status: string; /** Repo-relative path of the findings file. */ source: string; } /** One control's row in the report. */ export interface ControlRow { packId: string; control: string; kind: Control['kind']; /** The control's requirement, from the pack. */ requires: string; /** * The artifact that evidences this control, repo-relative. * * Present only on an `evidenced` control. A `checked-only` control has no evidence * artifact by construction, and the renderer asserts the field's absence. */ evidenceArtifact?: string; /** Whether that evidence was found. `evidenced` controls only. */ evidenceFound?: boolean; /** Findings raised against this control across the in-scope instances. */ findings: ReportFinding[]; /** Instances that explicitly recorded this control as checked with no issue. */ clearedIn: string[]; } /** A pack's section of the report. */ export interface PackSection { meta: PackMeta; /** Emitted from code when `reviewed_by` is null. Never copied from pack text. */ unreviewedNotice: string | null; controls: ControlRow[]; /** Criteria the pack states it does not cover, with the reason it gives. */ exclusions: { id: string; reason: string; note?: string; }[]; } /** The whole report. */ export interface ComplianceReport { generatedAt: string; /** Instances the report covers. */ instances: string[]; /** Instances left out, each with a reason. Never silently dropped. */ excluded: ExcludedInstance[]; packs: PackSection[]; warnings: string[]; } export interface ReportOptions { /** Limit to one instance. */ instance?: string; /** Limit to instances completed on or after this ISO date. */ since?: string; /** Injected clock, for deterministic tests. */ now?: Date; /** * Called with every path this module reads. * * A real seam rather than a test convenience: it is how the read allowlist is * *checked* rather than asserted in prose. Without it, "the report reads only * these paths" is a claim no test can falsify — and the claim matters, because a * report that quietly slurped an unrelated file would be handing a buyer whatever * that file contained. */ onRead?: (path: string) => void; } /** * Whether a path is one the report is permitted to read. * * Exported so a test can assert against the same predicate the module documents, * rather than a re-typed copy of it that could drift. */ export declare function isAllowedReadPath(projectRoot: string, path: string): boolean; /** * The notice text, emitted from code for any pack whose control text is unreviewed. * * One of the notice's three enforcement points. The others are pack-source validation * and a doctor check for the case where someone edits it out of an installed layer. */ export declare function unreviewedNoticeFor(meta: PackMeta): string | null; /** The sentence stating what a checked-only control does and does not establish. */ export declare function checkedOnlyCaveat(controlId: string): string; /** * Build the report. * * Reads only: `.aidlc/config.yaml`, each in-scope instance's `instance.yaml` and * `phase-*.yaml`, its compliance findings files, and the pack sources through the * resolver. Creates and writes nothing. */ export declare function computeComplianceReport(projectRoot: string, opts?: ReportOptions): ComplianceReport; /** * Render the report as markdown. * * Every path is already repo-relative by construction. A final assertion checks the * home directory does not appear, because that is the decidable form of the guarantee * and it does not depend on secret redaction — the redaction helper explicitly does * not classify paths as secrets. */ export declare function renderComplianceReport(report: ComplianceReport): string; //# sourceMappingURL=report.d.ts.map