Crafter.Review/tests/Normalize/main.cpp
Jorijn van der Graaf 71dba5690f
test(pipeline): the checks of the pure pipeline
Stream, Normalize, Merge, Dispositions, Config, CodeKeys and the pure half
of CommitsMode, each a test of its own (131 checks). The fixture rewrites
are checked in (code-keys/<name>/, commits3/), so the suite reads fixtures
and edits nothing. The allowlist, command-line and MCP checks of
CommitsMode come with the pool they test.

Among them: this binary's `<exe> sql` spelling counts as a SQL call, and a
result line with a raw U+2028 in a JSON string is still the result line.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 06:56:09 +01:00

70 lines
5.6 KiB
C++

// 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<std::string>().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<std::string> ids;
for (const Json& u : inv) ids.push_back(u.at("id").get<std::string>());
const std::string lens = "repo-bug-prover.md";
const Json first = Json::array({inv[0]});
auto run = [&](Json v, const std::vector<Json>& 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<Json> 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<std::string>().contains("CONTESTED"));
const std::vector<Json> 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;
}