feat(config): every lens off until the repository turns it on

Jorijn: "all lenses off by default and opt in only". Config::Defaults()
gives every lens run: false; a config that turns on none - a missing
`lenses` key included - has the one problem that names the lenses, so
config, freeze and run all stop on it; the template ships every lens off,
init says to turn lenses on, and the "no lens runs" preflight names the
cause. A consumer config without a `lenses` key now needs one, as the CI
smoke test's does.

Proven with the lens commit before it: the suite (26 passed), and the
dry-run comparison recorded there.
This commit is contained in:
Jorijn van der Graaf 2026-10-31 20:09:07 +01:00
commit 101471d81a
Signed by: jorijnvdgraaf
GPG key ID: 2937E59CDCC1BCFB
15 changed files with 513 additions and 269 deletions

View file

@ -196,15 +196,16 @@ echo "{\"type\":\"result\",\"subtype\":\"success\",\"is_error\":false,\"result\"
{"GIT_COMMITTER_NAME", "Me"}, {"GIT_COMMITTER_EMAIL", "me@example.com"}, {"CRAFTER_REVIEW_HOME", checkout.string()},
{"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) and the commit-truth lens off (it gets
// the last scenario).
// A repository with one commit to review, the three static code lenses
// on (every lens is off until a config turns it on; the functional
// lens needs a running application, the commit-truth lens 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}, "repo-facts": {"run": false}}})");
Write(repo / ".review-gates" / "config.json", R"({"lenses": {"repo-better-solution": {"run": true}, "repo-bug-prover": {"run": true}, "repo-security": {"run": true}}})");
Write(repo / "README.md", "a greeter\n");
Git(repo, {"add", "-A"});
Git(repo, {"commit", "-q", "-m", "base"});
@ -421,14 +422,14 @@ 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
// The commit-truth lens (2026-10-31), alone: a config that turns on
// only it (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}}})");
Write(base / "facts.json", R"({"lenses": {"repo-facts": {"run": true}}})");
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()});