// SPDX-License-Identifier: AGPL-3.0-only // SPDX-FileCopyrightText: Copyright (C) 2026 Catcrafts® export module Crafter.Review:Normalize; import std; import :Json; // From the raw structured output of a pass to its discharge, its coverage // contract and its derived verdict; the merge of a lens's parts with the // cross-unit rule; the coverage matrix. The structured output is the model's // JSON and stays JSON, with every field the model wrote. export namespace Crafter::Review::Normalize { // An exact id, else the one id of `universe` it is a prefix of, else // itself. Json ResolveId(const Json& id, std::span universe); // v: the raw structured output ({verdict, findings, notes, coverage?}). // Its notes get their items resolved in place, and the result holds them. // inventory: the units THIS pass must cover (null: no coverage contract); // allIds: every inventory id, for prefix resolution. Json NormalizeOutput(Json& v, std::span inForce, std::string_view lensFile, std::string_view hash, const Json& inventory, std::span allIds); // The distinct values of `items`, first occurrence kept, equal when their // canonical JSON is. std::vector Dedupe(std::span items); // parts: normalized outputs (each with partLabel, expectedIds); // missingUnits: unit ids whose process never returned. Coverage: one entry // per unit, blocking > immaterial > the rest, a tie to the later part // (the block, the zoomed view). The cross-unit rule: a unit cited by an // undischarged finding whose merged verdict is not blocking is // overwritten with the lens's blocking verdict. Json MergeParts(std::string_view lens, std::string_view lensFile, std::span parts, std::span missingUnits, const Json& stoppedEarly = nullptr); // Units x every lens that returned coverage; holes (a reviewed-kind unit // no lens owned) and defects. notReviewed: the unit ids no lens that runs // reads, listed, never holes. Json Matrix(const Json& inventory, std::span results, std::span notReviewed = {}); }