// SPDX-License-Identifier: AGPL-3.0-only // SPDX-FileCopyrightText: Copyright (C) 2026 Catcrafts® // Normalising a pass: the synthesized finding, prefix resolution, discharge, // contests, the vocabulary. import std; import Crafter.Review; using namespace Crafter::Review; namespace { std::int32_t Failures = 0; void Check(std::string_view name, bool cond, std::string_view detail = {}) { std::println("{}{}{}", cond ? " ok " : " FAIL ", name, !cond && !detail.empty() ? std::format(" ({})", detail) : std::string()); if (!cond) ++Failures; } bool AnyKind(const Json& violations, std::string_view part) { return std::ranges::any_of(violations, [&](const Json& v) { return v.at("kind").get().contains(part); }); } } int main() { std::println("normalize: synthesized finding, prefix resolution, discharge, contests, vocabulary"); const Json inv = Json::array({{{"id", "p1:x.py#1"}}, {{"id", "p1:src/components/a.tsx#1"}}, {{"id", "p1:src/components/a.tsx#2"}}}); std::vector ids; for (const Json& u : inv) ids.push_back(u.at("id").get()); const std::string lens = "repo-bug-prover.md"; const Json first = Json::array({inv[0]}); auto run = [&](Json v, const std::vector& inForce, std::string_view lensFile = "repo-bug-prover.md") { return Normalize::NormalizeOutput(v, inForce, lensFile, "h", first, ids); }; const Json n = run({{"verdict", "SEND-READY"}, {"findings", Json::array()}, {"notes", Json::array()}, {"coverage", {{{"item", "p1:x.py#1"}, {"verdict", "defect"}, {"basis", "x"}}}}}, {}); Check("defect without finding -> synthesized undischarged finding, FIX FIRST", n.at("verdict") == "FIX FIRST" && !n.at("findings").empty() && Dyn::Truthy(Dyn::Get(n.at("findings").at(0), "synthesized")) && n.at("undischarged") == 1); Check("declared SEND-READY over it -> contract violation", AnyKind(n.at("contractViolations"), "failed closed")); Check("prefix: a unique prefix resolves, an ambiguous one stays", Normalize::ResolveId("p1:x", ids) == ids[0] && Normalize::ResolveId("p1:src/components/a.tsx#", ids) == "p1:src/components/a.tsx#"); const Json n2 = run({{"verdict", "SEND-READY"}, {"findings", Json::array()}, {"notes", Json::array()}, {"coverage", {{{"item", "p1:x"}, {"verdict", "clear"}, {"basis", "b"}}}}}, {}); Check("abbreviated coverage id resolved -> no MISSING", n2.at("coverageMissing").empty() && n2.at("coverage").at(0).at("item") == ids[0]); const Json n3 = run({{"verdict", "SEND-READY"}, {"findings", Json::array()}, {"notes", Json::array()}, {"coverage", Json::array()}}, {}); Check("no coverage entry -> coverageMissing (NOT RETURNED)", n3.at("coverageMissing") == Json::array({ids[0]}) && !n3.at("contractViolations").empty()); const std::vector d = {{{"id", "w1"}, {"kind", "waiver-owner"}, {"hash", "h"}}}; auto finding = [&](const Json& extra) { Json f = {{"finding", "f"}, {"evidence", "e"}, {"proposedAction", "p"}, {"items", {ids[0]}}}; f.update(extra); return f; }; const Json n4 = run({{"verdict", "SEND-READY"}, {"findings", {finding({{"dischargedBy", "w1"}})}}, {"notes", Json::array()}, {"coverage", {{{"item", ids[0]}, {"verdict", "clear"}, {"basis", "discharged by w1"}}}}}, d); Check("dischargedBy an in-force id -> discharged, SEND-READY", n4.at("verdict") == "SEND-READY" && n4.at("findings").at(0).at("discharged") == true); const Json n5 = run({{"verdict", "SEND-READY"}, {"findings", {finding({{"dischargedBy", "nope"}})}}, {"notes", Json::array()}, {"coverage", {{{"item", ids[0]}, {"verdict", "clear"}, {"basis", "b"}}}}}, d); Check("dischargedBy an unknown id -> undischarged, FIX FIRST", n5.at("verdict") == "FIX FIRST" && n5.at("findings").at(0).at("discharged") == false); const Json n6 = run({{"verdict", "FIX FIRST"}, {"findings", {finding({{"contests", {{"id", "w1"}, {"why", "w"}}}})}}, {"notes", Json::array()}, {"coverage", {{{"item", ids[0]}, {"verdict", "defect"}, {"basis", "b"}}}}}, d); Check("contest of an unsettled entry blocks", n6.at("verdict") == "FIX FIRST" && !n6.at("contests").empty() && n6.at("contests").at(0).at("outcome").get().contains("CONTESTED")); const std::vector d2 = {{{"id", "w1"}, {"kind", "waiver-owner"}, {"hash", "h"}, {"reaffirmed", {{{"hash", "h"}}}}}}; const Json n7 = run({{"verdict", "FIX FIRST"}, {"findings", {finding({{"contests", {{"id", "w1"}, {"why", "w"}}}})}}, {"notes", Json::array()}, {"coverage", {{{"item", ids[0]}, {"verdict", "clear"}, {"basis", "b"}}}}}, d2); Check("contest of a reaffirmed entry is recorded, finding discharged (silent veto logged)", n7.at("verdict") == "SEND-READY" && n7.at("findings").at(0).at("discharged") == true && AnyKind(n7.at("contractViolations"), "silent veto")); const Json n8 = run({{"verdict", "SEND-READY"}, {"findings", Json::array()}, {"notes", {{{"kind", "unverified"}, {"note", "x"}, {"evidence", "e"}, {"action", "a"}, {"items", {ids[0]}}}}}, {"coverage", {{{"item", ids[0]}, {"verdict", "n/a"}, {"basis", "unverified: login failed"}}}}}, {}, Plan::FunctionalLens); Check("functional: n/a with an unverified note is a pass of the contract (not clear, not a hole in the pass)", n8.at("verdict") == "SEND-READY" && n8.at("coverageMissing").empty() && std::ranges::contains(Schema::NoteKinds, std::string_view("unverified")) && !std::ranges::contains(Schema::NoteKinds, std::string_view("disposition-review"))); return Failures ? 1 : 0; }