feat(lenses): the commit-truth lens, repo-facts, as Gate 4
Every claim in every commit message, and in the documentation the range adds or changes, proven or gone. The lens's block kinds are text, doc and slot: a message unit is keyed on its text, the base and the code up to its commit (MessageDeps); a documentation unit on its file, its normalised text, the base and the code of the whole range (DocKeyParts); a diffstat on its text alone; whole:order and whole:absent are asked in slot passes of its own, never stored. A documentation file's diff header and a part the commit writes nothing in are a mechanical n/a. Budgets 60/40 for a text or doc block, 50/35 for a slot; one read. Gate 4, after the proofs, so the messages and documents are read once the code they describe has settled; the owner's gate is 5. The goldens that follow from the lens table are derived by tests/Goldens/derive.py, which asserts that the recorded table still reproduces the recorded entries before it writes. Proven, with the opt-in commit after this one: the suite (26 passed); a dry run of a scratch range (2 commits, a README with sections) by the previous binary and this one with the three static lenses on and the rest off, 25 prompts and 4 system files byte for byte; with repo-facts on as well, those files unchanged and 10 passes and 1 system file added. The lens's firing proof in this pipeline is owed (the owner's go).
This commit is contained in:
parent
61ee4602f4
commit
febbfc3fcc
19 changed files with 2564 additions and 646 deletions
|
|
@ -61,7 +61,7 @@ for a in "$@"; do
|
|||
prev=$a
|
||||
done
|
||||
lens=$(sed -n 's/^# Lens: //p' "$sys" | head -n 1)
|
||||
ids=$(sed -n -e 's/^SCOPE - BLOCK PASS, unit "\([^"]*\)".*/\1/p' -e 's/^- \(whole:[a-z]*\) \[.*/\1/p')
|
||||
ids=$(sed -n -e 's/^SCOPE - BLOCK PASS, unit "\([^"]*\)".*/\1/p' -e 's/^SCOPE - SLOT PASS, unit "\([^"]*\)".*/\1/p' -e 's/^- \(whole:[a-z]*\) \[.*/\1/p')
|
||||
echo "$$ $lens" $ids >> "$FAKE_DIR/calls"
|
||||
echo "{\"type\":\"system\",\"subtype\":\"init\",\"session_id\":\"$sid\",\"model\":\"$model\",\"mcp_servers\":[],\"tools\":[\"Read\"]}"
|
||||
echo '{"type":"assistant","message":{"role":"assistant","content":[{"type":"text","text":"reading"}]}}'
|
||||
|
|
@ -197,13 +197,14 @@ echo "{\"type\":\"result\",\"subtype\":\"success\",\"is_error\":false,\"result\"
|
|||
{"REVIEW_GATES_BOARD", (base / "board.json").string()}, {"FAKE_DIR", fakeDir.string()}});
|
||||
|
||||
// A repository with one commit to review, the functional lens off (it
|
||||
// needs a running application).
|
||||
// needs a running application) and the commit-truth lens off (it gets
|
||||
// the last scenario).
|
||||
fs::create_directories(repo);
|
||||
Git(repo, {"init", "-q", "-b", "main"});
|
||||
Git(repo, {"config", "user.email", "me@example.com"});
|
||||
Git(repo, {"config", "user.name", "Me"});
|
||||
Write(repo / ".gitignore", ".review-gates/push/\n.review-gates/trees/\n");
|
||||
Write(repo / ".review-gates" / "config.json", R"({"lenses": {"repo-functional": {"run": false}}})");
|
||||
Write(repo / ".review-gates" / "config.json", R"({"lenses": {"repo-functional": {"run": false}, "repo-facts": {"run": false}}})");
|
||||
Write(repo / "README.md", "a greeter\n");
|
||||
Git(repo, {"add", "-A"});
|
||||
Git(repo, {"commit", "-q", "-m", "base"});
|
||||
|
|
@ -420,6 +421,32 @@ echo "{\"type\":\"result\",\"subtype\":\"success\",\"is_error\":false,\"result\"
|
|||
Check("an error escaping a full run (a reserve that is no number) ends it with its ValueError, exit 1",
|
||||
badReserve.returnCode == 1 && badReserve.err.contains("crafter-review: ValueError: could not convert string to float: 'x'"), badReserve.err);
|
||||
|
||||
// The commit-truth lens (2026-10-31), alone: a config that turns off
|
||||
// every other lens (through --config: the tracked config file must
|
||||
// stay as committed, or the tree is dirty) runs Gate 4 - its three text
|
||||
// blocks and its two slot passes (the stand-in answers a SLOT PASS
|
||||
// too) - push-ready, with the code units, the per-commit slots and
|
||||
// the functional lens's slot listed as not reviewed.
|
||||
{
|
||||
Write(base / "facts.json", R"({"lenses": {"repo-better-solution": {"run": false}, "repo-functional": {"run": false}, "repo-bug-prover": {"run": false}, "repo-security": {"run": false}}})");
|
||||
const std::int64_t before = calls();
|
||||
std::vector<std::string> truthArgs = runArgs({"--no-reuse", "--no-salvage"});
|
||||
truthArgs.insert(truthArgs.begin() + 1, {"--config", (base / "facts.json").string()});
|
||||
const Process::Captured truth = Process::Run(truthArgs, repo, std::chrono::seconds(60), {}, Env);
|
||||
const Json dumpT = LatestDump(gateDir, h8);
|
||||
const Json& processesT = dumpT.is_object() ? dumpT.at("processes") : Json::array();
|
||||
std::set<std::string> labels;
|
||||
for (const Json& p : processesT) labels.insert(Text(p.at("label")));
|
||||
const Json notReviewedT = dumpT.is_object() ? dumpT.at("coverage").at("notReviewed") : Json::array();
|
||||
auto notReviewed = [&](std::string_view id) { return std::ranges::any_of(notReviewedT, [&](const Json& x) { return x == id; }); };
|
||||
Check("the commit-truth lens alone: Gate 4 runs its three text blocks and its two slot passes (5 calls) - SEND-READY, exit 0; the code units, the per-commit slots and whole:behaviour are not reviewed",
|
||||
truth.returnCode == 0 && calls() - before == 5 && dumpT.is_object() && dumpT.at("overall") == "SEND-READY" && dumpT.at("stoppedAt").is_null()
|
||||
&& labels == std::set<std::string>{"repo-facts:block:p1:subject", "repo-facts:block:p1:msg", "repo-facts:block:p1:diffstat", "repo-facts:slot:whole:order", "repo-facts:slot:whole:absent"}
|
||||
&& Count(processesT, "kind", "slot") == 2 && dumpT.at("lensesOff") == Json::array({"repo-better-solution", "repo-functional", "repo-bug-prover", "repo-security"})
|
||||
&& notReviewed("p1:hello.py#1") && notReviewed("p1:absent") && notReviewed("whole:behaviour") && !notReviewed("whole:order") && !notReviewed("p1:msg"),
|
||||
std::format("exit {}, {} call(s), {}", truth.returnCode, calls() - before, dumpT.is_object() ? Text(dumpT.at("overall")) : truth.out + truth.err));
|
||||
}
|
||||
|
||||
// A stop between two gates: the next gate's pool starts aborted and
|
||||
// runs nothing of it.
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in a new issue