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:
Jorijn van der Graaf 2026-10-31 20:08:26 +01:00
commit febbfc3fcc
Signed by: jorijnvdgraaf
GPG key ID: 2937E59CDCC1BCFB
19 changed files with 2564 additions and 646 deletions

View file

@ -12,6 +12,9 @@ import :Json;
// progress.json and the prompts are made from them.
export namespace Crafter::Review::Plan {
constexpr std::string_view FunctionalLens = "repo-functional.md";
// The commit-truth lens (2026-10-31, the fp6 pipeline's repo-facts): the
// messages and the documentation of the range.
constexpr std::string_view FactsLens = "repo-facts.md";
// The reasoning effort when --effort is not given (2026-10-02: the push
// gates run at xhigh).
constexpr std::string_view Effort = "xhigh";
@ -40,16 +43,21 @@ export namespace Crafter::Review::Plan {
constexpr std::array<std::string_view, 2> ApproachSlots = {"whole:order", "whole:absent"};
constexpr std::array<std::string_view, 1> BehaviourSlots = {"whole:behaviour"};
constexpr std::array<std::string_view, 1> CodeBlocks = {"code"};
constexpr std::array<std::string_view, 3> TruthBlocks = {"text", "doc", "slot"};
// One row of LENSES. whole: "" (none), "first-repo" (the approach) or
// "functional" (the range exercised in the running application); every
// whole pass gates the lens's block passes and covers the slots named in
// `slots`. block: the unit kinds the lens zooms into. reuse: per-unit reuse
// across hashes; wholeReuse: the clean whole pass carries while the code
// of the range is unchanged. key: what a block is keyed on — "code" (its
// own hunk and the base; 2026-10-06) or "functional" (its hunk AND the
// code of the whole range: what the browser shows for a hunk depends on
// every other hunk). reads: the lens's code units need Reads clean reads.
// `slots`. A lens with no whole pass and "slot" among its block kinds
// asks each slot named in `slots` in a slot pass of its own (the
// commit-truth lens: whole:order and whole:absent). block: the unit kinds
// the lens zooms into. reuse: per-unit reuse across hashes; wholeReuse:
// the clean whole pass carries while the code of the range is unchanged.
// key: what a code block is keyed on — "code" (its own hunk and the base;
// 2026-10-06) or "functional" (its hunk AND the code of the whole range:
// what the browser shows for a hunk depends on every other hunk); a text
// or doc block is keyed by its kind whatever the lens's key (TextReuseKey,
// DocReuseKey). reads: the lens's code units need Reads clean reads.
// empirical: the lens's evidence is observation, so it needs an
// environment with an application under test, and a whole pass that never
// used the instrument is not evidence. perCommitSlots false: the lens
@ -71,7 +79,7 @@ export namespace Crafter::Review::Plan {
std::string_view env;
};
// In the order the dump and the prompts list them.
constexpr std::array<Lens, 4> Lenses = {{
constexpr std::array<Lens, 5> Lenses = {{
{"repo-better-solution.md", 1, "first-repo", ApproachSlots, CodeBlocks, "fable", true, true, true, "code", false, true, "none"},
{FunctionalLens, 2, "functional", BehaviourSlots, CodeBlocks, "opus", true, true, false, "functional", true, false, "browser"},
{"repo-bug-prover.md", 3, "", {}, CodeBlocks, "opus", true, false, true, "code", false, true, "none"},
@ -79,6 +87,13 @@ export namespace Crafter::Review::Plan {
// protections the repository promises? The bug-prover's shape beside
// it in Gate 3: one gate stop for both proofs.
{"repo-security.md", 3, "", {}, CodeBlocks, "opus", true, false, true, "code", false, true, "none"},
// The commit-truth lens (2026-10-31): every claim in every commit
// message, and in the documentation the range adds or changes, proven
// or gone. The text and doc units and the two whole slots, in a gate
// of its own after the proofs, so the messages and documents are read
// once the code they describe has settled. One read: its units are
// prose, keyed on their text and the code they describe.
{FactsLens, 4, "", ApproachSlots, TruthBlocks, "opus", true, false, false, "text", false, true, "none"},
}};
bool IsLens(std::string_view file);
// LENSES[file]; Dyn::Error (KeyError) for a file that is no lens.
@ -234,7 +249,26 @@ export namespace Crafter::Review::Plan {
std::optional<std::string> FunctionalReuseKey(const Json& job, std::string_view lensFile, std::string_view unitText, const CommitCode& cc,
std::span<const std::string> inForceIds, std::string_view charterSha, std::int32_t promptVersion,
std::string_view environment = {});
// By the lens's `key` kind.
// (ident, deps) of a doc unit - a hunk of a documentation file, or one
// heading-delimited part of it: keyed on its file and its own normalised
// text, like a code hunk, and on the base and the code of the whole
// range - a sentence must hold for the code as its commit leaves it AND
// as the range leaves it, so any code change in the range asks it again
// (2026-10-06).
std::pair<std::string, std::vector<std::string>> DocKeyParts(std::string_view unitId, const CommitCode& cc);
// What a message unit (pK:subject, pK:msg) depends on beside its own text:
// the base and the code of the range up to and including its commit - a
// message describes its commit's change and the state it changes, so a
// fix to that code asks the message again. Empty for every other unit (a
// diffstat states only its own numbers).
std::vector<std::string> MessageDeps(std::string_view unitId, const CommitCode& cc);
std::optional<std::string> DocReuseKey(const Json& job, std::string_view lensFile, std::string_view unitText, const CommitCode& cc,
std::span<const std::string> inForceIds, std::string_view charterSha, std::int32_t promptVersion,
std::string_view environment = {});
std::optional<std::string> TextReuseKey(const Json& job, std::string_view lensFile, std::string_view unitText, const CommitCode& cc,
std::span<const std::string> inForceIds, std::string_view charterSha, std::int32_t promptVersion,
std::string_view environment = {});
// By the job's unit kind (doc, text), else by the lens's `key` kind.
std::optional<std::string> BlockReuseKey(const Json& job, std::string_view lensFile, std::string_view unitText, const CommitCode& cc,
std::span<const std::string> inForceIds, std::string_view charterSha, std::int32_t promptVersion,
std::string_view environment = {});