Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | 122x 137x 2x 120x 76x 116x 134x 27x 27x 116x 116x 115x 115x 115x 115x 116x 116x 116x 116x 116x 232x 232x 137x | import { readFile } from "node:fs/promises";
import { resolve } from "node:path";
import {
evaluateProjectDirectory,
type ProjectCheckEvaluation,
} from "./check-command.js";
import { summarizeCoverage, type CoverageCount } from "./coverage.js";
import type { VerificationProjectCheckResult } from "./check.js";
import { readAllureCounts, type AllureCounts } from "./ci-summary.js";
import { parseCoverageSummary } from "./coverage-summary.js";
export type OverallStatus = "PASS" | "INCOMPLETE" | "FAIL";
export interface QualityOverview {
readonly status: OverallStatus;
readonly requirementCoverage?: CoverageCount;
readonly missingEvidence?: number;
readonly testResults?: AllureCounts;
readonly codeCoverageLines?: number;
}
/** Use Moura's authoritative pair states: failed Evidence outranks incomplete coverage. */
export function overallStatus(
check: VerificationProjectCheckResult,
hasEvaluationProblems = false,
): OverallStatus {
if (
check.entries.some(
(entry) => entry.status === "FAIL" || entry.status === "BROKEN",
)
)
return "FAIL";
return hasEvaluationProblems ||
check.entries.some((entry) => entry.status !== "PASS")
? "INCOMPLETE"
: "PASS";
}
/** Missing runtime Evidence includes explicit not-yet-implemented required pairs. */
export function countMissingEvidence(
check: VerificationProjectCheckResult,
): number {
return check.entries.filter(
(entry) => entry.status === "MISSING" || entry.status === "UNIMPLEMENTED",
).length;
}
export async function collectQualityOverview(
root: string,
): Promise<QualityOverview> {
const evaluation = await evaluateProjectDirectory(root, {
strictTraceability: true,
});
return qualityOverviewFromEvaluation(root, evaluation);
}
export async function qualityOverviewFromEvaluation(
root: string,
evaluation: ProjectCheckEvaluation,
): Promise<QualityOverview> {
let status: OverallStatus = "INCOMPLETE";
let requirementCoverage: CoverageCount | undefined;
let missingEvidence: number | undefined;
if (evaluation.kind === "checked") {
const hasEvaluationProblems =
evaluation.adapterIssues.length > 0 ||
evaluation.check.evidenceIssues.length > 0 ||
evaluation.traceabilityDiagnostics.length > 0;
status = overallStatus(evaluation.check, hasEvaluationProblems);
requirementCoverage = summarizeCoverage(
evaluation.manifest,
evaluation.check,
).requirements;
missingEvidence = countMissingEvidence(evaluation.check);
}
const testResults = await optional(async () =>
readAllureCounts(resolve(root, "allure-results")),
);
const coverage = await optional(async () =>
parseCoverageSummary(
JSON.parse(
await readFile(resolve(root, "coverage/coverage-summary.json"), "utf8"),
) as unknown,
),
);
return {
status,
...(requirementCoverage ? { requirementCoverage } : {}),
...(missingEvidence === undefined ? {} : { missingEvidence }),
...(testResults ? { testResults } : {}),
...(coverage ? { codeCoverageLines: coverage.lines.pct } : {}),
};
}
async function optional<T>(read: () => Promise<T>): Promise<T | undefined> {
try {
return await read();
} catch {
return undefined;
}
}
|